summaryrefslogtreecommitdiff
path: root/src/VBox/GuestHost/OpenGL/state_tracker
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2014-03-26 19:21:20 +0000
committer <>2014-05-08 15:03:54 +0000
commitfb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch)
treec2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/GuestHost/OpenGL/state_tracker
parent58ed4748338f9466599adfc8a9171280ed99e23f (diff)
downloadVirtualBox-master.tar.gz
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/GuestHost/OpenGL/state_tracker')
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/dump.cpp1741
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/dump_gen.py257
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/get_components.py144
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state.h21
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_attrib.c39
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_bits_globalop.h338
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c2
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c218
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_client.c218
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c332
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_enable.c7
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_error.c7
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c620
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_get.py2
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt21
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c60
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_init.c163
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_lists.c200
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_point.c259
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_point.txt1
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c3
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_program.c17
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c837
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_special7
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c1335
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c10
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c67
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c111
28 files changed, 6072 insertions, 965 deletions
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/dump.cpp b/src/VBox/GuestHost/OpenGL/state_tracker/dump.cpp
new file mode 100644
index 00000000..8132d9f9
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/dump.cpp
@@ -0,0 +1,1741 @@
+/* $Id: dump.cpp $ */
+
+/** @file
+ * Blitter API implementation
+ */
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#include "cr_blitter.h"
+#include "cr_spu.h"
+#include "chromium.h"
+#include "cr_error.h"
+#include "cr_net.h"
+#include "cr_rand.h"
+#include "cr_mem.h"
+#include "cr_string.h"
+#include <cr_dump.h>
+#include "cr_pixeldata.h"
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/mem.h>
+
+#include <stdio.h>
+
+#ifdef VBOX_WITH_CRDUMPER
+
+static uint32_t g_CrDbgDumpRecTexInfo = 1;
+static uint32_t g_CrDbgDumpAlphaData = 1;
+
+/* dump stuff */
+#pragma pack(1)
+typedef struct VBOX_BITMAPFILEHEADER {
+ uint16_t bfType;
+ uint32_t bfSize;
+ uint16_t bfReserved1;
+ uint16_t bfReserved2;
+ uint32_t bfOffBits;
+} VBOX_BITMAPFILEHEADER;
+
+typedef struct VBOX_BITMAPINFOHEADER {
+ uint32_t biSize;
+ int32_t biWidth;
+ int32_t biHeight;
+ uint16_t biPlanes;
+ uint16_t biBitCount;
+ uint32_t biCompression;
+ uint32_t biSizeImage;
+ int32_t biXPelsPerMeter;
+ int32_t biYPelsPerMeter;
+ uint32_t biClrUsed;
+ uint32_t biClrImportant;
+} VBOX_BITMAPINFOHEADER;
+#pragma pack()
+
+void crDmpImgBmp(CR_BLITTER_IMG *pImg, const char *pszFilename)
+{
+ static int sIdx = 0;
+
+ if ( pImg->bpp != 16
+ && pImg->bpp != 24
+ && pImg->bpp != 32)
+ {
+ crWarning("not supported bpp %d", pImg->bpp);
+ return;
+ }
+
+ FILE *f = fopen (pszFilename, "wb");
+ if (!f)
+ {
+ crWarning("fopen failed");
+ return;
+ }
+
+ VBOX_BITMAPFILEHEADER bf;
+
+ bf.bfType = 'MB';
+ bf.bfSize = sizeof (VBOX_BITMAPFILEHEADER) + sizeof (VBOX_BITMAPINFOHEADER) + pImg->cbData;
+ bf.bfReserved1 = 0;
+ bf.bfReserved2 = 0;
+ bf.bfOffBits = sizeof (VBOX_BITMAPFILEHEADER) + sizeof (VBOX_BITMAPINFOHEADER);
+
+ VBOX_BITMAPINFOHEADER bi;
+
+ bi.biSize = sizeof (bi);
+ bi.biWidth = pImg->width;
+ bi.biHeight = pImg->height;
+ bi.biPlanes = 1;
+ bi.biBitCount = pImg->bpp;
+ bi.biCompression = 0;
+ bi.biSizeImage = pImg->cbData;
+ bi.biXPelsPerMeter = 0;
+ bi.biYPelsPerMeter = 0;
+ bi.biClrUsed = 0;
+ bi.biClrImportant = 0;
+
+ fwrite (&bf, 1, sizeof (bf), f);
+ fwrite (&bi, 1, sizeof (bi), f);
+ fwrite (pImg->pvData, 1, pImg->cbData, f);
+
+ fclose (f);
+}
+
+typedef struct CRDUMPGETHWID_DATA
+{
+ GLuint hwid;
+ PFNCRDUMPGETHWID pfnGetHwid;
+ unsigned long Key;
+ void* pvObj;
+} CRDUMPGETHWID_DATA;
+
+static void crDmpHashtableSearchByHwidCB(unsigned long key, void *pData1, void *pData2)
+{
+ CRDUMPGETHWID_DATA *pData = (CRDUMPGETHWID_DATA*)pData2;
+ if (pData->pvObj)
+ return;
+
+ if (pData->hwid == pData->pfnGetHwid(pData1))
+ {
+ pData->Key = key;
+ pData->pvObj = pData1;
+ }
+}
+
+void* crDmpHashtableSearchByHwid(CRHashTable *pHash, GLuint hwid, PFNCRDUMPGETHWID pfnGetHwid, unsigned long *pKey)
+{
+ CRDUMPGETHWID_DATA Data = {0};
+ Data.hwid = hwid;
+ Data.pfnGetHwid = pfnGetHwid;
+ crHashtableWalk(pHash, crDmpHashtableSearchByHwidCB, &Data);
+
+ Assert(Data.pvObj);
+
+ if (pKey)
+ *pKey = Data.Key;
+ return Data.pvObj;
+}
+
+#if 0
+typedef struct CR_SERVER_DUMP_FIND_TEX
+{
+ GLint hwid;
+ CRTextureObj *pTobj
+} CR_SERVER_DUMP_FIND_TEX;
+
+void crServerDumpFindTexCb(unsigned long key, void *pData1, void *pData2)
+{
+ CR_SERVER_DUMP_FIND_TEX *pTex = (CR_SERVER_DUMP_FIND_TEX*)pData2;
+ CRTextureObj *pTobj = (CRTextureObj *)pData1;
+ if (pTobj->hwid == pTex->hwid)
+ pTex->pTobj = pTobj;
+}
+#endif
+
+#define CR_DUMP_MAKE_CASE(_val) case _val: return #_val
+#define CR_DUMP_MAKE_CASE_UNKNOWN(_val, _str, _pDumper) default: { \
+ crWarning("%s %d", (_str), _val); \
+ crDmpStrF((_pDumper), "WARNING: %s %d", (_str), _val); \
+ return (_str); \
+}
+
+DECLINLINE(size_t) crDmpFormatVal(char *pString, size_t cbString, const char *pszElFormat, uint32_t cbVal, const void *pvVal)
+{
+ if (pszElFormat[0] != '%' || pszElFormat[1] == '\0')
+ {
+ crWarning("invalid format %s", pszElFormat);
+ return 0;
+ }
+ switch (cbVal)
+ {
+ case 8:
+ return sprintf_s(pString, cbString, pszElFormat, *((double*)pvVal));
+ case 4:
+ {
+ /* we do not care only about type specifiers, all the rest is not accepted */
+ switch (pszElFormat[1])
+ {
+ case 'f':
+ /* float would be promoted to double */
+ return sprintf_s(pString, cbString, pszElFormat, *((float*)pvVal));
+ default:
+ return sprintf_s(pString, cbString, pszElFormat, *((uint32_t*)pvVal));
+ }
+ }
+ case 2:
+ return sprintf_s(pString, cbString, pszElFormat, *((uint16_t*)pvVal));
+ case 1:
+ return sprintf_s(pString, cbString, pszElFormat, *((uint8_t*)pvVal));
+ default:
+ crWarning("unsupported size %d", cbVal);
+ return 0;
+ }
+}
+
+VBOXDUMPDECL(size_t) crDmpFormatRawArray(char *pString, size_t cbString, const char *pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cVal)
+{
+ if (cbString < 2)
+ {
+ crWarning("too few buffer size");
+ return 0;
+ }
+
+ const size_t cbInitString = cbString;
+ *pString++ = '{';
+ --cbString;
+ size_t cbWritten;
+ const uint8_t *pu8Val = (const uint8_t *)pvVal;
+ for (uint32_t i = 0; i < cVal; ++i)
+ {
+ cbWritten = crDmpFormatVal(pString, cbString, pszElFormat, cbEl, (const void *)pu8Val);
+ pu8Val += cbEl;
+ Assert(cbString >= cbWritten);
+ pString += cbWritten;
+ cbString -= cbWritten;
+ if (i != cVal - 1)
+ {
+ cbWritten = sprintf_s(pString, cbString, ", ");
+ Assert(cbString >= cbWritten);
+ pString += cbWritten;
+ cbString -= cbWritten;
+ }
+ }
+
+ if (!cbString)
+ {
+ crWarning("too few buffer size");
+ return 0;
+ }
+ *pString++ = '}';
+ --cbString;
+
+ if (!cbString)
+ {
+ crWarning("too few buffer size");
+ return 0;
+ }
+ *pString++ = '\0';
+
+ return cbInitString - cbString;
+}
+
+VBOXDUMPDECL(size_t) crDmpFormatMatrixArray(char *pString, size_t cbString, const char *pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cX, uint32_t cY)
+{
+ if (cbString < 2)
+ {
+ crWarning("too few buffer size");
+ return 0;
+ }
+
+ const size_t cbInitString = cbString;
+ *pString++ = '{';
+ --cbString;
+ size_t cbWritten;
+ const uint8_t *pu8Val = (const uint8_t *)pvVal;
+ for (uint32_t i = 0; i < cY; ++i)
+ {
+ cbWritten = crDmpFormatRawArray(pString, cbString, pszElFormat, cbEl, (const void *)pu8Val, cX);
+ pu8Val += (cbEl * cX);
+ Assert(cbString >= cbWritten);
+ pString += cbWritten;
+ cbString -= cbWritten;
+ if (i != cY - 1)
+ {
+ if (cbString < 3)
+ {
+ crWarning("too few buffer size");
+ return 0;
+ }
+ *pString++ = ',';
+ --cbString;
+ *pString++ = '\n';
+ --cbString;
+ }
+ }
+ if (!cbString)
+ {
+ crWarning("too few buffer size");
+ return 0;
+ }
+ *pString++ = '}';
+ --cbString;
+
+ if (!cbString)
+ {
+ crWarning("too few buffer size");
+ return 0;
+ }
+ *pString++ = '\0';
+
+ return cbInitString - cbString;
+}
+
+VBOXDUMPDECL(size_t) crDmpFormatArray(char *pString, size_t cbString, const char *pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cVal)
+{
+ switch(cVal)
+ {
+ case 1:
+ return crDmpFormatVal(pString, cbString, pszElFormat, cbEl, pvVal);
+ case 16:
+ return crDmpFormatMatrixArray(pString, cbString, pszElFormat, cbEl, pvVal, 4, 4);
+ case 9:
+ return crDmpFormatMatrixArray(pString, cbString, pszElFormat, cbEl, pvVal, 3, 3);
+ case 0:
+ crWarning("value array is empty");
+ return 0;
+ default:
+ return crDmpFormatRawArray(pString, cbString, pszElFormat, cbEl, pvVal, cVal);
+ }
+}
+
+VBOXDUMPDECL(void) crRecDumpVertAttrv(CR_RECORDER *pRec, CRContext *ctx, GLuint idx, const char*pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cVal)
+{
+ char aBuf[1024];
+ crDmpFormatRawArray(aBuf, sizeof (aBuf), pszElFormat, cbEl, pvVal, cVal);
+ crDmpStrF(pRec->pDumper, "(%u, %s)", idx, aBuf);
+}
+
+VBOXDUMPDECL(void) crRecDumpVertAttrV(CR_RECORDER *pRec, CRContext *ctx, const char*pszFormat, va_list pArgList)
+{
+ crDmpStrV(pRec->pDumper, pszFormat, pArgList);
+}
+
+VBOXDUMPDECL(void) crRecDumpVertAttrF(CR_RECORDER *pRec, CRContext *ctx, const char*pszFormat, ...)
+{
+ va_list pArgList;
+ va_start(pArgList, pszFormat);
+ crRecDumpVertAttrV(pRec, ctx, pszFormat, pArgList);
+ va_end(pArgList);
+}
+
+void crRecDumpBuffer(CR_RECORDER *pRec, CRContext *ctx, GLint idRedirFBO, VBOXVR_TEXTURE *pRedirTex)
+{
+ GLenum texTarget = 0;
+ GLint hwBuf = 0, hwDrawBuf = 0;
+ GLint hwTex = 0, hwObjType = 0, hwTexLevel = 0, hwCubeFace = 0;
+ GLint width = 0, height = 0, depth = 0;
+ GLint id = 0;
+ CR_BLITTER_IMG Img = {0};
+ VBOXVR_TEXTURE Tex;
+ int rc;
+
+ pRec->pDispatch->GetIntegerv(GL_DRAW_BUFFER, &hwDrawBuf);
+ pRec->pDispatch->GetIntegerv(GL_FRAMEBUFFER_BINDING, &hwBuf);
+ if (hwBuf)
+ {
+ pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &hwTex);
+ pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &hwObjType);
+ if (hwObjType == GL_TEXTURE)
+ {
+ pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &hwTexLevel);
+ pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, &hwCubeFace);
+ if (hwCubeFace)
+ {
+ crWarning("cube face: unsupported");
+ return;
+ }
+
+ if (hwTexLevel)
+ {
+ crWarning("non-zero tex level attached, unsupported");
+ return;
+ }
+ }
+ else
+ {
+ crWarning("unsupported");
+ return;
+ }
+ }
+ else
+ {
+ crWarning("no buffer attached: unsupported");
+ return;
+ }
+
+ if (ctx->framebufferobject.drawFB)
+ {
+ GLuint iColor = (hwDrawBuf - GL_COLOR_ATTACHMENT0_EXT);
+ CRTextureObj *pTobj = (CRTextureObj *)crHashtableSearch(ctx->shared->textureTable, ctx->framebufferobject.drawFB->color[iColor].name);
+ CRTextureLevel *pTl = NULL;
+
+ id = pTobj->id;
+
+ Assert(iColor < RT_ELEMENTS(ctx->framebufferobject.drawFB->color));
+
+ if (!pTobj)
+ {
+ crWarning("no tobj");
+ return;
+ }
+ Assert(pTobj->hwid == hwTex);
+ Assert(pTobj);
+ Assert(ctx->framebufferobject.drawFB->hwid);
+ Assert(ctx->framebufferobject.drawFB->hwid == hwBuf);
+ Assert(ctx->framebufferobject.drawFB->drawbuffer[0] == hwDrawBuf);
+
+ Assert(ctx->framebufferobject.drawFB->color[iColor].level == hwTexLevel);
+ Assert(ctx->framebufferobject.drawFB->color[iColor].type == hwObjType);
+
+ texTarget = pTobj->target;
+
+ Assert(texTarget == GL_TEXTURE_2D);
+
+ pTl = &pTobj->level[0][hwTexLevel];
+
+ rc = CrBltEnter(pRec->pBlitter);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("CrBltEnter failed, rc %d", rc);
+ return;
+ }
+
+ pRec->pDispatch->BindTexture(texTarget, hwTex);
+
+ pRec->pDispatch->GetTexLevelParameteriv(texTarget, hwTexLevel, GL_TEXTURE_WIDTH, &width);
+ pRec->pDispatch->GetTexLevelParameteriv(texTarget, hwTexLevel, GL_TEXTURE_HEIGHT, &height);
+ pRec->pDispatch->GetTexLevelParameteriv(texTarget, hwTexLevel, GL_TEXTURE_DEPTH, &depth);
+
+ Assert(width == pTl->width);
+ Assert(height == pTl->height);
+ Assert(depth == pTl->depth);
+
+ pRec->pDispatch->BindTexture(texTarget, 0);
+ }
+ else
+ {
+ Assert(hwBuf == idRedirFBO);
+ if (!pRedirTex)
+ {
+ crWarning("pRedirTex is expected for non-FBO state!");
+ return;
+ }
+
+ Assert(hwTex == pRedirTex->hwid);
+
+ texTarget = pRedirTex->target;
+
+ width = pRedirTex->width;
+ height = pRedirTex->height;
+
+ rc = CrBltEnter(pRec->pBlitter);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("CrBltEnter failed, rc %d", rc);
+ return;
+ }
+ }
+
+ Tex.width = width;
+ Tex.height = height;
+ Tex.target = texTarget;
+ Tex.hwid = hwTex;
+
+ rc = CrBltImgGetTex(pRec->pBlitter, &Tex, GL_BGRA, &Img);
+ if (RT_SUCCESS(rc))
+ {
+ crDmpImgF(pRec->pDumper, &Img, "ctx(%d), BUFFER: id(%d) hwid(%d), width(%d), height(%d)", ctx, id, Tex.hwid, width, height);
+
+ if (g_CrDbgDumpAlphaData)
+ {
+ CR_BLITTER_IMG AlphaImg = {0};
+ rc = crRecAlphaImgCreate(&Img, &AlphaImg);
+ if (RT_SUCCESS(rc))
+ {
+ crDmpImgF(pRec->pDumper, &AlphaImg, "Buffer ALPHA Data");
+ crRecAlphaImgDestroy(&AlphaImg);
+ }
+ else
+ {
+ crWarning("crRecAlphaImgCreate failed rc %d", rc);
+ }
+ }
+
+ CrBltImgFree(pRec->pBlitter, &Img);
+ }
+ else
+ {
+ crWarning("CrBltImgGetTex failed, rc %d", rc);
+ }
+
+ CrBltLeave(pRec->pBlitter);
+}
+
+static const char *crRecDumpShaderTypeString(GLenum enmType, CR_DUMPER *pDumper)
+{
+ switch (enmType)
+ {
+ CR_DUMP_MAKE_CASE(GL_VERTEX_SHADER_ARB);
+ CR_DUMP_MAKE_CASE(GL_FRAGMENT_SHADER_ARB);
+ CR_DUMP_MAKE_CASE(GL_GEOMETRY_SHADER_ARB);
+ CR_DUMP_MAKE_CASE_UNKNOWN(enmType, "Unknown Shader Type", pDumper);
+ }
+}
+
+static const char *crRecDumpVarTypeString(GLenum enmType, CR_DUMPER *pDumper)
+{
+ switch (enmType)
+ {
+ CR_DUMP_MAKE_CASE(GL_BYTE);
+ CR_DUMP_MAKE_CASE(GL_UNSIGNED_BYTE);
+ CR_DUMP_MAKE_CASE(GL_SHORT);
+ CR_DUMP_MAKE_CASE(GL_UNSIGNED_SHORT);
+ CR_DUMP_MAKE_CASE(GL_FLOAT);
+ CR_DUMP_MAKE_CASE(GL_DOUBLE);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_VEC2);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_VEC3);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_VEC4);
+ CR_DUMP_MAKE_CASE(GL_INT);
+ CR_DUMP_MAKE_CASE(GL_UNSIGNED_INT);
+ CR_DUMP_MAKE_CASE(GL_INT_VEC2);
+ CR_DUMP_MAKE_CASE(GL_INT_VEC3);
+ CR_DUMP_MAKE_CASE(GL_INT_VEC4);
+ CR_DUMP_MAKE_CASE(GL_BOOL);
+ CR_DUMP_MAKE_CASE(GL_BOOL_VEC2);
+ CR_DUMP_MAKE_CASE(GL_BOOL_VEC3);
+ CR_DUMP_MAKE_CASE(GL_BOOL_VEC4);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_MAT2);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_MAT3);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_MAT4);
+ CR_DUMP_MAKE_CASE(GL_SAMPLER_1D);
+ CR_DUMP_MAKE_CASE(GL_SAMPLER_2D);
+ CR_DUMP_MAKE_CASE(GL_SAMPLER_3D);
+ CR_DUMP_MAKE_CASE(GL_SAMPLER_CUBE);
+ CR_DUMP_MAKE_CASE(GL_SAMPLER_1D_SHADOW);
+ CR_DUMP_MAKE_CASE(GL_SAMPLER_2D_SHADOW);
+ CR_DUMP_MAKE_CASE(GL_SAMPLER_2D_RECT_ARB);
+ CR_DUMP_MAKE_CASE(GL_SAMPLER_2D_RECT_SHADOW_ARB);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_MAT2x3);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_MAT2x4);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_MAT3x2);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_MAT3x4);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_MAT4x2);
+ CR_DUMP_MAKE_CASE(GL_FLOAT_MAT4x3);
+ CR_DUMP_MAKE_CASE_UNKNOWN(enmType, "Unknown Variable Type", pDumper);
+ }
+}
+
+static char *crRecDumpGetLine(char **ppszStr, uint32_t *pcbStr)
+{
+ char *pszStr, *pNewLine;
+ const uint32_t cbStr = *pcbStr;
+
+ if (!cbStr)
+ {
+ /* zero-length string */
+ return NULL;
+ }
+
+ if ((*ppszStr)[cbStr-1] != '\0')
+ {
+ crWarning("string should be null-rerminated, forcing it!");
+ (*ppszStr)[cbStr-1] = '\0';
+ }
+ pszStr = *ppszStr;
+ if (!*pszStr)
+ {
+ *pcbStr = 0;
+ return NULL;
+ }
+
+ if (!(pNewLine = strstr(pszStr, "\n")))
+ {
+ /* the string contains a single line! */
+ *ppszStr += strlen(pszStr);
+ *pcbStr = 0;
+ return pszStr;
+ }
+
+ *pNewLine = '\0';
+ *pcbStr = cbStr - (((uintptr_t)pNewLine) - ((uintptr_t)pszStr)) - 1;
+ Assert((*pcbStr) < UINT32_MAX/2);
+ Assert((*pcbStr) < cbStr);
+ *ppszStr = pNewLine + 1;
+
+ return pszStr;
+}
+
+static void crRecDumpStrByLine(CR_DUMPER *pDumper, char *pszStr, uint32_t cbStr)
+{
+ char *pszCurLine;
+ while ((pszCurLine = crRecDumpGetLine(&pszStr, &cbStr)) != NULL)
+ {
+ crDmpStrF(pDumper, "%s", pszCurLine);
+ }
+}
+
+static DECLCALLBACK(GLuint) crDmpGetHwidShaderCB(void *pvObj)
+{
+ return ((CRGLSLShader*)pvObj)->hwid;
+}
+
+static DECLCALLBACK(GLuint) crDmpGetHwidProgramCB(void *pvObj)
+{
+ return ((CRGLSLProgram*)pvObj)->hwid;
+}
+
+/* Context activation is done by the caller. */
+void crRecDumpLog(CR_RECORDER *pRec, GLint hwid)
+{
+ GLint cbLog = 0;
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_INFO_LOG_LENGTH_ARB, &cbLog);
+
+ crDmpStrF(pRec->pDumper, "Log===%d===", hwid);
+
+ if (cbLog > 1)
+ {
+ GLchar *pszLog = (GLchar *) crAlloc(cbLog*sizeof (GLchar));
+
+ pRec->pDispatch->GetInfoLogARB(hwid, cbLog, NULL, pszLog);
+
+ crRecDumpStrByLine(pRec->pDumper, pszLog, cbLog);
+
+ crFree(pszLog);
+ }
+ crDmpStrF(pRec->pDumper, "End Log======");
+}
+
+void crRecDumpShader(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
+{
+ GLint length = 0;
+ GLint type = 0;
+ GLint compileStatus = 0;
+
+#ifndef IN_GUEST
+ CRGLSLShader *pShad;
+
+ if (!id)
+ {
+ unsigned long tstKey = 0;
+ Assert(hwid);
+ pShad = (CRGLSLShader *)crDmpHashtableSearchByHwid(ctx->glsl.shaders, hwid, crDmpGetHwidShaderCB, &tstKey);
+ Assert(pShad);
+ if (!pShad)
+ return;
+ id = pShad->id;
+ Assert(tstKey == id);
+ }
+ else
+ {
+ pShad = (CRGLSLShader *)crHashtableSearch(ctx->glsl.shaders, id);
+ Assert(pShad);
+ if (!pShad)
+ return;
+ }
+
+ if (!hwid)
+ hwid = pShad->hwid;
+
+ Assert(pShad->hwid == hwid);
+ Assert(pShad->id == id);
+#else
+ if (!id)
+ id = hwid;
+ else if (!hwid)
+ hwid = id;
+
+ Assert(id);
+ Assert(hwid);
+ Assert(hwid == id);
+#endif
+
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_SUBTYPE_ARB, &type);
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus);
+ crDmpStrF(pRec->pDumper, "SHADER ctx(%d) id(%d) hwid(%d) type(%s) status(%d):", ctx->id, id, hwid, crRecDumpShaderTypeString(type, pRec->pDumper), compileStatus);
+
+ crRecDumpLog(pRec, hwid);
+
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &length);
+
+ char *pszSource = (char*)crCalloc(length + 1);
+ if (!pszSource)
+ {
+ crWarning("crCalloc failed");
+ crDmpStrF(pRec->pDumper, "WARNING: crCalloc failed");
+ return;
+ }
+
+ pRec->pDispatch->GetShaderSource(hwid, length, NULL, pszSource);
+ crRecDumpStrByLine(pRec->pDumper, pszSource, length);
+
+ crFree(pszSource);
+
+ crDmpStr(pRec->pDumper, "===END SHADER====");
+}
+
+void crRecDumpProgram(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
+{
+ GLint cShaders = 0, linkStatus = 0;
+ char *source = NULL;
+ CRGLSLProgram *pProg;
+
+ if (!id)
+ {
+ unsigned long tstKey = 0;
+ Assert(hwid);
+ pProg = (CRGLSLProgram*)crDmpHashtableSearchByHwid(ctx->glsl.programs, hwid, crDmpGetHwidProgramCB, &tstKey);
+ Assert(pProg);
+ if (!pProg)
+ return;
+ id = pProg->id;
+ Assert(tstKey == id);
+ }
+ else
+ {
+ pProg = (CRGLSLProgram *) crHashtableSearch(ctx->glsl.programs, id);
+ Assert(pProg);
+ if (!pProg)
+ return;
+ }
+
+ if (!hwid)
+ hwid = pProg->hwid;
+
+ Assert(pProg->hwid == hwid);
+ Assert(pProg->id == id);
+
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_ATTACHED_OBJECTS_ARB, &cShaders);
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_LINK_STATUS_ARB, &linkStatus);
+
+ crDmpStrF(pRec->pDumper, "PROGRAM ctx(%d) id(%d) hwid(%d) status(%d) shaders(%d):", ctx->id, id, hwid, linkStatus, cShaders);
+
+ crRecDumpLog(pRec, hwid);
+
+ VBoxGLhandleARB *pShaders = (VBoxGLhandleARB*)crCalloc(cShaders * sizeof (*pShaders));
+ if (!pShaders)
+ {
+ crWarning("crCalloc failed");
+ crDmpStrF(pRec->pDumper, "WARNING: crCalloc failed");
+ return;
+ }
+
+ pRec->pDispatch->GetAttachedObjectsARB(hwid, cShaders, NULL, pShaders);
+ for (GLint i = 0; i < cShaders; ++i)
+ {
+ if (pShaders[i])
+ crRecDumpShader(pRec, ctx, 0, pShaders[i]);
+ else
+ crDmpStrF(pRec->pDumper, "WARNING: Shader[%d] is null", i);
+ }
+
+ crFree(pShaders);
+
+ GLsizei cbLog = 0;
+
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_INFO_LOG_LENGTH_ARB, &cbLog);
+ if (cbLog)
+ {
+ char *pszLog = (char *)crCalloc(cbLog+1);
+ pRec->pDispatch->GetInfoLogARB(hwid, cbLog, NULL, pszLog);
+ crDmpStrF(pRec->pDumper, "==LOG==");
+ crRecDumpStrByLine(pRec->pDumper, pszLog, cbLog);
+ crDmpStrF(pRec->pDumper, "==Done LOG==");
+ crFree(pszLog);
+ }
+ else
+ {
+ crDmpStrF(pRec->pDumper, "==No LOG==");
+ }
+
+ crDmpStr(pRec->pDumper, "===END PROGRAM====");
+}
+
+void crRecRecompileShader(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
+{
+ GLint length = 0;
+ GLint type = 0;
+ GLint compileStatus = 0;
+ CRGLSLShader *pShad;
+
+ if (!id)
+ {
+ unsigned long tstKey = 0;
+ Assert(hwid);
+ pShad = (CRGLSLShader *)crDmpHashtableSearchByHwid(ctx->glsl.shaders, hwid, crDmpGetHwidShaderCB, &tstKey);
+ Assert(pShad);
+ if (!pShad)
+ return;
+ id = pShad->id;
+ Assert(tstKey == id);
+ }
+ else
+ {
+ pShad = (CRGLSLShader *)crHashtableSearch(ctx->glsl.shaders, id);
+ Assert(pShad);
+ if (!pShad)
+ return;
+ }
+
+ if (!hwid)
+ hwid = pShad->hwid;
+
+ Assert(pShad->hwid == hwid);
+ Assert(pShad->id == id);
+
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_SUBTYPE_ARB, &type);
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus);
+ crDmpStrF(pRec->pDumper, "==RECOMPILE SHADER ctx(%d) id(%d) hwid(%d) type(%s) status(%d)==", ctx->id, id, hwid, crRecDumpShaderTypeString(type, pRec->pDumper), compileStatus);
+
+ compileStatus = 0;
+ GLenum status;
+ while ((status = pRec->pDispatch->GetError()) != GL_NO_ERROR) {/*Assert(0);*/}
+ pRec->pDispatch->CompileShader(hwid);
+ while ((status = pRec->pDispatch->GetError()) != GL_NO_ERROR) {Assert(0);}
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus);
+
+ crDmpStrF(pRec->pDumper, "==Done RECOMPILE SHADER, status(%d)==", compileStatus);
+}
+
+void crRecRecompileProgram(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
+{
+ GLint cShaders = 0, linkStatus = 0;
+ char *source = NULL;
+ CRGLSLProgram *pProg;
+
+ if (!id)
+ {
+ unsigned long tstKey = 0;
+ Assert(hwid);
+ pProg = (CRGLSLProgram*)crDmpHashtableSearchByHwid(ctx->glsl.programs, hwid, crDmpGetHwidProgramCB, &tstKey);
+ Assert(pProg);
+ if (!pProg)
+ return;
+ id = pProg->id;
+ Assert(tstKey == id);
+ }
+ else
+ {
+ pProg = (CRGLSLProgram *) crHashtableSearch(ctx->glsl.programs, id);
+ Assert(pProg);
+ if (!pProg)
+ return;
+ }
+
+ if (!hwid)
+ hwid = pProg->hwid;
+
+ Assert(pProg->hwid == hwid);
+ Assert(pProg->id == id);
+
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_ATTACHED_OBJECTS_ARB, &cShaders);
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_LINK_STATUS_ARB, &linkStatus);
+
+ crDmpStrF(pRec->pDumper, "==RECOMPILE PROGRAM ctx(%d) id(%d) hwid(%d) status(%d) shaders(%d)==", ctx->id, id, hwid, linkStatus, cShaders);
+
+ VBoxGLhandleARB *pShaders = (VBoxGLhandleARB*)crCalloc(cShaders * sizeof (*pShaders));
+ if (!pShaders)
+ {
+ crWarning("crCalloc failed");
+ crDmpStrF(pRec->pDumper, "WARNING: crCalloc failed");
+ return;
+ }
+
+ pRec->pDispatch->GetAttachedObjectsARB(hwid, cShaders, NULL, pShaders);
+ for (GLint i = 0; i < cShaders; ++i)
+ {
+ crRecRecompileShader(pRec, ctx, 0, pShaders[i]);
+ }
+
+ crFree(pShaders);
+
+ linkStatus = 0;
+ GLenum status;
+ while ((status = pRec->pDispatch->GetError()) != GL_NO_ERROR) {/*Assert(0);*/}
+ pRec->pDispatch->LinkProgram(hwid);
+ while ((status = pRec->pDispatch->GetError()) != GL_NO_ERROR) {Assert(0);}
+ pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_LINK_STATUS_ARB, &linkStatus);
+
+ crDmpStrF(pRec->pDumper, "==Done RECOMPILE PROGRAM, status(%d)==", linkStatus);
+}
+
+VBOXDUMPDECL(void) crRecDumpCurrentProgram(CR_RECORDER *pRec, CRContext *ctx)
+{
+ GLint curProgram = 0;
+ pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram);
+ if (curProgram)
+ {
+ Assert(ctx->glsl.activeProgram);
+ if (!ctx->glsl.activeProgram)
+ crWarning("no active program state with active hw program");
+ else
+ Assert(ctx->glsl.activeProgram->hwid == curProgram);
+ crRecDumpProgram(pRec, ctx, 0, curProgram);
+ }
+ else
+ {
+ Assert(!ctx->glsl.activeProgram);
+ crDmpStrF(pRec->pDumper, "--no active program");
+ }
+}
+
+void crRecDumpProgramUniforms(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
+{
+ CRGLSLProgram *pProg;
+
+ if (!id)
+ {
+ unsigned long tstKey = 0;
+ Assert(hwid);
+ pProg = (CRGLSLProgram*)crDmpHashtableSearchByHwid(ctx->glsl.programs, hwid, crDmpGetHwidProgramCB, &tstKey);
+ Assert(pProg);
+ if (!pProg)
+ return;
+ id = pProg->id;
+ Assert(tstKey == id);
+ }
+ else
+ {
+ pProg = (CRGLSLProgram *) crHashtableSearch(ctx->glsl.programs, id);
+ Assert(pProg);
+ if (!pProg)
+ return;
+ }
+
+ if (!hwid)
+ hwid = pProg->hwid;
+
+ Assert(pProg->hwid == hwid);
+ Assert(pProg->id == id);
+
+ GLint maxUniformLen = 0, activeUniforms = 0, i, j, uniformsCount = 0;
+ GLenum type;
+ GLint size, location;
+ GLchar *pszName = NULL;
+ pRec->pDispatch->GetProgramiv(hwid, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen);
+ pRec->pDispatch->GetProgramiv(hwid, GL_ACTIVE_UNIFORMS, &activeUniforms);
+
+ if (!maxUniformLen)
+ {
+ if (activeUniforms)
+ {
+ crWarning("activeUniforms (%d), while maxUniformLen is zero", activeUniforms);
+ activeUniforms = 0;
+ }
+ }
+
+ if (activeUniforms>0)
+ {
+ pszName = (GLchar *) crAlloc((maxUniformLen+8)*sizeof(GLchar));
+
+ if (!pszName)
+ {
+ crWarning("crRecDumpProgramUniforms: out of memory");
+ return;
+ }
+ }
+
+ for (i=0; i<activeUniforms; ++i)
+ {
+ pRec->pDispatch->GetActiveUniform(hwid, i, maxUniformLen, NULL, &size, &type, pszName);
+ uniformsCount += size;
+ }
+ Assert(uniformsCount>=activeUniforms);
+
+ if (activeUniforms>0)
+ {
+ GLfloat fdata[16];
+ GLint idata[16];
+ char *pIndexStr=NULL;
+
+ for (i=0; i<activeUniforms; ++i)
+ {
+ bool fPrintBraketsWithName = false;
+ pRec->pDispatch->GetActiveUniform(hwid, i, maxUniformLen, NULL, &size, &type, pszName);
+
+ if (size>1)
+ {
+ pIndexStr = crStrchr(pszName, '[');
+ if (!pIndexStr)
+ {
+ pIndexStr = pszName+crStrlen(pszName);
+ fPrintBraketsWithName = true;
+ }
+ }
+
+ if (fPrintBraketsWithName)
+ {
+ crDmpStrF(pRec->pDumper, "%s %s[%d];", crRecDumpVarTypeString(type, pRec->pDumper), pszName, size);
+ Assert(size > 1);
+ }
+ else
+ crDmpStrF(pRec->pDumper, "%s %s;", crRecDumpVarTypeString(type, pRec->pDumper), pszName);
+
+ GLint uniformTypeSize = crStateGetUniformSize(type);
+ Assert(uniformTypeSize >= 1);
+
+ for (j=0; j<size; ++j)
+ {
+ if (size>1)
+ {
+ sprintf(pIndexStr, "[%i]", j);
+ }
+ location = pRec->pDispatch->GetUniformLocation(hwid, pszName);
+
+ if (crStateIsIntUniform(type))
+ {
+ pRec->pDispatch->GetUniformiv(hwid, location, &idata[0]);
+ switch (uniformTypeSize)
+ {
+ case 1:
+ crDmpStrF(pRec->pDumper, "%s = %d; //location %d", pszName, idata[0], location);
+ break;
+ case 2:
+ crDmpStrF(pRec->pDumper, "%s = {%d, %d}; //location %d", pszName, idata[0], idata[1], location);
+ break;
+ case 3:
+ crDmpStrF(pRec->pDumper, "%s = {%d, %d, %d}; //location %d", pszName, idata[0], idata[1], idata[2], location);
+ break;
+ case 4:
+ crDmpStrF(pRec->pDumper, "%s = {%d, %d, %d, %d}; //location %d", pszName, idata[0], idata[1], idata[2], idata[3], location);
+ break;
+ default:
+ for (GLint k = 0; k < uniformTypeSize; ++k)
+ {
+ crDmpStrF(pRec->pDumper, "%s[%d] = %d; //location %d", pszName, k, idata[k], location);
+ }
+ break;
+ }
+ }
+ else
+ {
+ pRec->pDispatch->GetUniformfv(hwid, location, &fdata[0]);
+ switch (uniformTypeSize)
+ {
+ case 1:
+ crDmpStrF(pRec->pDumper, "%s = %f; //location %d", pszName, fdata[0], location);
+ break;
+ case 2:
+ crDmpStrF(pRec->pDumper, "%s = {%f, %f}; //location %d", pszName, fdata[0], fdata[1], location);
+ break;
+ case 3:
+ crDmpStrF(pRec->pDumper, "%s = {%f, %f, %f}; //location %d", pszName, fdata[0], fdata[1], fdata[2], location);
+ break;
+ case 4:
+ crDmpStrF(pRec->pDumper, "%s = {%f, %f, %f, %f}; //location %d", pszName, fdata[0], fdata[1], fdata[2], fdata[3], location);
+ break;
+ default:
+ for (GLint k = 0; k < uniformTypeSize; ++k)
+ {
+ crDmpStrF(pRec->pDumper, "%s[%d] = %f; //location %d", pszName, k, fdata[k], location);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ crFree(pszName);
+ }
+}
+
+void crRecDumpProgramAttribs(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid)
+{
+ CRGLSLProgram *pProg;
+
+ if (!id)
+ {
+ unsigned long tstKey = 0;
+ Assert(hwid);
+ pProg = (CRGLSLProgram*)crDmpHashtableSearchByHwid(ctx->glsl.programs, hwid, crDmpGetHwidProgramCB, &tstKey);
+ Assert(pProg);
+ if (!pProg)
+ return;
+ id = pProg->id;
+ Assert(tstKey == id);
+ }
+ else
+ {
+ pProg = (CRGLSLProgram *) crHashtableSearch(ctx->glsl.programs, id);
+ Assert(pProg);
+ if (!pProg)
+ return;
+ }
+
+ if (!hwid)
+ hwid = pProg->hwid;
+
+ Assert(pProg->hwid == hwid);
+ Assert(pProg->id == id);
+
+ GLint maxAttribLen = 0, activeAttrib = 0, i, j, attribCount = 0;
+ GLenum type;
+ GLint size, location;
+ GLchar *pszName = NULL;
+ pRec->pDispatch->GetProgramiv(hwid, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttribLen);
+ pRec->pDispatch->GetProgramiv(hwid, GL_ACTIVE_ATTRIBUTES, &activeAttrib);
+
+ if (!maxAttribLen)
+ {
+ if (activeAttrib)
+ {
+ crWarning("activeAttrib (%d), while maxAttribLen is zero", activeAttrib);
+ activeAttrib = 0;
+ }
+ }
+
+ if (activeAttrib>0)
+ {
+ pszName = (GLchar *) crAlloc((maxAttribLen+8)*sizeof(GLchar));
+
+ if (!pszName)
+ {
+ crWarning("crRecDumpProgramAttrib: out of memory");
+ return;
+ }
+ }
+
+ for (i=0; i<activeAttrib; ++i)
+ {
+ pRec->pDispatch->GetActiveAttrib(hwid, i, maxAttribLen, NULL, &size, &type, pszName);
+ attribCount += size;
+ }
+ Assert(attribCount>=activeAttrib);
+
+ if (activeAttrib>0)
+ {
+ GLfloat fdata[16];
+ GLint idata[16];
+ char *pIndexStr=NULL;
+
+ for (i=0; i<activeAttrib; ++i)
+ {
+ bool fPrintBraketsWithName = false;
+ pRec->pDispatch->GetActiveAttrib(hwid, i, maxAttribLen, NULL, &size, &type, pszName);
+ GLint arrayBufferBind = 0, arrayEnabled = 0, arraySize = 0, arrayStride = 0, arrayType = 0, arrayNormalized = 0, arrayInteger = 0/*, arrayDivisor = 0*/;
+
+ pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &arrayBufferBind);
+ pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &arrayEnabled);
+ pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &arraySize);
+ pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &arrayStride);
+ pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &arrayType);
+ pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &arrayNormalized);
+ pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_INTEGER, &arrayInteger);
+// pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, &arrayDivisor);
+
+ if (size>1)
+ {
+ pIndexStr = crStrchr(pszName, '[');
+ if (!pIndexStr)
+ {
+ pIndexStr = pszName+crStrlen(pszName);
+ fPrintBraketsWithName = true;
+ }
+ }
+
+ if (fPrintBraketsWithName)
+ {
+ crDmpStrF(pRec->pDumper, "%s %s[%d];", crRecDumpVarTypeString(type, pRec->pDumper), pszName, size);
+ Assert(size > 1);
+ }
+ else
+ crDmpStrF(pRec->pDumper, "%s %s;", crRecDumpVarTypeString(type, pRec->pDumper), pszName);
+
+ crDmpStrF(pRec->pDumper, "Array buff(%d), enabled(%d) size(%d), stride(%d), type(%s), normalized(%d), integer(%d)", arrayBufferBind, arrayEnabled, arraySize, arrayStride, crRecDumpVarTypeString(arrayType, pRec->pDumper), arrayNormalized, arrayInteger);
+
+ GLint attribTypeSize = crStateGetUniformSize(type);
+ Assert(attribTypeSize >= 1);
+
+ for (j=0; j<size; ++j)
+ {
+ if (size>1)
+ {
+ sprintf(pIndexStr, "[%i]", j);
+ }
+ location = pRec->pDispatch->GetAttribLocation(hwid, pszName);
+
+ if (crStateIsIntUniform(type))
+ {
+ pRec->pDispatch->GetVertexAttribivARB(location, GL_CURRENT_VERTEX_ATTRIB, &idata[0]);
+ switch (attribTypeSize)
+ {
+ case 1:
+ crDmpStrF(pRec->pDumper, "%s = %d; //location %d", pszName, idata[0], location);
+ break;
+ case 2:
+ crDmpStrF(pRec->pDumper, "%s = {%d, %d}; //location %d", pszName, idata[0], idata[1], location);
+ break;
+ case 3:
+ crDmpStrF(pRec->pDumper, "%s = {%d, %d, %d}; //location %d", pszName, idata[0], idata[1], idata[2], location);
+ break;
+ case 4:
+ crDmpStrF(pRec->pDumper, "%s = {%d, %d, %d, %d}; //location %d", pszName, idata[0], idata[1], idata[2], idata[3], location);
+ break;
+ default:
+ for (GLint k = 0; k < attribTypeSize; ++k)
+ {
+ crDmpStrF(pRec->pDumper, "%s[%d] = %d; //location %d", pszName, k, idata[k], location);
+ }
+ break;
+ }
+ }
+ else
+ {
+ pRec->pDispatch->GetVertexAttribfvARB(location, GL_CURRENT_VERTEX_ATTRIB, &fdata[0]);
+ switch (attribTypeSize)
+ {
+ case 1:
+ crDmpStrF(pRec->pDumper, "%s = %f; //location %d", pszName, fdata[0], location);
+ break;
+ case 2:
+ crDmpStrF(pRec->pDumper, "%s = {%f, %f}; //location %d", pszName, fdata[0], fdata[1], location);
+ break;
+ case 3:
+ crDmpStrF(pRec->pDumper, "%s = {%f, %f, %f}; //location %d", pszName, fdata[0], fdata[1], fdata[2], location);
+ break;
+ case 4:
+ crDmpStrF(pRec->pDumper, "%s = {%f, %f, %f, %f}; //location %d", pszName, fdata[0], fdata[1], fdata[2], fdata[3], location);
+ break;
+ default:
+ for (GLint k = 0; k < attribTypeSize; ++k)
+ {
+ crDmpStrF(pRec->pDumper, "%s[%d] = %f; //location %d", pszName, k, fdata[k], location);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ crFree(pszName);
+ }
+}
+
+VBOXDUMPDECL(void) crRecDumpCurrentProgramUniforms(CR_RECORDER *pRec, CRContext *ctx)
+{
+ GLint curProgram = 0;
+ pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram);
+ if (curProgram)
+ {
+ Assert(ctx->glsl.activeProgram);
+ if (!ctx->glsl.activeProgram)
+ crWarning("no active program state with active hw program");
+ else
+ Assert(ctx->glsl.activeProgram->hwid == curProgram);
+ crRecDumpProgramUniforms(pRec, ctx, 0, curProgram);
+ }
+ else
+ {
+ Assert(!ctx->glsl.activeProgram);
+ crDmpStrF(pRec->pDumper, "--no active program");
+ }
+}
+
+VBOXDUMPDECL(void) crRecDumpCurrentProgramAttribs(CR_RECORDER *pRec, CRContext *ctx)
+{
+ GLint curProgram = 0;
+ pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram);
+ if (curProgram)
+ {
+ Assert(ctx->glsl.activeProgram);
+ if (!ctx->glsl.activeProgram)
+ crWarning("no active program state with active hw program");
+ else
+ Assert(ctx->glsl.activeProgram->hwid == curProgram);
+ crRecDumpProgramAttribs(pRec, ctx, 0, curProgram);
+ }
+ else
+ {
+ Assert(!ctx->glsl.activeProgram);
+ crDmpStrF(pRec->pDumper, "--no active program");
+ }
+}
+
+VBOXDUMPDECL(void) crRecRecompileCurrentProgram(CR_RECORDER *pRec, CRContext *ctx)
+{
+ GLint curProgram = 0;
+ pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram);
+ if (curProgram)
+ {
+ Assert(ctx->glsl.activeProgram);
+ if (!ctx->glsl.activeProgram)
+ crWarning("no active program state with active hw program");
+ else
+ Assert(ctx->glsl.activeProgram->hwid == curProgram);
+ crRecRecompileProgram(pRec, ctx, 0, curProgram);
+ }
+ else
+ {
+ Assert(!ctx->glsl.activeProgram);
+ crDmpStrF(pRec->pDumper, "--no active program");
+ }
+}
+
+int crRecAlphaImgCreate(const CR_BLITTER_IMG *pImg, CR_BLITTER_IMG *pAlphaImg)
+{
+ if (pImg->enmFormat != GL_RGBA
+ && pImg->enmFormat != GL_BGRA)
+ {
+ crWarning("unsupported format 0x%x", pImg->enmFormat);
+ return VERR_NOT_IMPLEMENTED;
+ }
+
+ pAlphaImg->bpp = 32;
+ pAlphaImg->pitch = pImg->width * 4;
+ pAlphaImg->cbData = pAlphaImg->pitch * pImg->height;
+ pAlphaImg->enmFormat = GL_BGRA;
+ pAlphaImg->width = pImg->width;
+ pAlphaImg->height = pImg->height;
+
+ pAlphaImg->pvData = RTMemAlloc(pAlphaImg->cbData);
+ if (!pAlphaImg->pvData)
+ {
+ crWarning("RTMemAlloc failed");
+ return VERR_NO_MEMORY;
+ }
+
+ uint8_t *pu8SrcBuf = (uint8_t*)pImg->pvData;
+ uint8_t *pu8DstBuf = (uint8_t*)pAlphaImg->pvData;
+ for (uint32_t ih = 0; ih < pAlphaImg->height; ++ih)
+ {
+ uint32_t *pu32SrcBuf = (uint32_t*)pu8SrcBuf;
+ uint32_t *pu32DstBuf = (uint32_t*)pu8DstBuf;
+ for (uint32_t iw = 0; iw < pAlphaImg->width; ++iw)
+ {
+ uint8_t alpha = (((*pu32SrcBuf) >> 24) & 0xff);
+ *pu32DstBuf = (0xff << 24) || (alpha << 16) || (alpha << 8) || alpha;
+ ++pu32SrcBuf;
+ ++pu32DstBuf;
+ }
+ pu8SrcBuf += pImg->pitch;
+ pu8DstBuf += pAlphaImg->pitch;
+ }
+
+ return VINF_SUCCESS;
+}
+
+void crRecAlphaImgDestroy(CR_BLITTER_IMG *pImg)
+{
+ RTMemFree(pImg->pvData);
+ pImg->pvData = NULL;
+}
+
+void crRecDumpTextureV(CR_RECORDER *pRec, const VBOXVR_TEXTURE *pTex, const char *pszStr, va_list pArgList)
+{
+ CR_BLITTER_IMG Img = {0};
+ int rc = CrBltEnter(pRec->pBlitter);
+ if (RT_SUCCESS(rc))
+ {
+ rc = CrBltImgGetTex(pRec->pBlitter, pTex, GL_BGRA, &Img);
+ if (RT_SUCCESS(rc))
+ {
+ crDmpImgV(pRec->pDumper, &Img, pszStr, pArgList);
+ if (g_CrDbgDumpAlphaData)
+ {
+ CR_BLITTER_IMG AlphaImg = {0};
+ rc = crRecAlphaImgCreate(&Img, &AlphaImg);
+ if (RT_SUCCESS(rc))
+ {
+ crDmpImgF(pRec->pDumper, &AlphaImg, "Texture ALPHA Data");
+ crRecAlphaImgDestroy(&AlphaImg);
+ }
+ else
+ {
+ crWarning("crRecAlphaImgCreate failed rc %d", rc);
+ }
+ }
+ CrBltImgFree(pRec->pBlitter, &Img);
+ }
+ else
+ {
+ crWarning("CrBltImgGetTex failed, rc %d", rc);
+ }
+ CrBltLeave(pRec->pBlitter);
+ }
+ else
+ {
+ crWarning("CrBltEnter failed, rc %d", rc);
+ }
+}
+
+void crRecDumpTextureF(CR_RECORDER *pRec, const VBOXVR_TEXTURE *pTex, const char *pszStr, ...)
+{
+ va_list pArgList;
+ va_start(pArgList, pszStr);
+ crRecDumpTextureV(pRec, pTex, pszStr, pArgList);
+ va_end(pArgList);
+}
+
+void crRecDumpTextureByIdV(CR_RECORDER *pRec, CRContext *ctx, GLint id, const char *pszStr, va_list pArgList)
+{
+ CRTextureObj *pTobj = (CRTextureObj *)crHashtableSearch(ctx->shared->textureTable, id);
+ if (!pTobj)
+ {
+ crWarning("no texture of id %d", id);
+ return;
+ }
+
+ CRTextureLevel *pTl = &pTobj->level[0][0 /* level */];
+ VBOXVR_TEXTURE Tex;
+ Tex.width = pTl->width;
+ Tex.height = pTl->height;
+ Tex.target = pTobj->target;
+ Assert(Tex.target == GL_TEXTURE_2D);
+ Tex.hwid = pTobj->hwid;
+ if (!Tex.hwid)
+ {
+ crWarning("no texture hwid of id %d", id);
+ return;
+ }
+
+ crRecDumpTextureV(pRec, &Tex, pszStr, pArgList);
+}
+
+void crRecDumpTextureByIdF(CR_RECORDER *pRec, CRContext *ctx, GLint id, const char *pszStr, ...)
+{
+ va_list pArgList;
+ va_start(pArgList, pszStr);
+ crRecDumpTextureByIdV(pRec, ctx, id, pszStr, pArgList);
+ va_end(pArgList);
+}
+
+void crRecDumpTextures(CR_RECORDER *pRec, CRContext *ctx)
+{
+ GLint maxUnits = 0;
+ GLint curTexUnit = 0;
+ GLint restoreTexUnit = 0;
+ GLint curProgram = 0;
+ int i;
+
+ pRec->pDispatch->GetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxUnits);
+ maxUnits = RT_MIN(CR_MAX_TEXTURE_UNITS, maxUnits);
+
+ pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram);
+ Assert(curProgram);
+ Assert(ctx->glsl.activeProgram && ctx->glsl.activeProgram->hwid == curProgram);
+
+ Assert(maxUnits);
+ pRec->pDispatch->GetIntegerv(GL_ACTIVE_TEXTURE, &curTexUnit);
+ restoreTexUnit = curTexUnit;
+ Assert(curTexUnit >= GL_TEXTURE0);
+ Assert(curTexUnit < GL_TEXTURE0 + maxUnits);
+
+ Assert(ctx->texture.curTextureUnit == restoreTexUnit - GL_TEXTURE0);
+
+ for (i = 0; i < maxUnits; ++i)
+ {
+ GLboolean enabled1D;
+ GLboolean enabled2D;
+ GLboolean enabled3D;
+ GLboolean enabledCubeMap;
+ GLboolean enabledRect;
+ CRTextureUnit *tu = &ctx->texture.unit[i];
+
+ if (i > 1)
+ break;
+
+ if (curTexUnit != i + GL_TEXTURE0)
+ {
+ pRec->pDispatch->ActiveTextureARB(i + GL_TEXTURE0);
+ curTexUnit = i + GL_TEXTURE0;
+ }
+
+ enabled1D = pRec->pDispatch->IsEnabled(GL_TEXTURE_1D);
+ enabled2D = pRec->pDispatch->IsEnabled(GL_TEXTURE_2D);
+ enabled3D = pRec->pDispatch->IsEnabled(GL_TEXTURE_3D);
+ enabledCubeMap = pRec->pDispatch->IsEnabled(GL_TEXTURE_CUBE_MAP_ARB);
+ enabledRect = pRec->pDispatch->IsEnabled(GL_TEXTURE_RECTANGLE_NV);
+
+ Assert(enabled1D == tu->enabled1D);
+ Assert(enabled2D == tu->enabled2D);
+ Assert(enabled3D == tu->enabled3D);
+ Assert(enabledCubeMap == tu->enabledCubeMap);
+ Assert(enabledRect == tu->enabledRect);
+
+ if (enabled1D)
+ {
+ crWarning("GL_TEXTURE_1D: unsupported");
+ }
+
+// if (enabled2D)
+ {
+ GLint hwTex = 0;
+ VBOXVR_TEXTURE Tex;
+
+ GLint width = 0, height = 0, depth = 0;
+ CRTextureObj *pTobj = tu->currentTexture2D;
+
+ pRec->pDispatch->GetIntegerv(GL_TEXTURE_BINDING_2D, &hwTex);
+ if (hwTex)
+ {
+ CRTextureLevel *pTl = &pTobj->level[0][0 /* level */];
+ Assert(pTobj
+ && pTobj->hwid == hwTex);
+
+ pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
+ pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
+ pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_DEPTH, &depth);
+
+ Assert(width == pTl->width);
+ Assert(height == pTl->height);
+ Assert(depth == pTl->depth);
+
+ Tex.width = width;
+ Tex.height = height;
+ Tex.target = GL_TEXTURE_2D;
+ Tex.hwid = hwTex;
+
+ if (g_CrDbgDumpRecTexInfo)
+ {
+ crRecDumpTexParam(pRec, ctx, GL_TEXTURE_2D);
+ crRecDumpTexEnv(pRec, ctx);
+ crRecDumpTexGen(pRec, ctx);
+ }
+
+ crRecDumpTextureF(pRec, &Tex, "ctx(%d), Unit %d: TEXTURE_2D id(%d) hwid(%d), width(%d), height(%d)", ctx, i, pTobj->id, pTobj->hwid, width, height);
+ }
+// else
+// {
+// Assert(!pTobj || pTobj->hwid == 0);
+// crWarning("no TEXTURE_2D bound!");
+// }
+ }
+#if 0
+ if (enabled3D)
+ {
+ crWarning("GL_TEXTURE_3D: unsupported");
+ }
+
+ if (enabledCubeMap)
+ {
+ crWarning("GL_TEXTURE_CUBE_MAP_ARB: unsupported");
+ }
+
+// if (enabledRect)
+ {
+ GLint hwTex = 0;
+ CR_BLITTER_IMG Img = {0};
+ VBOXVR_TEXTURE Tex;
+
+ GLint width = 0, height = 0, depth = 0;
+ CRTextureObj *pTobj = tu->currentTextureRect;
+
+ pRec->pDispatch->GetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_NV, &hwTex);
+ if (hwTex)
+ {
+ CRTextureLevel *pTl = &pTobj->level[0][0 /* level */];
+ Assert(pTobj
+ && pTobj->hwid == hwTex);
+
+ pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_NV, 0, GL_TEXTURE_WIDTH, &width);
+ pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_NV, 0, GL_TEXTURE_HEIGHT, &height);
+ pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_NV, 0, GL_TEXTURE_DEPTH, &depth);
+
+ Assert(width == pTl->width);
+ Assert(height == pTl->height);
+ Assert(depth == pTl->depth);
+
+ Tex.width = width;
+ Tex.height = height;
+ Tex.target = GL_TEXTURE_RECTANGLE_NV;
+ Tex.hwid = hwTex;
+
+ rc = CrBltEnter(pRec->pBlitter);
+ if (RT_SUCCESS(rc))
+ {
+ rc = CrBltImgGetTex(pRec->pBlitter, &Tex, GL_BGRA, &Img);
+ if (RT_SUCCESS(rc))
+ {
+ crDmpImgF(pRec->pDumper, &Img, "Unit %d: TEXTURE_RECTANGLE data", i);
+ CrBltImgFree(pRec->pBlitter, &Img);
+ }
+ else
+ {
+ crWarning("CrBltImgGetTex failed, rc %d", rc);
+ }
+ CrBltLeave(pRec->pBlitter);
+ }
+ else
+ {
+ crWarning("CrBltEnter failed, rc %d", rc);
+ }
+ }
+// else
+// {
+// Assert(!pTobj || pTobj->hwid == 0);
+// crWarning("no TEXTURE_RECTANGLE bound!");
+// }
+ }
+#endif
+ }
+
+ if (curTexUnit != restoreTexUnit)
+ {
+ pRec->pDispatch->ActiveTextureARB(restoreTexUnit);
+ curTexUnit = restoreTexUnit;
+ }
+}
+
+#ifdef RT_OS_WINDOWS
+static void crDmpPrint(const char* szString, ...)
+{
+ char szBuffer[4096] = {0};
+ va_list pArgList;
+ va_start(pArgList, szString);
+ RTStrPrintfV(szBuffer, sizeof (szBuffer), szString, pArgList);
+ va_end(pArgList);
+
+ OutputDebugStringA(szBuffer);
+}
+
+static void crDmpPrintDmlCmd(const char* pszDesc, const char* pszCmd)
+{
+ crDmpPrint("<?dml?><exec cmd=\"%s\">%s</exec>, ( %s )\n", pszCmd, pszDesc, pszCmd);
+}
+
+void crDmpPrintDumpDmlCmd(const char* pszDesc, const void *pvData, uint32_t width, uint32_t height, uint32_t bpp, uint32_t pitch)
+{
+ char Cmd[1024];
+ sprintf(Cmd, "!vbvdbg.ms 0x%p 0n%d 0n%d 0n%d 0n%d", pvData, width, height, bpp, pitch);
+ crDmpPrintDmlCmd(pszDesc, Cmd);
+}
+
+DECLCALLBACK(void) crDmpDumpImgDmlBreak(struct CR_DUMPER * pDumper, CR_BLITTER_IMG *pImg, const char*pszEntryDesc)
+{
+ crDmpPrintDumpDmlCmd(pszEntryDesc, pImg->pvData, pImg->width, pImg->height, pImg->bpp, pImg->pitch);
+ RT_BREAKPOINT();
+}
+
+DECLCALLBACK(void) crDmpDumpStrDbgPrint(struct CR_DUMPER * pDumper, const char*pszStr)
+{
+ crDmpPrint("%s\n", pszStr);
+}
+#endif
+
+static void crDmpHtmlDumpStrExact(struct CR_HTML_DUMPER * pDumper, const char *pszStr)
+{
+ fprintf(pDumper->pFile, "%s", pszStr);
+ fflush(pDumper->pFile);
+}
+
+static DECLCALLBACK(void) crDmpHtmlDumpStr(struct CR_DUMPER * pDumper, const char*pszStr)
+{
+ CR_HTML_DUMPER * pHtmlDumper = (CR_HTML_DUMPER*)pDumper;
+ fprintf(pHtmlDumper->pFile, "<pre>%s</pre>\n", pszStr);
+ fflush(pHtmlDumper->pFile);
+}
+
+static DECLCALLBACK(void) crDmpHtmlDumpImg(struct CR_DUMPER * pDumper, CR_BLITTER_IMG *pImg, const char*pszEntryDesc)
+{
+ CR_HTML_DUMPER * pHtmlDumper = (CR_HTML_DUMPER*)pDumper;
+ char szBuffer[4096] = {0};
+ size_t cbWritten = RTStrPrintf(szBuffer, sizeof(szBuffer), "%s/", pHtmlDumper->pszDir);
+ char *pszFileName = szBuffer + cbWritten;
+ RTStrPrintf(pszFileName, sizeof(szBuffer) - cbWritten, "img%d.bmp", ++pHtmlDumper->cImg);
+ crDmpImgBmp(pImg, szBuffer);
+ fprintf(pHtmlDumper->pFile, "<a href=\"%s\"><pre>%s</pre><img src=\"%s\" alt=\"%s\" width=\"150\" height=\"100\" /></a><br>\n",
+ pszFileName, pszEntryDesc, pszFileName, pszEntryDesc);
+ fflush(pHtmlDumper->pFile);
+}
+
+static void crDmpHtmlPrintHeader(struct CR_HTML_DUMPER * pDumper)
+{
+ fprintf(pDumper->pFile, "<html><body>\n");
+ fflush(pDumper->pFile);
+}
+
+static void crDmpHtmlPrintFooter(struct CR_HTML_DUMPER * pDumper)
+{
+ fprintf(pDumper->pFile, "</body></html>\n");
+ fflush(pDumper->pFile);
+}
+
+DECLEXPORT(bool) crDmpHtmlIsInited(struct CR_HTML_DUMPER * pDumper)
+{
+ return !!pDumper->pFile;
+}
+
+DECLEXPORT(void) crDmpHtmlTerm(struct CR_HTML_DUMPER * pDumper)
+{
+ crDmpHtmlPrintFooter(pDumper);
+ fclose (pDumper->pFile);
+ pDumper->pFile = NULL;
+}
+
+DECLEXPORT(int) crDmpHtmlInit(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile)
+{
+ int rc = VERR_NO_MEMORY;
+ pDumper->Base.pfnDumpImg = crDmpHtmlDumpImg;
+ pDumper->Base.pfnDumpStr = crDmpHtmlDumpStr;
+ pDumper->cImg = 0;
+ pDumper->pszDir = crStrdup(pszDir);
+ if (pDumper->pszDir)
+ {
+ pDumper->pszFile = crStrdup(pszFile);
+ if (pDumper->pszFile)
+ {
+ char szBuffer[4096] = {0};
+ RTStrPrintf(szBuffer, sizeof(szBuffer), "%s/%s", pszDir, pszFile);
+
+ pDumper->pszFile = crStrdup(pszFile);
+ pDumper->pFile = fopen(szBuffer, "w");
+ if (pDumper->pFile)
+ {
+ crDmpHtmlPrintHeader(pDumper);
+ return VINF_SUCCESS;
+ }
+ else
+ {
+ crWarning("open failed");
+ rc = VERR_OPEN_FAILED;
+ }
+ crFree((void*)pDumper->pszFile);
+ }
+ else
+ {
+ crWarning("open failed");
+ }
+ crFree((void*)pDumper->pszDir);
+ }
+ else
+ {
+ crWarning("open failed");
+ }
+ return rc;
+}
+
+DECLEXPORT(int) crDmpHtmlInitV(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile, va_list pArgList)
+{
+ char szBuffer[4096] = {0};
+ vsprintf_s(szBuffer, sizeof (szBuffer), pszFile, pArgList);
+ return crDmpHtmlInit(pDumper, pszDir, szBuffer);
+}
+
+DECLEXPORT(int) crDmpHtmlInitF(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile, ...)
+{
+ int rc;
+ va_list pArgList;
+ va_start(pArgList, pszFile);
+ rc = crDmpHtmlInitV(pDumper, pszDir, pszFile, pArgList);
+ va_end(pArgList);
+ return rc;
+}
+
+#endif
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/dump_gen.py b/src/VBox/GuestHost/OpenGL/state_tracker/dump_gen.py
new file mode 100644
index 00000000..7103ed4e
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/dump_gen.py
@@ -0,0 +1,257 @@
+import sys
+
+import apiutil
+
+import sys, re, string
+
+
+line_re = re.compile(r'^(\S+)\s+(GL_\S+)\s+(.*)\s*$')
+extensions_line_re = re.compile(r'^(\S+)\s+(GL_\S+)\s(\S+)\s+(.*)\s*$')
+
+params = {}
+extended_params = {}
+
+input = open( sys.argv[2]+"/state_isenabled.txt", 'r' )
+for line in input.readlines():
+ match = line_re.match( line )
+ if match:
+ type = match.group(1)
+ pname = match.group(2)
+ fields = string.split( match.group(3) )
+ params[pname] = ( type, fields )
+
+input = open( sys.argv[2]+"/state_extensions_isenabled.txt", 'r' )
+for line in input.readlines():
+ match = extensions_line_re.match( line )
+ if match:
+ type = match.group(1)
+ pname = match.group(2)
+ ifdef = match.group(3)
+ fields = string.split( match.group(4) )
+ extended_params[pname] = ( type, ifdef, fields )
+
+
+apiutil.CopyrightC()
+
+print """#include "cr_blitter.h"
+#include "cr_spu.h"
+#include "chromium.h"
+#include "cr_error.h"
+#include "cr_net.h"
+#include "cr_rand.h"
+#include "cr_mem.h"
+#include "cr_string.h"
+#include <cr_dump.h>
+#include "cr_pixeldata.h"
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/mem.h>
+
+#include <stdio.h>
+
+#ifdef VBOX_WITH_CRDUMPER
+"""
+
+from get_sizes import *;
+
+getprops = apiutil.ParamProps("GetDoublev")
+enableprops = apiutil.ParamProps("Enable")
+
+#print "//missing get props:"
+#for prop in getprops:
+# try:
+# tmp = num_get_values[prop]
+# except KeyError:
+# try:
+# keyvalues = extensions_num_get_values[prop]
+# except KeyError:
+# print "//%s" % prop
+#
+print """
+static void crRecDumpPrintVal(CR_DUMPER *pDumper, struct nv_struct *pDesc, float *pfData)
+{
+ char aBuf[4096];
+ crDmpFormatArray(aBuf, sizeof (aBuf), "%f", sizeof (float), pfData, pDesc->num_values);
+ crDmpStrF(pDumper, "%s = %s;", pDesc->pszName, aBuf);
+}
+
+
+void crRecDumpGlGetState(CR_RECORDER *pRec, CRContext *ctx)
+{
+ float afData[CR_MAX_GET_VALUES];
+ struct nv_struct *pDesc;
+
+ for (pDesc = num_values_array; pDesc->num_values != 0 ; pDesc++)
+ {
+ memset(afData, 0, sizeof(afData));
+ pRec->pDispatch->GetFloatv(pDesc->pname, afData);
+ crRecDumpPrintVal(pRec->pDumper, pDesc, afData);
+ }
+}
+
+void crRecDumpGlEnableState(CR_RECORDER *pRec, CRContext *ctx)
+{
+ GLboolean fEnabled;
+"""
+keys = params.keys()
+keys.sort();
+
+for pname in keys:
+ print "\tfEnabled = pRec->pDispatch->IsEnabled(%s);" % pname
+ print "\tcrDmpStrF(pRec->pDumper, \"%s = %%d;\", fEnabled);" % pname
+
+keys = extended_params.keys();
+keys.sort()
+
+for pname in keys:
+ (srctype,ifdef,fields) = extended_params[pname]
+ ext = ifdef[3:] # the extension name with the "GL_" prefix removed
+ ext = ifdef
+ print '#ifdef CR_%s' % ext
+ print "\tfEnabled = pRec->pDispatch->IsEnabled(%s);" % pname
+ print "\tcrDmpStrF(pRec->pDumper, \"%s = %%d;\", fEnabled);" % pname
+ print '#endif /* CR_%s */' % ext
+
+#print "//missing enable props:"
+#for prop in enableprops:
+# try:
+# keyvalues = params[prop]
+# except KeyError:
+# try:
+# keyvalues = extended_params[prop]
+# except KeyError:
+# print "//%s" % prop
+#
+print """
+}
+#endif
+"""
+
+texenv_mappings = {
+ 'GL_TEXTURE_ENV' : [
+ 'GL_TEXTURE_ENV_MODE',
+ 'GL_TEXTURE_ENV_COLOR',
+ 'GL_COMBINE_RGB',
+ 'GL_COMBINE_ALPHA',
+ 'GL_RGB_SCALE',
+ 'GL_ALPHA_SCALE',
+ 'GL_SRC0_RGB',
+ 'GL_SRC1_RGB',
+ 'GL_SRC2_RGB',
+ 'GL_SRC0_ALPHA',
+ 'GL_SRC1_ALPHA',
+ 'GL_SRC2_ALPHA'
+ ],
+ 'GL_TEXTURE_FILTER_CONTROL' : [
+ 'GL_TEXTURE_LOD_BIAS'
+ ],
+ 'GL_POINT_SPRITE' : [
+ 'GL_COORD_REPLACE'
+ ]
+}
+
+texgen_coords = [
+ 'GL_S',
+ 'GL_T',
+ 'GL_R',
+ 'GL_Q'
+]
+
+texgen_names = [
+ 'GL_TEXTURE_GEN_MODE',
+ 'GL_OBJECT_PLANE',
+ 'GL_EYE_PLANE'
+]
+
+texparam_names = [
+ 'GL_TEXTURE_MAG_FILTER',
+ 'GL_TEXTURE_MIN_FILTER',
+ 'GL_TEXTURE_MIN_LOD',
+ 'GL_TEXTURE_MAX_LOD',
+ 'GL_TEXTURE_BASE_LEVEL',
+ 'GL_TEXTURE_MAX_LEVEL',
+ 'GL_TEXTURE_WRAP_S',
+ 'GL_TEXTURE_WRAP_T',
+ 'GL_TEXTURE_WRAP_R',
+ 'GL_TEXTURE_BORDER_COLOR',
+ 'GL_TEXTURE_PRIORITY',
+ 'GL_TEXTURE_RESIDENT',
+ 'GL_TEXTURE_COMPARE_MODE',
+ 'GL_TEXTURE_COMPARE_FUNC',
+ 'GL_DEPTH_TEXTURE_MODE',
+ 'GL_GENERATE_MIPMAP'
+]
+
+print """
+void crRecDumpTexParam(CR_RECORDER *pRec, CRContext *ctx, GLenum enmTarget)
+{
+ GLfloat afBuf[4];
+ char acBuf[1024];
+ unsigned int cComponents;
+ crDmpStrF(pRec->pDumper, "==TEX_PARAM for target(0x%x)==", enmTarget);
+"""
+for pname in texparam_names:
+ print "\tcComponents = crStateHlpComponentsCount(%s);" % pname
+ print "\tAssert(cComponents <= RT_ELEMENTS(afBuf));"
+ print "\tmemset(afBuf, 0, sizeof (afBuf));"
+ print "\tpRec->pDispatch->GetTexParameterfv(enmTarget, %s, afBuf);" % pname
+ print "\tcrDmpFormatArray(acBuf, sizeof (acBuf), \"%f\", sizeof (afBuf[0]), afBuf, cComponents);"
+ print "\tcrDmpStrF(pRec->pDumper, \"%s = %%s;\", acBuf);" % pname
+print """
+ crDmpStrF(pRec->pDumper, "==Done TEX_PARAM for target(0x%x)==", enmTarget);
+}
+"""
+
+print """
+void crRecDumpTexEnv(CR_RECORDER *pRec, CRContext *ctx)
+{
+ GLfloat afBuf[4];
+ char acBuf[1024];
+ unsigned int cComponents;
+ crDmpStrF(pRec->pDumper, "==TEX_ENV==");
+"""
+
+keys = texenv_mappings.keys()
+keys.sort();
+
+for target in keys:
+ print "\tcrDmpStrF(pRec->pDumper, \"===%s===\");" % target
+ values = texenv_mappings[target]
+ for pname in values:
+ print "\tcComponents = crStateHlpComponentsCount(%s);" % pname
+ print "\tAssert(cComponents <= RT_ELEMENTS(afBuf));"
+ print "\tmemset(afBuf, 0, sizeof (afBuf));"
+ print "\tpRec->pDispatch->GetTexEnvfv(%s, %s, afBuf);" % (target, pname)
+ print "\tcrDmpFormatArray(acBuf, sizeof (acBuf), \"%f\", sizeof (afBuf[0]), afBuf, cComponents);"
+ print "\tcrDmpStrF(pRec->pDumper, \"%s = %%s;\", acBuf);" % pname
+ print "\tcrDmpStrF(pRec->pDumper, \"===Done %s===\");" % target
+print """
+ crDmpStrF(pRec->pDumper, "==Done TEX_ENV==");
+}
+"""
+
+
+print """
+void crRecDumpTexGen(CR_RECORDER *pRec, CRContext *ctx)
+{
+ GLdouble afBuf[4];
+ char acBuf[1024];
+ unsigned int cComponents;
+ crDmpStrF(pRec->pDumper, "==TEX_GEN==");
+"""
+
+for coord in texgen_coords:
+ print "\tcrDmpStrF(pRec->pDumper, \"===%s===\");" % coord
+ for pname in texgen_names:
+ print "\tcComponents = crStateHlpComponentsCount(%s);" % pname
+ print "\tAssert(cComponents <= RT_ELEMENTS(afBuf));"
+ print "\tmemset(afBuf, 0, sizeof (afBuf));"
+ print "\tpRec->pDispatch->GetTexGendv(%s, %s, afBuf);" % (coord, pname)
+ print "\tcrDmpFormatArray(acBuf, sizeof (acBuf), \"%f\", sizeof (afBuf[0]), afBuf, cComponents);"
+ print "\tcrDmpStrF(pRec->pDumper, \"%s = %%s;\", acBuf);" % pname
+ print "\tcrDmpStrF(pRec->pDumper, \"===Done %s===\");" % coord
+print """
+ crDmpStrF(pRec->pDumper, "==Done TEX_GEN==");
+}
+"""
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/get_components.py b/src/VBox/GuestHost/OpenGL/state_tracker/get_components.py
new file mode 100644
index 00000000..c9a32452
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/get_components.py
@@ -0,0 +1,144 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+
+num_components = {
+ 'GL_AMBIENT' : 4,
+ 'GL_DIFFUSE' : 4,
+ 'GL_SPECULAR' : 4,
+ 'GL_POSITION' : 4,
+ 'GL_SPOT_DIRECTION' : 3,
+ 'GL_SPOT_EXPONENT' : 1,
+ 'GL_SPOT_CUTOFF' : 1,
+ 'GL_CONSTANT_ATTENUATION' : 1,
+ 'GL_LINEAR_ATTENUATION' : 1,
+ 'GL_QUADRATIC_ATTENUATION' : 1,
+ 'GL_EMISSION' : 4,
+ 'GL_SHININESS' : 1,
+ 'GL_COLOR_INDEXES' : 3,
+ 'GL_TEXTURE_ENV_MODE' : 1,
+ 'GL_TEXTURE_ENV_COLOR' : 4,
+ 'GL_TEXTURE_GEN_MODE' : 1,
+ 'GL_OBJECT_PLANE' : 4,
+ 'GL_EYE_PLANE' : 4,
+ 'GL_TEXTURE_MAG_FILTER' : 1,
+ 'GL_TEXTURE_MIN_FILTER' : 1,
+ 'GL_TEXTURE_WRAP_S' : 1,
+ 'GL_TEXTURE_WRAP_T' : 1,
+ 'GL_TEXTURE_BORDER_COLOR' : 4,
+ 'GL_TEXTURE_WIDTH': 1,
+ 'GL_TEXTURE_HEIGHT': 1,
+ 'GL_TEXTURE_DEPTH': 1,
+ # 'GL_TEXTURE_INTERNAL_FORMAT': 1, THIS CONFLICTS WITH GL_TEXTURE_COMPONENTS!
+ 'GL_TEXTURE_BORDER': 1,
+ 'GL_TEXTURE_RED_SIZE': 1,
+ 'GL_TEXTURE_GREEN_SIZE': 1,
+ 'GL_TEXTURE_BLUE_SIZE': 1,
+ 'GL_TEXTURE_ALPHA_SIZE': 1,
+ 'GL_TEXTURE_LUMINANCE_SIZE': 1,
+ 'GL_TEXTURE_INTENSITY_SIZE': 1,
+ 'GL_TEXTURE_COMPONENTS': 1,
+ 'GL_TEXTURE_RESIDENT': 1
+}
+
+num_extended_components = {
+ 'GL_TEXTURE_MAX_ANISOTROPY_EXT': ( 1, 'CR_EXT_texture_filter_anisotropic' ),
+ 'GL_TEXTURE_WRAP_R': ( 1, 'CR_OPENGL_VERSION_1_2'),
+ 'GL_TEXTURE_PRIORITY': ( 1, 'CR_OPENGL_VERSION_1_2'),
+ 'GL_TEXTURE_MIN_LOD': ( 1, 'CR_OPENGL_VERSION_1_2'),
+ 'GL_TEXTURE_MAX_LOD': ( 1, 'CR_OPENGL_VERSION_1_2'),
+ 'GL_TEXTURE_BASE_LEVEL': ( 1, 'CR_OPENGL_VERSION_1_2'),
+ 'GL_TEXTURE_MAX_LEVEL': ( 1, 'CR_OPENGL_VERSION_1_2'),
+ 'GL_COMBINER_INPUT_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_MAPPING_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_COMPONENT_USAGE_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_AB_DOT_PRODUCT_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_CD_DOT_PRODUCT_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_MUX_SUM_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_SCALE_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_BIAS_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_AB_OUTPUT_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_CD_OUTPUT_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_SUM_OUTPUT_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_INPUT_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_INPUT_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_MAPPING_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_COMBINER_COMPONENT_USAGE_NV': ( 1, 'CR_NV_register_combiners'),
+ 'GL_CONSTANT_COLOR0_NV': ( 4, 'CR_NV_register_combiners'),
+ 'GL_CONSTANT_COLOR1_NV': ( 4, 'CR_NV_register_combiners'),
+ 'GL_COMBINE_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_COMBINE_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_SOURCE0_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_SOURCE1_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_SOURCE2_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_SOURCE0_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_SOURCE1_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_SOURCE2_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_OPERAND0_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_OPERAND1_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_OPERAND2_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_OPERAND0_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_OPERAND1_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_OPERAND2_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_RGB_SCALE_ARB': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_ALPHA_SCALE': (1, 'CR_ARB_texture_env_combine'),
+ 'GL_DEPTH_TEXTURE_MODE_ARB': (1, 'CR_ARB_depth_texture'),
+ 'GL_TEXTURE_DEPTH_SIZE_ARB': (1, 'CR_ARB_depth_texture'),
+ 'GL_TEXTURE_COMPARE_MODE_ARB': (1, 'CR_ARB_shadow'),
+ 'GL_TEXTURE_COMPARE_FUNC_ARB': (1, 'CR_ARB_shadow'),
+ 'GL_TEXTURE_COMPARE_FAIL_VALUE_ARB': (1, 'CR_ARB_shadow_ambient'),
+ 'GL_GENERATE_MIPMAP_SGIS': (1, 'CR_SGIS_generate_mipmap'),
+ 'GL_TEXTURE_LOD_BIAS_EXT': (1, 'CR_EXT_texture_lod_bias'),
+ 'GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB': (1, 'CR_any_vertex_program'),
+ 'GL_CURRENT_VERTEX_ATTRIB_ARB': (4, 'CR_any_vertex_program'),
+ 'GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB': (1, 'CR_any_vertex_program'),
+ 'GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB': (1, 'CR_any_vertex_program'),
+ 'GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB': (1, 'CR_any_vertex_program'),
+ 'GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB': (1, 'CR_any_vertex_program'),
+ 'GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB': (1, 'CR_any_vertex_program'),
+ 'GL_TRACK_MATRIX_NV': (24, 'CR_any_vertex_program'),
+ 'GL_TRACK_MATRIX_TRANSFORM_NV': (24, 'CR_any_vertex_program'),
+ 'GL_BUFFER_SIZE_ARB': (1, 'CR_ARB_vertex_buffer_object'),
+ 'GL_BUFFER_USAGE_ARB': (1, 'CR_ARB_vertex_buffer_object'),
+ 'GL_BUFFER_ACCESS_ARB': (1, 'CR_ARB_vertex_buffer_object'),
+ 'GL_BUFFER_MAPPED_ARB': (1, 'CR_ARB_vertex_buffer_object'),
+ 'GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB': (1, 'CR_ARB_vertex_buffer_object'),
+ 'GL_QUERY_COUNTER_BITS_ARB': (1, 'CR_ARB_occlusion_query'),
+ 'GL_QUERY_RESULT_AVAILABLE_ARB': (1, 'CR_ARB_occlusion_query'),
+ 'GL_QUERY_RESULT_ARB': (1, 'CR_ARB_occlusion_query'),
+ 'GL_CURRENT_QUERY_ARB': (1, 'CR_ARB_occlusion_query'),
+ 'GL_TEXTURE_COMPRESSED_IMAGE_SIZE': (1, 'CR_ARB_texture_compression'),
+ 'GL_TEXTURE_COMPRESSED': (1, 'CR_ARB_texture_compression'),
+ 'GL_COORD_REPLACE_ARB': (1, 'CR_ARB_point_sprite'),
+}
+
+print """unsigned int crStateHlpComponentsCount( GLenum pname )
+{
+ switch( pname )
+ {
+"""
+comps = num_components.keys();
+comps.sort();
+for comp in comps:
+ print '\t\t\tcase %s: return %d;' % (comp,num_components[comp])
+
+comps = num_extended_components.keys();
+comps.sort();
+for comp in comps:
+ (nc, ifdef) = num_extended_components[comp]
+ print '#ifdef %s' % ifdef
+ print '\t\t\tcase %s: return %d;' % (comp,nc)
+ print '#endif /* %s */' % ifdef
+
+print """
+ default:
+ crError( "Unknown parameter name in crStateHlpComponentsCount: %d", (int) pname );
+ break;
+ }
+ /* NOTREACHED */
+ return 0;
+}
+"""
+
+
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state.h b/src/VBox/GuestHost/OpenGL/state_tracker/state.h
index c94525a1..07429aa9 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state.h
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state.h
@@ -9,6 +9,16 @@
#include "cr_glstate.h"
+#define CRSTATE_CHECKERR_RET(expr, result, message, ret) \
+ if (expr) { \
+ crStateError(__LINE__, __FILE__, result, message); \
+ return ret; \
+ }
+
+#define CRSTATE_NO_RETURN
+
+#define CRSTATE_CHECKERR(expr, result, message) CRSTATE_CHECKERR_RET(expr, result, message, CRSTATE_NO_RETURN)
+
typedef struct _crCheckIDHWID {
GLuint id, hwid;
} crCheckIDHWID_t;
@@ -33,6 +43,11 @@ extern CRContext *__currentContext;
#define GetCurrentContext() __currentContext
#endif
+extern GLboolean g_bVBoxEnableDiffOnMakeCurrent;
+
+extern CRContext *g_pAvailableContexts[CR_MAX_CONTEXTS];
+extern uint32_t g_cContexts;
+
extern void crStateTextureInitTextureObj (CRContext *ctx, CRTextureObj *tobj, GLuint name, GLenum target);
extern void crStateTextureInitTextureFormat( CRTextureLevel *tl, GLenum internalFormat );
@@ -55,10 +70,10 @@ void crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID, CRContext *from, CRC
void crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID, CRContext *from, CRContext *to);
-void crStateGetTextureObjectAndImage(CRContext *g, GLenum texTarget, GLint level,
- CRTextureObj **obj, CRTextureLevel **img);
-
void crStateFreeBufferObject(void *data);
void crStateFreeFBO(void *data);
void crStateFreeRBO(void *data);
+
+void crStateGenNames(CRContext *g, CRHashTable *table, GLsizei n, GLuint *names);
+void crStateRegNames(CRContext *g, CRHashTable *table, GLsizei n, GLuint *names);
#endif
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_attrib.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_attrib.c
index 836c2221..68cbdb62 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_attrib.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_attrib.c
@@ -439,14 +439,17 @@ void STATE_APIENTRY crStatePushAttrib(GLbitfield mask)
if (mask & GL_STENCIL_BUFFER_BIT)
{
a->stencilBufferStack[a->stencilBufferStackDepth].stencilTest = g->stencil.stencilTest;
- a->stencilBufferStack[a->stencilBufferStackDepth].func = g->stencil.func;
- a->stencilBufferStack[a->stencilBufferStackDepth].mask = g->stencil.mask;
- a->stencilBufferStack[a->stencilBufferStackDepth].ref = g->stencil.ref;
- a->stencilBufferStack[a->stencilBufferStackDepth].fail = g->stencil.fail;
- a->stencilBufferStack[a->stencilBufferStackDepth].passDepthFail = g->stencil.passDepthFail;
- a->stencilBufferStack[a->stencilBufferStackDepth].passDepthPass = g->stencil.passDepthPass;
a->stencilBufferStack[a->stencilBufferStackDepth].clearValue = g->stencil.clearValue;
a->stencilBufferStack[a->stencilBufferStackDepth].writeMask = g->stencil.writeMask;
+ for (i = 0; i < CRSTATE_STENCIL_BUFFER_COUNT; ++i)
+ {
+ a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].func = g->stencil.buffers[i].func;
+ a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].mask = g->stencil.buffers[i].mask;
+ a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].ref = g->stencil.buffers[i].ref;
+ a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].fail = g->stencil.buffers[i].fail;
+ a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].passDepthFail = g->stencil.buffers[i].passDepthFail;
+ a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].passDepthPass = g->stencil.buffers[i].passDepthPass;
+ }
a->stencilBufferStackDepth++;
}
if (mask & GL_TEXTURE_BIT)
@@ -1033,20 +1036,28 @@ void STATE_APIENTRY crStatePopAttrib(void)
}
a->stencilBufferStackDepth--;
g->stencil.stencilTest = a->stencilBufferStack[a->stencilBufferStackDepth].stencilTest;
- g->stencil.func = a->stencilBufferStack[a->stencilBufferStackDepth].func;
- g->stencil.mask = a->stencilBufferStack[a->stencilBufferStackDepth].mask;
- g->stencil.ref = a->stencilBufferStack[a->stencilBufferStackDepth].ref;
- g->stencil.fail = a->stencilBufferStack[a->stencilBufferStackDepth].fail;
- g->stencil.passDepthFail = a->stencilBufferStack[a->stencilBufferStackDepth].passDepthFail;
- g->stencil.passDepthPass = a->stencilBufferStack[a->stencilBufferStackDepth].passDepthPass;
g->stencil.clearValue = a->stencilBufferStack[a->stencilBufferStackDepth].clearValue;
g->stencil.writeMask = a->stencilBufferStack[a->stencilBufferStackDepth].writeMask;
+ for (i = 0; i < CRSTATE_STENCIL_BUFFER_COUNT; ++i)
+ {
+ g->stencil.buffers[i].func = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].func;
+ g->stencil.buffers[i].mask = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].mask;
+ g->stencil.buffers[i].ref = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].ref;
+ g->stencil.buffers[i].fail = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].fail;
+ g->stencil.buffers[i].passDepthFail = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].passDepthFail;
+ g->stencil.buffers[i].passDepthPass = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].passDepthPass;
+ }
+
DIRTY(sb->stencil.dirty, g->neg_bitid);
DIRTY(sb->stencil.enable, g->neg_bitid);
- DIRTY(sb->stencil.func, g->neg_bitid);
- DIRTY(sb->stencil.op, g->neg_bitid);
DIRTY(sb->stencil.clearValue, g->neg_bitid);
DIRTY(sb->stencil.writeMask, g->neg_bitid);
+
+ for (i = 0; i < CRSTATE_STENCIL_BUFFER_REF_COUNT; ++i)
+ {
+ DIRTY(sb->stencil.bufferRefs[i].func, g->neg_bitid);
+ DIRTY(sb->stencil.bufferRefs[i].op, g->neg_bitid);
+ }
}
if (mask & GL_TEXTURE_BIT)
{
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_bits_globalop.h b/src/VBox/GuestHost/OpenGL/state_tracker/state_bits_globalop.h
new file mode 100644
index 00000000..351a85a3
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_bits_globalop.h
@@ -0,0 +1,338 @@
+/* $Id: state_bits_globalop.h $ */
+
+/** @file
+ * Global State bits operation
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <iprt/cdefs.h>
+
+#include <cr_version.h>
+
+#ifndef CRSTATE_BITS_OP
+# error "CRSTATE_BITS_OP must be defined!"
+#endif
+
+#define _CRSTATE_BITS_OP_SIZEOF(_val) CRSTATE_BITS_OP(_val, RT_SIZEOFMEMB(CRStateBits, _val))
+
+#ifndef CRSTATE_BITS_OP_VERSION
+# define CRSTATE_BITS_OP_VERSION SHCROGL_SSM_VERSION
+#endif
+
+do {
+int i;
+#ifdef _CRSTATE_BITS_OP_STENCIL_V_33
+# error "_CRSTATE_BITS_OP_STENCIL_V_33 must no be defined!"
+#endif
+#if CRSTATE_BITS_OP_VERSION < SHCROGL_SSM_VERSION_WITH_FIXED_STENCIL
+# define _CRSTATE_BITS_OP_STENCIL_V_33
+#endif
+
+#ifdef _CRSTATE_BITS_OP_STENCIL_V_33
+# ifndef CRSTATE_BITS_OP_STENCIL_OP_V_33
+# error "CRSTATE_BITS_OP_STENCIL_OP_V_33 undefined!"
+# endif
+# ifndef CRSTATE_BITS_OP_STENCIL_FUNC_V_33
+# error "CRSTATE_BITS_OP_STENCIL_FUNC_V_33 undefined!"
+# endif
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(attrib.dirty);
+
+_CRSTATE_BITS_OP_SIZEOF(buffer.dirty);
+_CRSTATE_BITS_OP_SIZEOF(buffer.enable);
+_CRSTATE_BITS_OP_SIZEOF(buffer.alphaFunc);
+_CRSTATE_BITS_OP_SIZEOF(buffer.depthFunc);
+_CRSTATE_BITS_OP_SIZEOF(buffer.blendFunc);
+_CRSTATE_BITS_OP_SIZEOF(buffer.logicOp);
+_CRSTATE_BITS_OP_SIZEOF(buffer.indexLogicOp);
+_CRSTATE_BITS_OP_SIZEOF(buffer.drawBuffer);
+_CRSTATE_BITS_OP_SIZEOF(buffer.readBuffer);
+_CRSTATE_BITS_OP_SIZEOF(buffer.indexMask);
+_CRSTATE_BITS_OP_SIZEOF(buffer.colorWriteMask);
+_CRSTATE_BITS_OP_SIZEOF(buffer.clearColor);
+_CRSTATE_BITS_OP_SIZEOF(buffer.clearIndex);
+_CRSTATE_BITS_OP_SIZEOF(buffer.clearDepth);
+_CRSTATE_BITS_OP_SIZEOF(buffer.clearAccum);
+_CRSTATE_BITS_OP_SIZEOF(buffer.depthMask);
+#ifdef CR_EXT_blend_color
+_CRSTATE_BITS_OP_SIZEOF(buffer.blendColor);
+#endif
+#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op)
+_CRSTATE_BITS_OP_SIZEOF(buffer.blendEquation);
+#endif
+#if defined(CR_EXT_blend_func_separate)
+_CRSTATE_BITS_OP_SIZEOF(buffer.blendFuncSeparate);
+#endif
+
+#ifdef CR_ARB_vertex_buffer_object
+_CRSTATE_BITS_OP_SIZEOF(bufferobject.dirty);
+_CRSTATE_BITS_OP_SIZEOF(bufferobject.arrayBinding);
+_CRSTATE_BITS_OP_SIZEOF(bufferobject.elementsBinding);
+# ifdef CR_ARB_pixel_buffer_object
+_CRSTATE_BITS_OP_SIZEOF(bufferobject.packBinding);
+_CRSTATE_BITS_OP_SIZEOF(bufferobject.unpackBinding);
+# endif
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(client.dirty);
+_CRSTATE_BITS_OP_SIZEOF(client.pack);
+_CRSTATE_BITS_OP_SIZEOF(client.unpack);
+_CRSTATE_BITS_OP_SIZEOF(client.enableClientState);
+_CRSTATE_BITS_OP_SIZEOF(client.clientPointer);
+CRSTATE_BITS_OP(client.v, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+CRSTATE_BITS_OP(client.n, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+CRSTATE_BITS_OP(client.c, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+CRSTATE_BITS_OP(client.i, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+CRSTATE_BITS_OP(client.e, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+CRSTATE_BITS_OP(client.s, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+CRSTATE_BITS_OP(client.f, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+for (i=0; i<CR_MAX_TEXTURE_UNITS; i++)
+{
+ CRSTATE_BITS_OP(client.t[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+}
+#ifdef CR_NV_vertex_program
+for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++)
+{
+ CRSTATE_BITS_OP(client.a[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+}
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(current.dirty);
+for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++)
+{
+ _CRSTATE_BITS_OP_SIZEOF(current.vertexAttrib[i]);
+}
+_CRSTATE_BITS_OP_SIZEOF(current.edgeFlag);
+_CRSTATE_BITS_OP_SIZEOF(current.colorIndex);
+_CRSTATE_BITS_OP_SIZEOF(current.rasterPos);
+
+
+_CRSTATE_BITS_OP_SIZEOF(eval.dirty);
+for (i=0; i<GLEVAL_TOT; i++)
+{
+ _CRSTATE_BITS_OP_SIZEOF(eval.eval1D[i]);
+ _CRSTATE_BITS_OP_SIZEOF(eval.eval2D[i]);
+ _CRSTATE_BITS_OP_SIZEOF(eval.enable1D[i]);
+ _CRSTATE_BITS_OP_SIZEOF(eval.enable2D[i]);
+}
+_CRSTATE_BITS_OP_SIZEOF(eval.enable);
+_CRSTATE_BITS_OP_SIZEOF(eval.grid1D);
+_CRSTATE_BITS_OP_SIZEOF(eval.grid2D);
+#ifdef CR_NV_vertex_program
+ /*@todo Those seems to be unused?
+_CRSTATE_BITS_OP_SIZEOF(eval.enableAttrib1D);
+_CRSTATE_BITS_OP_SIZEOF(eval.enableAttrib2D);
+ */
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(feedback.dirty);
+_CRSTATE_BITS_OP_SIZEOF(selection.dirty);
+
+_CRSTATE_BITS_OP_SIZEOF(fog.dirty);
+_CRSTATE_BITS_OP_SIZEOF(fog.color);
+_CRSTATE_BITS_OP_SIZEOF(fog.index);
+_CRSTATE_BITS_OP_SIZEOF(fog.density);
+_CRSTATE_BITS_OP_SIZEOF(fog.start);
+_CRSTATE_BITS_OP_SIZEOF(fog.end);
+_CRSTATE_BITS_OP_SIZEOF(fog.mode);
+_CRSTATE_BITS_OP_SIZEOF(fog.enable);
+#ifdef CR_NV_fog_distance
+_CRSTATE_BITS_OP_SIZEOF(fog.fogDistanceMode);
+#endif
+#ifdef CR_EXT_fog_coord
+_CRSTATE_BITS_OP_SIZEOF(fog.fogCoordinateSource);
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(hint.dirty);
+_CRSTATE_BITS_OP_SIZEOF(hint.perspectiveCorrection);
+_CRSTATE_BITS_OP_SIZEOF(hint.pointSmooth);
+_CRSTATE_BITS_OP_SIZEOF(hint.lineSmooth);
+_CRSTATE_BITS_OP_SIZEOF(hint.polygonSmooth);
+_CRSTATE_BITS_OP_SIZEOF(hint.fog);
+#ifdef CR_EXT_clip_volume_hint
+_CRSTATE_BITS_OP_SIZEOF(hint.clipVolumeClipping);
+
+#endif
+#ifdef CR_ARB_texture_compression
+_CRSTATE_BITS_OP_SIZEOF(hint.textureCompression);
+#endif
+#ifdef CR_SGIS_generate_mipmap
+_CRSTATE_BITS_OP_SIZEOF(hint.generateMipmap);
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(lighting.dirty);
+_CRSTATE_BITS_OP_SIZEOF(lighting.shadeModel);
+_CRSTATE_BITS_OP_SIZEOF(lighting.colorMaterial);
+_CRSTATE_BITS_OP_SIZEOF(lighting.lightModel);
+_CRSTATE_BITS_OP_SIZEOF(lighting.material);
+_CRSTATE_BITS_OP_SIZEOF(lighting.enable);
+for (i=0; i<CR_MAX_LIGHTS; ++i)
+{
+ _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].dirty);
+ _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].enable);
+ _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].ambient);
+ _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].diffuse);
+ _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].specular);
+ _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].position);
+ _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].attenuation);
+ _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].spot);
+}
+
+_CRSTATE_BITS_OP_SIZEOF(line.dirty);
+_CRSTATE_BITS_OP_SIZEOF(line.enable);
+_CRSTATE_BITS_OP_SIZEOF(line.width);
+_CRSTATE_BITS_OP_SIZEOF(line.stipple);
+
+_CRSTATE_BITS_OP_SIZEOF(lists.dirty);
+_CRSTATE_BITS_OP_SIZEOF(lists.base);
+
+_CRSTATE_BITS_OP_SIZEOF(multisample.dirty);
+_CRSTATE_BITS_OP_SIZEOF(multisample.enable);
+_CRSTATE_BITS_OP_SIZEOF(multisample.sampleAlphaToCoverage);
+_CRSTATE_BITS_OP_SIZEOF(multisample.sampleAlphaToOne);
+_CRSTATE_BITS_OP_SIZEOF(multisample.sampleCoverage);
+_CRSTATE_BITS_OP_SIZEOF(multisample.sampleCoverageValue);
+
+#if CR_ARB_occlusion_query
+_CRSTATE_BITS_OP_SIZEOF(occlusion.dirty);
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(pixel.dirty);
+_CRSTATE_BITS_OP_SIZEOF(pixel.transfer);
+_CRSTATE_BITS_OP_SIZEOF(pixel.zoom);
+_CRSTATE_BITS_OP_SIZEOF(pixel.maps);
+
+_CRSTATE_BITS_OP_SIZEOF(point.dirty);
+_CRSTATE_BITS_OP_SIZEOF(point.enableSmooth);
+_CRSTATE_BITS_OP_SIZEOF(point.size);
+#ifdef CR_ARB_point_parameters
+_CRSTATE_BITS_OP_SIZEOF(point.minSize);
+_CRSTATE_BITS_OP_SIZEOF(point.maxSize);
+_CRSTATE_BITS_OP_SIZEOF(point.fadeThresholdSize);
+_CRSTATE_BITS_OP_SIZEOF(point.distanceAttenuation);
+#endif
+#ifdef CR_ARB_point_sprite
+_CRSTATE_BITS_OP_SIZEOF(point.enableSprite);
+for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
+{
+ _CRSTATE_BITS_OP_SIZEOF(point.coordReplacement[i]);
+}
+#endif
+#if CRSTATE_BITS_OP_VERSION >= SHCROGL_SSM_VERSION_WITH_SPRITE_COORD_ORIGIN
+_CRSTATE_BITS_OP_SIZEOF(point.spriteCoordOrigin);
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(polygon.dirty);
+_CRSTATE_BITS_OP_SIZEOF(polygon.enable);
+_CRSTATE_BITS_OP_SIZEOF(polygon.offset);
+_CRSTATE_BITS_OP_SIZEOF(polygon.mode);
+_CRSTATE_BITS_OP_SIZEOF(polygon.stipple);
+
+_CRSTATE_BITS_OP_SIZEOF(program.dirty);
+_CRSTATE_BITS_OP_SIZEOF(program.vpEnable);
+_CRSTATE_BITS_OP_SIZEOF(program.fpEnable);
+_CRSTATE_BITS_OP_SIZEOF(program.vpBinding);
+_CRSTATE_BITS_OP_SIZEOF(program.fpBinding);
+for (i=0; i<CR_MAX_VERTEX_ATTRIBS; ++i)
+{
+ _CRSTATE_BITS_OP_SIZEOF(program.vertexAttribArrayEnable[i]);
+ _CRSTATE_BITS_OP_SIZEOF(program.map1AttribArrayEnable[i]);
+ _CRSTATE_BITS_OP_SIZEOF(program.map2AttribArrayEnable[i]);
+}
+for (i=0; i<CR_MAX_VERTEX_PROGRAM_ENV_PARAMS; ++i)
+{
+ _CRSTATE_BITS_OP_SIZEOF(program.vertexEnvParameter[i]);
+}
+for (i=0; i<CR_MAX_FRAGMENT_PROGRAM_ENV_PARAMS; ++i)
+{
+ _CRSTATE_BITS_OP_SIZEOF(program.fragmentEnvParameter[i]);
+}
+_CRSTATE_BITS_OP_SIZEOF(program.vertexEnvParameters);
+_CRSTATE_BITS_OP_SIZEOF(program.fragmentEnvParameters);
+for (i=0; i<CR_MAX_VERTEX_PROGRAM_ENV_PARAMS/4; ++i)
+{
+ _CRSTATE_BITS_OP_SIZEOF(program.trackMatrix[i]);
+}
+
+_CRSTATE_BITS_OP_SIZEOF(regcombiner.dirty);
+_CRSTATE_BITS_OP_SIZEOF(regcombiner.enable);
+_CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerVars);
+_CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerColor0);
+_CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerColor1);
+for (i=0; i<CR_MAX_GENERAL_COMBINERS; ++i)
+{
+ _CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerStageColor0[i]);
+ _CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerStageColor1[i]);
+ _CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerInput[i]);
+ _CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerOutput[i]);
+}
+_CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerFinalInput);
+
+_CRSTATE_BITS_OP_SIZEOF(stencil.dirty);
+_CRSTATE_BITS_OP_SIZEOF(stencil.enable);
+#ifdef _CRSTATE_BITS_OP_STENCIL_V_33
+_CRSTATE_BITS_OP_SIZEOF(stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func);
+_CRSTATE_BITS_OP_SIZEOF(stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op);
+for (i = CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK + 1; i < CRSTATE_STENCIL_BUFFER_REF_COUNT; ++i)
+{
+ CRSTATE_BITS_OP_STENCIL_FUNC_V_33(i, stencil.bufferRefs[i].func);
+ CRSTATE_BITS_OP_STENCIL_OP_V_33(i, stencil.bufferRefs[i].op);
+}
+_CRSTATE_BITS_OP_SIZEOF(stencil.clearValue);
+_CRSTATE_BITS_OP_SIZEOF(stencil.writeMask);
+#else
+_CRSTATE_BITS_OP_SIZEOF(stencil.enableTwoSideEXT);
+_CRSTATE_BITS_OP_SIZEOF(stencil.activeStencilFace);
+_CRSTATE_BITS_OP_SIZEOF(stencil.clearValue);
+_CRSTATE_BITS_OP_SIZEOF(stencil.writeMask);
+for (i = 0; i < CRSTATE_STENCIL_BUFFER_REF_COUNT; ++i)
+{
+ _CRSTATE_BITS_OP_SIZEOF(stencil.bufferRefs[i].func);
+ _CRSTATE_BITS_OP_SIZEOF(stencil.bufferRefs[i].op);
+}
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(texture.dirty);
+for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
+{
+ _CRSTATE_BITS_OP_SIZEOF(texture.enable[i]);
+ _CRSTATE_BITS_OP_SIZEOF(texture.current[i]);
+ _CRSTATE_BITS_OP_SIZEOF(texture.objGen[i]);
+ _CRSTATE_BITS_OP_SIZEOF(texture.eyeGen[i]);
+ _CRSTATE_BITS_OP_SIZEOF(texture.genMode[i]);
+ _CRSTATE_BITS_OP_SIZEOF(texture.envBit[i]);
+}
+
+_CRSTATE_BITS_OP_SIZEOF(transform.dirty);
+_CRSTATE_BITS_OP_SIZEOF(transform.matrixMode);
+_CRSTATE_BITS_OP_SIZEOF(transform.modelviewMatrix);
+_CRSTATE_BITS_OP_SIZEOF(transform.projectionMatrix);
+_CRSTATE_BITS_OP_SIZEOF(transform.colorMatrix);
+_CRSTATE_BITS_OP_SIZEOF(transform.textureMatrix);
+_CRSTATE_BITS_OP_SIZEOF(transform.programMatrix);
+_CRSTATE_BITS_OP_SIZEOF(transform.clipPlane);
+_CRSTATE_BITS_OP_SIZEOF(transform.enable);
+_CRSTATE_BITS_OP_SIZEOF(transform.base);
+
+_CRSTATE_BITS_OP_SIZEOF(viewport.dirty);
+_CRSTATE_BITS_OP_SIZEOF(viewport.v_dims);
+_CRSTATE_BITS_OP_SIZEOF(viewport.s_dims);
+_CRSTATE_BITS_OP_SIZEOF(viewport.enable);
+_CRSTATE_BITS_OP_SIZEOF(viewport.depth);
+
+} while (0);
+
+#undef CRSTATE_BITS_OP_VERSION
+#undef _CRSTATE_BITS_OP_STENCIL_V_33
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c
index 6214e889..90917ab5 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c
@@ -483,6 +483,7 @@ void STATE_APIENTRY crStateDrawBuffer (GLenum mode)
switch (mode)
{
case GL_NONE:
+ break;
case GL_FRONT_LEFT:
case GL_FRONT_RIGHT:
case GL_BACK_LEFT:
@@ -548,6 +549,7 @@ void STATE_APIENTRY crStateReadBuffer (GLenum mode)
switch (mode)
{
case GL_NONE:
+ break;
case GL_FRONT_LEFT:
case GL_FRONT_RIGHT:
case GL_BACK_LEFT:
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c
index 5a3d2e49..bd6a1e20 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c
@@ -22,16 +22,25 @@ static CRBufferObject *AllocBufferObject(GLuint name)
b->usage = GL_STATIC_DRAW_ARB;
b->access = GL_READ_WRITE_ARB;
b->bResyncOnRead = GL_FALSE;
-#ifndef IN_GUEST
CR_STATE_SHAREDOBJ_USAGE_INIT(b);
-#endif
}
return b;
}
-GLboolean crStateIsBufferBound(GLenum target)
+void STATE_APIENTRY crStateGenBuffersARB(GLsizei n, GLuint *buffers)
+{
+ CRContext *g = GetCurrentContext();
+ crStateGenNames(g, g->shared->buffersTable, n, buffers);
+}
+
+void crStateRegBuffers(GLsizei n, GLuint *buffers)
{
CRContext *g = GetCurrentContext();
+ crStateRegNames(g, g->shared->buffersTable, n, buffers);
+}
+
+GLboolean crStateIsBufferBoundForCtx(CRContext *g, GLenum target)
+{
CRBufferObjectState *b = &(g->bufferobject);
switch (target)
@@ -51,6 +60,12 @@ GLboolean crStateIsBufferBound(GLenum target)
}
}
+GLboolean crStateIsBufferBound(GLenum target)
+{
+ CRContext *g = GetCurrentContext();
+ return crStateIsBufferBoundForCtx(g, target);
+}
+
CRBufferObject *crStateGetBoundBufferObject(GLenum target, CRBufferObjectState *b)
{
switch (target)
@@ -70,6 +85,21 @@ CRBufferObject *crStateGetBoundBufferObject(GLenum target, CRBufferObjectState *
}
}
+DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsBufferARB( GLuint buffer )
+{
+ CRContext *g = GetCurrentContext();
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glIsBufferARB called in begin/end");
+ return GL_FALSE;
+ }
+
+ return buffer ? crHashtableIsKeyUsed(g->shared->buffersTable, buffer) : GL_FALSE;
+}
+
void crStateBufferObjectInit (CRContext *ctx)
{
CRStateBits *sb = GetCurrentBits();
@@ -93,7 +123,7 @@ void crStateBufferObjectInit (CRContext *ctx)
b->nullBuffer = AllocBufferObject(0);
b->arrayBuffer = b->nullBuffer;
b->elementsBuffer = b->nullBuffer;
- b->nullBuffer->refCount = 3;
+ b->nullBuffer->refCount += 2;
#ifdef CR_ARB_pixel_buffer_object
b->packBuffer = b->nullBuffer;
b->unpackBuffer = b->nullBuffer;
@@ -184,17 +214,22 @@ crStateBindBufferARB (GLenum target, GLuint buffer)
else {
newObj = (CRBufferObject *) crHashtableSearch(g->shared->buffersTable, buffer);
if (!newObj) {
+ CRSTATE_CHECKERR(!crHashtableIsKeyUsed(g->shared->buffersTable, buffer), GL_INVALID_OPERATION, "name is not a buffer object");
newObj = AllocBufferObject(buffer);
- if (!newObj) {
- crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glBindBuffer");
+ CRSTATE_CHECKERR(!newObj, GL_OUT_OF_MEMORY, "glBindBuffer");
+#ifndef IN_GUEST
+ diff_api.GenBuffersARB(1, &newObj->hwid);
+ if (!newObj->hwid)
+ {
+ crWarning("GenBuffersARB failed!");
+ crFree(newObj);
return;
}
+#endif
crHashtableAdd( g->shared->buffersTable, buffer, newObj );
}
-#ifndef IN_GUEST
CR_STATE_SHAREDOBJ_USAGE_SET(newObj, g);
-#endif
}
newObj->refCount++;
@@ -243,127 +278,124 @@ crStateBindBufferARB (GLenum target, GLuint buffer)
#endif
}
-void STATE_APIENTRY
-crStateDeleteBuffersARB(GLsizei n, const GLuint *buffers)
+static void ctStateBuffersRefsCleanup(CRContext *ctx, CRBufferObject *obj, CRbitvalue *neg_bitid)
{
- CRContext *g = GetCurrentContext();
- CRBufferObjectState *b = &(g->bufferobject);
+ CRBufferObjectState *b = &(ctx->bufferobject);
CRStateBits *sb = GetCurrentBits();
CRBufferObjectBits *bb = &(sb->bufferobject);
- int i;
+ int j, k;
- FLUSH();
-
- if (g->current.inBeginEnd) {
- crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
- "glDeleteBuffersARB called in Begin/End");
- return;
+ if (obj == b->arrayBuffer)
+ {
+ b->arrayBuffer = b->nullBuffer;
+ b->arrayBuffer->refCount++;
+ DIRTY(bb->dirty, neg_bitid);
+ DIRTY(bb->arrayBinding, neg_bitid);
}
-
- if (n < 0) {
- crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
- "glDeleteBuffersARB(n < 0)");
- return;
+ if (obj == b->elementsBuffer)
+ {
+ b->elementsBuffer = b->nullBuffer;
+ b->elementsBuffer->refCount++;
+ DIRTY(bb->dirty, neg_bitid);
+ DIRTY(bb->elementsBinding, neg_bitid);
}
-
- for (i = 0; i < n; i++) {
- if (buffers[i]) {
- CRBufferObject *obj = (CRBufferObject *)
- crHashtableSearch(g->shared->buffersTable, buffers[i]);
- if (obj) {
- if (obj == b->arrayBuffer)
- {
- b->arrayBuffer = b->nullBuffer;
- b->arrayBuffer->refCount++;
- DIRTY(bb->dirty, g->neg_bitid);
- DIRTY(bb->arrayBinding, g->neg_bitid);
- }
- else if (obj == b->elementsBuffer)
- {
- b->elementsBuffer = b->nullBuffer;
- b->elementsBuffer->refCount++;
- DIRTY(bb->dirty, g->neg_bitid);
- DIRTY(bb->elementsBinding, g->neg_bitid);
- }
#ifdef CR_ARB_pixel_buffer_object
- else if (obj == b->packBuffer)
- {
- b->packBuffer = b->nullBuffer;
- b->packBuffer->refCount++;
- DIRTY(bb->dirty, g->neg_bitid);
- DIRTY(bb->packBinding, g->neg_bitid);
- }
- else if (obj == b->unpackBuffer)
- {
- b->unpackBuffer = b->nullBuffer;
- b->unpackBuffer->refCount++;
- DIRTY(bb->dirty, g->neg_bitid);
- DIRTY(bb->unpackBinding, g->neg_bitid);
- }
+ if (obj == b->packBuffer)
+ {
+ b->packBuffer = b->nullBuffer;
+ b->packBuffer->refCount++;
+ DIRTY(bb->dirty, neg_bitid);
+ DIRTY(bb->packBinding, neg_bitid);
+ }
+ if (obj == b->unpackBuffer)
+ {
+ b->unpackBuffer = b->nullBuffer;
+ b->unpackBuffer->refCount++;
+ DIRTY(bb->dirty, neg_bitid);
+ DIRTY(bb->unpackBinding, neg_bitid);
+ }
#endif
- /* @todo check bindings with the vertex arrays */
- crHashtableDelete(g->shared->buffersTable, buffers[i], crStateFreeBufferObject);
+#ifdef CR_ARB_vertex_buffer_object
+ for (j=0; j<CRSTATECLIENT_MAX_VERTEXARRAYS; ++j)
+ {
+ CRClientPointer *cp = crStateGetClientPointerByIndex(j, &ctx->client.array);
+ if (obj == cp->buffer)
+ {
+ cp->buffer = b->nullBuffer;
+ ++b->nullBuffer->refCount;
+ }
+ }
+
+ for (k=0; k<ctx->client.vertexArrayStackDepth; ++k)
+ {
+ CRVertexArrays *pArray = &ctx->client.vertexArrayStack[k];
+ for (j=0; j<CRSTATECLIENT_MAX_VERTEXARRAYS; ++j)
+ {
+ CRClientPointer *cp = crStateGetClientPointerByIndex(j, pArray);
+ if (obj == cp->buffer)
+ {
+ cp->buffer = b->nullBuffer;
+ ++b->nullBuffer->refCount;
}
}
}
-}
+#endif
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(obj, ctx);
+}
void STATE_APIENTRY
-crStateGenBuffersARB(GLsizei n, GLuint * buffers)
+crStateDeleteBuffersARB(GLsizei n, const GLuint *buffers)
{
CRContext *g = GetCurrentContext();
- CRBufferObjectState *b = &(g->bufferobject);
- GLint start;
+ int i;
FLUSH();
if (g->current.inBeginEnd) {
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
- "glGenBuffersARB called in Begin/End");
+ "glDeleteBuffersARB called in Begin/End");
return;
}
if (n < 0) {
crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
- "glGenBuffersARB(n < 0)");
+ "glDeleteBuffersARB(n < 0)");
return;
}
- start = crHashtableAllocKeys(g->shared->buffersTable, n);
- if (start) {
- GLint i;
- for (i = 0; i < n; i++)
- buffers[i] = (GLuint) (start + i);
- }
- else {
- crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glGenBuffersARB");
- }
-}
-
+ for (i = 0; i < n; i++) {
+ if (buffers[i]) {
+ CRBufferObject *obj = (CRBufferObject *)
+ crHashtableSearch(g->shared->buffersTable, buffers[i]);
+ if (obj) {
+ int j;
-GLboolean STATE_APIENTRY
-crStateIsBufferARB(GLuint buffer)
-{
- CRContext *g = GetCurrentContext();
- CRBufferObjectState *b = &g->bufferobject;
+ ctStateBuffersRefsCleanup(g, obj, g->neg_bitid);
- FLUSH();
+ CR_STATE_SHAREDOBJ_USAGE_FOREACH_USED_IDX(obj, j)
+ {
+ /* saved state version <= SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS does not have usage bits info,
+ * so on restore, we set mark bits as used.
+ * This is why g_pAvailableContexts[j] could be NULL
+ * also g_pAvailableContexts[0] will hold default context, which we should discard */
+ CRContext *ctx = g_pAvailableContexts[j];
+ if (j && ctx)
+ {
+ ctStateBuffersRefsCleanup(ctx, obj, g->neg_bitid); /* <- yes, use g->neg_bitid, i.e. neg_bitid of the current context to ensure others bits get dirtified,
+ * but not the current context ones*/
+ }
+ else
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR_IDX(obj, j);
+ }
- if (g->current.inBeginEnd) {
- crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
- "glIsBufferARB called in begin/end");
- return GL_FALSE;
+ crHashtableDelete(g->shared->buffersTable, buffers[i], crStateFreeBufferObject);
+ }
+ }
}
-
- if (buffer && crHashtableSearch(g->shared->buffersTable, buffer))
- return GL_TRUE;
- else
- return GL_FALSE;
}
-
void STATE_APIENTRY
crStateBufferDataARB(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage)
{
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_client.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_client.c
index f0405c64..e02f3abe 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_client.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_client.c
@@ -83,8 +83,9 @@ static void crStateUnlockClientPointer(CRClientPointer* cp)
}
}
-void crStateClientDestroy(CRClientState *c)
+void crStateClientDestroy(CRContext *g)
{
+ CRClientState *c = &(g->client);
#ifdef CR_EXT_compiled_vertex_array
if (c->array.locked)
{
@@ -109,9 +110,9 @@ void crStateClientDestroy(CRClientState *c)
#endif
}
-void crStateClientInit(CRClientState *c)
+void crStateClientInit(CRContext *ctx)
{
- CRContext *g = GetCurrentContext();
+ CRClientState *c = &(ctx->client);
unsigned int i;
/* pixel pack/unpack */
@@ -151,7 +152,9 @@ void crStateClientInit(CRClientState *c)
c->array.v.stride = 0;
c->array.v.enabled = 0;
#ifdef CR_ARB_vertex_buffer_object
- c->array.v.buffer = g ? g->bufferobject.arrayBuffer : NULL;
+ c->array.v.buffer = ctx->bufferobject.arrayBuffer;
+ if (c->array.v.buffer)
+ ++c->array.v.buffer->refCount;
#endif
#ifdef CR_EXT_compiled_vertex_array
c->array.v.locked = GL_FALSE;
@@ -166,7 +169,9 @@ void crStateClientInit(CRClientState *c)
c->array.c.stride = 0;
c->array.c.enabled = 0;
#ifdef CR_ARB_vertex_buffer_object
- c->array.c.buffer = g ? g->bufferobject.arrayBuffer : NULL;
+ c->array.c.buffer = ctx->bufferobject.arrayBuffer;
+ if (c->array.c.buffer)
+ ++c->array.c.buffer->refCount;
#endif
#ifdef CR_EXT_compiled_vertex_array
c->array.c.locked = GL_FALSE;
@@ -181,7 +186,9 @@ void crStateClientInit(CRClientState *c)
c->array.f.stride = 0;
c->array.f.enabled = 0;
#ifdef CR_ARB_vertex_buffer_object
- c->array.f.buffer = g ? g->bufferobject.arrayBuffer : NULL;
+ c->array.f.buffer = ctx->bufferobject.arrayBuffer;
+ if (c->array.f.buffer)
+ ++c->array.f.buffer->refCount;
#endif
#ifdef CR_EXT_compiled_vertex_array
c->array.f.locked = GL_FALSE;
@@ -196,7 +203,9 @@ void crStateClientInit(CRClientState *c)
c->array.s.stride = 0;
c->array.s.enabled = 0;
#ifdef CR_ARB_vertex_buffer_object
- c->array.s.buffer = g ? g->bufferobject.arrayBuffer : NULL;
+ c->array.s.buffer = ctx->bufferobject.arrayBuffer;
+ if (c->array.s.buffer)
+ ++c->array.s.buffer->refCount;
#endif
#ifdef CR_EXT_compiled_vertex_array
c->array.s.locked = GL_FALSE;
@@ -211,7 +220,9 @@ void crStateClientInit(CRClientState *c)
c->array.e.stride = 0;
c->array.e.enabled = 0;
#ifdef CR_ARB_vertex_buffer_object
- c->array.e.buffer = g ? g->bufferobject.arrayBuffer : NULL;
+ c->array.e.buffer = ctx->bufferobject.arrayBuffer;
+ if (c->array.e.buffer)
+ ++c->array.e.buffer->refCount;
#endif
#ifdef CR_EXT_compiled_vertex_array
c->array.e.locked = GL_FALSE;
@@ -226,7 +237,9 @@ void crStateClientInit(CRClientState *c)
c->array.i.stride = 0;
c->array.i.enabled = 0;
#ifdef CR_ARB_vertex_buffer_object
- c->array.i.buffer = g ? g->bufferobject.arrayBuffer : NULL;
+ c->array.i.buffer = ctx->bufferobject.arrayBuffer;
+ if (c->array.i.buffer)
+ ++c->array.i.buffer->refCount;
#endif
#ifdef CR_EXT_compiled_vertex_array
c->array.i.locked = GL_FALSE;
@@ -241,7 +254,9 @@ void crStateClientInit(CRClientState *c)
c->array.n.stride = 0;
c->array.n.enabled = 0;
#ifdef CR_ARB_vertex_buffer_object
- c->array.n.buffer = g ? g->bufferobject.arrayBuffer : NULL;
+ c->array.n.buffer = ctx->bufferobject.arrayBuffer;
+ if (c->array.n.buffer)
+ ++c->array.n.buffer->refCount;
#endif
#ifdef CR_EXT_compiled_vertex_array
c->array.n.locked = GL_FALSE;
@@ -258,7 +273,9 @@ void crStateClientInit(CRClientState *c)
c->array.t[i].stride = 0;
c->array.t[i].enabled = 0;
#ifdef CR_ARB_vertex_buffer_object
- c->array.t[i].buffer = g ? g->bufferobject.arrayBuffer : NULL;
+ c->array.t[i].buffer = ctx->bufferobject.arrayBuffer;
+ if (c->array.t[i].buffer)
+ ++c->array.t[i].buffer->refCount;
#endif
#ifdef CR_EXT_compiled_vertex_array
c->array.t[i].locked = GL_FALSE;
@@ -275,7 +292,9 @@ void crStateClientInit(CRClientState *c)
c->array.a[i].size = 4;
c->array.a[i].stride = 0;
#ifdef CR_ARB_vertex_buffer_object
- c->array.a[i].buffer = g ? g->bufferobject.arrayBuffer : NULL;
+ c->array.a[i].buffer = ctx->bufferobject.arrayBuffer;
+ if (c->array.a[i].buffer)
+ ++c->array.a[i].buffer->refCount;
#endif
#ifdef CR_EXT_compiled_vertex_array
c->array.a[i].locked = GL_FALSE;
@@ -622,7 +641,14 @@ crStateClientSetPointer(CRClientPointer *cp, GLint size,
cp->stride = cp->bytesPerIndex;
#ifdef CR_ARB_vertex_buffer_object
+ if (cp->buffer)
+ {
+ --cp->buffer->refCount;
+ CRASSERT(cp->buffer->refCount && cp->buffer->refCount < UINT32_MAX/2);
+ }
cp->buffer = g->bufferobject.arrayBuffer;
+ if (cp->buffer)
+ ++cp->buffer->refCount;
#endif
}
@@ -1622,6 +1648,7 @@ crStateUseServerArrayElements(void)
#endif
}
+#define CR_BUFFER_HWID(_p) ((_p) ? (_p)->hwid : 0)
void
crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
@@ -1631,6 +1658,17 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
const CRClientState *to = &(toCtx->client);
GLint curClientTextureUnit = from->curClientTextureUnit;
int i;
+ GLint idHwArrayBuffer = CR_BUFFER_HWID(toCtx->bufferobject.arrayBuffer);
+ const GLint idHwInitialBuffer = idHwArrayBuffer;
+
+#ifdef DEBUG_misha
+ {
+ GLint tstHwBuffer = -1;
+ diff_api.GetIntegerv(GL_ARRAY_BUFFER_BINDING, &tstHwBuffer);
+ CRASSERT(idHwInitialBuffer == tstHwBuffer);
+ }
+#endif
+
if (CHECKDIRTY(cb->clientPointer, bitID)) {
/* one or more vertex pointers is dirty */
@@ -1638,7 +1676,14 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
if (from->array.v.size != to->array.v.size ||
from->array.v.type != to->array.v.type ||
from->array.v.stride != to->array.v.stride ||
+ from->array.v.p != to->array.v.p ||
from->array.v.buffer != to->array.v.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.v.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.VertexPointer(to->array.v.size, to->array.v.type,
to->array.v.stride, to->array.v.p);
from->array.v.size = to->array.v.size;
@@ -1653,7 +1698,14 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
if (CHECKDIRTY(cb->n, bitID)) {
if (from->array.n.type != to->array.n.type ||
from->array.n.stride != to->array.n.stride ||
+ from->array.n.p != to->array.n.p ||
from->array.n.buffer != to->array.n.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.n.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.NormalPointer(to->array.n.type,
to->array.n.stride, to->array.n.p);
from->array.n.type = to->array.n.type;
@@ -1668,7 +1720,14 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
if (from->array.c.size != to->array.c.size ||
from->array.c.type != to->array.c.type ||
from->array.c.stride != to->array.c.stride ||
+ from->array.c.p != to->array.c.p ||
from->array.c.buffer != to->array.c.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.c.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.ColorPointer(to->array.c.size, to->array.c.type,
to->array.c.stride, to->array.c.p);
from->array.c.size = to->array.c.size;
@@ -1683,7 +1742,14 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
if (CHECKDIRTY(cb->i, bitID)) {
if (from->array.i.type != to->array.i.type ||
from->array.i.stride != to->array.i.stride ||
+ from->array.i.p != to->array.i.p ||
from->array.i.buffer != to->array.i.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.i.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.IndexPointer(to->array.i.type,
to->array.i.stride, to->array.i.p);
from->array.i.type = to->array.i.type;
@@ -1699,7 +1765,14 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
if (from->array.t[i].size != to->array.t[i].size ||
from->array.t[i].type != to->array.t[i].type ||
from->array.t[i].stride != to->array.t[i].stride ||
+ from->array.t[i].p != to->array.t[i].p ||
from->array.t[i].buffer != to->array.t[i].buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.t[i].buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.ClientActiveTextureARB(GL_TEXTURE0_ARB + i);
curClientTextureUnit = i;
diff_api.TexCoordPointer(to->array.t[i].size, to->array.t[i].type,
@@ -1716,7 +1789,14 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
/* edge flag */
if (CHECKDIRTY(cb->e, bitID)) {
if (from->array.e.stride != to->array.e.stride ||
+ from->array.e.p != to->array.e.p ||
from->array.e.buffer != to->array.e.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.e.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.EdgeFlagPointer(to->array.e.stride, to->array.e.p);
from->array.e.stride = to->array.e.stride;
from->array.e.p = to->array.e.p;
@@ -1729,7 +1809,14 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
if (from->array.s.size != to->array.s.size ||
from->array.s.type != to->array.s.type ||
from->array.s.stride != to->array.s.stride ||
+ from->array.s.p != to->array.s.p ||
from->array.s.buffer != to->array.s.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.s.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.SecondaryColorPointerEXT(to->array.s.size, to->array.s.type,
to->array.s.stride, to->array.s.p);
from->array.s.size = to->array.s.size;
@@ -1744,7 +1831,14 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
if (CHECKDIRTY(cb->f, bitID)) {
if (from->array.f.type != to->array.f.type ||
from->array.f.stride != to->array.f.stride ||
+ from->array.f.p != to->array.f.p ||
from->array.f.buffer != to->array.f.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.f.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.FogCoordPointerEXT(to->array.f.type,
to->array.f.stride, to->array.f.p);
from->array.f.type = to->array.f.type;
@@ -1762,7 +1856,14 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
from->array.a[i].type != to->array.a[i].type ||
from->array.a[i].stride != to->array.a[i].stride ||
from->array.a[i].normalized != to->array.a[i].normalized ||
+ from->array.a[i].p != to->array.a[i].p ||
from->array.a[i].buffer != to->array.a[i].buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.a[i].buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.VertexAttribPointerARB(i, to->array.a[i].size,
to->array.a[i].type,
to->array.a[i].normalized,
@@ -1781,11 +1882,16 @@ crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID,
#endif
}
+ if (idHwArrayBuffer != idHwInitialBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwInitialBuffer);
+ }
+
if (CHECKDIRTY(cb->enableClientState, bitID)) {
/* update vertex array enable/disable flags */
glAble able[2];
- able[0] = diff_api.Disable;
- able[1] = diff_api.Enable;
+ able[0] = diff_api.DisableClientState;
+ able[1] = diff_api.EnableClientState;
if (from->array.v.enabled != to->array.v.enabled) {
able[to->array.v.enabled](GL_VERTEX_ARRAY);
from->array.v.enabled = to->array.v.enabled;
@@ -1849,6 +1955,16 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
const CRClientState *to = &(toCtx->client);
GLint curClientTextureUnit = from->curClientTextureUnit;
int i;
+ GLint idHwArrayBuffer = CR_BUFFER_HWID(toCtx->bufferobject.arrayBuffer);
+ const GLint idHwInitialBuffer = idHwArrayBuffer;
+
+#ifdef DEBUG_misha
+ {
+ GLint tstHwBuffer = -1;
+ diff_api.GetIntegerv(GL_ARRAY_BUFFER_BINDING, &tstHwBuffer);
+ CRASSERT(idHwInitialBuffer == tstHwBuffer);
+ }
+#endif
if (CHECKDIRTY(cb->clientPointer, bitID)) {
/* one or more vertex pointers is dirty */
@@ -1856,7 +1972,14 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
if (from->array.v.size != to->array.v.size ||
from->array.v.type != to->array.v.type ||
from->array.v.stride != to->array.v.stride ||
+ from->array.v.p != to->array.v.p ||
from->array.v.buffer != to->array.v.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.v.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.VertexPointer(to->array.v.size, to->array.v.type,
to->array.v.stride, to->array.v.p);
FILLDIRTY(cb->v);
@@ -1869,7 +1992,14 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
if (CHECKDIRTY(cb->n, bitID)) {
if (from->array.n.type != to->array.n.type ||
from->array.n.stride != to->array.n.stride ||
+ from->array.n.p != to->array.n.p ||
from->array.n.buffer != to->array.n.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.n.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.NormalPointer(to->array.n.type,
to->array.n.stride, to->array.n.p);
FILLDIRTY(cb->n);
@@ -1883,7 +2013,14 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
if (from->array.c.size != to->array.c.size ||
from->array.c.type != to->array.c.type ||
from->array.c.stride != to->array.c.stride ||
+ from->array.c.p != to->array.c.p ||
from->array.c.buffer != to->array.c.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.c.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.ColorPointer(to->array.c.size, to->array.c.type,
to->array.c.stride, to->array.c.p);
FILLDIRTY(cb->c);
@@ -1896,7 +2033,14 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
if (CHECKDIRTY(cb->i, bitID)) {
if (from->array.i.type != to->array.i.type ||
from->array.i.stride != to->array.i.stride ||
+ from->array.i.p != to->array.i.p ||
from->array.i.buffer != to->array.i.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.i.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.IndexPointer(to->array.i.type,
to->array.i.stride, to->array.i.p);
FILLDIRTY(cb->i);
@@ -1911,7 +2055,14 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
if (from->array.t[i].size != to->array.t[i].size ||
from->array.t[i].type != to->array.t[i].type ||
from->array.t[i].stride != to->array.t[i].stride ||
+ from->array.t[i].p != to->array.t[i].p ||
from->array.t[i].buffer != to->array.t[i].buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.t[i].buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.ClientActiveTextureARB(GL_TEXTURE0_ARB + i);
curClientTextureUnit = i;
diff_api.TexCoordPointer(to->array.t[i].size, to->array.t[i].type,
@@ -1926,7 +2077,14 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
/* edge flag */
if (CHECKDIRTY(cb->e, bitID)) {
if (from->array.e.stride != to->array.e.stride ||
+ from->array.e.p != to->array.e.p ||
from->array.e.buffer != to->array.e.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.e.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.EdgeFlagPointer(to->array.e.stride, to->array.e.p);
FILLDIRTY(cb->e);
FILLDIRTY(cb->clientPointer);
@@ -1939,7 +2097,14 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
if (from->array.s.size != to->array.s.size ||
from->array.s.type != to->array.s.type ||
from->array.s.stride != to->array.s.stride ||
+ from->array.s.p != to->array.s.p ||
from->array.s.buffer != to->array.s.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.s.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.SecondaryColorPointerEXT(to->array.s.size, to->array.s.type,
to->array.s.stride, to->array.s.p);
FILLDIRTY(cb->s);
@@ -1952,7 +2117,14 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
if (CHECKDIRTY(cb->f, bitID)) {
if (from->array.f.type != to->array.f.type ||
from->array.f.stride != to->array.f.stride ||
+ from->array.f.p != to->array.f.p ||
from->array.f.buffer != to->array.f.buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.f.buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.FogCoordPointerEXT(to->array.f.type,
to->array.f.stride, to->array.f.p);
FILLDIRTY(cb->f);
@@ -1969,7 +2141,14 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
from->array.a[i].type != to->array.a[i].type ||
from->array.a[i].stride != to->array.a[i].stride ||
from->array.a[i].normalized != to->array.a[i].normalized ||
+ from->array.a[i].p != to->array.a[i].p ||
from->array.a[i].buffer != to->array.a[i].buffer) {
+ GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.a[i].buffer);
+ if (idHwArrayBufferUsed != idHwArrayBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed);
+ idHwArrayBuffer = idHwArrayBufferUsed;
+ }
diff_api.VertexAttribPointerARB(i, to->array.a[i].size,
to->array.a[i].type,
to->array.a[i].normalized,
@@ -1985,11 +2164,16 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
#endif
}
+ if (idHwArrayBuffer != idHwInitialBuffer)
+ {
+ diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwInitialBuffer);
+ }
+
if (CHECKDIRTY(cb->enableClientState, bitID)) {
/* update vertex array enable/disable flags */
glAble able[2];
- able[0] = diff_api.Disable;
- able[1] = diff_api.Enable;
+ able[0] = diff_api.DisableClientState;
+ able[1] = diff_api.EnableClientState;
if (from->array.v.enabled != to->array.v.enabled) {
able[to->array.v.enabled](GL_VERTEX_ARRAY);
FILLDIRTY(cb->enableClientState);
@@ -2038,7 +2222,7 @@ crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,
if (from->array.a[i].enabled != to->array.a[i].enabled) {
if (to->array.a[i].enabled)
diff_api.EnableVertexAttribArrayARB(i);
- else
+ else
diff_api.DisableVertexAttribArrayARB(i);
FILLDIRTY(cb->enableClientState);
FILLDIRTY(cb->dirty);
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c
index d46a9561..c8e616d2 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c
@@ -8,6 +8,8 @@
#include "cr_error.h"
#include "cr_mem.h"
#include "cr_pixeldata.h"
+#include <iprt/err.h>
+#include <stdio.h>
void crStateDiffContext( CRContext *from, CRContext *to )
{
@@ -121,12 +123,165 @@ void crStateDiffContext( CRContext *from, CRContext *to )
}
}
-void crStateApplyFBImage(CRContext *to)
+void crStateFreeFBImageLegacy(CRContext *to)
+{
+ if (to->buffer.pFrontImg)
+ {
+ crFree(to->buffer.pFrontImg);
+ to->buffer.pFrontImg = NULL;
+ }
+ if (to->buffer.pBackImg)
+ {
+ crFree(to->buffer.pBackImg);
+ to->buffer.pBackImg = NULL;
+ }
+
+ to->buffer.storedWidth = 0;
+ to->buffer.storedHeight = 0;
+}
+
+int crStateAcquireFBImage(CRContext *to, CRFBData *data)
+{
+ CRBufferState *pBuf = &to->buffer;
+ CRPixelPackState packing = to->client.pack;
+ uint32_t i;
+
+ diff_api.PixelStorei(GL_PACK_SKIP_ROWS, 0);
+ diff_api.PixelStorei(GL_PACK_SKIP_PIXELS, 0);
+ diff_api.PixelStorei(GL_PACK_ALIGNMENT, 1);
+ diff_api.PixelStorei(GL_PACK_ROW_LENGTH, 0);
+ diff_api.PixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
+ diff_api.PixelStorei(GL_PACK_SKIP_IMAGES, 0);
+ diff_api.PixelStorei(GL_PACK_SWAP_BYTES, 0);
+ diff_api.PixelStorei(GL_PACK_LSB_FIRST, 0);
+
+ if (to->bufferobject.packBuffer->hwid>0)
+ {
+ diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
+ }
+
+ for (i = 0; i < data->cElements; ++i)
+ {
+ CRFBDataElement *el = &data->aElements[i];
+
+ if (el->enmFormat == GL_DEPTH_COMPONENT || el->enmFormat == GL_DEPTH_STENCIL)
+ {
+ if (!to->buffer.depthTest)
+ {
+ diff_api.Enable(GL_DEPTH_TEST);
+ }
+ if (to->pixel.depthScale != 1.0f)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_SCALE, 1.0f);
+ }
+ if (to->pixel.depthBias != 0.0f)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_BIAS, 0.0f);
+ }
+ }
+ if (el->enmFormat == GL_STENCIL_INDEX || el->enmFormat == GL_DEPTH_STENCIL)
+ {
+ if (!to->stencil.stencilTest)
+ {
+ diff_api.Enable(GL_STENCIL_TEST);
+ }
+ if (to->pixel.mapStencil)
+ {
+ diff_api.PixelTransferi (GL_MAP_STENCIL, GL_FALSE);
+ }
+ if (to->pixel.indexOffset)
+ {
+ diff_api.PixelTransferi (GL_INDEX_OFFSET, 0);
+ }
+ if (to->pixel.indexShift)
+ {
+ diff_api.PixelTransferi (GL_INDEX_SHIFT, 0);
+ }
+ }
+
+ diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, el->idFBO);
+
+ if (el->enmBuffer)
+ diff_api.ReadBuffer(el->enmBuffer);
+
+ diff_api.ReadPixels(el->posX, el->posY, el->width, el->height, el->enmFormat, el->enmType, el->pvData);
+ crDebug("Acquired %d;%d;%d;%d;%d;0x%p fb image", el->enmBuffer, el->width, el->height, el->enmFormat, el->enmType, el->pvData);
+
+ if (el->enmFormat == GL_DEPTH_COMPONENT || el->enmFormat == GL_DEPTH_STENCIL)
+ {
+ if (to->pixel.depthScale != 1.0f)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_SCALE, to->pixel.depthScale);
+ }
+ if (to->pixel.depthBias != 0.0f)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_BIAS, to->pixel.depthBias);
+ }
+ if (!to->buffer.depthTest)
+ {
+ diff_api.Disable(GL_DEPTH_TEST);
+ }
+ }
+ if (el->enmFormat == GL_STENCIL_INDEX || el->enmFormat == GL_DEPTH_STENCIL)
+ {
+ if (to->pixel.indexOffset)
+ {
+ diff_api.PixelTransferi (GL_INDEX_OFFSET, to->pixel.indexOffset);
+ }
+ if (to->pixel.indexShift)
+ {
+ diff_api.PixelTransferi (GL_INDEX_SHIFT, to->pixel.indexShift);
+ }
+ if (to->pixel.mapStencil)
+ {
+ diff_api.PixelTransferi (GL_MAP_STENCIL, GL_TRUE);
+ }
+ if (!to->stencil.stencilTest)
+ {
+ diff_api.Disable(GL_STENCIL_TEST);
+ }
+ }
+ }
+
+ if (to->bufferobject.packBuffer->hwid>0)
+ {
+ diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, to->bufferobject.packBuffer->hwid);
+ }
+ if (to->framebufferobject.readFB)
+ {
+ CRASSERT(to->framebufferobject.readFB->hwid);
+ diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, to->framebufferobject.readFB->hwid);
+ diff_api.ReadBuffer(to->framebufferobject.readFB->readbuffer);
+
+ }
+ else if (data->idOverrrideFBO)
+ {
+ diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, data->idOverrrideFBO);
+ diff_api.ReadBuffer(GL_COLOR_ATTACHMENT0);
+ }
+ else
+ {
+ diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
+ diff_api.ReadBuffer(to->buffer.readBuffer);
+ }
+
+ diff_api.PixelStorei(GL_PACK_SKIP_ROWS, packing.skipRows);
+ diff_api.PixelStorei(GL_PACK_SKIP_PIXELS, packing.skipPixels);
+ diff_api.PixelStorei(GL_PACK_ALIGNMENT, packing.alignment);
+ diff_api.PixelStorei(GL_PACK_ROW_LENGTH, packing.rowLength);
+ diff_api.PixelStorei(GL_PACK_IMAGE_HEIGHT, packing.imageHeight);
+ diff_api.PixelStorei(GL_PACK_SKIP_IMAGES, packing.skipImages);
+ diff_api.PixelStorei(GL_PACK_SWAP_BYTES, packing.swapBytes);
+ diff_api.PixelStorei(GL_PACK_LSB_FIRST, packing.psLSBFirst);
+ return VINF_SUCCESS;
+}
+
+void crStateApplyFBImage(CRContext *to, CRFBData *data)
{
- if (to->buffer.pFrontImg || to->buffer.pBackImg)
{
CRBufferState *pBuf = &to->buffer;
CRPixelPackState unpack = to->client.unpack;
+ uint32_t i;
diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
@@ -137,11 +292,6 @@ void crStateApplyFBImage(CRContext *to)
diff_api.PixelStorei(GL_UNPACK_SWAP_BYTES, 0);
diff_api.PixelStorei(GL_UNPACK_LSB_FIRST, 0);
- if (to->framebufferobject.drawFB)
- {
- diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
- }
-
if (to->bufferobject.unpackBuffer->hwid>0)
{
diff_api.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
@@ -151,25 +301,84 @@ void crStateApplyFBImage(CRContext *to)
diff_api.Disable(GL_SCISSOR_TEST);
diff_api.Disable(GL_BLEND);
diff_api.Disable(GL_COLOR_LOGIC_OP);
+ diff_api.Disable(GL_DEPTH_TEST);
+ diff_api.Disable(GL_STENCIL_TEST);
- if (pBuf->pFrontImg)
+ for (i = 0; i < data->cElements; ++i)
{
- diff_api.DrawBuffer(GL_FRONT);
- diff_api.WindowPos2iARB(0, 0);
- diff_api.DrawPixels(pBuf->storedWidth, pBuf->storedHeight, GL_RGBA, GL_UNSIGNED_BYTE, pBuf->pFrontImg);
- crDebug("Applied %ix%i fb image", pBuf->storedWidth, pBuf->storedHeight);
- crFree(pBuf->pFrontImg);
- pBuf->pFrontImg = NULL;
- }
+ CRFBDataElement *el = &data->aElements[i];
+#if 0
+ char fname[200];
+ sprintf(fname, "./img_apply_%p_%d_%d.tga", to, i, el->enmFormat);
+ crDumpNamedTGA(fname, el->width, el->height, el->pvData);
+#endif
- if (pBuf->pBackImg)
- {
- diff_api.DrawBuffer(GL_BACK);
- diff_api.WindowPos2iARB(0, 0);
- diff_api.DrawPixels(pBuf->storedWidth, pBuf->storedHeight, GL_RGBA, GL_UNSIGNED_BYTE, pBuf->pBackImg);
- crDebug("Applied %ix%i bb image", pBuf->storedWidth, pBuf->storedHeight);
- crFree(pBuf->pBackImg);
- pBuf->pBackImg = NULL;
+ if (el->enmFormat == GL_DEPTH_COMPONENT || el->enmFormat == GL_DEPTH_STENCIL)
+ {
+ diff_api.Enable(GL_DEPTH_TEST);
+ if (to->pixel.depthScale != 1.0f)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_SCALE, 1.0f);
+ }
+ if (to->pixel.depthBias != 0.0f)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_BIAS, 0.0f);
+ }
+ }
+ if (el->enmFormat == GL_STENCIL_INDEX || el->enmFormat == GL_DEPTH_STENCIL)
+ {
+ diff_api.Enable(GL_STENCIL_TEST);
+ if (to->pixel.mapStencil)
+ {
+ diff_api.PixelTransferi (GL_MAP_STENCIL, GL_FALSE);
+ }
+ if (to->pixel.indexOffset)
+ {
+ diff_api.PixelTransferi (GL_INDEX_OFFSET, 0);
+ }
+ if (to->pixel.indexShift)
+ {
+ diff_api.PixelTransferi (GL_INDEX_SHIFT, 0);
+ }
+ }
+
+ diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, el->idFBO);
+
+ if (el->enmBuffer)
+ diff_api.DrawBuffer(el->enmBuffer);
+
+ diff_api.WindowPos2iARB(el->posX, el->posY);
+ diff_api.DrawPixels(el->width, el->height, el->enmFormat, el->enmType, el->pvData);
+ crDebug("Applied %d;%d;%d;%d;%d;0x%p fb image", el->enmBuffer, el->width, el->height, el->enmFormat, el->enmType, el->pvData);
+
+ if (el->enmFormat == GL_DEPTH_COMPONENT || el->enmFormat == GL_DEPTH_STENCIL)
+ {
+ if (to->pixel.depthScale != 1.0f)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_SCALE, to->pixel.depthScale);
+ }
+ if (to->pixel.depthBias != 0.0f)
+ {
+ diff_api.PixelTransferf (GL_DEPTH_BIAS, to->pixel.depthBias);
+ }
+ diff_api.Disable(GL_DEPTH_TEST);
+ }
+ if (el->enmFormat == GL_STENCIL_INDEX || el->enmFormat == GL_DEPTH_STENCIL)
+ {
+ if (to->pixel.indexOffset)
+ {
+ diff_api.PixelTransferi (GL_INDEX_OFFSET, to->pixel.indexOffset);
+ }
+ if (to->pixel.indexShift)
+ {
+ diff_api.PixelTransferi (GL_INDEX_SHIFT, to->pixel.indexShift);
+ }
+ if (to->pixel.mapStencil)
+ {
+ diff_api.PixelTransferi (GL_MAP_STENCIL, GL_TRUE);
+ }
+ diff_api.Disable(GL_STENCIL_TEST);
+ }
}
diff_api.WindowPos3fvARB(to->current.rasterAttrib[VERT_ATTRIB_POS]);
@@ -179,10 +388,20 @@ void crStateApplyFBImage(CRContext *to)
}
if (to->framebufferobject.drawFB)
{
+ CRASSERT(to->framebufferobject.drawFB->hwid);
diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, to->framebufferobject.drawFB->hwid);
+ diff_api.DrawBuffer(to->framebufferobject.drawFB->drawbuffer[0]);
+ }
+ else if (data->idOverrrideFBO)
+ {
+ diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, data->idOverrrideFBO);
+ diff_api.DrawBuffer(GL_COLOR_ATTACHMENT0);
+ }
+ else
+ {
+ diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
+ diff_api.DrawBuffer(to->buffer.drawBuffer);
}
- diff_api.DrawBuffer(to->framebufferobject.drawFB ?
- to->framebufferobject.drawFB->drawbuffer[0] : to->buffer.drawBuffer);
if (to->buffer.alphaTest)
{
diff_api.Enable(GL_ALPHA_TEST);
@@ -199,6 +418,14 @@ void crStateApplyFBImage(CRContext *to)
{
diff_api.Enable(GL_COLOR_LOGIC_OP);
}
+ if (to->buffer.depthTest)
+ {
+ diff_api.Enable(GL_DEPTH_TEST);
+ }
+ if (to->stencil.stencilTest)
+ {
+ diff_api.Enable(GL_STENCIL_TEST);
+ }
diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, unpack.skipRows);
diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, unpack.skipPixels);
@@ -341,34 +568,59 @@ void crStateSwitchContext( CRContext *from, CRContext *to )
}
#ifdef WINDOWS
- crStateApplyFBImage(to);
+ if (to->buffer.pFrontImg)
+ {
+ CRFBData *pLazyData = (CRFBData *)to->buffer.pFrontImg;
+ crStateApplyFBImage(to, pLazyData);
+ crStateFreeFBImageLegacy(to);
+ }
#endif
}
-CRContext * crStateSwichPrepare(CRContext *toCtx, GLboolean fMultipleContexts, GLuint idFBO)
+void crStateSyncHWErrorState(CRContext *ctx)
{
- CRContext *fromCtx = GetCurrentContext();
-
- if (!fMultipleContexts)
+ GLenum err;
+ while ((err = diff_api.GetError()) != GL_NO_ERROR)
{
+ if (ctx->error != GL_NO_ERROR)
+ ctx->error = err;
+ }
+}
+
+void crStateSwitchPrepare(CRContext *toCtx, CRContext *fromCtx, GLuint idDrawFBO, GLuint idReadFBO)
+{
+ if (!fromCtx)
+ return;
+
+ if (g_bVBoxEnableDiffOnMakeCurrent && toCtx && toCtx != fromCtx)
+ crStateSyncHWErrorState(fromCtx);
+
#ifdef CR_EXT_framebuffer_object
- if (fromCtx)
- crStateFramebufferObjectDisableHW(fromCtx, idFBO);
+ crStateFramebufferObjectDisableHW(fromCtx, idDrawFBO, idReadFBO);
#endif
- }
- return fromCtx;
}
-void crStateSwichPostprocess(CRContext *fromCtx, GLboolean fMultipleContexts, GLuint idFBO)
+void crStateSwitchPostprocess(CRContext *toCtx, CRContext *fromCtx, GLuint idDrawFBO, GLuint idReadFBO)
{
- CRContext *toCtx = GetCurrentContext();;
- if (!fromCtx || !toCtx)
+ if (!toCtx)
return;
- if (!fMultipleContexts)
+ if (g_bVBoxEnableDiffOnMakeCurrent && fromCtx && toCtx != fromCtx)
{
-#ifdef CR_EXT_framebuffer_object
- crStateFramebufferObjectReenableHW(fromCtx, toCtx, idFBO);
+ GLenum err;
+ while ((err = diff_api.GetError()) != GL_NO_ERROR)
+ {
+ static int cErrPrints = 0;
+#ifndef DEBUG_misha
+ if (cErrPrints < 5)
#endif
+ {
+ ++cErrPrints;
+ crWarning("gl error (0x%x) after context switch, ignoring.. (%d out of 5) ..", err, cErrPrints);
+ }
+ }
}
+#ifdef CR_EXT_framebuffer_object
+ crStateFramebufferObjectReenableHW(fromCtx, toCtx, idDrawFBO, idReadFBO);
+#endif
}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_enable.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_enable.c
index 75a1534d..185de9eb 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_enable.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_enable.c
@@ -496,6 +496,13 @@ static void __enableSet (CRContext *g, CRStateBits *sb, CRbitvalue *neg_bitid,
else
crStateDisableClientState(cap);
break;
+#ifdef CR_EXT_stencil_two_side
+ case GL_STENCIL_TEST_TWO_SIDE_EXT:
+ g->stencil.stencilTwoSideEXT= val;
+ DIRTY(sb->stencil.enableTwoSideEXT, neg_bitid);
+ DIRTY(sb->stencil.dirty, neg_bitid);
+ break;
+#endif
default:
crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable called with bogus cap: 0x%x", cap);
return;
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_error.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_error.c
index 60eaa457..07a7b494 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_error.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_error.c
@@ -18,9 +18,14 @@ void crStateError( int line, const char *file, GLenum error, const char *format,
char errstr[8096];
va_list args;
- g->error = error;
+ CRASSERT(error != GL_NO_ERROR);
+ if (g->error == GL_NO_ERROR)
+ g->error = error;
+
+#ifndef DEBUG_misha
if (crGetenv("CR_DEBUG"))
+#endif
{
char *glerr;
va_start( args, format );
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c
index cdd3cecd..2f150361 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -22,12 +22,6 @@
#include "state_internals.h"
#include "cr_mem.h"
-#define CRSTATE_FBO_CHECKERR(expr, result, message) \
- if (expr) { \
- crStateError(__LINE__, __FILE__, result, message); \
- return; \
- }
-
DECLEXPORT(void) STATE_APIENTRY
crStateFramebufferObjectInit(CRContext *ctx)
{
@@ -39,6 +33,82 @@ crStateFramebufferObjectInit(CRContext *ctx)
ctx->shared->bFBOResyncNeeded = GL_FALSE;
}
+void STATE_APIENTRY crStateGenFramebuffersEXT(GLsizei n, GLuint *buffers)
+{
+ CRContext *g = GetCurrentContext();
+ crStateGenNames(g, g->shared->fbTable, n, buffers);
+}
+
+void STATE_APIENTRY crStateGenRenderbuffersEXT(GLsizei n, GLuint *buffers)
+{
+ CRContext *g = GetCurrentContext();
+ crStateGenNames(g, g->shared->rbTable, n, buffers);
+}
+
+void crStateRegFramebuffers(GLsizei n, GLuint *buffers)
+{
+ CRContext *g = GetCurrentContext();
+ crStateRegNames(g, g->shared->fbTable, n, buffers);
+}
+
+void crStateRegRenderbuffers(GLsizei n, GLuint *buffers)
+{
+ CRContext *g = GetCurrentContext();
+ crStateRegNames(g, g->shared->rbTable, n, buffers);
+}
+
+static void crStateInitFrameBuffer(CRFramebufferObject *fbo);
+
+static CRFramebufferObject *
+crStateFramebufferAllocate(CRContext *ctx, GLuint name)
+{
+ CRFramebufferObject *buffer = (CRFramebufferObject*) crCalloc(sizeof(CRFramebufferObject));
+ CRSTATE_CHECKERR_RET(!buffer, GL_OUT_OF_MEMORY, "crStateFramebufferAllocate", NULL);
+ buffer->id = name;
+#ifndef IN_GUEST
+ diff_api.GenFramebuffersEXT(1, &buffer->hwid);
+ if (!buffer->hwid)
+ {
+ crWarning("GenFramebuffersEXT failed!");
+ crFree(buffer);
+ return NULL;
+ }
+#else
+ buffer->hwid = name;
+#endif
+
+ crStateInitFrameBuffer(buffer);
+ crHashtableAdd(ctx->shared->fbTable, name, buffer);
+ CR_STATE_SHAREDOBJ_USAGE_INIT(buffer);
+
+ return buffer;
+}
+
+static CRRenderbufferObject *
+crStateRenderbufferAllocate(CRContext *ctx, GLuint name)
+{
+ CRRenderbufferObject *buffer = (CRRenderbufferObject*) crCalloc(sizeof(CRRenderbufferObject));
+ CRSTATE_CHECKERR_RET(!buffer, GL_OUT_OF_MEMORY, "crStateRenderbufferAllocate", NULL);
+ buffer->id = name;
+#ifndef IN_GUEST
+ diff_api.GenRenderbuffersEXT(1, &buffer->hwid);
+ if (!buffer->hwid)
+ {
+ crWarning("GenRenderbuffersEXT failed!");
+ crFree(buffer);
+ return NULL;
+ }
+#else
+ buffer->hwid = name;
+#endif
+
+ buffer->internalformat = GL_RGBA;
+ crHashtableAdd(ctx->shared->rbTable, name, buffer);
+ CR_STATE_SHAREDOBJ_USAGE_INIT(buffer);
+
+ return buffer;
+}
+
void crStateFreeFBO(void *data)
{
CRFramebufferObject *pObj = (CRFramebufferObject *)data;
@@ -83,28 +153,18 @@ crStateBindRenderbufferEXT(GLenum target, GLuint renderbuffer)
CRContext *g = GetCurrentContext();
CRFramebufferObjectState *fbo = &g->framebufferobject;
- CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
- CRSTATE_FBO_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
+ CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
+ CRSTATE_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
if (renderbuffer)
{
fbo->renderbuffer = (CRRenderbufferObject*) crHashtableSearch(g->shared->rbTable, renderbuffer);
if (!fbo->renderbuffer)
{
- fbo->renderbuffer = (CRRenderbufferObject*) crCalloc(sizeof(CRRenderbufferObject));
- CRSTATE_FBO_CHECKERR(!fbo->renderbuffer, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT");
- fbo->renderbuffer->id = renderbuffer;
- fbo->renderbuffer->hwid = renderbuffer;
- fbo->renderbuffer->internalformat = GL_RGBA;
- crHashtableAdd(g->shared->rbTable, renderbuffer, fbo->renderbuffer);
-#ifndef IN_GUEST
- CR_STATE_SHAREDOBJ_USAGE_INIT(fbo->renderbuffer);
-#endif
+ CRSTATE_CHECKERR(!crHashtableIsKeyUsed(g->shared->rbTable, renderbuffer), GL_INVALID_OPERATION, "name is not a renderbuffer");
+ fbo->renderbuffer = crStateRenderbufferAllocate(g, renderbuffer);
}
-#ifndef IN_GUEST
CR_STATE_SHAREDOBJ_USAGE_SET(fbo->renderbuffer, g);
-#endif
-
}
else fbo->renderbuffer = NULL;
}
@@ -147,6 +207,22 @@ static void crStateCheckFBOAttachments(CRFramebufferObject *pFBO, GLuint rbo, GL
}
}
+static void ctStateRenderbufferRefsCleanup(CRContext *g, GLuint fboId, CRRenderbufferObject *rbo)
+{
+ CRFramebufferObjectState *fbo = &g->framebufferobject;
+
+ if (fbo->renderbuffer==rbo)
+ {
+ fbo->renderbuffer = NULL;
+ }
+
+ /* check the attachments of current framebuffers */
+ crStateCheckFBOAttachments(fbo->readFB, fboId, GL_READ_FRAMEBUFFER);
+ crStateCheckFBOAttachments(fbo->drawFB, fboId, GL_DRAW_FRAMEBUFFER);
+
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(rbo, g);
+}
+
DECLEXPORT(void) STATE_APIENTRY
crStateDeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
{
@@ -154,8 +230,8 @@ crStateDeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
CRFramebufferObjectState *fbo = &g->framebufferobject;
int i;
- CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
- CRSTATE_FBO_CHECKERR(n<0, GL_INVALID_OPERATION, "n<0");
+ CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
+ CRSTATE_CHECKERR(n<0, GL_INVALID_OPERATION, "n<0");
for (i = 0; i < n; i++)
{
@@ -165,15 +241,29 @@ crStateDeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
rbo = (CRRenderbufferObject*) crHashtableSearch(g->shared->rbTable, renderbuffers[i]);
if (rbo)
{
- if (fbo->renderbuffer==rbo)
+ int j;
+
+ ctStateRenderbufferRefsCleanup(g, renderbuffers[i], rbo);
+ CR_STATE_SHAREDOBJ_USAGE_FOREACH_USED_IDX(rbo, j)
{
- fbo->renderbuffer = NULL;
+ /* saved state version <= SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS does not have usage bits info,
+ * so on restore, we set mark bits as used.
+ * This is why g_pAvailableContexts[j] could be NULL
+ * also g_pAvailableContexts[0] will hold default context, which we should discard */
+ CRContext *ctx = g_pAvailableContexts[j];
+ if (j && ctx)
+ {
+ CRFramebufferObjectState *ctxFbo;
+ CRASSERT(ctx);
+ ctxFbo = &ctx->framebufferobject;
+ if (ctxFbo->renderbuffer==rbo)
+ crWarning("deleting RBO being used by another context %d", ctx->id);
+
+ ctStateRenderbufferRefsCleanup(ctx, renderbuffers[i], rbo);
+ }
+ else
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR_IDX(rbo, j);
}
-
- /* check the attachments of current framebuffers */
- crStateCheckFBOAttachments(fbo->readFB, renderbuffers[i], GL_READ_FRAMEBUFFER);
- crStateCheckFBOAttachments(fbo->drawFB, renderbuffers[i], GL_DRAW_FRAMEBUFFER);
-
crHashtableDelete(g->shared->rbTable, renderbuffers[i], crStateFreeRBO);
}
}
@@ -187,9 +277,9 @@ crStateRenderbufferStorageEXT(GLenum target, GLenum internalformat, GLsizei widt
CRFramebufferObjectState *fbo = &g->framebufferobject;
CRRenderbufferObject *rb = fbo->renderbuffer;
- CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
- CRSTATE_FBO_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
- CRSTATE_FBO_CHECKERR(!rb, GL_INVALID_OPERATION, "no bound renderbuffer");
+ CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
+ CRSTATE_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
+ CRSTATE_CHECKERR(!rb, GL_INVALID_OPERATION, "no bound renderbuffer");
rb->width = width;
rb->height = height;
@@ -203,9 +293,9 @@ crStateGetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
CRFramebufferObjectState *fbo = &g->framebufferobject;
CRRenderbufferObject *rb = fbo->renderbuffer;
- CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
- CRSTATE_FBO_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
- CRSTATE_FBO_CHECKERR(!rb, GL_INVALID_OPERATION, "no bound renderbuffer");
+ CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
+ CRSTATE_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
+ CRSTATE_CHECKERR(!rb, GL_INVALID_OPERATION, "no bound renderbuffer");
switch (pname)
{
@@ -224,10 +314,10 @@ crStateGetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
- CRSTATE_FBO_CHECKERR(GL_TRUE, GL_INVALID_OPERATION, "unimplemented");
+ CRSTATE_CHECKERR(GL_TRUE, GL_INVALID_OPERATION, "unimplemented");
break;
default:
- CRSTATE_FBO_CHECKERR(GL_TRUE, GL_INVALID_ENUM, "invalid pname");
+ CRSTATE_CHECKERR(GL_TRUE, GL_INVALID_ENUM, "invalid pname");
}
}
@@ -286,8 +376,8 @@ crStateBindFramebufferEXT(GLenum target, GLuint framebuffer)
CRFramebufferObjectState *fbo = &g->framebufferobject;
CRFramebufferObject *pFBO=NULL;
- CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
- CRSTATE_FBO_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
+ CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
+ CRSTATE_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
GL_INVALID_ENUM, "invalid target");
if (framebuffer)
@@ -295,20 +385,12 @@ crStateBindFramebufferEXT(GLenum target, GLuint framebuffer)
pFBO = (CRFramebufferObject*) crHashtableSearch(g->shared->fbTable, framebuffer);
if (!pFBO)
{
- pFBO = (CRFramebufferObject*) crCalloc(sizeof(CRFramebufferObject));
- CRSTATE_FBO_CHECKERR(!pFBO, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
- pFBO->id = framebuffer;
- pFBO->hwid = framebuffer;
- crStateInitFrameBuffer(pFBO);
- crHashtableAdd(g->shared->fbTable, framebuffer, pFBO);
-#ifndef IN_GUEST
- CR_STATE_SHAREDOBJ_USAGE_INIT(pFBO);
-#endif
+ CRSTATE_CHECKERR(!crHashtableIsKeyUsed(g->shared->fbTable, framebuffer), GL_INVALID_OPERATION, "name is not a framebuffer");
+ pFBO = crStateFramebufferAllocate(g, framebuffer);
}
-#ifndef IN_GUEST
+
CR_STATE_SHAREDOBJ_USAGE_SET(pFBO, g);
-#endif
}
/* @todo: http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
@@ -331,15 +413,29 @@ crStateBindFramebufferEXT(GLenum target, GLuint framebuffer)
}
}
+static void ctStateFramebufferRefsCleanup(CRContext *g, CRFramebufferObject *fb)
+{
+ CRFramebufferObjectState *fbo = &g->framebufferobject;
+ if (fbo->readFB==fb)
+ {
+ fbo->readFB = NULL;
+ }
+ if (fbo->drawFB==fb)
+ {
+ fbo->drawFB = NULL;
+ }
+
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(fb, g);
+}
+
DECLEXPORT(void) STATE_APIENTRY
crStateDeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
{
CRContext *g = GetCurrentContext();
- CRFramebufferObjectState *fbo = &g->framebufferobject;
int i;
- CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
- CRSTATE_FBO_CHECKERR(n<0, GL_INVALID_OPERATION, "n<0");
+ CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
+ CRSTATE_CHECKERR(n<0, GL_INVALID_OPERATION, "n<0");
for (i = 0; i < n; i++)
{
@@ -349,13 +445,32 @@ crStateDeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
fb = (CRFramebufferObject*) crHashtableSearch(g->shared->fbTable, framebuffers[i]);
if (fb)
{
- if (fbo->readFB==fb)
- {
- fbo->readFB = NULL;
- }
- if (fbo->drawFB==fb)
+ int j;
+
+ ctStateFramebufferRefsCleanup(g, fb);
+
+ CR_STATE_SHAREDOBJ_USAGE_FOREACH_USED_IDX(fb, j)
{
- fbo->drawFB = NULL;
+ /* saved state version <= SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS does not have usage bits info,
+ * so on restore, we set mark bits as used.
+ * This is why g_pAvailableContexts[j] could be NULL
+ * also g_pAvailableContexts[0] will hold default context, which we should discard */
+ CRContext *ctx = g_pAvailableContexts[j];
+ if (j && ctx)
+ {
+ CRFramebufferObjectState *ctxFbo;
+ CRASSERT(ctx);
+ ctxFbo = &ctx->framebufferobject;
+ if (ctxFbo->readFB==fb)
+ crWarning("deleting FBO being used as read buffer by another context %d", ctx->id);
+
+ if (ctxFbo->drawFB==fb)
+ crWarning("deleting FBO being used as draw buffer by another context %d", ctx->id);
+
+ ctStateFramebufferRefsCleanup(ctx, fb);
+ }
+ else
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR_IDX(fb, j);
}
crHashtableDelete(g->shared->fbTable, framebuffers[i], crStateFreeFBO);
}
@@ -380,27 +495,72 @@ unsigned int crLog2Floor(unsigned int x)
return (x & 0x0000003f) - 1;
}
-static void crStateFramebufferTextureCheck(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level,
- GLboolean *failed, CRFBOAttachmentPoint **ap, CRTextureObj **tobj)
+static GLuint crStateFramebufferGet(CRFramebufferObjectState *fbo, GLenum target, CRFramebufferObject **apFBOs)
+{
+ GLuint cPBOs = 0;
+ switch (target)
+ {
+ case GL_READ_FRAMEBUFFER:
+ cPBOs = 1;
+ apFBOs[0] = fbo->readFB;
+ break;
+ case GL_DRAW_FRAMEBUFFER:
+ cPBOs = 1;
+ apFBOs[0] = fbo->drawFB;
+ break;
+ case GL_FRAMEBUFFER:
+ if (fbo->readFB == fbo->drawFB)
+ {
+ cPBOs = 1;
+ apFBOs[0] = fbo->readFB;
+ }
+ else
+ {
+ cPBOs = 2;
+ apFBOs[0] = fbo->readFB;
+ apFBOs[1] = fbo->drawFB;
+ }
+ break;
+ default:
+ crWarning("unexpected target value: 0x%x", target);
+ cPBOs = 0;
+ break;
+ }
+
+ return cPBOs;
+}
+
+static GLuint crStateFramebufferTextureCheck(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level,
+ CRFBOAttachmentPoint **aap, CRTextureObj **tobj)
{
CRContext *g = GetCurrentContext();
CRFramebufferObjectState *fbo = &g->framebufferobject;
- CRFramebufferObject *pFBO;
+ CRFramebufferObject *apFBOs[2];
+ GLuint cFBOs = 0, i;
GLuint maxtexsizelog2;
- *failed = GL_TRUE;
+ CRSTATE_CHECKERR_RET(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end", 0);
+ CRSTATE_CHECKERR_RET(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
+ GL_INVALID_ENUM, "invalid target", 0);
- CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
- CRSTATE_FBO_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
- GL_INVALID_ENUM, "invalid target");
- pFBO = GL_READ_FRAMEBUFFER==target ? fbo->readFB : fbo->drawFB;
- CRSTATE_FBO_CHECKERR(!pFBO, GL_INVALID_OPERATION, "no fbo bound");
- CRSTATE_FBO_CHECKERR(!crStateGetFBOAttachmentPoint(pFBO, attachment, ap), GL_INVALID_ENUM, "invalid attachment");
+ cFBOs = crStateFramebufferGet(fbo, target, apFBOs);
+ CRSTATE_CHECKERR_RET(!cFBOs, GL_INVALID_ENUM, "unexpected target", 0);
+ for (i = 0; i < cFBOs; ++i)
+ {
+ CRSTATE_CHECKERR_RET(!apFBOs[i], GL_INVALID_OPERATION, "zero fbo bound", 0);
+ }
+
+ Assert(cFBOs);
+ Assert(cFBOs <= 2);
+
+ for (i = 0; i < cFBOs; ++i)
+ {
+ CRSTATE_CHECKERR_RET(!crStateGetFBOAttachmentPoint(apFBOs[i], attachment, &aap[i]), GL_INVALID_ENUM, "invalid attachment", 0);
+ }
if (!texture)
{
- *failed = GL_FALSE;
- return;
+ return cFBOs;
}
switch (textarget)
@@ -428,27 +588,33 @@ static void crStateFramebufferTextureCheck(GLenum target, GLenum attachment, GLe
*tobj = crStateTextureGet(textarget, texture);
break;
default:
- CRSTATE_FBO_CHECKERR(GL_TRUE, GL_INVALID_OPERATION, "invalid textarget");
+ CRSTATE_CHECKERR_RET(GL_TRUE, GL_INVALID_OPERATION, "invalid textarget", 0);
}
- CRSTATE_FBO_CHECKERR(!*tobj, GL_INVALID_OPERATION, "invalid textarget/texture combo");
+ CRSTATE_CHECKERR_RET(!*tobj, GL_INVALID_OPERATION, "invalid textarget/texture combo", 0);
if (GL_TEXTURE_RECTANGLE_ARB==textarget)
{
- CRSTATE_FBO_CHECKERR(level!=0, GL_INVALID_VALUE, "non zero mipmap level");
+ CRSTATE_CHECKERR_RET(level!=0, GL_INVALID_VALUE, "non zero mipmap level", 0);
}
- CRSTATE_FBO_CHECKERR(level<0, GL_INVALID_VALUE, "level<0");
- CRSTATE_FBO_CHECKERR(level>maxtexsizelog2, GL_INVALID_VALUE, "level too big");
-
- *failed = GL_FALSE;
+ CRSTATE_CHECKERR_RET(level<0, GL_INVALID_VALUE, "level<0", 0);
+ CRSTATE_CHECKERR_RET(level>maxtexsizelog2, GL_INVALID_VALUE, "level too big", 0);
#ifdef IN_GUEST
- if ((*ap)->type!=GL_TEXTURE || (*ap)->name!=texture || (*ap)->level!=level)
+ for (i = 0; i < cFBOs; ++i)
{
- pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
+ if ((aap[i])->type!=GL_TEXTURE || (aap[i])->name!=texture || (aap[i])->level!=level)
+ {
+ apFBOs[i]->status = GL_FRAMEBUFFER_UNDEFINED;
+ }
}
#endif
+
+ Assert(cFBOs);
+ Assert(cFBOs <= 2);
+
+ return cFBOs;
}
DECLEXPORT(void) STATE_APIENTRY
@@ -456,29 +622,33 @@ crStateFramebufferTexture1DEXT(GLenum target, GLenum attachment, GLenum textarge
{
CRContext *g = GetCurrentContext();
CRFramebufferObjectState *fbo = &g->framebufferobject;
- CRFBOAttachmentPoint *ap;
+ CRFBOAttachmentPoint *aap[2];
+ GLuint cap, i;
CRTextureObj *tobj;
- GLboolean failed;
- crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, &failed, &ap, &tobj);
- if (failed) return;
+ cap = crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, aap, &tobj);
+ if (!cap) return;
if (!texture)
{
- crStateInitFBOAttachmentPoint(ap);
+ for (i = 0; i < cap; ++i)
+ {
+ crStateInitFBOAttachmentPoint(aap[i]);
+ }
return;
}
- CRSTATE_FBO_CHECKERR(textarget!=GL_TEXTURE_1D, GL_INVALID_OPERATION, "textarget");
+ CRSTATE_CHECKERR(textarget!=GL_TEXTURE_1D, GL_INVALID_OPERATION, "textarget");
-#ifndef IN_GUEST
CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g);
-#endif
- crStateInitFBOAttachmentPoint(ap);
- ap->type = GL_TEXTURE;
- ap->name = texture;
- ap->level = level;
+ for (i = 0; i < cap; ++i)
+ {
+ crStateInitFBOAttachmentPoint(aap[i]);
+ aap[i]->type = GL_TEXTURE;
+ aap[i]->name = texture;
+ aap[i]->level = level;
+ }
}
DECLEXPORT(void) STATE_APIENTRY
@@ -486,32 +656,36 @@ crStateFramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarge
{
CRContext *g = GetCurrentContext();
CRFramebufferObjectState *fbo = &g->framebufferobject;
- CRFBOAttachmentPoint *ap;
+ CRFBOAttachmentPoint *aap[2];
+ GLuint cap, i;
CRTextureObj *tobj;
- GLboolean failed;
- crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, &failed, &ap, &tobj);
- if (failed) return;
+ cap = crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, aap, &tobj);
+ if (!cap) return;
if (!texture)
{
- crStateInitFBOAttachmentPoint(ap);
+ for (i = 0; i < cap; ++i)
+ {
+ crStateInitFBOAttachmentPoint(aap[i]);
+ }
return;
}
- CRSTATE_FBO_CHECKERR(GL_TEXTURE_1D==textarget || GL_TEXTURE_3D==textarget, GL_INVALID_OPERATION, "textarget");
+ CRSTATE_CHECKERR(GL_TEXTURE_1D==textarget || GL_TEXTURE_3D==textarget, GL_INVALID_OPERATION, "textarget");
-#ifndef IN_GUEST
CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g);
-#endif
- crStateInitFBOAttachmentPoint(ap);
- ap->type = GL_TEXTURE;
- ap->name = texture;
- ap->level = level;
- if (textarget!=GL_TEXTURE_2D && textarget!=GL_TEXTURE_RECTANGLE_ARB)
+ for (i = 0; i < cap; ++i)
{
- ap->face = textarget;
+ crStateInitFBOAttachmentPoint(aap[i]);
+ aap[i]->type = GL_TEXTURE;
+ aap[i]->name = texture;
+ aap[i]->level = level;
+ if (textarget!=GL_TEXTURE_2D && textarget!=GL_TEXTURE_RECTANGLE_ARB)
+ {
+ aap[i]->face = textarget;
+ }
}
}
@@ -520,31 +694,35 @@ crStateFramebufferTexture3DEXT(GLenum target, GLenum attachment, GLenum textarge
{
CRContext *g = GetCurrentContext();
CRFramebufferObjectState *fbo = &g->framebufferobject;
- CRFBOAttachmentPoint *ap;
+ CRFBOAttachmentPoint *aap[2];
+ GLuint cap, i;
CRTextureObj *tobj;
- GLboolean failed;
- crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, &failed, &ap, &tobj);
- if (failed) return;
+ cap = crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, aap, &tobj);
+ if (!cap) return;
if (!texture)
{
- crStateInitFBOAttachmentPoint(ap);
+ for (i = 0; i < cap; ++i)
+ {
+ crStateInitFBOAttachmentPoint(aap[i]);
+ }
return;
}
- CRSTATE_FBO_CHECKERR(zoffset>(g->limits.max3DTextureSize-1), GL_INVALID_VALUE, "zoffset too big");
- CRSTATE_FBO_CHECKERR(textarget!=GL_TEXTURE_3D, GL_INVALID_OPERATION, "textarget");
+ CRSTATE_CHECKERR(zoffset>(g->limits.max3DTextureSize-1), GL_INVALID_VALUE, "zoffset too big");
+ CRSTATE_CHECKERR(textarget!=GL_TEXTURE_3D, GL_INVALID_OPERATION, "textarget");
-#ifndef IN_GUEST
CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g);
-#endif
- crStateInitFBOAttachmentPoint(ap);
- ap->type = GL_TEXTURE;
- ap->name = texture;
- ap->level = level;
- ap->zoffset = zoffset;
+ for (i = 0; i < cap; ++i)
+ {
+ crStateInitFBOAttachmentPoint(aap[i]);
+ aap[i]->type = GL_TEXTURE;
+ aap[i]->name = texture;
+ aap[i]->level = level;
+ aap[i]->zoffset = zoffset;
+ }
}
DECLEXPORT(void) STATE_APIENTRY
@@ -552,41 +730,62 @@ crStateFramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenum rende
{
CRContext *g = GetCurrentContext();
CRFramebufferObjectState *fbo = &g->framebufferobject;
- CRFramebufferObject *pFBO;
- CRFBOAttachmentPoint *ap;
+ CRFramebufferObject *apFBOs[2];
+ GLuint cFBOs, i;
+ CRFBOAttachmentPoint *aap[2];
CRRenderbufferObject *rb;
- CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
- CRSTATE_FBO_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
+ CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
+ CRSTATE_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
GL_INVALID_ENUM, "invalid target");
- pFBO = GL_READ_FRAMEBUFFER==target ? fbo->readFB : fbo->drawFB;
- CRSTATE_FBO_CHECKERR(!pFBO, GL_INVALID_OPERATION, "no fbo bound");
- CRSTATE_FBO_CHECKERR(!crStateGetFBOAttachmentPoint(pFBO, attachment, &ap), GL_INVALID_ENUM, "invalid attachment");
+ cFBOs = crStateFramebufferGet(fbo, target, apFBOs);
+ CRSTATE_CHECKERR(!cFBOs, GL_INVALID_OPERATION, "no fbo bound");
+ for (i = 0; i < cFBOs; ++i)
+ {
+ CRSTATE_CHECKERR(!apFBOs[i], GL_INVALID_OPERATION, "zero fbo bound");
+ }
+
+ for (i = 0; i < cFBOs; ++i)
+ {
+ CRSTATE_CHECKERR(!crStateGetFBOAttachmentPoint(apFBOs[i], attachment, &aap[i]), GL_INVALID_ENUM, "invalid attachment");
+ }
if (!renderbuffer)
{
-#ifdef IN_GUEST
- if (ap->type!=GL_NONE)
+ for (i = 0; i < cFBOs; ++i)
{
- pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
- }
+#ifdef IN_GUEST
+ if (&aap[i]->type!=GL_NONE)
+ {
+ apFBOs[i]->status = GL_FRAMEBUFFER_UNDEFINED;
+ }
#endif
- crStateInitFBOAttachmentPoint(ap);
+ crStateInitFBOAttachmentPoint(aap[i]);
+ }
return;
}
rb = (CRRenderbufferObject*) crHashtableSearch(g->shared->rbTable, renderbuffer);
- CRSTATE_FBO_CHECKERR(!rb, GL_INVALID_OPERATION, "rb doesn't exist");
+ if (!rb)
+ {
+ CRSTATE_CHECKERR(!crHashtableIsKeyUsed(g->shared->rbTable, renderbuffer), GL_INVALID_OPERATION, "rb doesn't exist");
+ rb = crStateRenderbufferAllocate(g, renderbuffer);
+ }
+ CR_STATE_SHAREDOBJ_USAGE_SET(rb, g);
+
+ for (i = 0; i < cFBOs; ++i)
+ {
#ifdef IN_GUEST
- if (ap->type!=GL_RENDERBUFFER_EXT || ap->name!=renderbuffer)
+ if (aap[i]->type!=GL_RENDERBUFFER_EXT || aap[i]->name!=renderbuffer)
{
- pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
+ apFBOs[i]->status = GL_FRAMEBUFFER_UNDEFINED;
}
#endif
- crStateInitFBOAttachmentPoint(ap);
- ap->type = GL_RENDERBUFFER_EXT;
- ap->name = renderbuffer;
+ crStateInitFBOAttachmentPoint(aap[i]);
+ aap[i]->type = GL_RENDERBUFFER_EXT;
+ aap[i]->name = renderbuffer;
+ }
}
DECLEXPORT(void) STATE_APIENTRY
@@ -594,40 +793,87 @@ crStateGetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
{
CRContext *g = GetCurrentContext();
CRFramebufferObjectState *fbo = &g->framebufferobject;
- CRFramebufferObject *pFBO;
+ CRFramebufferObject *apFBOs[2];
+ GLint cFBOs = 0, i;
CRFBOAttachmentPoint *ap;
- CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
- CRSTATE_FBO_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
+ CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
+ CRSTATE_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
GL_INVALID_ENUM, "invalid target");
- pFBO = GL_READ_FRAMEBUFFER==target ? fbo->readFB : fbo->drawFB;
- CRSTATE_FBO_CHECKERR(!pFBO, GL_INVALID_OPERATION, "no fbo bound");
- CRSTATE_FBO_CHECKERR(!crStateGetFBOAttachmentPoint(pFBO, attachment, &ap), GL_INVALID_ENUM, "invalid attachment");
- switch (pname)
+ cFBOs = crStateFramebufferGet(fbo, target, apFBOs);
+
+ CRSTATE_CHECKERR(!cFBOs, GL_INVALID_OPERATION, "no fbo bound");
+ for (i = 0; i < cFBOs; ++i)
{
- case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
- *params = ap->type;
- break;
- case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
- CRSTATE_FBO_CHECKERR(ap->type!=GL_RENDERBUFFER_EXT && ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "can't query object name when it's not bound")
- *params = ap->name;
- break;
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
- CRSTATE_FBO_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture");
- *params = ap->level;
- break;
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
- CRSTATE_FBO_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture");
- *params = ap->face;
- break;
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
- CRSTATE_FBO_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture");
- *params = ap->zoffset;
- break;
- default:
- CRSTATE_FBO_CHECKERR(GL_TRUE, GL_INVALID_ENUM, "invalid pname");
+ CRSTATE_CHECKERR(!apFBOs[i], GL_INVALID_OPERATION, "zero fbo bound");
+ }
+
+ if(cFBOs != 1)
+ {
+ crWarning("different FBPs attached to draw and read buffers, returning info for the read buffer");
+ }
+
+ for (i = 0; i < 1; ++i)
+ {
+ CRSTATE_CHECKERR(!crStateGetFBOAttachmentPoint(apFBOs[i], attachment, &ap), GL_INVALID_ENUM, "invalid attachment");
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
+ *params = ap->type;
+ break;
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
+ CRSTATE_CHECKERR(ap->type!=GL_RENDERBUFFER_EXT && ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "can't query object name when it's not bound")
+ *params = ap->name;
+ break;
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
+ CRSTATE_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture");
+ *params = ap->level;
+ break;
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
+ CRSTATE_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture");
+ *params = ap->face;
+ break;
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
+ CRSTATE_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture");
+ *params = ap->zoffset;
+ break;
+ default:
+ CRSTATE_CHECKERR(GL_TRUE, GL_INVALID_ENUM, "invalid pname");
+ }
+ }
+}
+
+DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsFramebufferEXT( GLuint framebuffer )
+{
+ CRContext *g = GetCurrentContext();
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glIsFramebufferEXT called in begin/end");
+ return GL_FALSE;
}
+
+ return framebuffer ? crHashtableIsKeyUsed(g->shared->fbTable, framebuffer) : GL_FALSE;
+}
+
+DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsRenderbufferEXT( GLuint renderbuffer )
+{
+ CRContext *g = GetCurrentContext();
+
+
+ FLUSH();
+
+ if (g->current.inBeginEnd) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glIsRenderbufferEXT called in begin/end");
+ return GL_FALSE;
+ }
+
+ return renderbuffer ? crHashtableIsKeyUsed(g->shared->rbTable, renderbuffer) : GL_FALSE;
}
DECLEXPORT(void) STATE_APIENTRY
@@ -642,8 +888,11 @@ static void crStateSyncRenderbuffersCB(unsigned long key, void *data1, void *dat
diff_api.GenRenderbuffersEXT(1, &pRBO->hwid);
- diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, pRBO->hwid);
- diff_api.RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, pRBO->internalformat, pRBO->width, pRBO->height);
+ if (pRBO->width && pRBO->height)
+ {
+ diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, pRBO->hwid);
+ diff_api.RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, pRBO->internalformat, pRBO->width, pRBO->height);
+ }
}
static void crStateSyncAP(CRFBOAttachmentPoint *pAP, GLenum ap, CRContext *ctx)
@@ -774,36 +1023,37 @@ crStateFramebufferObjectSwitch(CRContext *from, CRContext *to)
}
DECLEXPORT(void) STATE_APIENTRY
-crStateFramebufferObjectDisableHW(CRContext *ctx, GLuint idFBO)
+crStateFramebufferObjectDisableHW(CRContext *ctx, GLuint idDrawFBO, GLuint idReadFBO)
{
- GLboolean fAdjustDrawReadBuffers = GL_FALSE;
+ GLenum idDrawBuffer = 0, idReadBuffer = 0;
- if (ctx->framebufferobject.drawFB || idFBO)
+ if (ctx->framebufferobject.drawFB || idDrawFBO)
{
diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
- fAdjustDrawReadBuffers = GL_TRUE;
+ idDrawBuffer = ctx->buffer.drawBuffer;
}
- if (ctx->framebufferobject.readFB ||idFBO)
+ if (ctx->framebufferobject.readFB || idReadFBO)
{
diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
- fAdjustDrawReadBuffers = GL_TRUE;
+ idReadBuffer = ctx->buffer.readBuffer;
}
- if (fAdjustDrawReadBuffers)
- {
- diff_api.DrawBuffer(GL_BACK);
- diff_api.ReadBuffer(GL_BACK);
- }
+ if (idDrawBuffer)
+ diff_api.DrawBuffer(idDrawBuffer);
+ if (idReadBuffer)
+ diff_api.ReadBuffer(idReadBuffer);
if (ctx->framebufferobject.renderbuffer)
diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
}
DECLEXPORT(void) STATE_APIENTRY
-crStateFramebufferObjectReenableHW(CRContext *fromCtx, CRContext *toCtx, GLuint idFBO)
+crStateFramebufferObjectReenableHW(CRContext *fromCtx, CRContext *toCtx, GLuint idDrawFBO, GLuint idReadFBO)
{
GLuint idReadBuffer = 0, idDrawBuffer = 0;
+ if (!fromCtx)
+ fromCtx = toCtx; /* <- in case fromCtx is zero, set it to toCtx to ensure framebuffer state gets re-enabled correctly */
if ((fromCtx->framebufferobject.drawFB) /* <- the FBO state was reset in crStateFramebufferObjectDisableHW */
&& fromCtx->framebufferobject.drawFB == toCtx->framebufferobject.drawFB) /* .. and it was NOT restored properly in crStateFramebufferObjectSwitch */
@@ -811,9 +1061,9 @@ crStateFramebufferObjectReenableHW(CRContext *fromCtx, CRContext *toCtx, GLuint
diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, toCtx->framebufferobject.drawFB->hwid);
idDrawBuffer = toCtx->framebufferobject.drawFB->drawbuffer[0];
}
- else if (idFBO && !toCtx->framebufferobject.drawFB)
+ else if (idDrawFBO && !toCtx->framebufferobject.drawFB)
{
- diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, idFBO);
+ diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, idDrawFBO);
idDrawBuffer = GL_COLOR_ATTACHMENT0;
}
@@ -823,9 +1073,9 @@ crStateFramebufferObjectReenableHW(CRContext *fromCtx, CRContext *toCtx, GLuint
diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, toCtx->framebufferobject.readFB->hwid);
idReadBuffer = toCtx->framebufferobject.readFB->readbuffer;
}
- else if (idFBO && !toCtx->framebufferobject.readFB)
+ else if (idReadFBO && !toCtx->framebufferobject.readFB)
{
- diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, idFBO);
+ diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, idReadFBO);
idReadBuffer = GL_COLOR_ATTACHMENT0;
}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py b/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py
index 674eb6b6..759c30d9 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py
@@ -233,3 +233,5 @@ for rettype in types:
print '\t\t\treturn;'
print '\t}'
print '}'
+
+from get_components import * \ No newline at end of file
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt
index 01974573..150d350b 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt
@@ -80,6 +80,7 @@ GLfloat GL_POINT_SIZE g->point.pointSize
GLfloat GL_POINT_SIZE_MIN_ARB g->point.minSize
GLfloat GL_POINT_SIZE_MAX_ARB g->point.maxSize
GLfloat GL_POINT_FADE_THRESHOLD_SIZE_ARB g->point.fadeThresholdSize
+GLfloat GL_POINT_SPRITE_COORD_ORIGIN g->point.spriteCoordOrigin
GLfloat GL_POINT_DISTANCE_ATTENUATION_ARB g->point.distanceAttenuation[0] g->point.distanceAttenuation[1] g->point.distanceAttenuation[2]
GLboolean GL_NORMALIZE g->transform.normalize
@@ -233,13 +234,19 @@ GLint GL_LIST_INDEX g->lists.currentIndex
GLenum GL_LIST_MODE g->lists.mode
GLint GL_STENCIL_CLEAR_VALUE g->stencil.clearValue
-GLint GL_STENCIL_FAIL g->stencil.fail
-GLint GL_STENCIL_FUNC g->stencil.func
-GLint GL_STENCIL_PASS_DEPTH_FAIL g->stencil.passDepthFail
-GLint GL_STENCIL_PASS_DEPTH_PASS g->stencil.passDepthPass
-GLint GL_STENCIL_REF g->stencil.ref
+GLint GL_STENCIL_FAIL g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_FRONT:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].fail
+GLint GL_STENCIL_BACK_FAIL g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_BACK:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].fail
+GLint GL_STENCIL_FUNC g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_FRONT:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].func
+GLint GL_STENCIL_BACK_FUNC g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_BACK:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].func
+GLint GL_STENCIL_PASS_DEPTH_FAIL g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_FRONT:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthFail
+GLint GL_STENCIL_BACK_PASS_DEPTH_FAIL g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_BACK:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthFail
+GLint GL_STENCIL_PASS_DEPTH_PASS g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_FRONT:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthPass
+GLint GL_STENCIL_BACK_PASS_DEPTH_PASS g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_BACK:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthPass
+GLint GL_STENCIL_REF g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_FRONT:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].ref
+GLint GL_STENCIL_BACK_REF g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_BACK:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].ref
GLboolean GL_STENCIL_TEST g->stencil.stencilTest
-GLint GL_STENCIL_VALUE_MASK g->stencil.mask
+GLint GL_STENCIL_VALUE_MASK g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_FRONT:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].mask
+GLint GL_STENCIL_BACK_VALUE_MASK g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_BACK:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].mask
GLint GL_STENCIL_WRITEMASK g->stencil.writeMask
GLfloat GL_CURRENT_INDEX g->current.colorIndex
@@ -308,3 +315,5 @@ GLint GL_RENDERBUFFER_BINDING_EXT (g->framebufferobject.renderbuffer?g->framebuf
#CVA
GLint GL_ARRAY_ELEMENT_LOCK_FIRST_EXT g->client.array.lockFirst
GLint GL_ARRAY_ELEMENT_LOCK_COUNT_EXT g->client.array.lockCount
+
+GLint GL_ACTIVE_STENCIL_FACE_EXT g->stencil.activeStencilFace \ No newline at end of file
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c
index 7741007b..48d5a7e8 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -258,6 +258,21 @@ DECLEXPORT(GLuint) STATE_APIENTRY crStateGLSLProgramHWIDtoID(GLuint hwid)
return parms.id;
}
+DECLEXPORT(GLuint) STATE_APIENTRY crStateDeleteObjectARB( VBoxGLhandleARB obj )
+{
+ GLuint hwId = crStateGetProgramHWID(obj);
+ if (hwId)
+ {
+ crStateDeleteProgram(obj);
+ }
+ else
+ {
+ hwId = crStateGetShaderHWID(obj);
+ crStateDeleteShader(obj);
+ }
+ return hwId;
+}
+
DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateShader(GLuint hwid, GLenum type)
{
CRGLSLShader *pShader;
@@ -267,13 +282,17 @@ DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateShader(GLuint hwid, GLenum type)
#ifdef IN_GUEST
CRASSERT(!crStateGetShaderObj(stateId));
#else
- /* the id may not necesserily be hwid after save state restoration */
- while ((pShader = crStateGetShaderObj(stateId)) != NULL)
+ /* the proogram and shader names must not intersect because DeleteObjectARB must distinguish between them
+ * see crStateDeleteObjectARB
+ * this is why use programs table for shader keys allocation */
+ stateId = crHashtableAllocKeys(g->glsl.programs, 1);
+ if (!stateId)
{
- GLuint newStateId = stateId + 7;
- crDebug("Shader object %d already exists, generating a new one, %d", stateId, newStateId);
- stateId = newStateId;
+ crWarning("failed to allocate program key");
+ return 0;
}
+
+ Assert((pShader = crStateGetShaderObj(stateId)) == NULL);
#endif
pShader = (CRGLSLShader *) crAlloc(sizeof(*pShader));
@@ -311,19 +330,18 @@ DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateProgram(GLuint hwid)
CRASSERT(!crStateGetProgramObj(stateId));
}
#else
- /* the id may not necesserily be hwid after save state restoration */
- while ((pProgram = crStateGetProgramObj(stateId)) != NULL)
+ stateId = crHashtableAllocKeys(g->glsl.programs, 1);
+ if (!stateId)
{
- GLuint newStateId = stateId + 7;
- crDebug("Program object %d already exists, generating a new one, %d", stateId, newStateId);
- stateId = newStateId;
+ crWarning("failed to allocate program key");
+ return 0;
}
#endif
pProgram = (CRGLSLProgram *) crAlloc(sizeof(*pProgram));
if (!pProgram)
{
- crWarning("crStateCreateShader: Out of memory!");
+ crWarning("crStateCreateProgram: Out of memory!");
return 0;
}
@@ -363,6 +381,11 @@ DECLEXPORT(void) STATE_APIENTRY crStateCompileShader(GLuint shader)
pShader->compiled = GL_TRUE;
}
+static void crStateDbgCheckNoProgramOfId(void *data)
+{
+ crError("Unexpected Program id");
+}
+
DECLEXPORT(void) STATE_APIENTRY crStateDeleteShader(GLuint shader)
{
CRGLSLShader *pShader = crStateGetShaderObj(shader);
@@ -378,6 +401,10 @@ DECLEXPORT(void) STATE_APIENTRY crStateDeleteShader(GLuint shader)
{
CRContext *g = GetCurrentContext();
crHashtableDelete(g->glsl.shaders, shader, crStateFreeGLSLShader);
+ /* since we use programs table for key allocation key allocation, we need to
+ * free the key in the programs table.
+ * See comment in crStateCreateShader */
+ crHashtableDelete(g->glsl.programs, shader, crStateDbgCheckNoProgramOfId);
}
}
@@ -598,8 +625,7 @@ DECLEXPORT(void) STATE_APIENTRY crStateBindAttribLocation(GLuint program, GLuint
{
if (!crStrcmp(pProgram->currentState.pAttribs[i].name, name))
{
- crFree(pProgram->currentState.pAttribs[i].name);
- pProgram->currentState.pAttribs[i].name = crStrdup(name);
+ pProgram->currentState.pAttribs[i].index = index;
return;
}
}
@@ -1186,6 +1212,7 @@ static void crStateGLSLCreateProgramCB(unsigned long key, void *data1, void *dat
DECLEXPORT(void) STATE_APIENTRY crStateGLSLSwitch(CRContext *from, CRContext *to)
{
+ GLboolean fForceUseProgramSet = GL_FALSE;
if (to->glsl.bResyncNeeded)
{
to->glsl.bResyncNeeded = GL_FALSE;
@@ -1194,10 +1221,13 @@ DECLEXPORT(void) STATE_APIENTRY crStateGLSLSwitch(CRContext *from, CRContext *to
crHashtableWalk(to->glsl.programs, crStateGLSLCreateProgramCB, to);
+ /* crStateGLSLCreateProgramCB changes the current program, ensure we have the proper program re-sored */
+ fForceUseProgramSet = GL_TRUE;
+
crHashtableWalk(to->glsl.shaders, crStateGLSLSyncShadersCB, NULL);
}
- if (to->glsl.activeProgram != from->glsl.activeProgram)
+ if (to->glsl.activeProgram != from->glsl.activeProgram || fForceUseProgramSet)
{
diff_api.UseProgram(to->glsl.activeProgram ? to->glsl.activeProgram->hwid : 0);
}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c
index f8ac1f5a..49bcd38b 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c
@@ -17,13 +17,14 @@ CRContext *__currentContext = NULL;
#endif
CRStateBits *__currentBits = NULL;
-GLboolean g_availableContexts[CR_MAX_CONTEXTS];
+CRContext *g_pAvailableContexts[CR_MAX_CONTEXTS];
+uint32_t g_cContexts = 0;
static CRSharedState *gSharedState=NULL;
static CRContext *defaultContext = NULL;
-static GLboolean g_bVBoxEnableDiffOnMakeCurrent = GL_TRUE;
+GLboolean g_bVBoxEnableDiffOnMakeCurrent = GL_TRUE;
/**
@@ -60,7 +61,6 @@ crStateDeleteTextureCallback(void *texObj)
crStateDeleteTextureObject((CRTextureObj *) texObj);
}
-#ifndef IN_GUEST
typedef struct CR_STATE_RELEASEOBJ
{
CRContext *pCtx;
@@ -102,7 +102,7 @@ static void ReleaseRBOCallback(unsigned long key, void *data1, void *data2)
if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj))
crHashtableDelete(pData->s->rbTable, key, crStateFreeRBO);
}
-#endif
+
/**
* Decrement shared state's refcount and delete when it hits zero.
*/
@@ -110,6 +110,7 @@ DECLEXPORT(void)
crStateFreeShared(CRContext *pContext, CRSharedState *s)
{
s->refCount--;
+ Assert(s->refCount >= 0);
if (s->refCount <= 0) {
if (s==gSharedState)
{
@@ -122,8 +123,7 @@ crStateFreeShared(CRContext *pContext, CRSharedState *s)
crFreeHashtable(s->rbTable, crStateFreeRBO);
crFree(s);
}
-#ifndef IN_GUEST
- else
+ else if (pContext)
{
/* evaluate usage bits*/
CR_STATE_RELEASEOBJ CbData;
@@ -134,7 +134,22 @@ crStateFreeShared(CRContext *pContext, CRSharedState *s)
crHashtableWalk(s->fbTable, ReleaseFBOCallback, &CbData);
crHashtableWalk(s->rbTable, ReleaseRBOCallback, &CbData);
}
-#endif
+}
+
+DECLEXPORT(CRSharedState *) crStateGlobalSharedAcquire()
+{
+ if (!gSharedState)
+ {
+ crWarning("No Global Shared State!");
+ return NULL;
+ }
+ gSharedState->refCount++;
+ return gSharedState;
+}
+
+DECLEXPORT(void) crStateGlobalSharedRelease()
+{
+ crStateFreeShared(NULL, gSharedState);
}
DECLEXPORT(void) STATE_APIENTRY
@@ -218,11 +233,26 @@ static CRContext *
crStateCreateContextId(int i, const CRLimitsState *limits,
GLint visBits, CRContext *shareCtx)
{
- CRContext *ctx = (CRContext *) crCalloc( sizeof( *ctx ) );
+ CRContext *ctx;
int j;
int node32 = i >> 5;
int node = i & 0x1f;
+ if (g_pAvailableContexts[i] != NULL)
+ {
+ crWarning("trying to create context with used id");
+ return NULL;
+ }
+
+ ctx = (CRContext *) crCalloc( sizeof( *ctx ) );
+ if (!ctx)
+ {
+ crWarning("failed to allocate context");
+ return NULL;
+ }
+ g_pAvailableContexts[i] = ctx;
+ ++g_cContexts;
+ CRASSERT(g_cContexts < RT_ELEMENTS(g_pAvailableContexts));
ctx->id = i;
#ifdef CHROMIUM_THREADSAFE
VBoxTlsRefInit(ctx, crStateContextDtor);
@@ -252,7 +282,7 @@ crStateCreateContextId(int i, const CRLimitsState *limits,
crStateExtensionsInit( &(ctx->limits), &(ctx->extensions) );
crStateBufferObjectInit( ctx ); /* must precede client state init! */
- crStateClientInit( &(ctx->client) );
+ crStateClientInit( ctx );
crStateBufferInit( ctx );
crStateCurrentInit( ctx );
@@ -330,7 +360,23 @@ crStateCreateContextId(int i, const CRLimitsState *limits,
static void
crStateFreeContext(CRContext *ctx)
{
- crStateClientDestroy( &(ctx->client) );
+#ifndef DEBUG_misha
+ CRASSERT(g_pAvailableContexts[ctx->id] == ctx);
+#endif
+ if (g_pAvailableContexts[ctx->id] == ctx)
+ {
+ g_pAvailableContexts[ctx->id] = NULL;
+ --g_cContexts;
+ CRASSERT(g_cContexts < RT_ELEMENTS(g_pAvailableContexts));
+ }
+ else
+ {
+#ifndef DEBUG_misha
+ crWarning("freeing context %p, id(%d) not being in the context list", ctx, ctx->id);
+#endif
+ }
+
+ crStateClientDestroy( ctx );
crStateLimitsDestroy( &(ctx->limits) );
crStateBufferObjectDestroy( ctx );
crStateEvaluatorDestroy( ctx );
@@ -377,10 +423,15 @@ void crStateInit(void)
crStateClientInitBits( &(__currentBits->client) );
crStateLightingInitBits( &(__currentBits->lighting) );
} else
+ {
+#ifndef DEBUG_misha
crWarning("State tracker is being re-initialized..\n");
+#endif
+ }
for (i=0;i<CR_MAX_CONTEXTS;i++)
- g_availableContexts[i] = 0;
+ g_pAvailableContexts[i] = NULL;
+ g_cContexts = 0;
#ifdef CHROMIUM_THREADSAFE
if (!__isContextTLSInited)
@@ -411,11 +462,14 @@ void crStateInit(void)
/* Reset diff_api */
crMemZero(&diff_api, sizeof(SPUDispatchTable));
+ Assert(!gSharedState);
+ gSharedState = NULL;
+
/* Allocate the default/NULL context */
+ CRASSERT(g_pAvailableContexts[0] == NULL);
defaultContext = crStateCreateContextId(0, NULL, CR_RGB_BIT, NULL);
- CRASSERT(g_availableContexts[0] == 0);
- g_availableContexts[0] = 1; /* in use forever */
-
+ CRASSERT(g_pAvailableContexts[0] == defaultContext);
+ CRASSERT(g_cContexts == 1);
#ifdef CHROMIUM_THREADSAFE
SetCurrentContext(defaultContext);
#else
@@ -425,6 +479,7 @@ void crStateInit(void)
void crStateDestroy(void)
{
+ int i;
if (__currentBits)
{
crStateClientDestroyBits(&(__currentBits->client));
@@ -433,6 +488,25 @@ void crStateDestroy(void)
__currentBits = NULL;
}
+ SetCurrentContext(NULL);
+
+ for (i = CR_MAX_CONTEXTS-1; i >= 0; i--)
+ {
+ if (g_pAvailableContexts[i])
+ {
+#ifdef CHROMIUM_THREADSAFE
+ if (VBoxTlsRefIsFunctional(g_pAvailableContexts[i]))
+ VBoxTlsRefRelease(g_pAvailableContexts[i]);
+#else
+ crStateFreeContext(g_pAvailableContexts[i]);
+#endif
+ }
+ }
+
+ /* default context was stored in g_pAvailableContexts[0], so it was destroyed already */
+ defaultContext = NULL;
+
+
#ifdef CHROMIUM_THREADSAFE
crFreeTSD(&__contextTSD);
__isContextTLSInited = 0;
@@ -452,7 +526,7 @@ void crStateDestroy(void)
* (i.e. the old context to the new context). The transformation
* is accomplished by calling GL functions through the 'diff_api'
* so that the downstream GL machine (represented by the __currentContext
- * structure) is updated to reflect the new context state. Finally,
+ * structure) is updated to reflect the new context state. Finally,
* we point __currentContext to the new context.
*
* A subtle problem we have to deal with is context destruction.
@@ -485,35 +559,46 @@ void crStateDestroy(void)
CRContext *
crStateCreateContext(const CRLimitsState *limits, GLint visBits, CRContext *share)
{
- int i;
+ return crStateCreateContextEx(limits, visBits, share, -1);
+}
+CRContext *
+crStateCreateContextEx(const CRLimitsState *limits, GLint visBits, CRContext *share, GLint presetID)
+{
/* Must have created the default context via crStateInit() first */
CRASSERT(defaultContext);
- for (i = 1 ; i < CR_MAX_CONTEXTS ; i++)
+ if (presetID>0)
{
- if (!g_availableContexts[i])
+ if(g_pAvailableContexts[presetID])
{
- g_availableContexts[i] = 1; /* it's no longer available */
- return crStateCreateContextId( i, limits, visBits, share );
+ crWarning("requesting to create context with already allocated id");
+ return NULL;
}
}
- crError( "Out of available contexts in crStateCreateContexts (max %d)",
- CR_MAX_CONTEXTS );
- /* never get here */
- return NULL;
-}
-
-CRContext *
-crStateCreateContextEx(const CRLimitsState *limits, GLint visBits, CRContext *share, GLint presetID)
-{
- if (presetID>0)
+ else
{
- CRASSERT(!g_availableContexts[presetID]);
- g_availableContexts[presetID] = 1;
- return crStateCreateContextId(presetID, limits, visBits, share);
+ int i;
+
+ for (i = 1 ; i < CR_MAX_CONTEXTS ; i++)
+ {
+ if (!g_pAvailableContexts[i])
+ {
+ presetID = i;
+ break;
+ }
+ }
+
+ if (presetID<=0)
+ {
+ crError( "Out of available contexts in crStateCreateContexts (max %d)",
+ CR_MAX_CONTEXTS );
+ /* never get here */
+ return NULL;
+ }
}
- else return crStateCreateContext(limits, visBits, share);
+
+ return crStateCreateContextId(presetID, limits, visBits, share);
}
void crStateDestroyContext( CRContext *ctx )
@@ -535,9 +620,17 @@ void crStateDestroyContext( CRContext *ctx )
/* ensure matrix state is also current */
crStateMatrixMode(defaultContext->transform.matrixMode);
}
- g_availableContexts[ctx->id] = 0;
#ifdef CHROMIUM_THREADSAFE
+ VBoxTlsRefMarkDestroy(ctx);
+# ifdef IN_GUEST
+ if (VBoxTlsRefCountGet(ctx) > 1 && ctx->shared == gSharedState)
+ {
+ /* we always need to free the global shared state to prevent the situation when guest thinks the shared objects are still valid, while host destroys them */
+ crStateFreeShared(ctx, ctx->shared);
+ ctx->shared = crStateAllocShared();
+ }
+# endif
VBoxTlsRefRelease(ctx);
#else
crStateFreeContext(ctx);
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_lists.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_lists.c
index 09831311..005f9462 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_lists.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_lists.c
@@ -30,7 +30,7 @@ void crStateListsInit(CRContext *ctx)
RESET(lb->dirty, ctx->bitid);
}
-/*#define CRSTATE_DEBUG_QUERY_HW_STATE*/
+//#define CRSTATE_DEBUG_QUERY_HW_STATE
#ifndef CRSTATE_DEBUG_QUERY_HW_STATE
# define CRSTATE_SET_CAP(state, value, format) g->state=value
@@ -168,7 +168,7 @@ void crStateListsInit(CRContext *ctx)
} \
}
-void STATE_APIENTRY crStateQueryHWState()
+void STATE_APIENTRY crStateQueryHWState(GLuint fbFbo, GLuint bbFbo)
{
CRContext *g = GetCurrentContext();
CRStateBits *sb = GetCurrentBits();
@@ -217,12 +217,68 @@ void STATE_APIENTRY crStateQueryHWState()
if (CHECKDIRTY(sb->buffer.drawBuffer, negbitID))
{
- CRSTATE_SET_ENUM(buffer.drawBuffer, GL_DRAW_BUFFER);
+ GLuint buf = 0;
+ diff_api.GetIntegerv(GL_DRAW_BUFFER, &buf);
+
+ if (buf == GL_COLOR_ATTACHMENT0_EXT && (bbFbo || fbFbo))
+ {
+ GLuint binding = 0;
+ diff_api.GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &binding);
+ if (!binding)
+ {
+ crWarning("HW state synch: GL_DRAW_FRAMEBUFFER_BINDING is NULL");
+ }
+
+ if (bbFbo && binding == bbFbo)
+ {
+ g->buffer.drawBuffer = GL_BACK;
+ }
+ else if (fbFbo && binding == fbFbo)
+ {
+ g->buffer.drawBuffer = GL_FRONT;
+ }
+ else
+ {
+ g->buffer.drawBuffer = buf;
+ }
+ }
+ else
+ {
+ g->buffer.drawBuffer = buf;
+ }
}
if (CHECKDIRTY(sb->buffer.readBuffer, negbitID))
{
- CRSTATE_SET_ENUM(buffer.readBuffer, GL_READ_BUFFER);
+ GLuint buf = 0;
+ diff_api.GetIntegerv(GL_READ_BUFFER, &buf);
+
+ if (buf == GL_COLOR_ATTACHMENT0_EXT && (bbFbo || fbFbo))
+ {
+ GLuint binding = 0;
+ diff_api.GetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &binding);
+ if (!binding)
+ {
+ crWarning("HW state synch: GL_READ_FRAMEBUFFER_BINDING is NULL");
+ }
+
+ if (bbFbo && binding == bbFbo)
+ {
+ g->buffer.readBuffer = GL_BACK;
+ }
+ else if (fbFbo && binding == fbFbo)
+ {
+ g->buffer.readBuffer = GL_FRONT;
+ }
+ else
+ {
+ g->buffer.readBuffer = buf;
+ }
+ }
+ else
+ {
+ g->buffer.readBuffer = buf;
+ }
}
if (CHECKDIRTY(sb->buffer.indexMask, negbitID))
@@ -295,23 +351,122 @@ void STATE_APIENTRY crStateQueryHWState()
if (CHECKDIRTY(sb->stencil.dirty, negbitID))
{
+ GLenum activeFace;
+ GLboolean backIsSet = GL_FALSE, frontIsSet = GL_FALSE;
+
if (CHECKDIRTY(sb->stencil.enable, negbitID))
{
CRSTATE_SET_ENABLED(stencil.stencilTest, GL_STENCIL_TEST);
}
- if (CHECKDIRTY(sb->stencil.func, negbitID))
+ if (CHECKDIRTY(sb->stencil.enableTwoSideEXT, negbitID))
{
- CRSTATE_SET_ENUM(stencil.func, GL_STENCIL_FUNC);
- CRSTATE_SET_INT(stencil.ref, GL_STENCIL_REF);
- CRSTATE_SET_INT(stencil.mask, GL_STENCIL_VALUE_MASK);
+ CRSTATE_SET_ENABLED(stencil.stencilTwoSideEXT, GL_STENCIL_TEST_TWO_SIDE_EXT);
}
- if (CHECKDIRTY(sb->stencil.op, negbitID))
+ if (CHECKDIRTY(sb->stencil.activeStencilFace, negbitID))
{
- CRSTATE_SET_ENUM(stencil.fail, GL_STENCIL_FAIL);
- CRSTATE_SET_ENUM(stencil.passDepthFail, GL_STENCIL_PASS_DEPTH_FAIL);
- CRSTATE_SET_ENUM(stencil.passDepthPass, GL_STENCIL_PASS_DEPTH_PASS);
+ CRSTATE_SET_ENUM(stencil.activeStencilFace, GL_ACTIVE_STENCIL_FACE_EXT);
+ }
+
+ activeFace = g->stencil.activeStencilFace;
+
+
+#define CRSTATE_SET_STENCIL_FUNC(_idx, _suff) do { \
+ CRSTATE_SET_ENUM(stencil.buffers[(_idx)].func, GL_STENCIL##_suff##FUNC); \
+ CRSTATE_SET_INT(stencil.buffers[(_idx)].ref, GL_STENCIL##_suff##REF); \
+ CRSTATE_SET_INT(stencil.buffers[(_idx)].mask, GL_STENCIL##_suff##VALUE_MASK); \
+ } while (0)
+
+#define CRSTATE_SET_STENCIL_OP(_idx, _suff) do { \
+ CRSTATE_SET_ENUM(stencil.buffers[(_idx)].fail, GL_STENCIL##_suff##FAIL); \
+ CRSTATE_SET_ENUM(stencil.buffers[(_idx)].passDepthFail, GL_STENCIL##_suff##PASS_DEPTH_FAIL); \
+ CRSTATE_SET_ENUM(stencil.buffers[(_idx)].passDepthPass, GL_STENCIL##_suff##PASS_DEPTH_PASS); \
+ } while (0)
+
+ /* func */
+
+ if (CHECKDIRTY(sb->stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, negbitID))
+ {
+ /* this if branch is not needed here actually, just in case ogl drivers misbehave */
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_SET_STENCIL_FUNC(CRSTATE_STENCIL_BUFFER_ID_BACK, _BACK_);
+ backIsSet = GL_TRUE;
+ }
+
+ if (CHECKDIRTY(sb->stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, negbitID))
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+ CRSTATE_SET_STENCIL_FUNC(CRSTATE_STENCIL_BUFFER_ID_FRONT, _);
+ frontIsSet = GL_TRUE;
+ }
+
+ if ((!frontIsSet || !backIsSet) && CHECKDIRTY(sb->stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, negbitID))
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+ CRSTATE_SET_STENCIL_FUNC(CRSTATE_STENCIL_BUFFER_ID_FRONT, _);
+ if (!backIsSet)
+ {
+ g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func = g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func;
+ g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref = g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref;
+ g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask = g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask;
+ }
+ }
+
+ /* op */
+ backIsSet = GL_FALSE, frontIsSet = GL_FALSE;
+
+ if (CHECKDIRTY(sb->stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, negbitID))
+ {
+ /* this if branch is not needed here actually, just in case ogl drivers misbehave */
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_SET_STENCIL_OP(CRSTATE_STENCIL_BUFFER_ID_BACK, _BACK_);
+ backIsSet = GL_TRUE;
+ }
+
+ if (CHECKDIRTY(sb->stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, negbitID))
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+ CRSTATE_SET_STENCIL_OP(CRSTATE_STENCIL_BUFFER_ID_FRONT, _);
+ frontIsSet = GL_TRUE;
+ }
+
+ if ((!frontIsSet || !backIsSet) && CHECKDIRTY(sb->stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, negbitID))
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+ CRSTATE_SET_STENCIL_OP(CRSTATE_STENCIL_BUFFER_ID_FRONT, _);
+ if (!backIsSet)
+ {
+ g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail = g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail;
+ g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail = g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail;
+ g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass = g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass;
+ }
}
if (CHECKDIRTY(sb->stencil.clearValue, negbitID))
@@ -499,12 +654,12 @@ void STATE_APIENTRY crStateQueryHWState()
{
CRSTATE_SET_MATERIAL_COLOR(lighting.ambient[0], GL_FRONT, GL_AMBIENT);
CRSTATE_SET_MATERIAL_COLOR(lighting.ambient[1], GL_BACK, GL_AMBIENT);
- CRSTATE_SET_MATERIAL_COLOR(lighting.diffuse[0], GL_FRONT, GL_AMBIENT);
- CRSTATE_SET_MATERIAL_COLOR(lighting.diffuse[1], GL_BACK, GL_AMBIENT);
- CRSTATE_SET_MATERIAL_COLOR(lighting.specular[0], GL_FRONT, GL_AMBIENT);
- CRSTATE_SET_MATERIAL_COLOR(lighting.specular[1], GL_BACK, GL_AMBIENT);
- CRSTATE_SET_MATERIAL_COLOR(lighting.emission[0], GL_FRONT, GL_AMBIENT);
- CRSTATE_SET_MATERIAL_COLOR(lighting.emission[1], GL_BACK, GL_AMBIENT);
+ CRSTATE_SET_MATERIAL_COLOR(lighting.diffuse[0], GL_FRONT, GL_DIFFUSE);
+ CRSTATE_SET_MATERIAL_COLOR(lighting.diffuse[1], GL_BACK, GL_DIFFUSE);
+ CRSTATE_SET_MATERIAL_COLOR(lighting.specular[0], GL_FRONT, GL_SPECULAR);
+ CRSTATE_SET_MATERIAL_COLOR(lighting.specular[1], GL_BACK, GL_SPECULAR);
+ CRSTATE_SET_MATERIAL_COLOR(lighting.emission[0], GL_FRONT, GL_EMISSION);
+ CRSTATE_SET_MATERIAL_COLOR(lighting.emission[1], GL_BACK, GL_EMISSION);
CRSTATE_SET_MATERIAL_F(lighting.shininess[0], GL_FRONT, GL_SHININESS);
CRSTATE_SET_MATERIAL_F(lighting.shininess[1], GL_BACK, GL_SHININESS);
}
@@ -1093,7 +1248,7 @@ void STATE_APIENTRY crStateNewList (GLuint list, GLenum mode)
l->mode = mode;
}
-void STATE_APIENTRY crStateEndList (void)
+void STATE_APIENTRY crStateEndList (void)
{
CRContext *g = GetCurrentContext();
CRListsState *l = &(g->lists);
@@ -1110,13 +1265,6 @@ void STATE_APIENTRY crStateEndList (void)
return;
}
-#ifndef IN_GUEST
- if (l->mode==GL_COMPILE)
- {
- crStateQueryHWState();
- }
-#endif
-
l->currentIndex = 0;
l->mode = 0;
}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_point.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_point.c
index fbaac24d..de40c089 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_point.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_point.c
@@ -40,6 +40,9 @@ void crStatePointInit (CRContext *ctx)
}
#endif
+ p->spriteCoordOrigin = (GLfloat)GL_UPPER_LEFT;
+ RESET(pb->spriteCoordOrigin, ctx->bitid);
+
RESET(pb->dirty, ctx->bitid);
/*
@@ -167,6 +170,17 @@ void STATE_APIENTRY crStatePointParameterfvARB(GLenum pname, const GLfloat *para
return;
}
break;
+ case GL_POINT_SPRITE_COORD_ORIGIN:
+ {
+ GLenum enmVal = (GLenum)params[0];
+ if (enmVal != GL_LOWER_LEFT && enmVal != GL_UPPER_LEFT) {
+ crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glPointParameterfvARB invalid GL_POINT_SPRITE_COORD_ORIGIN value: %f", params[0]);
+ return;
+ }
+ p->spriteCoordOrigin = params[0];
+ DIRTY(pb->spriteCoordOrigin, g->neg_bitid);
+ break;
+ }
default:
crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glPointParameterfvARB invalid enum: %f", pname);
return;
@@ -186,3 +200,248 @@ void STATE_APIENTRY crStatePointParameteriv(GLenum pname, const GLint *params)
GLfloat f_param = (GLfloat) (*params);
crStatePointParameterfvARB( pname, &f_param );
}
+
+void crStatePointDiff(CRPointBits *b, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ CRPointState *from = &(fromCtx->point);
+ CRPointState *to = &(toCtx->point);
+ unsigned int j, i;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+ Assert(0);
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+ i = 0; /* silence compiler */
+ if (CHECKDIRTY(b->enableSmooth, bitID))
+ {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (from->pointSmooth != to->pointSmooth)
+ {
+ able[to->pointSmooth](GL_POINT_SMOOTH);
+ from->pointSmooth = to->pointSmooth;
+ }
+ CLEARDIRTY(b->enableSmooth, nbitID);
+ }
+ if (CHECKDIRTY(b->size, bitID))
+ {
+ if (from->pointSize != to->pointSize)
+ {
+ diff_api.PointSize (to->pointSize);
+ from->pointSize = to->pointSize;
+ }
+ CLEARDIRTY(b->size, nbitID);
+ }
+ if (CHECKDIRTY(b->minSize, bitID))
+ {
+ if (from->minSize != to->minSize)
+ {
+ diff_api.PointParameterfARB (GL_POINT_SIZE_MIN_ARB, to->minSize);
+ from->minSize = to->minSize;
+ }
+ CLEARDIRTY(b->minSize, nbitID);
+ }
+ if (CHECKDIRTY(b->maxSize, bitID))
+ {
+ if (from->maxSize != to->maxSize)
+ {
+ diff_api.PointParameterfARB (GL_POINT_SIZE_MAX_ARB, to->maxSize);
+ from->maxSize = to->maxSize;
+ }
+ CLEARDIRTY(b->maxSize, nbitID);
+ }
+ if (CHECKDIRTY(b->fadeThresholdSize, bitID))
+ {
+ if (from->fadeThresholdSize != to->fadeThresholdSize)
+ {
+ diff_api.PointParameterfARB (GL_POINT_FADE_THRESHOLD_SIZE_ARB, to->fadeThresholdSize);
+ from->fadeThresholdSize = to->fadeThresholdSize;
+ }
+ CLEARDIRTY(b->fadeThresholdSize, nbitID);
+ }
+ if (CHECKDIRTY(b->spriteCoordOrigin, bitID))
+ {
+ if (from->spriteCoordOrigin != to->spriteCoordOrigin)
+ {
+ diff_api.PointParameterfARB (GL_POINT_SPRITE_COORD_ORIGIN, to->spriteCoordOrigin);
+ from->spriteCoordOrigin = to->spriteCoordOrigin;
+ }
+ CLEARDIRTY(b->spriteCoordOrigin, nbitID);
+ }
+ if (CHECKDIRTY(b->distanceAttenuation, bitID))
+ {
+ if (from->distanceAttenuation[0] != to->distanceAttenuation[0] || from->distanceAttenuation[1] != to->distanceAttenuation[1] || from->distanceAttenuation[2] != to->distanceAttenuation[2]) {
+ diff_api.PointParameterfvARB (GL_POINT_DISTANCE_ATTENUATION_ARB, to->distanceAttenuation);
+ from->distanceAttenuation[0] = to->distanceAttenuation[0];
+ from->distanceAttenuation[1] = to->distanceAttenuation[1];
+ from->distanceAttenuation[2] = to->distanceAttenuation[2];
+ }
+ CLEARDIRTY(b->distanceAttenuation, nbitID);
+ }
+ if (CHECKDIRTY(b->enableSprite, bitID))
+ {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (from->pointSprite != to->pointSprite)
+ {
+ able[to->pointSprite](GL_POINT_SPRITE_ARB);
+ from->pointSprite = to->pointSprite;
+ }
+ CLEARDIRTY(b->enableSprite, nbitID);
+ }
+ {
+ unsigned int activeUnit = (unsigned int) -1;
+ for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) {
+ if (CHECKDIRTY(b->coordReplacement[i], bitID))
+ {
+ GLint replacement = to->coordReplacement[i];
+ if (activeUnit != i) {
+ diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB );
+ activeUnit = i;
+ }
+ diff_api.TexEnviv(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, &replacement);
+ from->coordReplacement[i] = to->coordReplacement[i];
+ CLEARDIRTY(b->coordReplacement[i], nbitID);
+ }
+ }
+ if (activeUnit != toCtx->texture.curTextureUnit)
+ diff_api.ActiveTextureARB(GL_TEXTURE0 + toCtx->texture.curTextureUnit);
+ }
+ CLEARDIRTY(b->dirty, nbitID);
+}
+
+void crStatePointSwitch(CRPointBits *b, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ CRPointState *from = &(fromCtx->point);
+ CRPointState *to = &(toCtx->point);
+ unsigned int j, i;
+ GLboolean fEnabled;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+ i = 0; /* silence compiler */
+ if (CHECKDIRTY(b->enableSmooth, bitID))
+ {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (from->pointSmooth != to->pointSmooth)
+ {
+ able[to->pointSmooth](GL_POINT_SMOOTH);
+ FILLDIRTY(b->enableSmooth);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->enableSmooth, nbitID);
+ }
+ if (CHECKDIRTY(b->size, bitID))
+ {
+ if (from->pointSize != to->pointSize)
+ {
+ diff_api.PointSize (to->pointSize);
+ FILLDIRTY(b->size);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->size, nbitID);
+ }
+ if (CHECKDIRTY(b->minSize, bitID))
+ {
+ if (from->minSize != to->minSize)
+ {
+ diff_api.PointParameterfARB (GL_POINT_SIZE_MIN_ARB, to->minSize);
+ FILLDIRTY(b->minSize);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->minSize, nbitID);
+ }
+ if (CHECKDIRTY(b->maxSize, bitID))
+ {
+ if (from->maxSize != to->maxSize)
+ {
+ diff_api.PointParameterfARB (GL_POINT_SIZE_MAX_ARB, to->maxSize);
+ FILLDIRTY(b->maxSize);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->maxSize, nbitID);
+ }
+ if (CHECKDIRTY(b->fadeThresholdSize, bitID))
+ {
+ if (from->fadeThresholdSize != to->fadeThresholdSize)
+ {
+ diff_api.PointParameterfARB (GL_POINT_FADE_THRESHOLD_SIZE_ARB, to->fadeThresholdSize);
+ FILLDIRTY(b->fadeThresholdSize);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->fadeThresholdSize, nbitID);
+ }
+ if (CHECKDIRTY(b->spriteCoordOrigin, bitID))
+ {
+ if (from->spriteCoordOrigin != to->spriteCoordOrigin)
+ {
+ diff_api.PointParameterfARB (GL_POINT_SPRITE_COORD_ORIGIN, to->spriteCoordOrigin);
+ FILLDIRTY(b->spriteCoordOrigin);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->spriteCoordOrigin, nbitID);
+ }
+ if (CHECKDIRTY(b->distanceAttenuation, bitID))
+ {
+ if (from->distanceAttenuation[0] != to->distanceAttenuation[0] || from->distanceAttenuation[1] != to->distanceAttenuation[1] || from->distanceAttenuation[2] != to->distanceAttenuation[2]) {
+ diff_api.PointParameterfvARB (GL_POINT_DISTANCE_ATTENUATION_ARB, to->distanceAttenuation);
+ FILLDIRTY(b->distanceAttenuation);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->distanceAttenuation, nbitID);
+ }
+ fEnabled = from->pointSprite;
+ {
+ unsigned int activeUnit = (unsigned int) -1;
+ for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) {
+ if (CHECKDIRTY(b->coordReplacement[i], bitID))
+ {
+ if (!fEnabled)
+ {
+ diff_api.Enable(GL_POINT_SPRITE_ARB);
+ fEnabled = GL_TRUE;
+ }
+#if 0
+ /*don't set coord replacement, it will be set just before drawing points when necessary,
+ * to work around gpu driver bugs
+ * See crServerDispatch[Begin|End|Draw*] */
+ GLint replacement = to->coordReplacement[i];
+ if (activeUnit != i) {
+ diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB );
+ activeUnit = i;
+ }
+ diff_api.TexEnviv(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, &replacement);
+#endif
+ CLEARDIRTY(b->coordReplacement[i], nbitID);
+ }
+ }
+ if (activeUnit != toCtx->texture.curTextureUnit)
+ diff_api.ActiveTextureARB(GL_TEXTURE0 + toCtx->texture.curTextureUnit);
+ }
+ if (CHECKDIRTY(b->enableSprite, bitID))
+ {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (fEnabled != to->pointSprite)
+ {
+ able[to->pointSprite](GL_POINT_SPRITE_ARB);
+ FILLDIRTY(b->enableSprite);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->enableSprite, nbitID);
+ }
+ else if (fEnabled != to->pointSprite)
+ {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ able[to->pointSprite](GL_POINT_SPRITE_ARB);
+ }
+ CLEARDIRTY(b->dirty, nbitID);
+}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_point.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_point.txt
index 69ab8a70..ba92c153 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_point.txt
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_point.txt
@@ -7,6 +7,7 @@
:minSize:minSize:PointParameterfARB,GL_POINT_SIZE_MIN_ARB
:maxSize:maxSize:PointParameterfARB,GL_POINT_SIZE_MAX_ARB
:fadeThresholdSize:fadeThresholdSize:PointParameterfARB,GL_POINT_FADE_THRESHOLD_SIZE_ARB
+:spriteCoordOrigin:spriteCoordOrigin:PointParameterfARB,GL_POINT_SPRITE_COORD_ORIGIN
#:distanceAttenuation:distanceAttenuation:PointParameterfvARB,GL_POINT_DISTANCE_ATTENUATION_ARB
-:distanceAttenuation:*if (from->distanceAttenuation[0] != to->distanceAttenuation[0] || from->distanceAttenuation[1] != to->distanceAttenuation[1] || from->distanceAttenuation[2] != to->distanceAttenuation[2]) {
-:distanceAttenuation:* diff_api.PointParameterfvARB (GL_POINT_DISTANCE_ATTENUATION_ARB, to->distanceAttenuation);
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c
index 31410bed..611e2f18 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c
@@ -180,8 +180,7 @@ void STATE_APIENTRY crStatePolygonStipple (const GLubyte *p)
if (!p && !crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
{
- crStateError(__LINE__, __FILE__, GL_NO_ERROR,
- "Void pointer passed to PolygonStipple");
+ crDebug("Void pointer passed to PolygonStipple");
return;
}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_program.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_program.c
index 2b0940bb..e8dd5971 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_program.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_program.c
@@ -267,25 +267,10 @@ void STATE_APIENTRY crStateGenProgramsNV(GLsizei n, GLuint *ids)
{
CRContext *g = GetCurrentContext();
CRProgramState *p = &(g->program);
- GLint start, i;
- if (g->current.inBeginEnd) {
- crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
- "glGenProgramsNV called in Begin/End");
- return;
- }
-
- if (n < 0) {
- crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glGenProgramsNV(n)");
- return;
- }
-
- start = crHashtableAllocKeys(p->programHash , n);
- for (i = 0; i < n; i++)
- ids[i] = (GLuint) (start + i);
+ crStateGenNames(g, p->programHash, n, ids);
}
-
void STATE_APIENTRY crStateGenProgramsARB(GLsizei n, GLuint *ids)
{
crStateGenProgramsNV(n, ids);
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c
index eadc228a..6b2a5baa 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2008 Oracle Corporation
+ * Copyright (C) 2008-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -85,6 +85,18 @@ static int32_t crStateAllocAndSSMR3GetMem(PSSMHANDLE pSSM, void **pBuffer, size_
} \
} while (0)
+#define SHCROGL_ROUNDBOUND(_v, _b) (((_v) + ((_b) - 1)) & ~((_b) - 1))
+#define SHCROGL_ALIGNTAILSIZE(_v, _b) (SHCROGL_ROUNDBOUND((_v),(_b)) - (_v))
+#define SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT_SIZE(_type, _field, _oldFieldType, _nextFieldAllignment) (SHCROGL_ALIGNTAILSIZE(((RT_OFFSETOF(_type, _field) + sizeof (_oldFieldType))), (_nextFieldAllignment)))
+#define SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT(_type, _field, _oldFieldType, _nextFieldAllignment) do { \
+ const int32_t cbAlignment = SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT_SIZE(_type, _field, _oldFieldType, _nextFieldAllignment); \
+ /*AssertCompile(SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField) >= 0 && SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField) < sizeof (void*));*/ \
+ if (cbAlignment) { \
+ rc = SSMR3Skip(pSSM, cbAlignment); \
+ } \
+ } while (0)
+
+
#define SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField) (sizeof (_type) - RT_OFFSETOF(_type, _lastField) - RT_SIZEOFMEMB(_type, _lastField))
#define SHCROGL_CUT_TAIL_ALIGNMENT(_type, _lastField) do { \
const int32_t cbAlignment = SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField); \
@@ -139,6 +151,35 @@ static int32_t crStateLoadTextureUnit_v_BEFORE_CTXUSAGE_BITS(CRTextureUnit *t, P
return rc;
}
+static int crStateLoadStencilPoint_v_37(CRPointState *pPoint, PSSMHANDLE pSSM)
+{
+ int rc = VINF_SUCCESS;
+ SHCROGL_GET_STRUCT_HEAD(pPoint, CRPointState, spriteCoordOrigin);
+ pPoint->spriteCoordOrigin = (GLfloat)GL_UPPER_LEFT;
+ return rc;
+}
+
+static int32_t crStateLoadStencilState_v_33(CRStencilState *s, PSSMHANDLE pSSM)
+{
+ CRStencilState_v_33 stencilV33;
+ int32_t rc = SSMR3GetMem(pSSM, &stencilV33, sizeof (stencilV33));
+ AssertRCReturn(rc, rc);
+ s->stencilTest = stencilV33.stencilTest;
+ s->stencilTwoSideEXT = GL_FALSE;
+ s->activeStencilFace = GL_FRONT;
+ s->clearValue = stencilV33.clearValue;
+ s->writeMask = stencilV33.writeMask;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func = stencilV33.func;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask = stencilV33.mask;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref = stencilV33.ref;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail = stencilV33.fail;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail = stencilV33.passDepthFail;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass = stencilV33.passDepthPass;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK] = s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT];
+ crStateStencilBufferInit(&s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK]);
+ return VINF_SUCCESS;
+}
+
static int32_t crStateLoadTextureState_v_BEFORE_CTXUSAGE_BITS(CRTextureState *t, PSSMHANDLE pSSM)
{
GLint i;
@@ -202,6 +243,47 @@ static int32_t crStateLoadTextureState_v_BEFORE_CTXUSAGE_BITS(CRTextureState *t,
SHCROGL_CUT_TAIL_ALIGNMENT(CRTextureState, unit);
+ return VINF_SUCCESS;
+}
+
+static int32_t crStateStencilBufferStack_v_33(CRStencilBufferStack *s, PSSMHANDLE pSSM)
+{
+ CRStencilBufferStack_v_33 stackV33;
+ int32_t rc = SSMR3GetMem(pSSM, &stackV33, sizeof (stackV33));
+
+ s->stencilTest = stackV33.stencilTest;
+ s->stencilTwoSideEXT = GL_FALSE;
+ s->activeStencilFace = GL_FRONT;
+ s->clearValue = stackV33.clearValue;
+ s->writeMask = stackV33.writeMask;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func = stackV33.func;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask = stackV33.mask;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref = stackV33.ref;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail = stackV33.fail;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail = stackV33.passDepthFail;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass = stackV33.passDepthPass;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK] = s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT];
+
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].func = GL_ALWAYS;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].mask = 0xFFFFFFFF;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].ref = 0;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].fail = GL_KEEP;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthFail = GL_KEEP;
+ s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthPass = GL_KEEP;
+
+ return VINF_SUCCESS;
+}
+
+static int32_t crStateLoadAttribState_v_33(CRAttribState *t, PSSMHANDLE pSSM)
+{
+ int32_t i, rc;
+ SHCROGL_GET_STRUCT_HEAD(t, CRAttribState, stencilBufferStack);
+ for (i = 0; i < CR_MAX_ATTRIB_STACK_DEPTH; ++i)
+ {
+ rc = crStateStencilBufferStack_v_33(&t->stencilBufferStack[i], pSSM);
+ AssertRCReturn(rc, rc);
+ }
+ SHCROGL_GET_STRUCT_TAIL(t, CRAttribState, textureStackDepth);
return rc;
}
@@ -221,7 +303,14 @@ static int32_t crStateLoadTextureStack_v_BEFORE_CTXUSAGE_BITS(CRTextureStack *t,
static int32_t crStateLoadAttribState_v_BEFORE_CTXUSAGE_BITS(CRAttribState *t, PSSMHANDLE pSSM)
{
int32_t i, rc;
- SHCROGL_GET_STRUCT_HEAD(t, CRAttribState, textureStack);
+
+ SHCROGL_GET_STRUCT_HEAD(t, CRAttribState, stencilBufferStack);
+ for (i = 0; i < CR_MAX_ATTRIB_STACK_DEPTH; ++i)
+ {
+ rc = crStateStencilBufferStack_v_33(&t->stencilBufferStack[i], pSSM);
+ AssertRCReturn(rc, rc);
+ }
+ SHCROGL_GET_STRUCT_PART(t, CRAttribState, textureStackDepth, textureStack);
for (i = 0; i < CR_MAX_ATTRIB_STACK_DEPTH; ++i)
{
rc = crStateLoadTextureStack_v_BEFORE_CTXUSAGE_BITS(&t->textureStack[i], pSSM);
@@ -1069,6 +1158,15 @@ static void crStateSaveGLSLProgramCB(unsigned long key, void *data1, void *data2
diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen);
diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORMS, &activeUniforms);
+ if (!maxUniformLen)
+ {
+ if (activeUniforms)
+ {
+ crWarning("activeUniforms (%d), while maxUniformLen is zero", activeUniforms);
+ activeUniforms = 0;
+ }
+ }
+
if (activeUniforms>0)
{
name = (GLchar *) crAlloc((maxUniformLen+8)*sizeof(GLchar));
@@ -1148,7 +1246,11 @@ static int32_t crStateSaveClientPointer(CRVertexArrays *pArrays, int32_t index,
cp = crStateGetClientPointerByIndex(index, pArrays);
- rc = SSMR3PutU32(pSSM, cp->buffer->id);
+ if (cp->buffer)
+ rc = SSMR3PutU32(pSSM, cp->buffer->id);
+ else
+ rc = SSMR3PutU32(pSSM, 0);
+
AssertRCReturn(rc, rc);
#ifdef CR_EXT_compiled_vertex_array
@@ -1304,6 +1406,59 @@ static int32_t crStateLoadCurrentBits(CRStateBits *pBits, PSSMHANDLE pSSM)
return VINF_SUCCESS;
}
+static void crStateSaveKeysCB(unsigned long firstKey, unsigned long count, void *data)
+{
+ PSSMHANDLE pSSM = (PSSMHANDLE)data;
+ int rc;
+ CRASSERT(firstKey);
+ CRASSERT(count);
+ rc = SSMR3PutU32(pSSM, firstKey);
+ CRASSERT(RT_SUCCESS(rc));
+ rc = SSMR3PutU32(pSSM, count);
+ CRASSERT(RT_SUCCESS(rc));
+}
+
+static int32_t crStateSaveKeys(CRHashTable *pHash, PSSMHANDLE pSSM)
+{
+ crHashtableWalkKeys(pHash, crStateSaveKeysCB , pSSM);
+ /* use null terminator */
+ SSMR3PutU32(pSSM, 0);
+ return VINF_SUCCESS;
+}
+
+static int32_t crStateLoadKeys(CRHashTable *pHash, PSSMHANDLE pSSM, uint32_t u32Version)
+{
+ uint32_t u32Key, u32Count, i;
+ int rc;
+ for(;;)
+ {
+ rc = SSMR3GetU32(pSSM, &u32Key);
+ AssertRCReturn(rc, rc);
+
+ if (!u32Key)
+ return rc;
+
+ rc = SSMR3GetU32(pSSM, &u32Count);
+ AssertRCReturn(rc, rc);
+
+ CRASSERT(u32Count);
+
+ if (u32Version > SHCROGL_SSM_VERSION_WITH_BUGGY_KEYS)
+ {
+ for (i = u32Key; i < u32Count + u32Key; ++i)
+ {
+ GLboolean fIsNew = crHashtableAllocRegisterKey(pHash, i);
+#if 0 //def DEBUG_misha
+ CRASSERT(fIsNew);
+#endif
+ }
+ }
+ }
+
+ return rc;
+}
+
+
int32_t crStateSaveContext(CRContext *pContext, PSSMHANDLE pSSM)
{
int32_t rc, i;
@@ -1312,30 +1467,18 @@ int32_t crStateSaveContext(CRContext *pContext, PSSMHANDLE pSSM)
CRASSERT(pContext && pSSM);
- pContext->buffer.storedWidth = pContext->buffer.width;
- pContext->buffer.storedHeight = pContext->buffer.height;
+ CRASSERT(pContext->client.attribStackDepth == 0);
- CRASSERT(VBoxTlsRefIsFunctional(pContext));
+ /* this stuff is not used anymore, zero it up for sanity */
+ pContext->buffer.storedWidth = 0;
+ pContext->buffer.storedHeight = 0;
- /* do not increment the saved state version due to VBOXTLSREFDATA addition to CRContext */
- rc = SSMR3PutMem(pSSM, pContext, VBOXTLSREFDATA_OFFSET(CRContext));
- AssertRCReturn(rc, rc);
-
- /* now store bitid & neg_bitid */
- rc = SSMR3PutMem(pSSM, pContext->bitid, sizeof (pContext->bitid) + sizeof (pContext->neg_bitid));
- AssertRCReturn(rc, rc);
+ CRASSERT(VBoxTlsRefIsFunctional(pContext));
- /* the pre-VBOXTLSREFDATA CRContext structure might have additional allignment bits before the CRContext::shared */
- ui32 = VBOXTLSREFDATA_OFFSET(CRContext) + sizeof (pContext->bitid) + sizeof (pContext->neg_bitid);
- ui32 &= (sizeof (void*) - 1);
- if (ui32)
- {
- void* pTmp = NULL;
- rc = SSMR3PutMem(pSSM, &pTmp, ui32);
- AssertRCReturn(rc, rc);
- }
+ /* make sure the gl error state is captured by our state mechanism to store the correct gl error value */
+ crStateSyncHWErrorState(pContext);
- rc = SSMR3PutMem(pSSM, &pContext->shared, sizeof (CRContext) - RT_OFFSETOF(CRContext, shared));
+ rc = SSMR3PutMem(pSSM, pContext, sizeof (*pContext));
AssertRCReturn(rc, rc);
if (crHashtableNumElements(pContext->shared->dlistTable)>0)
@@ -1412,6 +1555,8 @@ int32_t crStateSaveContext(CRContext *pContext, PSSMHANDLE pSSM)
if (bSaveShared)
{
CRASSERT(pContext->shared && pContext->shared->textureTable);
+ rc = crStateSaveKeys(pContext->shared->textureTable, pSSM);
+ AssertRCReturn(rc, rc);
ui32 = crHashtableNumElements(pContext->shared->textureTable);
rc = SSMR3PutU32(pSSM, ui32);
AssertRCReturn(rc, rc);
@@ -1509,6 +1654,11 @@ int32_t crStateSaveContext(CRContext *pContext, PSSMHANDLE pSSM)
#ifdef CR_ARB_vertex_buffer_object
/* Save buffer objects */
+ if (bSaveShared)
+ {
+ rc = crStateSaveKeys(pContext->shared->buffersTable, pSSM);
+ AssertRCReturn(rc, rc);
+ }
ui32 = bSaveShared? crHashtableNumElements(pContext->shared->buffersTable):0;
rc = SSMR3PutU32(pSSM, ui32);
AssertRCReturn(rc, rc);
@@ -1576,10 +1726,15 @@ int32_t crStateSaveContext(CRContext *pContext, PSSMHANDLE pSSM)
/* Save FBOs */
if (bSaveShared)
{
+ rc = crStateSaveKeys(pContext->shared->fbTable, pSSM);
+ AssertRCReturn(rc, rc);
ui32 = crHashtableNumElements(pContext->shared->fbTable);
rc = SSMR3PutU32(pSSM, ui32);
AssertRCReturn(rc, rc);
crHashtableWalk(pContext->shared->fbTable, crStateSaveFramebuffersCB, pSSM);
+
+ rc = crStateSaveKeys(pContext->shared->rbTable, pSSM);
+ AssertRCReturn(rc, rc);
ui32 = crHashtableNumElements(pContext->shared->rbTable);
rc = SSMR3PutU32(pSSM, ui32);
AssertRCReturn(rc, rc);
@@ -1607,72 +1762,6 @@ int32_t crStateSaveContext(CRContext *pContext, PSSMHANDLE pSSM)
AssertRCReturn(rc, rc);
#endif
- if (pContext->buffer.storedWidth && pContext->buffer.storedHeight)
- {
- CRBufferState *pBuf = &pContext->buffer;
- CRPixelPackState packing = pContext->client.pack;
- GLint cbData;
- void *pData;
-
- cbData = crPixelSize(GL_RGBA, GL_UNSIGNED_BYTE) * pBuf->storedWidth * pBuf->storedHeight;
- pData = crAlloc(cbData);
-
- if (!pData)
- {
- return VERR_NO_MEMORY;
- }
-
- diff_api.PixelStorei(GL_PACK_SKIP_ROWS, 0);
- diff_api.PixelStorei(GL_PACK_SKIP_PIXELS, 0);
- diff_api.PixelStorei(GL_PACK_ALIGNMENT, 1);
- diff_api.PixelStorei(GL_PACK_ROW_LENGTH, 0);
- diff_api.PixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
- diff_api.PixelStorei(GL_PACK_SKIP_IMAGES, 0);
- diff_api.PixelStorei(GL_PACK_SWAP_BYTES, 0);
- diff_api.PixelStorei(GL_PACK_LSB_FIRST, 0);
-
- if (pContext->framebufferobject.readFB)
- {
- diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
- }
- if (pContext->bufferobject.packBuffer->hwid>0)
- {
- diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
- }
-
- diff_api.ReadBuffer(GL_FRONT);
- diff_api.ReadPixels(0, 0, pBuf->storedWidth, pBuf->storedHeight, GL_RGBA, GL_UNSIGNED_BYTE, pData);
- rc = SSMR3PutMem(pSSM, pData, cbData);
- AssertRCReturn(rc, rc);
-
- diff_api.ReadBuffer(GL_BACK);
- diff_api.ReadPixels(0, 0, pBuf->storedWidth, pBuf->storedHeight, GL_RGBA, GL_UNSIGNED_BYTE, pData);
- rc = SSMR3PutMem(pSSM, pData, cbData);
- AssertRCReturn(rc, rc);
-
- if (pContext->bufferobject.packBuffer->hwid>0)
- {
- diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pContext->bufferobject.packBuffer->hwid);
- }
- if (pContext->framebufferobject.readFB)
- {
- diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, pContext->framebufferobject.readFB->hwid);
- }
- diff_api.ReadBuffer(pContext->framebufferobject.readFB ?
- pContext->framebufferobject.readFB->readbuffer : pContext->buffer.readBuffer);
-
- diff_api.PixelStorei(GL_PACK_SKIP_ROWS, packing.skipRows);
- diff_api.PixelStorei(GL_PACK_SKIP_PIXELS, packing.skipPixels);
- diff_api.PixelStorei(GL_PACK_ALIGNMENT, packing.alignment);
- diff_api.PixelStorei(GL_PACK_ROW_LENGTH, packing.rowLength);
- diff_api.PixelStorei(GL_PACK_IMAGE_HEIGHT, packing.imageHeight);
- diff_api.PixelStorei(GL_PACK_SKIP_IMAGES, packing.skipImages);
- diff_api.PixelStorei(GL_PACK_SWAP_BYTES, packing.swapBytes);
- diff_api.PixelStorei(GL_PACK_LSB_FIRST, packing.psLSBFirst);
-
- crFree(pData);
- }
-
return VINF_SUCCESS;
}
@@ -1693,6 +1782,77 @@ static void crStateFindSharedCB(unsigned long key, void *data1, void *data2)
}
}
+int32_t crStateSaveGlobals(PSSMHANDLE pSSM)
+{
+ /* don't need that for now */
+#if 0
+ CRStateBits *pBits;
+ int rc;
+
+ CRASSERT(g_cContexts >= 1);
+ if (g_cContexts <= 1)
+ return VINF_SUCCESS;
+
+ pBits = GetCurrentBits();
+#define CRSTATE_BITS_OP(_var, _size) \
+ rc = SSMR3PutMem(pSSM, (pBits->_var), _size); \
+ AssertRCReturn(rc, rc);
+#include "state_bits_globalop.h"
+#undef CRSTATE_BITS_OP
+#endif
+ return VINF_SUCCESS;
+}
+
+int32_t crStateLoadGlobals(PSSMHANDLE pSSM, uint32_t u32Version)
+{
+ CRStateBits *pBits;
+ int rc;
+ CRASSERT(g_cContexts >= 1);
+ if (g_cContexts <= 1)
+ return VINF_SUCCESS;
+
+ pBits = GetCurrentBits();
+
+ if (u32Version >= SHCROGL_SSM_VERSION_WITH_STATE_BITS)
+ {
+#define CRSTATE_BITS_OP(_var, _size) \
+ rc = SSMR3GetMem(pSSM, (pBits->_var), _size); \
+ AssertRCReturn(rc, rc);
+
+ if (u32Version < SHCROGL_SSM_VERSION_WITH_FIXED_STENCIL)
+ {
+#define CRSTATE_BITS_OP_VERSION (SHCROGL_SSM_VERSION_WITH_FIXED_STENCIL - 1)
+#define CRSTATE_BITS_OP_STENCIL_FUNC_V_33(_i, _var) do {} while (0)
+#define CRSTATE_BITS_OP_STENCIL_OP_V_33(_i, _var) do {} while (0)
+#include "state_bits_globalop.h"
+#undef CRSTATE_BITS_OP_VERSION
+#undef CRSTATE_BITS_OP_STENCIL_FUNC_V_33
+#undef CRSTATE_BITS_OP_STENCIL_OP_V_33
+ }
+ else if (u32Version < SHCROGL_SSM_VERSION_WITH_SPRITE_COORD_ORIGIN)
+ {
+#define CRSTATE_BITS_OP_VERSION (SHCROGL_SSM_VERSION_WITH_SPRITE_COORD_ORIGIN - 1)
+#include "state_bits_globalop.h"
+#undef CRSTATE_BITS_OP_VERSION
+ }
+ else
+ {
+ /* we do not put dirty bits to state anymore,
+ * nop */
+//#include "state_bits_globalop.h"
+ }
+#undef CRSTATE_BITS_OP
+ /* always dirty all bits */
+ /* return VINF_SUCCESS; */
+ }
+
+#define CRSTATE_BITS_OP(_var, _size) FILLDIRTY(pBits->_var);
+#include "state_bits_globalop.h"
+#undef CRSTATE_BITS_OP
+ return VINF_SUCCESS;
+}
+
+
#define SLC_COPYPTR(ptr) pTmpContext->ptr = pContext->ptr
#define SLC_ASSSERT_NULL_PTR(ptr) CRASSERT(!pContext->ptr)
@@ -1707,12 +1867,7 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
uint32_t uiNumElems, ui, k;
unsigned long key;
GLboolean bLoadShared = GL_TRUE;
- union {
- CRbitvalue bitid[CR_MAX_BITARRAY];
- struct {
- VBOXTLSREFDATA
- } tlsRef;
- } bitid;
+ GLenum err;
CRASSERT(pContext && pSSM);
@@ -1723,70 +1878,130 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
CRASSERT(VBoxTlsRefIsFunctional(pContext));
- /* do not increment the saved state version due to VBOXTLSREFDATA addition to CRContext */
- rc = SSMR3GetMem(pSSM, pTmpContext, VBOXTLSREFDATA_OFFSET(CRContext));
- AssertRCReturn(rc, rc);
-
- /* VBox 4.1.8 had a bug that VBOXTLSREFDATA was also stored in the snapshot,
- * thus the saved state data format was changed w/o changing the saved state version.
- * here we determine whether the saved state contains VBOXTLSREFDATA, and if so, treat it accordingly */
- rc = SSMR3GetMem(pSSM, &bitid, sizeof (bitid));
- AssertRCReturn(rc, rc);
-
- /* the bitid array has one bit set only. this is why if bitid.tlsRef has both cTlsRefs
- * and enmTlsRefState non-zero - this is definitely NOT a bit id and is a VBOXTLSREFDATA */
- if (bitid.tlsRef.enmTlsRefState == VBOXTLSREFDATA_STATE_INITIALIZED
- && bitid.tlsRef.cTlsRefs)
+ if (u32Version <= SHCROGL_SSM_VERSION_WITH_INVALID_ERROR_STATE)
{
- /* VBOXTLSREFDATA is stored, skip it */
- crMemcpy(&pTmpContext->bitid, ((uint8_t*)&bitid) + VBOXTLSREFDATA_SIZE(), sizeof (bitid) - VBOXTLSREFDATA_SIZE());
- rc = SSMR3GetMem(pSSM, ((uint8_t*)&pTmpContext->bitid) + sizeof (pTmpContext->bitid) - VBOXTLSREFDATA_SIZE(), sizeof (pTmpContext->neg_bitid) + VBOXTLSREFDATA_SIZE());
+ union {
+ CRbitvalue bitid[CR_MAX_BITARRAY];
+ struct {
+ VBOXTLSREFDATA
+ } tlsRef;
+ } bitid;
+
+ /* do not increment the saved state version due to VBOXTLSREFDATA addition to CRContext */
+ rc = SSMR3GetMem(pSSM, pTmpContext, VBOXTLSREFDATA_OFFSET(CRContext));
AssertRCReturn(rc, rc);
- ui = VBOXTLSREFDATA_OFFSET(CRContext) + VBOXTLSREFDATA_SIZE() + sizeof (pTmpContext->bitid) + sizeof (pTmpContext->neg_bitid);
- ui = RT_OFFSETOF(CRContext, shared) - ui;
- }
- else
- {
- /* VBOXTLSREFDATA is NOT stored */
- crMemcpy(&pTmpContext->bitid, &bitid, sizeof (bitid));
- rc = SSMR3GetMem(pSSM, &pTmpContext->neg_bitid, sizeof (pTmpContext->neg_bitid));
+ /* VBox 4.1.8 had a bug that VBOXTLSREFDATA was also stored in the snapshot,
+ * thus the saved state data format was changed w/o changing the saved state version.
+ * here we determine whether the saved state contains VBOXTLSREFDATA, and if so, treat it accordingly */
+ rc = SSMR3GetMem(pSSM, &bitid, sizeof (bitid));
AssertRCReturn(rc, rc);
- /* the pre-VBOXTLSREFDATA CRContext structure might have additional allignment bits before the CRContext::shared */
- ui = VBOXTLSREFDATA_OFFSET(CRContext) + sizeof (pTmpContext->bitid) + sizeof (pTmpContext->neg_bitid);
+ /* the bitid array has one bit set only. this is why if bitid.tlsRef has both cTlsRefs
+ * and enmTlsRefState non-zero - this is definitely NOT a bit id and is a VBOXTLSREFDATA */
+ if (bitid.tlsRef.enmTlsRefState == VBOXTLSREFDATA_STATE_INITIALIZED
+ && bitid.tlsRef.cTlsRefs)
+ {
+ /* VBOXTLSREFDATA is stored, skip it */
+ crMemcpy(&pTmpContext->bitid, ((uint8_t*)&bitid) + VBOXTLSREFDATA_SIZE(), sizeof (bitid) - VBOXTLSREFDATA_SIZE());
+ rc = SSMR3GetMem(pSSM, ((uint8_t*)&pTmpContext->bitid) + sizeof (pTmpContext->bitid) - VBOXTLSREFDATA_SIZE(), sizeof (pTmpContext->neg_bitid) + VBOXTLSREFDATA_SIZE());
+ AssertRCReturn(rc, rc);
- ui &= (sizeof (void*) - 1);
- }
+ ui = VBOXTLSREFDATA_OFFSET(CRContext) + VBOXTLSREFDATA_SIZE() + sizeof (pTmpContext->bitid) + sizeof (pTmpContext->neg_bitid);
+ ui = RT_OFFSETOF(CRContext, shared) - ui;
+ }
+ else
+ {
+ /* VBOXTLSREFDATA is NOT stored */
+ crMemcpy(&pTmpContext->bitid, &bitid, sizeof (bitid));
+ rc = SSMR3GetMem(pSSM, &pTmpContext->neg_bitid, sizeof (pTmpContext->neg_bitid));
+ AssertRCReturn(rc, rc);
- if (ui)
- {
- void* pTmp = NULL;
- rc = SSMR3GetMem(pSSM, &pTmp, ui);
- AssertRCReturn(rc, rc);
- }
+ /* the pre-VBOXTLSREFDATA CRContext structure might have additional allignment bits before the CRContext::shared */
+ ui = VBOXTLSREFDATA_OFFSET(CRContext) + sizeof (pTmpContext->bitid) + sizeof (pTmpContext->neg_bitid);
- /* we will later do crMemcpy from entire pTmpContext to pContext,
- * for simplicity store the VBOXTLSREFDATA from the pContext to pTmpContext */
- VBOXTLSREFDATA_COPY(pTmpContext, pContext);
+ ui &= (sizeof (void*) - 1);
+ }
- if (u32Version == SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS)
+ if (ui)
+ {
+ void* pTmp = NULL;
+ rc = SSMR3GetMem(pSSM, &pTmp, ui);
+ AssertRCReturn(rc, rc);
+ }
+
+ if (u32Version == SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS)
+ {
+ SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, shared, attrib);
+ rc = crStateLoadAttribState_v_BEFORE_CTXUSAGE_BITS(&pTmpContext->attrib, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRContext, attrib, buffer);
+ SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, buffer, point);
+ rc = crStateLoadStencilPoint_v_37(&pTmpContext->point, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, polygon, stencil);
+ rc = crStateLoadStencilState_v_33(&pTmpContext->stencil, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT(CRContext, stencil, CRStencilState_v_33, sizeof (void*));
+ rc = crStateLoadTextureState_v_BEFORE_CTXUSAGE_BITS(&pTmpContext->texture, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRContext, texture, transform);
+ SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, transform);
+ }
+ else
+ {
+ SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, shared, attrib);
+ rc = crStateLoadAttribState_v_33(&pTmpContext->attrib, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_CUT_FIELD_ALIGNMENT(CRContext, attrib, buffer);
+ SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, buffer, point);
+ rc = crStateLoadStencilPoint_v_37(&pTmpContext->point, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, polygon, stencil);
+ rc = crStateLoadStencilState_v_33(&pTmpContext->stencil, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT(CRContext, stencil, CRStencilState_v_33, sizeof (void*));
+ SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, texture);
+ }
+
+ pTmpContext->error = GL_NO_ERROR; /* <- the error state contained some random error data here
+ * treat as no error */
+ }
+ else if (u32Version < SHCROGL_SSM_VERSION_WITH_FIXED_STENCIL)
{
- SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, shared, attrib);
- rc = crStateLoadAttribState_v_BEFORE_CTXUSAGE_BITS(&pTmpContext->attrib, pSSM);
+ SHCROGL_GET_STRUCT_HEAD(pTmpContext, CRContext, attrib);
+ rc = crStateLoadAttribState_v_33(&pTmpContext->attrib, pSSM);
AssertRCReturn(rc, rc);
SHCROGL_CUT_FIELD_ALIGNMENT(CRContext, attrib, buffer);
- SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, buffer, texture);
- rc = crStateLoadTextureState_v_BEFORE_CTXUSAGE_BITS(&pTmpContext->texture, pSSM);
+ SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, buffer, point);
+ rc = crStateLoadStencilPoint_v_37(&pTmpContext->point, pSSM);
AssertRCReturn(rc, rc);
- SHCROGL_CUT_FIELD_ALIGNMENT(CRContext, texture, transform);
- SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, transform);
+ SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, polygon, stencil);
+ rc = crStateLoadStencilState_v_33(&pTmpContext->stencil, pSSM);
+ AssertRCReturn(rc, rc);
+ SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT(CRContext, stencil, CRStencilState_v_33, sizeof (void*));
+ SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, texture);
+ }
+ else if (u32Version < SHCROGL_SSM_VERSION_WITH_SPRITE_COORD_ORIGIN)
+ {
+ SHCROGL_GET_STRUCT_HEAD(pTmpContext, CRContext, point);
+ crStateLoadStencilPoint_v_37(&pTmpContext->point, pSSM);
+ SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, polygon);
}
else
{
- SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, shared);
+ rc = SSMR3GetMem(pSSM, pTmpContext, sizeof (*pTmpContext));
+ AssertRCReturn(rc, rc);
}
+ /* preserve the error to restore it at the end of context creation,
+ * it should not normally change, but just in case it it changed */
+ err = pTmpContext->error;
+
+ /* we will later do crMemcpy from entire pTmpContext to pContext,
+ * for simplicity store the VBOXTLSREFDATA from the pContext to pTmpContext */
+ VBOXTLSREFDATA_COPY(pTmpContext, pContext);
+
/* Deal with shared state */
{
crFindSharedCtxParms_t parms;
@@ -2018,6 +2233,13 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
{
/* Load shared textures */
CRASSERT(pContext->shared && pContext->shared->textureTable);
+
+ if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS)
+ {
+ rc = crStateLoadKeys(pContext->shared->buffersTable, pSSM, u32Version);
+ AssertRCReturn(rc, rc);
+ }
+
rc = SSMR3GetU32(pSSM, &uiNumElems);
AssertRCReturn(rc, rc);
for (ui=0; ui<uiNumElems; ++ui)
@@ -2120,6 +2342,15 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
/* Load buffer objects */
#ifdef CR_ARB_vertex_buffer_object
+ if (bLoadShared)
+ {
+ if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS)
+ {
+ rc = crStateLoadKeys(pContext->shared->textureTable, pSSM, u32Version);
+ AssertRCReturn(rc, rc);
+ }
+ }
+
rc = SSMR3GetU32(pSSM, &uiNumElems);
AssertRCReturn(rc, rc);
for (ui=0; ui<=uiNumElems; ++ui) /*ui<=uiNumElems to load nullBuffer in same loop*/
@@ -2242,6 +2473,12 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
/* Load FBOs */
if (bLoadShared)
{
+ if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS)
+ {
+ rc = crStateLoadKeys(pContext->shared->fbTable, pSSM, u32Version);
+ AssertRCReturn(rc, rc);
+ }
+
rc = SSMR3GetU32(pSSM, &uiNumElems);
AssertRCReturn(rc, rc);
for (ui=0; ui<uiNumElems; ++ui)
@@ -2256,9 +2493,17 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
rc = crStateLoadFramebufferObject(pFBO, pSSM, u32Version);
AssertRCReturn(rc, rc);
+ Assert(key == pFBO->id);
+
crHashtableAdd(pContext->shared->fbTable, key, pFBO);
}
+ if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS)
+ {
+ rc = crStateLoadKeys(pContext->shared->rbTable, pSSM, u32Version);
+ AssertRCReturn(rc, rc);
+ }
+
rc = SSMR3GetU32(pSSM, &uiNumElems);
AssertRCReturn(rc, rc);
for (ui=0; ui<uiNumElems; ++ui)
@@ -2304,7 +2549,10 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
for (ui=0; ui<uiNumElems; ++ui)
{
CRGLSLShader *pShader = crStateLoadGLSLShader(pSSM);
+ GLboolean fNewKeyCheck;
if (!pShader) return VERR_SSM_UNEXPECTED_DATA;
+ fNewKeyCheck = crHashtableAllocRegisterKey(pContext->glsl.programs, pShader->id);
+ CRASSERT(fNewKeyCheck);
crHashtableAdd(pContext->glsl.shaders, pShader->id, pShader);
}
@@ -2416,310 +2664,11 @@ int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRST
pContext->glsl.bResyncNeeded = GL_TRUE;
#endif
-
- /*Restore front/back buffer images*/
- if (pContext->buffer.storedWidth && pContext->buffer.storedHeight)
- {
- CRBufferState *pBuf = &pContext->buffer;
- GLint cbData;
- void *pData;
-
- cbData = crPixelSize(GL_RGBA, GL_UNSIGNED_BYTE) * pBuf->storedWidth * pBuf->storedHeight;
-
- pData = crAlloc(cbData);
- if (!pData)
- {
- pBuf->pFrontImg = NULL;
- pBuf->pBackImg = NULL;
- return VERR_NO_MEMORY;
- }
-
- rc = SSMR3GetMem(pSSM, pData, cbData);
- AssertRCReturn(rc, rc);
-
- pBuf->pFrontImg = pData;
-
- pData = crAlloc(cbData);
- if (!pData)
- {
- pBuf->pBackImg = NULL;
- return VERR_NO_MEMORY;
- }
-
- rc = SSMR3GetMem(pSSM, pData, cbData);
- AssertRCReturn(rc, rc);
-
- pBuf->pBackImg = pData;
- }
-
-
- /*Mark all as dirty to make sure we'd restore correct context state*/
+ if (pContext->error != err)
{
- CRStateBits *pBits = GetCurrentBits();
-
- FILLDIRTY(pBits->attrib.dirty);
-
- FILLDIRTY(pBits->buffer.dirty);
- FILLDIRTY(pBits->buffer.enable);
- FILLDIRTY(pBits->buffer.alphaFunc);
- FILLDIRTY(pBits->buffer.depthFunc);
- FILLDIRTY(pBits->buffer.blendFunc);
- FILLDIRTY(pBits->buffer.logicOp);
- FILLDIRTY(pBits->buffer.indexLogicOp);
- FILLDIRTY(pBits->buffer.drawBuffer);
- FILLDIRTY(pBits->buffer.readBuffer);
- FILLDIRTY(pBits->buffer.indexMask);
- FILLDIRTY(pBits->buffer.colorWriteMask);
- FILLDIRTY(pBits->buffer.clearColor);
- FILLDIRTY(pBits->buffer.clearIndex);
- FILLDIRTY(pBits->buffer.clearDepth);
- FILLDIRTY(pBits->buffer.clearAccum);
- FILLDIRTY(pBits->buffer.depthMask);
-#ifdef CR_EXT_blend_color
- FILLDIRTY(pBits->buffer.blendColor);
-#endif
-#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op)
- FILLDIRTY(pBits->buffer.blendEquation);
-#endif
-#if defined(CR_EXT_blend_func_separate)
- FILLDIRTY(pBits->buffer.blendFuncSeparate);
-#endif
-
-#ifdef CR_ARB_vertex_buffer_object
- FILLDIRTY(pBits->bufferobject.dirty);
- FILLDIRTY(pBits->bufferobject.arrayBinding);
- FILLDIRTY(pBits->bufferobject.elementsBinding);
-# ifdef CR_ARB_pixel_buffer_object
- FILLDIRTY(pBits->bufferobject.packBinding);
- FILLDIRTY(pBits->bufferobject.unpackBinding);
-# endif
-#endif
-
- FILLDIRTY(pBits->client.dirty);
- FILLDIRTY(pBits->client.pack);
- FILLDIRTY(pBits->client.unpack);
- FILLDIRTY(pBits->client.enableClientState);
- FILLDIRTY(pBits->client.clientPointer);
- FILLDIRTY(pBits->client.v);
- FILLDIRTY(pBits->client.n);
- FILLDIRTY(pBits->client.c);
- FILLDIRTY(pBits->client.i);
- FILLDIRTY(pBits->client.e);
- FILLDIRTY(pBits->client.s);
- FILLDIRTY(pBits->client.f);
- for (i=0; i<CR_MAX_TEXTURE_UNITS; i++)
- {
- FILLDIRTY(pBits->client.t[i]);
- }
-#ifdef CR_NV_vertex_program
- for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++)
- {
- FILLDIRTY(pBits->client.a[i]);
- }
-#endif
-
- FILLDIRTY(pBits->current.dirty);
- for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++)
- {
- FILLDIRTY(pBits->current.vertexAttrib[i]);
- }
- FILLDIRTY(pBits->current.edgeFlag);
- FILLDIRTY(pBits->current.colorIndex);
- FILLDIRTY(pBits->current.rasterPos);
-
-
- FILLDIRTY(pBits->eval.dirty);
- for (i=0; i<GLEVAL_TOT; i++)
- {
- FILLDIRTY(pBits->eval.eval1D[i]);
- FILLDIRTY(pBits->eval.eval2D[i]);
- FILLDIRTY(pBits->eval.enable1D[i]);
- FILLDIRTY(pBits->eval.enable2D[i]);
- }
- FILLDIRTY(pBits->eval.enable);
- FILLDIRTY(pBits->eval.grid1D);
- FILLDIRTY(pBits->eval.grid2D);
-#ifdef CR_NV_vertex_program
- /*@todo Those seems to be unused?
- FILLDIRTY(pBits->eval.enableAttrib1D);
- FILLDIRTY(pBits->eval.enableAttrib2D);
- */
-#endif
-
- FILLDIRTY(pBits->feedback.dirty);
- FILLDIRTY(pBits->selection.dirty);
-
- FILLDIRTY(pBits->fog.dirty);
- FILLDIRTY(pBits->fog.color);
- FILLDIRTY(pBits->fog.index);
- FILLDIRTY(pBits->fog.density);
- FILLDIRTY(pBits->fog.start);
- FILLDIRTY(pBits->fog.end);
- FILLDIRTY(pBits->fog.mode);
- FILLDIRTY(pBits->fog.enable);
-#ifdef CR_NV_fog_distance
- FILLDIRTY(pBits->fog.fogDistanceMode);
-#endif
-#ifdef CR_EXT_fog_coord
- FILLDIRTY(pBits->fog.fogCoordinateSource);
-#endif
-
- FILLDIRTY(pBits->hint.dirty);
- FILLDIRTY(pBits->hint.perspectiveCorrection);
- FILLDIRTY(pBits->hint.pointSmooth);
- FILLDIRTY(pBits->hint.lineSmooth);
- FILLDIRTY(pBits->hint.polygonSmooth);
- FILLDIRTY(pBits->hint.fog);
-#ifdef CR_EXT_clip_volume_hint
- FILLDIRTY(pBits->hint.clipVolumeClipping);
-
-#endif
-#ifdef CR_ARB_texture_compression
- FILLDIRTY(pBits->hint.textureCompression);
-#endif
-#ifdef CR_SGIS_generate_mipmap
- FILLDIRTY(pBits->hint.generateMipmap);
-#endif
-
- FILLDIRTY(pBits->lighting.dirty);
- FILLDIRTY(pBits->lighting.shadeModel);
- FILLDIRTY(pBits->lighting.colorMaterial);
- FILLDIRTY(pBits->lighting.lightModel);
- FILLDIRTY(pBits->lighting.material);
- FILLDIRTY(pBits->lighting.enable);
- for (i=0; i<CR_MAX_LIGHTS; ++i)
- {
- FILLDIRTY(pBits->lighting.light[i].dirty);
- FILLDIRTY(pBits->lighting.light[i].enable);
- FILLDIRTY(pBits->lighting.light[i].ambient);
- FILLDIRTY(pBits->lighting.light[i].diffuse);
- FILLDIRTY(pBits->lighting.light[i].specular);
- FILLDIRTY(pBits->lighting.light[i].position);
- FILLDIRTY(pBits->lighting.light[i].attenuation);
- FILLDIRTY(pBits->lighting.light[i].spot);
- }
-
- FILLDIRTY(pBits->line.dirty);
- FILLDIRTY(pBits->line.enable);
- FILLDIRTY(pBits->line.width);
- FILLDIRTY(pBits->line.stipple);
-
- FILLDIRTY(pBits->lists.dirty);
- FILLDIRTY(pBits->lists.base);
-
- FILLDIRTY(pBits->multisample.dirty);
- FILLDIRTY(pBits->multisample.enable);
- FILLDIRTY(pBits->multisample.sampleAlphaToCoverage);
- FILLDIRTY(pBits->multisample.sampleAlphaToOne);
- FILLDIRTY(pBits->multisample.sampleCoverage);
- FILLDIRTY(pBits->multisample.sampleCoverageValue);
-
-#if CR_ARB_occlusion_query
- FILLDIRTY(pBits->occlusion.dirty);
-#endif
-
- FILLDIRTY(pBits->pixel.dirty);
- FILLDIRTY(pBits->pixel.transfer);
- FILLDIRTY(pBits->pixel.zoom);
- FILLDIRTY(pBits->pixel.maps);
-
- FILLDIRTY(pBits->point.dirty);
- FILLDIRTY(pBits->point.enableSmooth);
- FILLDIRTY(pBits->point.size);
-#ifdef CR_ARB_point_parameters
- FILLDIRTY(pBits->point.minSize);
- FILLDIRTY(pBits->point.maxSize);
- FILLDIRTY(pBits->point.fadeThresholdSize);
- FILLDIRTY(pBits->point.distanceAttenuation);
-#endif
-#ifdef CR_ARB_point_sprite
- FILLDIRTY(pBits->point.enableSprite);
- for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
- {
- FILLDIRTY(pBits->point.coordReplacement[i]);
- }
-#endif
-
- FILLDIRTY(pBits->polygon.dirty);
- FILLDIRTY(pBits->polygon.enable);
- FILLDIRTY(pBits->polygon.offset);
- FILLDIRTY(pBits->polygon.mode);
- FILLDIRTY(pBits->polygon.stipple);
-
- FILLDIRTY(pBits->program.dirty);
- FILLDIRTY(pBits->program.vpEnable);
- FILLDIRTY(pBits->program.fpEnable);
- FILLDIRTY(pBits->program.vpBinding);
- FILLDIRTY(pBits->program.fpBinding);
- for (i=0; i<CR_MAX_VERTEX_ATTRIBS; ++i)
- {
- FILLDIRTY(pBits->program.vertexAttribArrayEnable[i]);
- FILLDIRTY(pBits->program.map1AttribArrayEnable[i]);
- FILLDIRTY(pBits->program.map2AttribArrayEnable[i]);
- }
- for (i=0; i<CR_MAX_VERTEX_PROGRAM_ENV_PARAMS; ++i)
- {
- FILLDIRTY(pBits->program.vertexEnvParameter[i]);
- }
- for (i=0; i<CR_MAX_FRAGMENT_PROGRAM_ENV_PARAMS; ++i)
- {
- FILLDIRTY(pBits->program.fragmentEnvParameter[i]);
- }
- FILLDIRTY(pBits->program.vertexEnvParameters);
- FILLDIRTY(pBits->program.fragmentEnvParameters);
- for (i=0; i<CR_MAX_VERTEX_PROGRAM_ENV_PARAMS/4; ++i)
- {
- FILLDIRTY(pBits->program.trackMatrix[i]);
- }
-
- FILLDIRTY(pBits->regcombiner.dirty);
- FILLDIRTY(pBits->regcombiner.enable);
- FILLDIRTY(pBits->regcombiner.regCombinerVars);
- FILLDIRTY(pBits->regcombiner.regCombinerColor0);
- FILLDIRTY(pBits->regcombiner.regCombinerColor1);
- for (i=0; i<CR_MAX_GENERAL_COMBINERS; ++i)
- {
- FILLDIRTY(pBits->regcombiner.regCombinerStageColor0[i]);
- FILLDIRTY(pBits->regcombiner.regCombinerStageColor1[i]);
- FILLDIRTY(pBits->regcombiner.regCombinerInput[i]);
- FILLDIRTY(pBits->regcombiner.regCombinerOutput[i]);
- }
- FILLDIRTY(pBits->regcombiner.regCombinerFinalInput);
-
- FILLDIRTY(pBits->stencil.dirty);
- FILLDIRTY(pBits->stencil.enable);
- FILLDIRTY(pBits->stencil.func);
- FILLDIRTY(pBits->stencil.op);
- FILLDIRTY(pBits->stencil.clearValue);
- FILLDIRTY(pBits->stencil.writeMask);
-
- FILLDIRTY(pBits->texture.dirty);
- for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
- {
- FILLDIRTY(pBits->texture.enable[i]);
- FILLDIRTY(pBits->texture.current[i]);
- FILLDIRTY(pBits->texture.objGen[i]);
- FILLDIRTY(pBits->texture.eyeGen[i]);
- FILLDIRTY(pBits->texture.genMode[i]);
- FILLDIRTY(pBits->texture.envBit[i]);
- }
-
- FILLDIRTY(pBits->transform.dirty);
- FILLDIRTY(pBits->transform.matrixMode);
- FILLDIRTY(pBits->transform.modelviewMatrix);
- FILLDIRTY(pBits->transform.projectionMatrix);
- FILLDIRTY(pBits->transform.colorMatrix);
- FILLDIRTY(pBits->transform.textureMatrix);
- FILLDIRTY(pBits->transform.programMatrix);
- FILLDIRTY(pBits->transform.clipPlane);
- FILLDIRTY(pBits->transform.enable);
- FILLDIRTY(pBits->transform.base);
-
- FILLDIRTY(pBits->viewport.dirty);
- FILLDIRTY(pBits->viewport.v_dims);
- FILLDIRTY(pBits->viewport.s_dims);
- FILLDIRTY(pBits->viewport.enable);
- FILLDIRTY(pBits->viewport.depth);
+ crWarning("context error state changed on context restore, was 0x%x, but became 0x%x, resetting to its original value",
+ err, pContext->error);
+ pContext->error = err;
}
return VINF_SUCCESS;
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_special b/src/VBox/GuestHost/OpenGL/state_tracker/state_special
index e0bcc305..dfdca2f1 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_special
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_special
@@ -157,6 +157,9 @@ GetIntegerv
GetError
StencilFunc
StencilOp
+StencilFuncSeparate
+StencilOpSeparate
+ActiveStencilFaceEXT
ClearStencil
StencilMask
Viewport
@@ -375,3 +378,7 @@ ValidateProgram
BindAttribLocation
GetUniformLocation
CopyTexImage2D
+GenFramebuffersEXT
+GenRenderbuffersEXT
+IsRenderbufferEXT
+IsFramebufferEXT
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c
index e284b31a..d543e301 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c
@@ -9,24 +9,74 @@
#include "state/cr_statetypes.h"
#include "state_internals.h"
+
+static GLint crStateStencilBufferGetIdxAndCount(CRStencilState *s, GLenum face, GLint *pIdx, GLint *pBitsIdx)
+{
+ switch (face)
+ {
+ case GL_FRONT_AND_BACK:
+ *pIdx = 0;
+ *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK;
+ return 2;
+ case GL_FRONT:
+ *pIdx = CRSTATE_STENCIL_BUFFER_ID_FRONT;
+ *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_FRONT;
+ return 1;
+ case GL_BACK:
+ *pIdx = CRSTATE_STENCIL_BUFFER_ID_BACK;
+ *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_BACK;
+ return 1;
+ case 0:
+ if (!s->stencilTwoSideEXT || s->activeStencilFace == GL_FRONT)
+ {
+ /* both front and back */
+ *pIdx = 0;
+ *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK;
+ return 2;
+ }
+ *pIdx = CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK;
+ *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK;
+ return 1;
+ default:
+ crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateStencilBufferGetIdxAndCount");
+ return 0;
+ }
+ crError("should never be here!");
+ return 0;
+}
+
+void crStateStencilBufferInit(CRStencilBufferState *s)
+{
+ s->func = GL_ALWAYS;
+ s->mask = 0xFFFFFFFF;
+ s->ref = 0;
+
+ s->fail = GL_KEEP;
+ s->passDepthFail = GL_KEEP;
+ s->passDepthPass = GL_KEEP;
+}
+
+static void crStateStencilBufferRefBitsInit(CRContext *ctx, CRStencilBufferRefBits *sb)
+{
+ RESET(sb->func, ctx->bitid);
+ RESET(sb->op, ctx->bitid);
+}
+
void crStateStencilInit(CRContext *ctx)
{
CRStencilState *s = &ctx->stencil;
CRStateBits *stateb = GetCurrentBits();
CRStencilBits *sb = &(stateb->stencil);
+ int i;
s->stencilTest = GL_FALSE;
RESET(sb->enable, ctx->bitid);
- s->func = GL_ALWAYS;
- s->mask = 0xFFFFFFFF;
- s->ref = 0;
- RESET(sb->func, ctx->bitid);
+ s->stencilTwoSideEXT = GL_FALSE;
+ RESET(sb->enableTwoSideEXT, ctx->bitid);
- s->fail = GL_KEEP;
- s->passDepthFail = GL_KEEP;
- s->passDepthPass = GL_KEEP;
- RESET(sb->op, ctx->bitid);
+ s->activeStencilFace = GL_FRONT;
+ RESET(sb->activeStencilFace, ctx->bitid);
s->clearValue = 0;
RESET(sb->clearValue, ctx->bitid);
@@ -35,53 +85,101 @@ void crStateStencilInit(CRContext *ctx)
RESET(sb->writeMask, ctx->bitid);
RESET(sb->dirty, ctx->bitid);
+
+ for (i = 0; i < CRSTATE_STENCIL_BUFFER_COUNT; ++i)
+ {
+ crStateStencilBufferInit(&s->buffers[i]);
+ }
+
+ for (i = 0; i < CRSTATE_STENCIL_BUFFER_REF_COUNT; ++i)
+ {
+ crStateStencilBufferRefBitsInit(ctx, &sb->bufferRefs[i]);
+ }
}
-void STATE_APIENTRY crStateStencilFunc(GLenum func, GLint ref, GLuint mask)
+static void crStateStencilBufferFunc(CRContext *g, CRStencilBufferState *s, GLenum func, GLint ref, GLuint mask)
{
- CRContext *g = GetCurrentContext();
- CRStencilState *s = &(g->stencil);
- CRStateBits *stateb = GetCurrentBits();
- CRStencilBits *sb = &(stateb->stencil);
+ s->func = func;
+ s->ref = ref;
+ s->mask = mask;
+}
+static void crStateStencilFuncPerform(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+ CRContext *g = GetCurrentContext();
+ CRStencilState *s = &(g->stencil);
+ CRStateBits *stateb = GetCurrentBits();
+ CRStencilBits *sb = &(stateb->stencil);
+ GLint idx, bitsIdx, count, i;
- if (g->current.inBeginEnd)
- {
- crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
- "glStencilFunc called in begin/end");
- return;
- }
- FLUSH();
+ if (g->current.inBeginEnd)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
+ "glStencilFunc called in begin/end");
+ return;
+ }
- if (func != GL_NEVER &&
- func != GL_LESS &&
- func != GL_LEQUAL &&
- func != GL_GREATER &&
- func != GL_GEQUAL &&
- func != GL_EQUAL &&
- func != GL_NOTEQUAL &&
- func != GL_ALWAYS)
- {
- crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
- "glStencilFunc called with bogu func: %d", func);
- return;
- }
+ FLUSH();
- s->func = func;
- s->ref = ref;
- s->mask = mask;
+ if (func != GL_NEVER &&
+ func != GL_LESS &&
+ func != GL_LEQUAL &&
+ func != GL_GREATER &&
+ func != GL_GEQUAL &&
+ func != GL_EQUAL &&
+ func != GL_NOTEQUAL &&
+ func != GL_ALWAYS)
+ {
+ crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
+ "glStencilFunc called with bogu func: %d", func);
+ return;
+ }
- DIRTY(sb->func, g->neg_bitid);
- DIRTY(sb->dirty, g->neg_bitid);
+ count = crStateStencilBufferGetIdxAndCount(s, face, &idx, &bitsIdx);
+ if (count)
+ {
+ for (i = idx; i < idx + count; ++i)
+ {
+ crStateStencilBufferFunc(g, &s->buffers[i], func, ref, mask);
+ }
+ DIRTY(sb->bufferRefs[bitsIdx].func, g->neg_bitid);
+
+ DIRTY(sb->dirty, g->neg_bitid);
+ }
+}
+
+void STATE_APIENTRY crStateStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+ if (!face)
+ {
+ /* crStateStencilFuncPerform accepts 0 value, while glStencilFuncSeparate does not,
+ * filter it out here */
+ crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateStencilFuncSeparate");
+ return;
+ }
+ crStateStencilFuncPerform(face, func, ref, mask);
}
-void STATE_APIENTRY crStateStencilOp (GLenum fail, GLenum zfail, GLenum zpass)
+void STATE_APIENTRY crStateStencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+ crStateStencilFuncPerform(0, func, ref, mask);
+}
+
+static void STATE_APIENTRY crStateStencilBufferOp (CRContext *g, CRStencilBufferState *s, GLenum fail, GLenum zfail, GLenum zpass)
+{
+ s->fail = fail;
+ s->passDepthFail = zfail;
+ s->passDepthPass = zpass;
+}
+
+static void crStateStencilOpPerform (GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
{
CRContext *g = GetCurrentContext();
CRStencilState *s = &(g->stencil);
CRStateBits *stateb = GetCurrentBits();
CRStencilBits *sb = &(stateb->stencil);
+ GLint idx, bitsIdx, count, i;
if (g->current.inBeginEnd)
{
@@ -146,14 +244,36 @@ void STATE_APIENTRY crStateStencilOp (GLenum fail, GLenum zfail, GLenum zpass)
return;
}
- s->fail = fail;
- s->passDepthFail = zfail;
- s->passDepthPass = zpass;
+ count = crStateStencilBufferGetIdxAndCount(s, face, &idx, &bitsIdx);
+ if (count)
+ {
+ for (i = idx; i < idx + count; ++i)
+ {
+ crStateStencilBufferOp(g, &s->buffers[i], fail, zfail, zpass);
+ }
- DIRTY(sb->op, g->neg_bitid);
- DIRTY(sb->dirty, g->neg_bitid);
+ DIRTY(sb->bufferRefs[bitsIdx].op, g->neg_bitid);
+
+ DIRTY(sb->dirty, g->neg_bitid);
+ }
}
+void STATE_APIENTRY crStateStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+{
+ if (!face)
+ {
+ /* crStateStencilOpPerform accepts 0 value, while glStencilOpSeparate does not,
+ * filter it out here */
+ crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateStencilOpSeparate");
+ return;
+ }
+ crStateStencilOpPerform (0, fail, zfail, zpass);
+}
+
+void STATE_APIENTRY crStateStencilOp (GLenum fail, GLenum zfail, GLenum zpass)
+{
+ crStateStencilOpPerform (0, fail, zfail, zpass);
+}
void STATE_APIENTRY crStateClearStencil (GLint c)
{
@@ -171,7 +291,6 @@ void STATE_APIENTRY crStateClearStencil (GLint c)
FLUSH();
-
s->clearValue = c;
DIRTY(sb->clearValue, g->neg_bitid);
@@ -199,3 +318,1129 @@ void STATE_APIENTRY crStateStencilMask (GLuint mask)
DIRTY(sb->writeMask, g->neg_bitid);
DIRTY(sb->dirty, g->neg_bitid);
}
+
+void STATE_APIENTRY crStateActiveStencilFaceEXT (GLenum face)
+{
+ CRContext *g = GetCurrentContext();
+ CRStencilState *s = &(g->stencil);
+ CRStateBits *stateb = GetCurrentBits();
+ CRStencilBits *sb = &(stateb->stencil);
+
+ switch (face)
+ {
+ case GL_FRONT:
+ case GL_BACK:
+ s->activeStencilFace = face;
+ break;
+ default:
+ crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateActiveStencilFaceEXT");
+ return;
+ }
+
+ DIRTY(sb->activeStencilFace, g->neg_bitid);
+ DIRTY(sb->dirty, g->neg_bitid);
+}
+
+#ifdef CRSTATE_DEBUG_STENCIL_ERR
+#define CRSTATE_CLEARERR() do { \
+ while (diff_api.GetError() != GL_NO_ERROR) {} \
+ } while (0)
+
+#define CRSTATE_CHECKGLERR(_op) do {\
+ GLenum _glErr; \
+ CRSTATE_CLEARERR(); \
+ _op; \
+ while ((_glErr = diff_api.GetError()) != GL_NO_ERROR) { Assert(0);} \
+ }while (0)
+#else
+#define CRSTATE_CHECKGLERR(_op) do { _op; } while (0)
+#endif
+
+#define CR_STATE_STENCIL_FUNC_MATCH(_s1, _i1, _s2, _i2) (\
+ (_s1)->buffers[(_i1)].func == (_s2)->buffers[(_i2)].func && \
+ (_s1)->buffers[(_i1)].ref == (_s2)->buffers[(_i2)].ref && \
+ (_s1)->buffers[(_i1)].mask == (_s2)->buffers[(_i2)].mask)
+
+#define CR_STATE_STENCIL_FUNC_COPY(_s1, _i1, _s2, _i2) do { \
+ (_s1)->buffers[(_i1)].func = (_s2)->buffers[(_i2)].func; \
+ (_s1)->buffers[(_i1)].ref = (_s2)->buffers[(_i2)].ref; \
+ (_s1)->buffers[(_i1)].mask = (_s2)->buffers[(_i2)].mask; \
+ } while (0)
+
+
+#define CR_STATE_STENCIL_OP_MATCH(_s1, _i1, _s2, _i2) (\
+ (_s1)->buffers[(_i1)].fail == (_s2)->buffers[(_i2)].fail && \
+ (_s1)->buffers[(_i1)].passDepthFail == (_s2)->buffers[(_i2)].passDepthFail && \
+ (_s1)->buffers[(_i1)].passDepthPass == (_s2)->buffers[(_i2)].passDepthPass)
+
+#define CR_STATE_STENCIL_OP_COPY(_s1, _i1, _s2, _i2) do { \
+ (_s1)->buffers[(_i1)].fail = (_s2)->buffers[(_i2)].fail; \
+ (_s1)->buffers[(_i1)].passDepthFail = (_s2)->buffers[(_i2)].passDepthFail; \
+ (_s1)->buffers[(_i1)].passDepthPass = (_s2)->buffers[(_i2)].passDepthPass; \
+ } while (0)
+
+
+void crStateStencilDiff(CRStencilBits *b, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ CRStencilState *from = &(fromCtx->stencil);
+ CRStencilState *to = &(toCtx->stencil);
+ unsigned int j, i;
+ GLenum activeFace;
+ GLboolean backIsSet = GL_FALSE, frontIsSet = GL_FALSE, frontBackDirty, frontDirty, backDirty;
+ GLchar frontMatch = -1, backMatch = -1, toFrontBackMatch = -1;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+ i = 0; /* silence compiler */
+
+ if (CHECKDIRTY(b->enable, bitID))
+ {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (from->stencilTest != to->stencilTest)
+ {
+ able[to->stencilTest](GL_STENCIL_TEST);
+ from->stencilTest = to->stencilTest;
+ }
+ CLEARDIRTY(b->enable, nbitID);
+ }
+
+ if (CHECKDIRTY(b->enableTwoSideEXT, bitID))
+ {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (from->stencilTwoSideEXT != to->stencilTwoSideEXT)
+ {
+ able[to->stencilTwoSideEXT](GL_STENCIL_TEST_TWO_SIDE_EXT);
+ from->stencilTwoSideEXT = to->stencilTwoSideEXT;
+ }
+ CLEARDIRTY(b->enableTwoSideEXT, nbitID);
+ }
+
+ if (CHECKDIRTY(b->clearValue, bitID))
+ {
+ if (from->clearValue != to->clearValue)
+ {
+ diff_api.ClearStencil (to->clearValue);
+ from->clearValue = to->clearValue;
+ }
+ CLEARDIRTY(b->clearValue, nbitID);
+ }
+
+ activeFace = to->activeStencilFace;
+
+
+ /* func */
+ frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, bitID);
+ frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, bitID);
+ backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, bitID);
+#define CR_STATE_STENCIL_FUNC_FRONT_MATCH() ( \
+ frontMatch >= 0 ? \
+ frontMatch \
+ : (frontMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT)))
+
+#define CR_STATE_STENCIL_FUNC_BACK_MATCH() ( \
+ backMatch >= 0 ? \
+ backMatch \
+ : (backMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
+
+#define CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH() ( \
+ toFrontBackMatch >= 0 ? \
+ toFrontBackMatch \
+ : (toFrontBackMatch = CR_STATE_STENCIL_FUNC_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
+
+ if (frontBackDirty)
+ {
+ if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()
+ || !CR_STATE_STENCIL_FUNC_BACK_MATCH())
+ {
+ if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
+
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
+
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ frontIsSet = GL_TRUE;
+ }
+ else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask);
+
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK);
+
+ backIsSet = GL_TRUE;
+ }
+ }
+
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, nbitID);
+ }
+
+ if (frontDirty)
+ {
+ if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
+ {
+ if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH())
+ {
+ if (!frontIsSet || !backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
+
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
+ {
+ if (!frontIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
+
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ frontIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
+ {
+ if (!backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask);
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK);
+ backIsSet = GL_TRUE;
+ }
+ }
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, nbitID);
+ }
+
+
+ if (backDirty)
+ {
+ if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
+ {
+ if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH())
+ {
+ if (!frontIsSet || !backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
+
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
+ {
+ if (!frontIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
+
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ frontIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
+ {
+ if (!backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask);
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK);
+ backIsSet = GL_TRUE;
+ }
+ }
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, nbitID);
+ }
+
+ if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, bitID))
+ {
+ if (!CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK))
+ {
+ if (activeFace == GL_FRONT)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_BACK);
+ activeFace = GL_BACK;
+ }
+
+ diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].mask);
+ CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK);
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, nbitID);
+ }
+
+#undef CR_STATE_STENCIL_FUNC_FRONT_MATCH
+#undef CR_STATE_STENCIL_FUNC_BACK_MATCH
+#undef CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH
+
+ /* op */
+ backIsSet = GL_FALSE, frontIsSet = GL_FALSE;
+ frontMatch = -1, backMatch = -1, toFrontBackMatch = -1;
+ frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, bitID);
+ frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, bitID);
+ backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, bitID);
+
+#define CR_STATE_STENCIL_OP_FRONT_MATCH() ( \
+ frontMatch >= 0 ? \
+ frontMatch \
+ : (frontMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT)))
+
+#define CR_STATE_STENCIL_OP_BACK_MATCH() ( \
+ backMatch >= 0 ? \
+ backMatch \
+ : (backMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
+
+#define CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH() ( \
+ toFrontBackMatch >= 0 ? \
+ toFrontBackMatch \
+ : (toFrontBackMatch = CR_STATE_STENCIL_OP_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
+
+ if (frontBackDirty)
+ {
+ if (!CR_STATE_STENCIL_OP_FRONT_MATCH()
+ || !CR_STATE_STENCIL_OP_BACK_MATCH())
+ {
+ if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
+
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ else if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ frontIsSet = GL_TRUE;
+ }
+ else if (!CR_STATE_STENCIL_OP_BACK_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass);
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK);
+ backIsSet = GL_TRUE;
+ }
+ }
+
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, nbitID);
+ }
+
+ if (frontDirty)
+ {
+ if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
+ {
+ if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH())
+ {
+ if (!frontIsSet || !backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
+
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
+ {
+ if (!frontIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
+
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+
+ frontIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_OP_BACK_MATCH())
+ {
+ if (!backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass);
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK);
+ backIsSet = GL_TRUE;
+ }
+ }
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, nbitID);
+ }
+
+
+ if (backDirty)
+ {
+ if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
+ {
+ if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH())
+ {
+ if (!frontIsSet || !backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
+
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
+ {
+ if (!frontIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
+
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
+
+ frontIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_OP_BACK_MATCH())
+ {
+ if (!backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass);
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK);
+ backIsSet = GL_TRUE;
+ }
+ }
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, nbitID);
+ }
+
+ if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, bitID))
+ {
+ if (!CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK))
+ {
+ if (activeFace == GL_FRONT)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_BACK);
+ activeFace = GL_BACK;
+ }
+
+ diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthPass);
+ CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK);
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, nbitID);
+ }
+
+#undef CR_STATE_STENCIL_OP_FRONT_MATCH
+#undef CR_STATE_STENCIL_OP_BACK_MATCH
+#undef CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH
+
+
+ if (activeFace != to->activeStencilFace)
+ {
+ diff_api.ActiveStencilFaceEXT(activeFace);
+ }
+
+ if (CHECKDIRTY(b->activeStencilFace, bitID))
+ {
+ if (from->activeStencilFace != to->activeStencilFace)
+ {
+ /* we already did it ( see above )*/
+ /* diff_api.ActiveStencilFaceEXT(to->activeStencilFace); */
+ from->activeStencilFace = to->activeStencilFace;
+ }
+ CLEARDIRTY(b->activeStencilFace, nbitID);
+ }
+
+ if (CHECKDIRTY(b->writeMask, bitID))
+ {
+ if (from->writeMask != to->writeMask)
+ {
+ diff_api.StencilMask (to->writeMask);
+ from->writeMask = to->writeMask;
+ }
+ CLEARDIRTY(b->writeMask, nbitID);
+ }
+ CLEARDIRTY(b->dirty, nbitID);
+}
+
+void crStateStencilSwitch(CRStencilBits *b, CRbitvalue *bitID,
+ CRContext *fromCtx, CRContext *toCtx)
+{
+ CRStencilState *from = &(fromCtx->stencil);
+ CRStencilState *to = &(toCtx->stencil);
+ unsigned int j, i;
+ GLenum activeFace;
+ GLboolean backIsSet = GL_FALSE, frontIsSet = GL_FALSE, frontBackDirty, frontDirty, backDirty;
+ GLchar frontMatch = -1, backMatch = -1, toFrontBackMatch = -1;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+ i = 0; /* silence compiler */
+
+ if (CHECKDIRTY(b->enable, bitID))
+ {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (from->stencilTest != to->stencilTest)
+ {
+ CRSTATE_CHECKGLERR(able[to->stencilTest](GL_STENCIL_TEST));
+ FILLDIRTY(b->enable);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->enable, nbitID);
+ }
+ if (CHECKDIRTY(b->enableTwoSideEXT, bitID))
+ {
+ glAble able[2];
+ able[0] = diff_api.Disable;
+ able[1] = diff_api.Enable;
+ if (from->stencilTwoSideEXT != to->stencilTwoSideEXT)
+ {
+ CRSTATE_CHECKGLERR(able[to->stencilTwoSideEXT](GL_STENCIL_TEST_TWO_SIDE_EXT));
+ FILLDIRTY(b->enableTwoSideEXT);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->enableTwoSideEXT, nbitID);
+ }
+ if (CHECKDIRTY(b->clearValue, bitID))
+ {
+ if (from->clearValue != to->clearValue)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ClearStencil (to->clearValue));
+ FILLDIRTY(b->clearValue);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->clearValue, nbitID);
+ }
+
+ activeFace = from->activeStencilFace;
+
+ /* func */
+ frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, bitID);
+ frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, bitID);
+ backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, bitID);
+#define CR_STATE_STENCIL_FUNC_FRONT_MATCH() ( \
+ frontMatch >= 0 ? \
+ frontMatch \
+ : (frontMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT)))
+
+#define CR_STATE_STENCIL_FUNC_BACK_MATCH() ( \
+ backMatch >= 0 ? \
+ backMatch \
+ : (backMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
+
+#define CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH() ( \
+ toFrontBackMatch >= 0 ? \
+ toFrontBackMatch \
+ : (toFrontBackMatch = CR_STATE_STENCIL_FUNC_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
+
+ if (frontBackDirty)
+ {
+ if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()
+ || !CR_STATE_STENCIL_FUNC_BACK_MATCH())
+ {
+ if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask));
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask));
+ frontIsSet = GL_TRUE;
+ }
+ else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask));
+ backIsSet = GL_TRUE;
+ }
+ FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func);
+ FILLDIRTY(b->dirty);
+ }
+
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, nbitID);
+ }
+
+ if (frontDirty)
+ {
+ if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
+ {
+ if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH())
+ {
+ if (!frontIsSet || !backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask));
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
+ {
+ if (!frontIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask));
+ frontIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
+ {
+ if (!backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask));
+ backIsSet = GL_TRUE;
+ }
+ }
+ FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, nbitID);
+ }
+
+
+ if (backDirty)
+ {
+ if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
+ {
+ if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH())
+ {
+ if (!frontIsSet || !backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask));
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
+ {
+ if (!frontIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask));
+ frontIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
+ {
+ if (!backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ diff_api.ActiveStencilFaceEXT(GL_FRONT);
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask));
+ backIsSet = GL_TRUE;
+ }
+ }
+ FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, nbitID);
+ }
+
+ if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, bitID))
+ {
+ if (!CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK))
+ {
+ if (activeFace == GL_FRONT)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_BACK));
+ activeFace = GL_BACK;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].func,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].ref,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].mask));
+
+ FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, nbitID);
+ }
+
+#undef CR_STATE_STENCIL_FUNC_FRONT_MATCH
+#undef CR_STATE_STENCIL_FUNC_BACK_MATCH
+#undef CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH
+
+ /* op */
+ backIsSet = GL_FALSE, frontIsSet = GL_FALSE;
+ frontMatch = -1, backMatch = -1, toFrontBackMatch = -1;
+ frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, bitID);
+ frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, bitID);
+ backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, bitID);
+
+#define CR_STATE_STENCIL_OP_FRONT_MATCH() ( \
+ frontMatch >= 0 ? \
+ frontMatch \
+ : (frontMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT)))
+
+#define CR_STATE_STENCIL_OP_BACK_MATCH() ( \
+ backMatch >= 0 ? \
+ backMatch \
+ : (backMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
+
+#define CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH() ( \
+ toFrontBackMatch >= 0 ? \
+ toFrontBackMatch \
+ : (toFrontBackMatch = CR_STATE_STENCIL_OP_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
+
+ if (frontBackDirty)
+ {
+ if (!CR_STATE_STENCIL_OP_FRONT_MATCH()
+ || !CR_STATE_STENCIL_OP_BACK_MATCH())
+ {
+ if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT));
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass));
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ else if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT));
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass));
+ frontIsSet = GL_TRUE;
+ }
+ else if (!CR_STATE_STENCIL_OP_BACK_MATCH())
+ {
+ if (activeFace == GL_BACK)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT));
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass));
+ backIsSet = GL_TRUE;
+ }
+ FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op);
+ FILLDIRTY(b->dirty);
+ }
+
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, nbitID);
+ }
+
+ if (frontDirty)
+ {
+ if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
+ {
+ if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH())
+ {
+ if (!frontIsSet || !backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT));
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass));
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
+ {
+ if (!frontIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT));
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass));
+ frontIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_OP_BACK_MATCH())
+ {
+ if (!backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT));
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass));
+ backIsSet = GL_TRUE;
+ }
+ }
+
+ FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, nbitID);
+ }
+
+
+ if (backDirty)
+ {
+ if (!CR_STATE_STENCIL_OP_BACK_MATCH())
+ {
+ if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH())
+ {
+ if (!frontIsSet || !backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT));
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass));
+
+ frontIsSet = GL_TRUE;
+ backIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
+ {
+ if (!frontIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT));
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass));
+ frontIsSet = GL_TRUE;
+ }
+ }
+ else if (!CR_STATE_STENCIL_OP_BACK_MATCH())
+ {
+ if (!backIsSet)
+ {
+ if (activeFace == GL_BACK)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT));
+ activeFace = GL_FRONT;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass));
+ backIsSet = GL_TRUE;
+ }
+ }
+
+ FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, nbitID);
+ }
+
+ if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, bitID))
+ {
+ if (!CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK))
+ {
+ if (activeFace == GL_FRONT)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_BACK));
+ activeFace = GL_BACK;
+ }
+
+ CRSTATE_CHECKGLERR(diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].fail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthFail,
+ to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthPass));
+
+ FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, nbitID);
+ }
+
+#undef CR_STATE_STENCIL_OP_FRONT_MATCH
+#undef CR_STATE_STENCIL_OP_BACK_MATCH
+#undef CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH
+
+ if (activeFace != to->activeStencilFace)
+ {
+ CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(activeFace));
+ }
+
+ if (CHECKDIRTY(b->activeStencilFace, bitID))
+ {
+ if (from->activeStencilFace != to->activeStencilFace)
+ {
+ /* we already did it ( see above )*/
+ /* diff_api.ActiveStencilFaceEXT(to->activeStencilFace); */
+ FILLDIRTY(b->activeStencilFace);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->activeStencilFace, nbitID);
+ }
+
+ if (CHECKDIRTY(b->writeMask, bitID))
+ {
+ if (from->writeMask != to->writeMask)
+ {
+ CRSTATE_CHECKGLERR(diff_api.StencilMask (to->writeMask));
+ FILLDIRTY(b->writeMask);
+ FILLDIRTY(b->dirty);
+ }
+ CLEARDIRTY(b->writeMask, nbitID);
+ }
+
+ CLEARDIRTY(b->dirty, nbitID);
+}
+
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c
index 00adbfff..5ac9028a 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c
@@ -603,6 +603,10 @@ crStateTextureObjectDiff(CRContext *fromCtx,
CRTextureState *from = &(fromCtx->texture);
glAble able[2];
int u = 0; /* always use texture unit 0 for diff'ing */
+ GLuint hwid = crStateGetTextureObjHWID(tobj);
+
+ if (!hwid)
+ return;
able[0] = diff_api.Disable;
able[1] = diff_api.Enable;
@@ -619,7 +623,7 @@ crStateTextureObjectDiff(CRContext *fromCtx,
}
#endif
- diff_api.BindTexture(tobj->target, crStateGetTextureObjHWID(tobj));
+ diff_api.BindTexture(tobj->target, hwid);
if (alwaysDirty || CHECKDIRTY(tobj->paramsBit[u], bitID))
{
@@ -1448,7 +1452,7 @@ crStateDiffAllTextureObjects( CRContext *g, CRbitvalue *bitID, GLboolean bForceU
#endif
/* restore bindings */
- diff_api.ActiveTextureARB(GL_TEXTURE0_ARB + origUnit);
+ /* first restore unit 0 bindings the unit 0 is active currently */
diff_api.BindTexture(GL_TEXTURE_1D, orig1D);
diff_api.BindTexture(GL_TEXTURE_2D, orig2D);
diff_api.BindTexture(GL_TEXTURE_3D, orig3D);
@@ -1458,4 +1462,6 @@ crStateDiffAllTextureObjects( CRContext *g, CRbitvalue *bitID, GLboolean bForceU
#ifdef CR_NV_texture_rectangle
diff_api.BindTexture(GL_TEXTURE_RECTANGLE_NV, origRect);
#endif
+ /* now restore the proper active unit */
+ diff_api.ActiveTextureARB(GL_TEXTURE0_ARB + origUnit);
}
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c
index 6917197b..41d96125 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c
@@ -245,7 +245,7 @@ crStateGetTextureObjectAndImage(CRContext *g, GLenum texTarget, GLint level,
return;
default:
/* fall-through */
- ;
+ ;
}
#ifdef CR_NV_texture_rectangle
@@ -308,6 +308,7 @@ crStateGetTextureObjectAndImage(CRContext *g, GLenum texTarget, GLint level,
}
#endif
+ crWarning("unexpected texTarget 0x%x", texTarget);
*obj = NULL;
*img = NULL;
}
@@ -971,6 +972,13 @@ crStateTexSubImage1D(GLenum target, GLint level, GLint xoffset,
return; /* GL error state already set */
}
+#ifdef DEBUG_misha
+ CRASSERT(tl->bytes);
+ CRASSERT(tl->height);
+ CRASSERT(tl->width);
+ CRASSERT(tl->depth);
+#endif
+
#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
xoffset += tl->border;
@@ -1024,6 +1032,13 @@ crStateTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
CRASSERT(tobj);
CRASSERT(tl);
+#ifdef DEBUG_misha
+ CRASSERT(tl->bytes);
+ CRASSERT(tl->height);
+ CRASSERT(tl->width);
+ CRASSERT(tl->depth);
+#endif
+
#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
xoffset += tl->border;
yoffset += tl->border;
@@ -1109,6 +1124,14 @@ crStateTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
return; /* GL error state already set */
}
+#ifdef DEBUG_misha
+ CRASSERT(target == GL_TEXTURE_3D);
+ CRASSERT(tl->bytes);
+ CRASSERT(tl->height);
+ CRASSERT(tl->width);
+ CRASSERT(tl->depth);
+#endif
+
#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
xoffset += tl->border;
yoffset += tl->border;
@@ -1416,6 +1439,14 @@ crStateCompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
return; /* GL error state already set */
}
+#ifdef DEBUG_misha
+ CRASSERT(target == GL_TEXTURE_1D);
+ CRASSERT(tl->bytes);
+ CRASSERT(tl->height);
+ CRASSERT(tl->width);
+ CRASSERT(tl->depth);
+#endif
+
#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
xoffset += tl->border;
@@ -1456,11 +1487,19 @@ crStateCompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
CRStateBits *sb = GetCurrentBits();
CRTextureBits *tb = &(sb->texture);
CRTextureUnit *unit = t->unit + t->curTextureUnit;
- CRTextureObj *tobj = unit->currentTexture1D;
+ CRTextureObj *tobj = unit->currentTexture2D;
CRTextureLevel *tl = tobj->level[0] + level;
FLUSH();
+#ifdef DEBUG_misha
+ CRASSERT(target == GL_TEXTURE_2D);
+ CRASSERT(tl->bytes);
+ CRASSERT(tl->height);
+ CRASSERT(tl->width);
+ CRASSERT(tl->depth);
+#endif
+
if (ErrorCheckTexSubImage(2, target, level, xoffset, yoffset, 0,
width, height, 1)) {
return; /* GL error state already set */
@@ -1510,11 +1549,19 @@ crStateCompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
CRStateBits *sb = GetCurrentBits();
CRTextureBits *tb = &(sb->texture);
CRTextureUnit *unit = t->unit + t->curTextureUnit;
- CRTextureObj *tobj = unit->currentTexture1D;
+ CRTextureObj *tobj = unit->currentTexture3D;
CRTextureLevel *tl = tobj->level[0] + level;
FLUSH();
+#ifdef DEBUG_misha
+ CRASSERT(target == GL_TEXTURE_3D);
+ CRASSERT(tl->bytes);
+ CRASSERT(tl->height);
+ CRASSERT(tl->width);
+ CRASSERT(tl->depth);
+#endif
+
if (ErrorCheckTexSubImage(3, target, level, xoffset, yoffset, zoffset,
width, height, depth)) {
return; /* GL error state already set */
@@ -1580,6 +1627,13 @@ crStateGetCompressedTexImageARB(GLenum target, GLint level, GLvoid * img)
return;
}
+#ifdef DEBUG_misha
+ CRASSERT(tl->bytes);
+ CRASSERT(tl->height);
+ CRASSERT(tl->width);
+ CRASSERT(tl->depth);
+#endif
+
#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
crMemcpy(img, tl->img, tl->bytes);
#else
@@ -1616,6 +1670,13 @@ crStateGetTexImage(GLenum target, GLint level, GLenum format,
return;
}
+#ifdef DEBUG_misha
+ CRASSERT(tl->bytes);
+ CRASSERT(tl->height);
+ CRASSERT(tl->width);
+ CRASSERT(tl->depth);
+#endif
+
switch (format)
{
case GL_RED:
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c
index 951a0e55..5da27393 100644
--- a/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c
@@ -250,10 +250,8 @@ crStateTextureInitTextureObj(CRContext *ctx, CRTextureObj *tobj,
RESET(tobj->paramsBit[i], ctx->bitid);
}
-#ifndef IN_GUEST
CR_STATE_SHAREDOBJ_USAGE_INIT(tobj);
CR_STATE_SHAREDOBJ_USAGE_SET(tobj, ctx);
-#endif
}
@@ -620,9 +618,29 @@ crStateDeleteTextureObject(CRTextureObj *tobj)
crFree(tobj);
}
-void STATE_APIENTRY crStateGenTextures(GLsizei n, GLuint *textures)
+void crStateRegNames(CRContext *g, CRHashTable *table, GLsizei n, GLuint *names)
+{
+ GLint i;
+ for (i = 0; i < n; i++)
+ {
+ if (names[i])
+ {
+ GLboolean isNewKey = crHashtableAllocRegisterKey(table, names[i]);
+ CRASSERT(isNewKey);
+ }
+ else
+ crWarning("RegNames: requested to register a null name");
+ }
+}
+
+void crStateRegTextures(GLsizei n, GLuint *names)
{
CRContext *g = GetCurrentContext();
+ crStateRegNames(g, g->shared->textureTable, n, names);
+}
+
+void crStateGenNames(CRContext *g, CRHashTable *table, GLsizei n, GLuint *names)
+{
GLint start;
FLUSH();
@@ -630,23 +648,23 @@ void STATE_APIENTRY crStateGenTextures(GLsizei n, GLuint *textures)
if (g->current.inBeginEnd)
{
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
- "glGenTextures called in Begin/End");
+ "crStateGenNames called in Begin/End");
return;
}
if (n < 0)
{
crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
- "Negative n passed to glGenTextures: %d", n);
+ "Negative n passed to crStateGenNames: %d", n);
return;
}
- start = crHashtableAllocKeys(g->shared->textureTable, n);
+ start = crHashtableAllocKeys(table, n);
if (start)
{
GLint i;
for (i = 0; i < n; i++)
- textures[i] = (GLuint) (start + i);
+ names[i] = (GLuint) (start + i);
}
else
{
@@ -654,6 +672,12 @@ void STATE_APIENTRY crStateGenTextures(GLsizei n, GLuint *textures)
}
}
+void STATE_APIENTRY crStateGenTextures(GLsizei n, GLuint *textures)
+{
+ CRContext *g = GetCurrentContext();
+ crStateGenNames(g, g->shared->textureTable, n, textures);
+}
+
static void crStateTextureCheckFBOAPs(GLenum target, GLuint texture)
{
GLuint u;
@@ -730,6 +754,7 @@ static void crStateCleanupTextureRefs(CRContext *g, CRTextureObj *tObj)
#endif
}
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(tObj, g);
}
void STATE_APIENTRY crStateDeleteTextures(GLsizei n, const GLuint *textures)
@@ -760,15 +785,39 @@ void STATE_APIENTRY crStateDeleteTextures(GLsizei n, const GLuint *textures)
{
GLuint name = textures[i];
CRTextureObj *tObj;
+ if (!name)
+ continue;
+
GET_TOBJ(tObj, g, name);
- if (name && tObj)
+ if (tObj)
{
+ GLuint j;
+
crStateCleanupTextureRefs(g, tObj);
+ CR_STATE_SHAREDOBJ_USAGE_FOREACH_USED_IDX(tObj, j)
+ {
+ /* saved state version <= SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS does not have usage bits info,
+ * so on restore, we set mark bits as used.
+ * This is why g_pAvailableContexts[j] could be NULL
+ * also g_pAvailableContexts[0] will hold default context, which we should discard */
+ CRContext *ctx = g_pAvailableContexts[j];
+ if (j && ctx)
+ crStateCleanupTextureRefs(ctx, tObj);
+ else
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR_IDX(tObj, j);
+ }
+
/* on the host side, ogl texture object is deleted by a separate cr_server.head_spu->dispatch_table.DeleteTextures(n, newTextures);
* in crServerDispatchDeleteTextures, we just delete a state object here, which crStateDeleteTextureObject does */
crHashtableDelete(g->shared->textureTable, name, (CRHashtableCallback)crStateDeleteTextureObject);
}
+ else
+ {
+ /* call crHashtableDelete in any way, to ensure the allocated key is freed */
+ Assert(crHashtableIsKeyUsed(g->shared->textureTable, name));
+ crHashtableDelete(g->shared->textureTable, name, NULL);
+ }
}
DIRTY(tb->dirty, g->neg_bitid);
@@ -858,8 +907,17 @@ DECLEXPORT(void) crStateSetTextureUsed(GLuint texture, GLboolean used)
GET_TOBJ(tobj, g, texture);
if (!tobj)
{
- crWarning("crStateSetTextureUsed: failed to fined a HW name for texture(%d)!", texture);
- return;
+#ifdef IN_GUEST
+ if (used)
+ {
+ tobj = crStateTextureAllocate_t(g, texture);
+ }
+ else
+#endif
+ {
+ crWarning("crStateSetTextureUsed: failed to fined a HW name for texture(%d)!", texture);
+ return;
+ }
}
if (used)
@@ -870,8 +928,6 @@ DECLEXPORT(void) crStateSetTextureUsed(GLuint texture, GLboolean used)
CRTextureBits *tb = &(sb->texture);
CRTextureState *t = &(g->texture);
- CR_STATE_SHAREDOBJ_USAGE_CLEAR(tobj, g);
-
crStateCleanupTextureRefs(g, tobj);
if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(tobj))
@@ -953,12 +1009,11 @@ void STATE_APIENTRY crStateBindTexture(GLenum target, GLuint texture)
GET_TOBJ(tobj, g, texture);
if (!tobj)
{
+ Assert(crHashtableIsKeyUsed(g->shared->textureTable, texture));
tobj = crStateTextureAllocate_t(g, texture);
}
-#ifndef IN_GUEST
CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g);
-#endif
/* Check the targets */
if (tobj->target == GL_NONE)
@@ -3204,10 +3259,28 @@ void STATE_APIENTRY
crStatePrioritizeTextures(GLsizei n, const GLuint *textures,
const GLclampf *priorities)
{
- UNUSED(n);
- UNUSED(textures);
+ CRContext *g = GetCurrentContext();
+ CRTextureObj *tobj;
+ GLsizei i;
UNUSED(priorities);
- /* TODO: */
+
+ for (i = 0; i < n; ++i)
+ {
+ GLuint tex = textures[i];
+ GET_TOBJ(tobj, g, tex);
+ if (!tobj)
+ {
+ Assert(crHashtableIsKeyUsed(g->shared->textureTable, tex));
+ tobj = crStateTextureAllocate_t(g, tex);
+ }
+
+ /* so far the code just ensures the tex object is created to make
+ * the crserverlib code be able to pass it to host ogl */
+
+ /* TODO: store texture priorities in the state data to be able to restore it properly
+ * on save state load */
+ }
+
return;
}
@@ -3259,7 +3332,9 @@ DECLEXPORT(GLuint) STATE_APIENTRY crStateTextureHWIDtoID(GLuint hwid)
DECLEXPORT(GLuint) STATE_APIENTRY crStateGetTextureHWID(GLuint id)
{
CRContext *g = GetCurrentContext();
- CRTextureObj *tobj = GET_TOBJ(tobj, g, id);
+ CRTextureObj *tobj;
+
+ GET_TOBJ(tobj, g, id);
#ifdef DEBUG_misha
if (id)