diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
commit | f8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch) | |
tree | 26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/GuestHost/OpenGL/state_tracker | |
parent | Initial commit. (diff) | |
download | virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.tar.xz virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.zip |
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/GuestHost/OpenGL/state_tracker')
71 files changed, 40963 insertions, 0 deletions
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/Makefile.kup b/src/VBox/GuestHost/OpenGL/state_tracker/Makefile.kup new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/Makefile.kup diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/convert.py b/src/VBox/GuestHost/OpenGL/state_tracker/convert.py new file mode 100755 index 00000000..1adbf4e6 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/convert.py @@ -0,0 +1,75 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys + +# Two different paths to the packer and opengl_stub directories since this +# script will be called from both cr/state_tracker/ and cr/spu/tilesort/. +sys.path.append( '../packer' ) +sys.path.append( '../../packer' ) +sys.path.append( '../glapi_parser' ) +sys.path.append( '../../glapi_parser' ) +from pack_currenttypes import * +import apiutil + +apiutil.CopyrightC() + +print(''' +#include "state/cr_statetypes.h" + +static double __read_double( const void *src ) +{ + const unsigned int *ui = (const unsigned int *) src; + double d; + ((unsigned int *) &d)[0] = ui[0]; + ((unsigned int *) &d)[1] = ui[1]; + return d; +} +''') + +for k in sorted(gltypes.keys()): + for i in range(1,5): + print('static void __convert_%s%d (GLfloat *dst, const %s *src) {' % (k,i,gltypes[k]['type'])) + if k == 'd': + for j in range(i-1): + print('\t*dst++ = (GLfloat) __read_double(src++);') + print('\t*dst = (GLfloat) __read_double(src);') + else: + for j in range(i-1): + print('\t*dst++ = (GLfloat) *src++;') + print('\t*dst = (GLfloat) *src;') + print('}\n') + +scale = { + 'ub' : 'CR_MAXUBYTE', + 'b' : 'CR_MAXBYTE', + 'us' : 'CR_MAXUSHORT', + 's' : 'CR_MAXSHORT', + 'ui' : 'CR_MAXUINT', + 'i' : 'CR_MAXINT', + 'f' : '', + 'd' : '' +} + +for k in sorted(gltypes.keys()): + if k != 'f' and k != 'd' and k != 'l': + if k[0:1] == "N": + k2 = k[1:] + else: + k2 = k + for i in range(1,5): + print('static void __convert_rescale_%s%d (GLfloat *dst, const %s *src) {' % (k,i,gltypes[k2]['type'])) + for j in range(i-1): + print('\t*dst++ = ((GLfloat) *src++) / %s;' % scale[k2]) + print('\t*dst = ((GLfloat) *src) / %s;' % scale[k2]) + print('}\n') + +print(''' + +static void __convert_boolean (GLboolean *dst, const GLboolean *src) { + *dst = *src; +} +''') diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/dump.cpp b/src/VBox/GuestHost/OpenGL/state_tracker/dump.cpp new file mode 100644 index 00000000..42a41df1 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/dump.cpp @@ -0,0 +1,1741 @@ +/* $Id: dump.cpp $ */ + +/** @file + * Blitter API implementation + */ +/* + * Copyright (C) 2013-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ +#include "cr_blitter.h" +#include "cr_spu.h" +#include "chromium.h" +#include "cr_error.h" +#include "cr_net.h" +#include "cr_rand.h" +#include "cr_mem.h" +#include "cr_string.h" +#include <cr_dump.h> +#include "cr_pixeldata.h" + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/mem.h> + +#include <stdio.h> + +#ifdef VBOX_WITH_CRDUMPER + +static uint32_t g_CrDbgDumpRecTexInfo = 1; +static uint32_t g_CrDbgDumpAlphaData = 1; + +/* dump stuff */ +#pragma pack(1) +typedef struct VBOX_BITMAPFILEHEADER { + uint16_t bfType; + uint32_t bfSize; + uint16_t bfReserved1; + uint16_t bfReserved2; + uint32_t bfOffBits; +} VBOX_BITMAPFILEHEADER; + +typedef struct VBOX_BITMAPINFOHEADER { + uint32_t biSize; + int32_t biWidth; + int32_t biHeight; + uint16_t biPlanes; + uint16_t biBitCount; + uint32_t biCompression; + uint32_t biSizeImage; + int32_t biXPelsPerMeter; + int32_t biYPelsPerMeter; + uint32_t biClrUsed; + uint32_t biClrImportant; +} VBOX_BITMAPINFOHEADER; +#pragma pack() + +void crDmpImgBmp(CR_BLITTER_IMG *pImg, const char *pszFilename) +{ + static int sIdx = 0; + + if ( pImg->bpp != 16 + && pImg->bpp != 24 + && pImg->bpp != 32) + { + crWarning("not supported bpp %d", pImg->bpp); + return; + } + + FILE *f = fopen (pszFilename, "wb"); + if (!f) + { + crWarning("fopen failed"); + return; + } + + VBOX_BITMAPFILEHEADER bf; + + bf.bfType = 'MB'; + bf.bfSize = sizeof (VBOX_BITMAPFILEHEADER) + sizeof (VBOX_BITMAPINFOHEADER) + pImg->cbData; + bf.bfReserved1 = 0; + bf.bfReserved2 = 0; + bf.bfOffBits = sizeof (VBOX_BITMAPFILEHEADER) + sizeof (VBOX_BITMAPINFOHEADER); + + VBOX_BITMAPINFOHEADER bi; + + bi.biSize = sizeof (bi); + bi.biWidth = pImg->width; + bi.biHeight = pImg->height; + bi.biPlanes = 1; + bi.biBitCount = pImg->bpp; + bi.biCompression = 0; + bi.biSizeImage = pImg->cbData; + bi.biXPelsPerMeter = 0; + bi.biYPelsPerMeter = 0; + bi.biClrUsed = 0; + bi.biClrImportant = 0; + + fwrite (&bf, 1, sizeof (bf), f); + fwrite (&bi, 1, sizeof (bi), f); + fwrite (pImg->pvData, 1, pImg->cbData, f); + + fclose (f); +} + +typedef struct CRDUMPGETHWID_DATA +{ + GLuint hwid; + PFNCRDUMPGETHWID pfnGetHwid; + unsigned long Key; + void* pvObj; +} CRDUMPGETHWID_DATA; + +static void crDmpHashtableSearchByHwidCB(unsigned long key, void *pData1, void *pData2) +{ + CRDUMPGETHWID_DATA *pData = (CRDUMPGETHWID_DATA*)pData2; + if (pData->pvObj) + return; + + if (pData->hwid == pData->pfnGetHwid(pData1)) + { + pData->Key = key; + pData->pvObj = pData1; + } +} + +void* crDmpHashtableSearchByHwid(CRHashTable *pHash, GLuint hwid, PFNCRDUMPGETHWID pfnGetHwid, unsigned long *pKey) +{ + CRDUMPGETHWID_DATA Data = {0}; + Data.hwid = hwid; + Data.pfnGetHwid = pfnGetHwid; + crHashtableWalk(pHash, crDmpHashtableSearchByHwidCB, &Data); + + Assert(Data.pvObj); + + if (pKey) + *pKey = Data.Key; + return Data.pvObj; +} + +#if 0 +typedef struct CR_SERVER_DUMP_FIND_TEX +{ + GLint hwid; + CRTextureObj *pTobj +} CR_SERVER_DUMP_FIND_TEX; + +void crServerDumpFindTexCb(unsigned long key, void *pData1, void *pData2) +{ + CR_SERVER_DUMP_FIND_TEX *pTex = (CR_SERVER_DUMP_FIND_TEX*)pData2; + CRTextureObj *pTobj = (CRTextureObj *)pData1; + if (pTobj->hwid == pTex->hwid) + pTex->pTobj = pTobj; +} +#endif + +#define CR_DUMP_MAKE_CASE(_val) case _val: return #_val +#define CR_DUMP_MAKE_CASE_UNKNOWN(_val, _str, _pDumper) default: { \ + crWarning("%s %d", (_str), _val); \ + crDmpStrF((_pDumper), "WARNING: %s %d", (_str), _val); \ + return (_str); \ +} + +DECLINLINE(size_t) crDmpFormatVal(char *pString, size_t cbString, const char *pszElFormat, uint32_t cbVal, const void *pvVal) +{ + if (pszElFormat[0] != '%' || pszElFormat[1] == '\0') + { + crWarning("invalid format %s", pszElFormat); + return 0; + } + switch (cbVal) + { + case 8: + return sprintf_s(pString, cbString, pszElFormat, *((double*)pvVal)); + case 4: + { + /* we do not care only about type specifiers, all the rest is not accepted */ + switch (pszElFormat[1]) + { + case 'f': + /* float would be promoted to double */ + return sprintf_s(pString, cbString, pszElFormat, *((float*)pvVal)); + default: + return sprintf_s(pString, cbString, pszElFormat, *((uint32_t*)pvVal)); + } + } + case 2: + return sprintf_s(pString, cbString, pszElFormat, *((uint16_t*)pvVal)); + case 1: + return sprintf_s(pString, cbString, pszElFormat, *((uint8_t*)pvVal)); + default: + crWarning("unsupported size %d", cbVal); + return 0; + } +} + +VBOXDUMPDECL(size_t) crDmpFormatRawArray(char *pString, size_t cbString, const char *pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cVal) +{ + if (cbString < 2) + { + crWarning("too few buffer size"); + return 0; + } + + const size_t cbInitString = cbString; + *pString++ = '{'; + --cbString; + size_t cbWritten; + const uint8_t *pu8Val = (const uint8_t *)pvVal; + for (uint32_t i = 0; i < cVal; ++i) + { + cbWritten = crDmpFormatVal(pString, cbString, pszElFormat, cbEl, (const void *)pu8Val); + pu8Val += cbEl; + Assert(cbString >= cbWritten); + pString += cbWritten; + cbString -= cbWritten; + if (i != cVal - 1) + { + cbWritten = sprintf_s(pString, cbString, ", "); + Assert(cbString >= cbWritten); + pString += cbWritten; + cbString -= cbWritten; + } + } + + if (!cbString) + { + crWarning("too few buffer size"); + return 0; + } + *pString++ = '}'; + --cbString; + + if (!cbString) + { + crWarning("too few buffer size"); + return 0; + } + *pString++ = '\0'; + + return cbInitString - cbString; +} + +VBOXDUMPDECL(size_t) crDmpFormatMatrixArray(char *pString, size_t cbString, const char *pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cX, uint32_t cY) +{ + if (cbString < 2) + { + crWarning("too few buffer size"); + return 0; + } + + const size_t cbInitString = cbString; + *pString++ = '{'; + --cbString; + size_t cbWritten; + const uint8_t *pu8Val = (const uint8_t *)pvVal; + for (uint32_t i = 0; i < cY; ++i) + { + cbWritten = crDmpFormatRawArray(pString, cbString, pszElFormat, cbEl, (const void *)pu8Val, cX); + pu8Val += (cbEl * cX); + Assert(cbString >= cbWritten); + pString += cbWritten; + cbString -= cbWritten; + if (i != cY - 1) + { + if (cbString < 3) + { + crWarning("too few buffer size"); + return 0; + } + *pString++ = ','; + --cbString; + *pString++ = '\n'; + --cbString; + } + } + if (!cbString) + { + crWarning("too few buffer size"); + return 0; + } + *pString++ = '}'; + --cbString; + + if (!cbString) + { + crWarning("too few buffer size"); + return 0; + } + *pString++ = '\0'; + + return cbInitString - cbString; +} + +VBOXDUMPDECL(size_t) crDmpFormatArray(char *pString, size_t cbString, const char *pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cVal) +{ + switch(cVal) + { + case 1: + return crDmpFormatVal(pString, cbString, pszElFormat, cbEl, pvVal); + case 16: + return crDmpFormatMatrixArray(pString, cbString, pszElFormat, cbEl, pvVal, 4, 4); + case 9: + return crDmpFormatMatrixArray(pString, cbString, pszElFormat, cbEl, pvVal, 3, 3); + case 0: + crWarning("value array is empty"); + return 0; + default: + return crDmpFormatRawArray(pString, cbString, pszElFormat, cbEl, pvVal, cVal); + } +} + +VBOXDUMPDECL(void) crRecDumpVertAttrv(CR_RECORDER *pRec, CRContext *ctx, GLuint idx, const char*pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cVal) +{ + char aBuf[1024]; + crDmpFormatRawArray(aBuf, sizeof (aBuf), pszElFormat, cbEl, pvVal, cVal); + crDmpStrF(pRec->pDumper, "(%u, %s)", idx, aBuf); +} + +VBOXDUMPDECL(void) crRecDumpVertAttrV(CR_RECORDER *pRec, CRContext *ctx, const char*pszFormat, va_list pArgList) +{ + crDmpStrV(pRec->pDumper, pszFormat, pArgList); +} + +VBOXDUMPDECL(void) crRecDumpVertAttrF(CR_RECORDER *pRec, CRContext *ctx, const char*pszFormat, ...) +{ + va_list pArgList; + va_start(pArgList, pszFormat); + crRecDumpVertAttrV(pRec, ctx, pszFormat, pArgList); + va_end(pArgList); +} + +void crRecDumpBuffer(CR_RECORDER *pRec, CRContext *ctx, GLint idRedirFBO, VBOXVR_TEXTURE *pRedirTex) +{ + GLenum texTarget = 0; + GLint hwBuf = 0, hwDrawBuf = 0; + GLint hwTex = 0, hwObjType = 0, hwTexLevel = 0, hwCubeFace = 0; + GLint width = 0, height = 0, depth = 0; + GLint id = 0; + CR_BLITTER_IMG Img = {0}; + VBOXVR_TEXTURE Tex; + int rc; + + pRec->pDispatch->GetIntegerv(GL_DRAW_BUFFER, &hwDrawBuf); + pRec->pDispatch->GetIntegerv(GL_FRAMEBUFFER_BINDING, &hwBuf); + if (hwBuf) + { + pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &hwTex); + pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &hwObjType); + if (hwObjType == GL_TEXTURE) + { + pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &hwTexLevel); + pRec->pDispatch->GetFramebufferAttachmentParameterivEXT(GL_DRAW_FRAMEBUFFER, hwDrawBuf, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, &hwCubeFace); + if (hwCubeFace) + { + crWarning("cube face: unsupported"); + return; + } + + if (hwTexLevel) + { + crWarning("non-zero tex level attached, unsupported"); + return; + } + } + else + { + crWarning("unsupported"); + return; + } + } + else + { + crWarning("no buffer attached: unsupported"); + return; + } + + if (ctx->framebufferobject.drawFB) + { + GLuint iColor = (hwDrawBuf - GL_COLOR_ATTACHMENT0_EXT); + CRTextureObj *pTobj = (CRTextureObj *)crHashtableSearch(ctx->shared->textureTable, ctx->framebufferobject.drawFB->color[iColor].name); + CRTextureLevel *pTl = NULL; + + id = pTobj->id; + + Assert(iColor < RT_ELEMENTS(ctx->framebufferobject.drawFB->color)); + + if (!pTobj) + { + crWarning("no tobj"); + return; + } + Assert(pTobj->hwid == hwTex); + Assert(pTobj); + Assert(ctx->framebufferobject.drawFB->hwid); + Assert(ctx->framebufferobject.drawFB->hwid == hwBuf); + Assert(ctx->framebufferobject.drawFB->drawbuffer[0] == hwDrawBuf); + + Assert(ctx->framebufferobject.drawFB->color[iColor].level == hwTexLevel); + Assert(ctx->framebufferobject.drawFB->color[iColor].type == hwObjType); + + texTarget = pTobj->target; + + Assert(texTarget == GL_TEXTURE_2D); + + pTl = &pTobj->level[0][hwTexLevel]; + + rc = CrBltEnter(pRec->pBlitter); + if (!RT_SUCCESS(rc)) + { + crWarning("CrBltEnter failed, rc %d", rc); + return; + } + + pRec->pDispatch->BindTexture(texTarget, hwTex); + + pRec->pDispatch->GetTexLevelParameteriv(texTarget, hwTexLevel, GL_TEXTURE_WIDTH, &width); + pRec->pDispatch->GetTexLevelParameteriv(texTarget, hwTexLevel, GL_TEXTURE_HEIGHT, &height); + pRec->pDispatch->GetTexLevelParameteriv(texTarget, hwTexLevel, GL_TEXTURE_DEPTH, &depth); + + Assert(width == pTl->width); + Assert(height == pTl->height); + Assert(depth == pTl->depth); + + pRec->pDispatch->BindTexture(texTarget, 0); + } + else + { + Assert(hwBuf == idRedirFBO); + if (!pRedirTex) + { + crWarning("pRedirTex is expected for non-FBO state!"); + return; + } + + Assert(hwTex == pRedirTex->hwid); + + texTarget = pRedirTex->target; + + width = pRedirTex->width; + height = pRedirTex->height; + + rc = CrBltEnter(pRec->pBlitter); + if (!RT_SUCCESS(rc)) + { + crWarning("CrBltEnter failed, rc %d", rc); + return; + } + } + + Tex.width = width; + Tex.height = height; + Tex.target = texTarget; + Tex.hwid = hwTex; + + rc = CrBltImgGetTex(pRec->pBlitter, &Tex, GL_BGRA, &Img); + if (RT_SUCCESS(rc)) + { + crDmpImgF(pRec->pDumper, &Img, "ctx(%d), BUFFER: id(%d) hwid(%d), width(%d), height(%d)", ctx, id, Tex.hwid, width, height); + + if (g_CrDbgDumpAlphaData) + { + CR_BLITTER_IMG AlphaImg = {0}; + rc = crRecAlphaImgCreate(&Img, &AlphaImg); + if (RT_SUCCESS(rc)) + { + crDmpImgF(pRec->pDumper, &AlphaImg, "Buffer ALPHA Data"); + crRecAlphaImgDestroy(&AlphaImg); + } + else + { + crWarning("crRecAlphaImgCreate failed rc %d", rc); + } + } + + CrBltImgFree(pRec->pBlitter, &Img); + } + else + { + crWarning("CrBltImgGetTex failed, rc %d", rc); + } + + CrBltLeave(pRec->pBlitter); +} + +static const char *crRecDumpShaderTypeString(GLenum enmType, CR_DUMPER *pDumper) +{ + switch (enmType) + { + CR_DUMP_MAKE_CASE(GL_VERTEX_SHADER_ARB); + CR_DUMP_MAKE_CASE(GL_FRAGMENT_SHADER_ARB); + CR_DUMP_MAKE_CASE(GL_GEOMETRY_SHADER_ARB); + CR_DUMP_MAKE_CASE_UNKNOWN(enmType, "Unknown Shader Type", pDumper); + } +} + +static const char *crRecDumpVarTypeString(GLenum enmType, CR_DUMPER *pDumper) +{ + switch (enmType) + { + CR_DUMP_MAKE_CASE(GL_BYTE); + CR_DUMP_MAKE_CASE(GL_UNSIGNED_BYTE); + CR_DUMP_MAKE_CASE(GL_SHORT); + CR_DUMP_MAKE_CASE(GL_UNSIGNED_SHORT); + CR_DUMP_MAKE_CASE(GL_FLOAT); + CR_DUMP_MAKE_CASE(GL_DOUBLE); + CR_DUMP_MAKE_CASE(GL_FLOAT_VEC2); + CR_DUMP_MAKE_CASE(GL_FLOAT_VEC3); + CR_DUMP_MAKE_CASE(GL_FLOAT_VEC4); + CR_DUMP_MAKE_CASE(GL_INT); + CR_DUMP_MAKE_CASE(GL_UNSIGNED_INT); + CR_DUMP_MAKE_CASE(GL_INT_VEC2); + CR_DUMP_MAKE_CASE(GL_INT_VEC3); + CR_DUMP_MAKE_CASE(GL_INT_VEC4); + CR_DUMP_MAKE_CASE(GL_BOOL); + CR_DUMP_MAKE_CASE(GL_BOOL_VEC2); + CR_DUMP_MAKE_CASE(GL_BOOL_VEC3); + CR_DUMP_MAKE_CASE(GL_BOOL_VEC4); + CR_DUMP_MAKE_CASE(GL_FLOAT_MAT2); + CR_DUMP_MAKE_CASE(GL_FLOAT_MAT3); + CR_DUMP_MAKE_CASE(GL_FLOAT_MAT4); + CR_DUMP_MAKE_CASE(GL_SAMPLER_1D); + CR_DUMP_MAKE_CASE(GL_SAMPLER_2D); + CR_DUMP_MAKE_CASE(GL_SAMPLER_3D); + CR_DUMP_MAKE_CASE(GL_SAMPLER_CUBE); + CR_DUMP_MAKE_CASE(GL_SAMPLER_1D_SHADOW); + CR_DUMP_MAKE_CASE(GL_SAMPLER_2D_SHADOW); + CR_DUMP_MAKE_CASE(GL_SAMPLER_2D_RECT_ARB); + CR_DUMP_MAKE_CASE(GL_SAMPLER_2D_RECT_SHADOW_ARB); + CR_DUMP_MAKE_CASE(GL_FLOAT_MAT2x3); + CR_DUMP_MAKE_CASE(GL_FLOAT_MAT2x4); + CR_DUMP_MAKE_CASE(GL_FLOAT_MAT3x2); + CR_DUMP_MAKE_CASE(GL_FLOAT_MAT3x4); + CR_DUMP_MAKE_CASE(GL_FLOAT_MAT4x2); + CR_DUMP_MAKE_CASE(GL_FLOAT_MAT4x3); + CR_DUMP_MAKE_CASE_UNKNOWN(enmType, "Unknown Variable Type", pDumper); + } +} + +static char *crRecDumpGetLine(char **ppszStr, uint32_t *pcbStr) +{ + char *pszStr, *pNewLine; + const uint32_t cbStr = *pcbStr; + + if (!cbStr) + { + /* zero-length string */ + return NULL; + } + + if ((*ppszStr)[cbStr-1] != '\0') + { + crWarning("string should be null-rerminated, forcing it!"); + (*ppszStr)[cbStr-1] = '\0'; + } + pszStr = *ppszStr; + if (!*pszStr) + { + *pcbStr = 0; + return NULL; + } + + if (!(pNewLine = strstr(pszStr, "\n"))) + { + /* the string contains a single line! */ + *ppszStr += strlen(pszStr); + *pcbStr = 0; + return pszStr; + } + + *pNewLine = '\0'; + *pcbStr = cbStr - (((uintptr_t)pNewLine) - ((uintptr_t)pszStr)) - 1; + Assert((*pcbStr) < UINT32_MAX/2); + Assert((*pcbStr) < cbStr); + *ppszStr = pNewLine + 1; + + return pszStr; +} + +static void crRecDumpStrByLine(CR_DUMPER *pDumper, char *pszStr, uint32_t cbStr) +{ + char *pszCurLine; + while ((pszCurLine = crRecDumpGetLine(&pszStr, &cbStr)) != NULL) + { + crDmpStrF(pDumper, "%s", pszCurLine); + } +} + +static DECLCALLBACK(GLuint) crDmpGetHwidShaderCB(void *pvObj) +{ + return ((CRGLSLShader*)pvObj)->hwid; +} + +static DECLCALLBACK(GLuint) crDmpGetHwidProgramCB(void *pvObj) +{ + return ((CRGLSLProgram*)pvObj)->hwid; +} + +/* Context activation is done by the caller. */ +void crRecDumpLog(CR_RECORDER *pRec, GLint hwid) +{ + GLint cbLog = 0; + pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_INFO_LOG_LENGTH_ARB, &cbLog); + + crDmpStrF(pRec->pDumper, "Log===%d===", hwid); + + if (cbLog > 1) + { + GLchar *pszLog = (GLchar *) crAlloc(cbLog*sizeof (GLchar)); + + pRec->pDispatch->GetInfoLogARB(hwid, cbLog, NULL, pszLog); + + crRecDumpStrByLine(pRec->pDumper, pszLog, cbLog); + + crFree(pszLog); + } + crDmpStrF(pRec->pDumper, "End Log======"); +} + +void crRecDumpShader(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid) +{ + GLint length = 0; + GLint type = 0; + GLint compileStatus = 0; + +#ifndef IN_GUEST + CRGLSLShader *pShad; + + if (!id) + { + unsigned long tstKey = 0; + Assert(hwid); + pShad = (CRGLSLShader *)crDmpHashtableSearchByHwid(ctx->glsl.shaders, hwid, crDmpGetHwidShaderCB, &tstKey); + Assert(pShad); + if (!pShad) + return; + id = pShad->id; + Assert(tstKey == id); + } + else + { + pShad = (CRGLSLShader *)crHashtableSearch(ctx->glsl.shaders, id); + Assert(pShad); + if (!pShad) + return; + } + + if (!hwid) + hwid = pShad->hwid; + + Assert(pShad->hwid == hwid); + Assert(pShad->id == id); +#else + if (!id) + id = hwid; + else if (!hwid) + hwid = id; + + Assert(id); + Assert(hwid); + Assert(hwid == id); +#endif + + pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_SUBTYPE_ARB, &type); + pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus); + crDmpStrF(pRec->pDumper, "SHADER ctx(%d) id(%d) hwid(%d) type(%s) status(%d):", ctx->id, id, hwid, crRecDumpShaderTypeString(type, pRec->pDumper), compileStatus); + + crRecDumpLog(pRec, hwid); + + pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &length); + + char *pszSource = (char*)crCalloc(length + 1); + if (!pszSource) + { + crWarning("crCalloc failed"); + crDmpStrF(pRec->pDumper, "WARNING: crCalloc failed"); + return; + } + + pRec->pDispatch->GetShaderSource(hwid, length, NULL, pszSource); + crRecDumpStrByLine(pRec->pDumper, pszSource, length); + + crFree(pszSource); + + crDmpStr(pRec->pDumper, "===END SHADER===="); +} + +void crRecDumpProgram(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid) +{ + GLint cShaders = 0, linkStatus = 0; + char *source = NULL; + CRGLSLProgram *pProg; + + if (!id) + { + unsigned long tstKey = 0; + Assert(hwid); + pProg = (CRGLSLProgram*)crDmpHashtableSearchByHwid(ctx->glsl.programs, hwid, crDmpGetHwidProgramCB, &tstKey); + Assert(pProg); + if (!pProg) + return; + id = pProg->id; + Assert(tstKey == id); + } + else + { + pProg = (CRGLSLProgram *) crHashtableSearch(ctx->glsl.programs, id); + Assert(pProg); + if (!pProg) + return; + } + + if (!hwid) + hwid = pProg->hwid; + + Assert(pProg->hwid == hwid); + Assert(pProg->id == id); + + pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_ATTACHED_OBJECTS_ARB, &cShaders); + pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_LINK_STATUS_ARB, &linkStatus); + + crDmpStrF(pRec->pDumper, "PROGRAM ctx(%d) id(%d) hwid(%d) status(%d) shaders(%d):", ctx->id, id, hwid, linkStatus, cShaders); + + crRecDumpLog(pRec, hwid); + + VBoxGLhandleARB *pShaders = (VBoxGLhandleARB*)crCalloc(cShaders * sizeof (*pShaders)); + if (!pShaders) + { + crWarning("crCalloc failed"); + crDmpStrF(pRec->pDumper, "WARNING: crCalloc failed"); + return; + } + + pRec->pDispatch->GetAttachedObjectsARB(hwid, cShaders, NULL, pShaders); + for (GLint i = 0; i < cShaders; ++i) + { + if (pShaders[i]) + crRecDumpShader(pRec, ctx, 0, pShaders[i]); + else + crDmpStrF(pRec->pDumper, "WARNING: Shader[%d] is null", i); + } + + crFree(pShaders); + + GLsizei cbLog = 0; + + pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_INFO_LOG_LENGTH_ARB, &cbLog); + if (cbLog) + { + char *pszLog = (char *)crCalloc(cbLog+1); + pRec->pDispatch->GetInfoLogARB(hwid, cbLog, NULL, pszLog); + crDmpStrF(pRec->pDumper, "==LOG=="); + crRecDumpStrByLine(pRec->pDumper, pszLog, cbLog); + crDmpStrF(pRec->pDumper, "==Done LOG=="); + crFree(pszLog); + } + else + { + crDmpStrF(pRec->pDumper, "==No LOG=="); + } + + crDmpStr(pRec->pDumper, "===END PROGRAM===="); +} + +void crRecRecompileShader(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid) +{ + GLint length = 0; + GLint type = 0; + GLint compileStatus = 0; + CRGLSLShader *pShad; + + if (!id) + { + unsigned long tstKey = 0; + Assert(hwid); + pShad = (CRGLSLShader *)crDmpHashtableSearchByHwid(ctx->glsl.shaders, hwid, crDmpGetHwidShaderCB, &tstKey); + Assert(pShad); + if (!pShad) + return; + id = pShad->id; + Assert(tstKey == id); + } + else + { + pShad = (CRGLSLShader *)crHashtableSearch(ctx->glsl.shaders, id); + Assert(pShad); + if (!pShad) + return; + } + + if (!hwid) + hwid = pShad->hwid; + + Assert(pShad->hwid == hwid); + Assert(pShad->id == id); + + pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_SUBTYPE_ARB, &type); + pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus); + crDmpStrF(pRec->pDumper, "==RECOMPILE SHADER ctx(%d) id(%d) hwid(%d) type(%s) status(%d)==", ctx->id, id, hwid, crRecDumpShaderTypeString(type, pRec->pDumper), compileStatus); + + compileStatus = 0; + GLenum status; + while ((status = pRec->pDispatch->GetError()) != GL_NO_ERROR) {/*Assert(0);*/} + pRec->pDispatch->CompileShader(hwid); + while ((status = pRec->pDispatch->GetError()) != GL_NO_ERROR) {Assert(0);} + pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus); + + crDmpStrF(pRec->pDumper, "==Done RECOMPILE SHADER, status(%d)==", compileStatus); +} + +void crRecRecompileProgram(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid) +{ + GLint cShaders = 0, linkStatus = 0; + char *source = NULL; + CRGLSLProgram *pProg; + + if (!id) + { + unsigned long tstKey = 0; + Assert(hwid); + pProg = (CRGLSLProgram*)crDmpHashtableSearchByHwid(ctx->glsl.programs, hwid, crDmpGetHwidProgramCB, &tstKey); + Assert(pProg); + if (!pProg) + return; + id = pProg->id; + Assert(tstKey == id); + } + else + { + pProg = (CRGLSLProgram *) crHashtableSearch(ctx->glsl.programs, id); + Assert(pProg); + if (!pProg) + return; + } + + if (!hwid) + hwid = pProg->hwid; + + Assert(pProg->hwid == hwid); + Assert(pProg->id == id); + + pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_ATTACHED_OBJECTS_ARB, &cShaders); + pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_LINK_STATUS_ARB, &linkStatus); + + crDmpStrF(pRec->pDumper, "==RECOMPILE PROGRAM ctx(%d) id(%d) hwid(%d) status(%d) shaders(%d)==", ctx->id, id, hwid, linkStatus, cShaders); + + VBoxGLhandleARB *pShaders = (VBoxGLhandleARB*)crCalloc(cShaders * sizeof (*pShaders)); + if (!pShaders) + { + crWarning("crCalloc failed"); + crDmpStrF(pRec->pDumper, "WARNING: crCalloc failed"); + return; + } + + pRec->pDispatch->GetAttachedObjectsARB(hwid, cShaders, NULL, pShaders); + for (GLint i = 0; i < cShaders; ++i) + { + crRecRecompileShader(pRec, ctx, 0, pShaders[i]); + } + + crFree(pShaders); + + linkStatus = 0; + GLenum status; + while ((status = pRec->pDispatch->GetError()) != GL_NO_ERROR) {/*Assert(0);*/} + pRec->pDispatch->LinkProgram(hwid); + while ((status = pRec->pDispatch->GetError()) != GL_NO_ERROR) {Assert(0);} + pRec->pDispatch->GetObjectParameterivARB(hwid, GL_OBJECT_LINK_STATUS_ARB, &linkStatus); + + crDmpStrF(pRec->pDumper, "==Done RECOMPILE PROGRAM, status(%d)==", linkStatus); +} + +VBOXDUMPDECL(void) crRecDumpCurrentProgram(CR_RECORDER *pRec, CRContext *ctx) +{ + GLint curProgram = 0; + pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram); + if (curProgram) + { + Assert(ctx->glsl.activeProgram); + if (!ctx->glsl.activeProgram) + crWarning("no active program state with active hw program"); + else + Assert(ctx->glsl.activeProgram->hwid == curProgram); + crRecDumpProgram(pRec, ctx, 0, curProgram); + } + else + { + Assert(!ctx->glsl.activeProgram); + crDmpStrF(pRec->pDumper, "--no active program"); + } +} + +void crRecDumpProgramUniforms(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid) +{ + CRGLSLProgram *pProg; + + if (!id) + { + unsigned long tstKey = 0; + Assert(hwid); + pProg = (CRGLSLProgram*)crDmpHashtableSearchByHwid(ctx->glsl.programs, hwid, crDmpGetHwidProgramCB, &tstKey); + Assert(pProg); + if (!pProg) + return; + id = pProg->id; + Assert(tstKey == id); + } + else + { + pProg = (CRGLSLProgram *) crHashtableSearch(ctx->glsl.programs, id); + Assert(pProg); + if (!pProg) + return; + } + + if (!hwid) + hwid = pProg->hwid; + + Assert(pProg->hwid == hwid); + Assert(pProg->id == id); + + GLint maxUniformLen = 0, activeUniforms = 0, i, j, uniformsCount = 0; + GLenum type; + GLint size, location; + GLchar *pszName = NULL; + pRec->pDispatch->GetProgramiv(hwid, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen); + pRec->pDispatch->GetProgramiv(hwid, GL_ACTIVE_UNIFORMS, &activeUniforms); + + if (!maxUniformLen) + { + if (activeUniforms) + { + crWarning("activeUniforms (%d), while maxUniformLen is zero", activeUniforms); + activeUniforms = 0; + } + } + + if (activeUniforms>0) + { + pszName = (GLchar *) crAlloc((maxUniformLen+8)*sizeof(GLchar)); + + if (!pszName) + { + crWarning("crRecDumpProgramUniforms: out of memory"); + return; + } + } + + for (i=0; i<activeUniforms; ++i) + { + pRec->pDispatch->GetActiveUniform(hwid, i, maxUniformLen, NULL, &size, &type, pszName); + uniformsCount += size; + } + Assert(uniformsCount>=activeUniforms); + + if (activeUniforms>0) + { + GLfloat fdata[16]; + GLint idata[16]; + char *pIndexStr=NULL; + + for (i=0; i<activeUniforms; ++i) + { + bool fPrintBraketsWithName = false; + pRec->pDispatch->GetActiveUniform(hwid, i, maxUniformLen, NULL, &size, &type, pszName); + + if (size>1) + { + pIndexStr = crStrchr(pszName, '['); + if (!pIndexStr) + { + pIndexStr = pszName+crStrlen(pszName); + fPrintBraketsWithName = true; + } + } + + if (fPrintBraketsWithName) + { + crDmpStrF(pRec->pDumper, "%s %s[%d];", crRecDumpVarTypeString(type, pRec->pDumper), pszName, size); + Assert(size > 1); + } + else + crDmpStrF(pRec->pDumper, "%s %s;", crRecDumpVarTypeString(type, pRec->pDumper), pszName); + + GLint uniformTypeSize = crStateGetUniformSize(type); + Assert(uniformTypeSize >= 1); + + for (j=0; j<size; ++j) + { + if (size>1) + { + sprintf(pIndexStr, "[%i]", j); + } + location = pRec->pDispatch->GetUniformLocation(hwid, pszName); + + if (crStateIsIntUniform(type)) + { + pRec->pDispatch->GetUniformiv(hwid, location, &idata[0]); + switch (uniformTypeSize) + { + case 1: + crDmpStrF(pRec->pDumper, "%s = %d; //location %d", pszName, idata[0], location); + break; + case 2: + crDmpStrF(pRec->pDumper, "%s = {%d, %d}; //location %d", pszName, idata[0], idata[1], location); + break; + case 3: + crDmpStrF(pRec->pDumper, "%s = {%d, %d, %d}; //location %d", pszName, idata[0], idata[1], idata[2], location); + break; + case 4: + crDmpStrF(pRec->pDumper, "%s = {%d, %d, %d, %d}; //location %d", pszName, idata[0], idata[1], idata[2], idata[3], location); + break; + default: + for (GLint k = 0; k < uniformTypeSize; ++k) + { + crDmpStrF(pRec->pDumper, "%s[%d] = %d; //location %d", pszName, k, idata[k], location); + } + break; + } + } + else + { + pRec->pDispatch->GetUniformfv(hwid, location, &fdata[0]); + switch (uniformTypeSize) + { + case 1: + crDmpStrF(pRec->pDumper, "%s = %f; //location %d", pszName, fdata[0], location); + break; + case 2: + crDmpStrF(pRec->pDumper, "%s = {%f, %f}; //location %d", pszName, fdata[0], fdata[1], location); + break; + case 3: + crDmpStrF(pRec->pDumper, "%s = {%f, %f, %f}; //location %d", pszName, fdata[0], fdata[1], fdata[2], location); + break; + case 4: + crDmpStrF(pRec->pDumper, "%s = {%f, %f, %f, %f}; //location %d", pszName, fdata[0], fdata[1], fdata[2], fdata[3], location); + break; + default: + for (GLint k = 0; k < uniformTypeSize; ++k) + { + crDmpStrF(pRec->pDumper, "%s[%d] = %f; //location %d", pszName, k, fdata[k], location); + } + break; + } + } + } + } + + crFree(pszName); + } +} + +void crRecDumpProgramAttribs(CR_RECORDER *pRec, CRContext *ctx, GLint id, GLint hwid) +{ + CRGLSLProgram *pProg; + + if (!id) + { + unsigned long tstKey = 0; + Assert(hwid); + pProg = (CRGLSLProgram*)crDmpHashtableSearchByHwid(ctx->glsl.programs, hwid, crDmpGetHwidProgramCB, &tstKey); + Assert(pProg); + if (!pProg) + return; + id = pProg->id; + Assert(tstKey == id); + } + else + { + pProg = (CRGLSLProgram *) crHashtableSearch(ctx->glsl.programs, id); + Assert(pProg); + if (!pProg) + return; + } + + if (!hwid) + hwid = pProg->hwid; + + Assert(pProg->hwid == hwid); + Assert(pProg->id == id); + + GLint maxAttribLen = 0, activeAttrib = 0, i, j, attribCount = 0; + GLenum type; + GLint size, location; + GLchar *pszName = NULL; + pRec->pDispatch->GetProgramiv(hwid, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttribLen); + pRec->pDispatch->GetProgramiv(hwid, GL_ACTIVE_ATTRIBUTES, &activeAttrib); + + if (!maxAttribLen) + { + if (activeAttrib) + { + crWarning("activeAttrib (%d), while maxAttribLen is zero", activeAttrib); + activeAttrib = 0; + } + } + + if (activeAttrib>0) + { + pszName = (GLchar *) crAlloc((maxAttribLen+8)*sizeof(GLchar)); + + if (!pszName) + { + crWarning("crRecDumpProgramAttrib: out of memory"); + return; + } + } + + for (i=0; i<activeAttrib; ++i) + { + pRec->pDispatch->GetActiveAttrib(hwid, i, maxAttribLen, NULL, &size, &type, pszName); + attribCount += size; + } + Assert(attribCount>=activeAttrib); + + if (activeAttrib>0) + { + GLfloat fdata[16]; + GLint idata[16]; + char *pIndexStr=NULL; + + for (i=0; i<activeAttrib; ++i) + { + bool fPrintBraketsWithName = false; + pRec->pDispatch->GetActiveAttrib(hwid, i, maxAttribLen, NULL, &size, &type, pszName); + GLint arrayBufferBind = 0, arrayEnabled = 0, arraySize = 0, arrayStride = 0, arrayType = 0, arrayNormalized = 0, arrayInteger = 0/*, arrayDivisor = 0*/; + + pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &arrayBufferBind); + pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &arrayEnabled); + pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &arraySize); + pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &arrayStride); + pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &arrayType); + pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &arrayNormalized); + pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_INTEGER, &arrayInteger); +// pRec->pDispatch->GetVertexAttribivARB(i, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, &arrayDivisor); + + if (size>1) + { + pIndexStr = crStrchr(pszName, '['); + if (!pIndexStr) + { + pIndexStr = pszName+crStrlen(pszName); + fPrintBraketsWithName = true; + } + } + + if (fPrintBraketsWithName) + { + crDmpStrF(pRec->pDumper, "%s %s[%d];", crRecDumpVarTypeString(type, pRec->pDumper), pszName, size); + Assert(size > 1); + } + else + crDmpStrF(pRec->pDumper, "%s %s;", crRecDumpVarTypeString(type, pRec->pDumper), pszName); + + crDmpStrF(pRec->pDumper, "Array buff(%d), enabled(%d) size(%d), stride(%d), type(%s), normalized(%d), integer(%d)", arrayBufferBind, arrayEnabled, arraySize, arrayStride, crRecDumpVarTypeString(arrayType, pRec->pDumper), arrayNormalized, arrayInteger); + + GLint attribTypeSize = crStateGetUniformSize(type); + Assert(attribTypeSize >= 1); + + for (j=0; j<size; ++j) + { + if (size>1) + { + sprintf(pIndexStr, "[%i]", j); + } + location = pRec->pDispatch->GetAttribLocation(hwid, pszName); + + if (crStateIsIntUniform(type)) + { + pRec->pDispatch->GetVertexAttribivARB(location, GL_CURRENT_VERTEX_ATTRIB, &idata[0]); + switch (attribTypeSize) + { + case 1: + crDmpStrF(pRec->pDumper, "%s = %d; //location %d", pszName, idata[0], location); + break; + case 2: + crDmpStrF(pRec->pDumper, "%s = {%d, %d}; //location %d", pszName, idata[0], idata[1], location); + break; + case 3: + crDmpStrF(pRec->pDumper, "%s = {%d, %d, %d}; //location %d", pszName, idata[0], idata[1], idata[2], location); + break; + case 4: + crDmpStrF(pRec->pDumper, "%s = {%d, %d, %d, %d}; //location %d", pszName, idata[0], idata[1], idata[2], idata[3], location); + break; + default: + for (GLint k = 0; k < attribTypeSize; ++k) + { + crDmpStrF(pRec->pDumper, "%s[%d] = %d; //location %d", pszName, k, idata[k], location); + } + break; + } + } + else + { + pRec->pDispatch->GetVertexAttribfvARB(location, GL_CURRENT_VERTEX_ATTRIB, &fdata[0]); + switch (attribTypeSize) + { + case 1: + crDmpStrF(pRec->pDumper, "%s = %f; //location %d", pszName, fdata[0], location); + break; + case 2: + crDmpStrF(pRec->pDumper, "%s = {%f, %f}; //location %d", pszName, fdata[0], fdata[1], location); + break; + case 3: + crDmpStrF(pRec->pDumper, "%s = {%f, %f, %f}; //location %d", pszName, fdata[0], fdata[1], fdata[2], location); + break; + case 4: + crDmpStrF(pRec->pDumper, "%s = {%f, %f, %f, %f}; //location %d", pszName, fdata[0], fdata[1], fdata[2], fdata[3], location); + break; + default: + for (GLint k = 0; k < attribTypeSize; ++k) + { + crDmpStrF(pRec->pDumper, "%s[%d] = %f; //location %d", pszName, k, fdata[k], location); + } + break; + } + } + } + } + + crFree(pszName); + } +} + +VBOXDUMPDECL(void) crRecDumpCurrentProgramUniforms(CR_RECORDER *pRec, CRContext *ctx) +{ + GLint curProgram = 0; + pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram); + if (curProgram) + { + Assert(ctx->glsl.activeProgram); + if (!ctx->glsl.activeProgram) + crWarning("no active program state with active hw program"); + else + Assert(ctx->glsl.activeProgram->hwid == curProgram); + crRecDumpProgramUniforms(pRec, ctx, 0, curProgram); + } + else + { + Assert(!ctx->glsl.activeProgram); + crDmpStrF(pRec->pDumper, "--no active program"); + } +} + +VBOXDUMPDECL(void) crRecDumpCurrentProgramAttribs(CR_RECORDER *pRec, CRContext *ctx) +{ + GLint curProgram = 0; + pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram); + if (curProgram) + { + Assert(ctx->glsl.activeProgram); + if (!ctx->glsl.activeProgram) + crWarning("no active program state with active hw program"); + else + Assert(ctx->glsl.activeProgram->hwid == curProgram); + crRecDumpProgramAttribs(pRec, ctx, 0, curProgram); + } + else + { + Assert(!ctx->glsl.activeProgram); + crDmpStrF(pRec->pDumper, "--no active program"); + } +} + +VBOXDUMPDECL(void) crRecRecompileCurrentProgram(CR_RECORDER *pRec, CRContext *ctx) +{ + GLint curProgram = 0; + pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram); + if (curProgram) + { + Assert(ctx->glsl.activeProgram); + if (!ctx->glsl.activeProgram) + crWarning("no active program state with active hw program"); + else + Assert(ctx->glsl.activeProgram->hwid == curProgram); + crRecRecompileProgram(pRec, ctx, 0, curProgram); + } + else + { + Assert(!ctx->glsl.activeProgram); + crDmpStrF(pRec->pDumper, "--no active program"); + } +} + +int crRecAlphaImgCreate(const CR_BLITTER_IMG *pImg, CR_BLITTER_IMG *pAlphaImg) +{ + if (pImg->enmFormat != GL_RGBA + && pImg->enmFormat != GL_BGRA) + { + crWarning("unsupported format 0x%x", pImg->enmFormat); + return VERR_NOT_IMPLEMENTED; + } + + pAlphaImg->bpp = 32; + pAlphaImg->pitch = pImg->width * 4; + pAlphaImg->cbData = pAlphaImg->pitch * pImg->height; + pAlphaImg->enmFormat = GL_BGRA; + pAlphaImg->width = pImg->width; + pAlphaImg->height = pImg->height; + + pAlphaImg->pvData = RTMemAlloc(pAlphaImg->cbData); + if (!pAlphaImg->pvData) + { + crWarning("RTMemAlloc failed"); + return VERR_NO_MEMORY; + } + + uint8_t *pu8SrcBuf = (uint8_t*)pImg->pvData; + uint8_t *pu8DstBuf = (uint8_t*)pAlphaImg->pvData; + for (uint32_t ih = 0; ih < pAlphaImg->height; ++ih) + { + uint32_t *pu32SrcBuf = (uint32_t*)pu8SrcBuf; + uint32_t *pu32DstBuf = (uint32_t*)pu8DstBuf; + for (uint32_t iw = 0; iw < pAlphaImg->width; ++iw) + { + uint8_t alpha = (((*pu32SrcBuf) >> 24) & 0xff); + *pu32DstBuf = (0xff << 24) || (alpha << 16) || (alpha << 8) || alpha; + ++pu32SrcBuf; + ++pu32DstBuf; + } + pu8SrcBuf += pImg->pitch; + pu8DstBuf += pAlphaImg->pitch; + } + + return VINF_SUCCESS; +} + +void crRecAlphaImgDestroy(CR_BLITTER_IMG *pImg) +{ + RTMemFree(pImg->pvData); + pImg->pvData = NULL; +} + +void crRecDumpTextureV(CR_RECORDER *pRec, const VBOXVR_TEXTURE *pTex, const char *pszStr, va_list pArgList) +{ + CR_BLITTER_IMG Img = {0}; + int rc = CrBltEnter(pRec->pBlitter); + if (RT_SUCCESS(rc)) + { + rc = CrBltImgGetTex(pRec->pBlitter, pTex, GL_BGRA, &Img); + if (RT_SUCCESS(rc)) + { + crDmpImgV(pRec->pDumper, &Img, pszStr, pArgList); + if (g_CrDbgDumpAlphaData) + { + CR_BLITTER_IMG AlphaImg = {0}; + rc = crRecAlphaImgCreate(&Img, &AlphaImg); + if (RT_SUCCESS(rc)) + { + crDmpImgF(pRec->pDumper, &AlphaImg, "Texture ALPHA Data"); + crRecAlphaImgDestroy(&AlphaImg); + } + else + { + crWarning("crRecAlphaImgCreate failed rc %d", rc); + } + } + CrBltImgFree(pRec->pBlitter, &Img); + } + else + { + crWarning("CrBltImgGetTex failed, rc %d", rc); + } + CrBltLeave(pRec->pBlitter); + } + else + { + crWarning("CrBltEnter failed, rc %d", rc); + } +} + +void crRecDumpTextureF(CR_RECORDER *pRec, const VBOXVR_TEXTURE *pTex, const char *pszStr, ...) +{ + va_list pArgList; + va_start(pArgList, pszStr); + crRecDumpTextureV(pRec, pTex, pszStr, pArgList); + va_end(pArgList); +} + +void crRecDumpTextureByIdV(CR_RECORDER *pRec, CRContext *ctx, GLint id, const char *pszStr, va_list pArgList) +{ + CRTextureObj *pTobj = (CRTextureObj *)crHashtableSearch(ctx->shared->textureTable, id); + if (!pTobj) + { + crWarning("no texture of id %d", id); + return; + } + + CRTextureLevel *pTl = &pTobj->level[0][0 /* level */]; + VBOXVR_TEXTURE Tex; + Tex.width = pTl->width; + Tex.height = pTl->height; + Tex.target = pTobj->target; + Assert(Tex.target == GL_TEXTURE_2D); + Tex.hwid = pTobj->hwid; + if (!Tex.hwid) + { + crWarning("no texture hwid of id %d", id); + return; + } + + crRecDumpTextureV(pRec, &Tex, pszStr, pArgList); +} + +void crRecDumpTextureByIdF(CR_RECORDER *pRec, CRContext *ctx, GLint id, const char *pszStr, ...) +{ + va_list pArgList; + va_start(pArgList, pszStr); + crRecDumpTextureByIdV(pRec, ctx, id, pszStr, pArgList); + va_end(pArgList); +} + +void crRecDumpTextures(CR_RECORDER *pRec, CRContext *ctx) +{ + GLint maxUnits = 0; + GLint curTexUnit = 0; + GLint restoreTexUnit = 0; + GLint curProgram = 0; + int i; + + pRec->pDispatch->GetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxUnits); + maxUnits = RT_MIN(CR_MAX_TEXTURE_UNITS, maxUnits); + + pRec->pDispatch->GetIntegerv(GL_CURRENT_PROGRAM, &curProgram); + Assert(curProgram); + Assert(ctx->glsl.activeProgram && ctx->glsl.activeProgram->hwid == curProgram); + + Assert(maxUnits); + pRec->pDispatch->GetIntegerv(GL_ACTIVE_TEXTURE, &curTexUnit); + restoreTexUnit = curTexUnit; + Assert(curTexUnit >= GL_TEXTURE0); + Assert(curTexUnit < GL_TEXTURE0 + maxUnits); + + Assert(ctx->texture.curTextureUnit == restoreTexUnit - GL_TEXTURE0); + + for (i = 0; i < maxUnits; ++i) + { + GLboolean enabled1D; + GLboolean enabled2D; + GLboolean enabled3D; + GLboolean enabledCubeMap; + GLboolean enabledRect; + CRTextureUnit *tu = &ctx->texture.unit[i]; + + if (i > 1) + break; + + if (curTexUnit != i + GL_TEXTURE0) + { + pRec->pDispatch->ActiveTextureARB(i + GL_TEXTURE0); + curTexUnit = i + GL_TEXTURE0; + } + + enabled1D = pRec->pDispatch->IsEnabled(GL_TEXTURE_1D); + enabled2D = pRec->pDispatch->IsEnabled(GL_TEXTURE_2D); + enabled3D = pRec->pDispatch->IsEnabled(GL_TEXTURE_3D); + enabledCubeMap = pRec->pDispatch->IsEnabled(GL_TEXTURE_CUBE_MAP_ARB); + enabledRect = pRec->pDispatch->IsEnabled(GL_TEXTURE_RECTANGLE_NV); + + Assert(enabled1D == tu->enabled1D); + Assert(enabled2D == tu->enabled2D); + Assert(enabled3D == tu->enabled3D); + Assert(enabledCubeMap == tu->enabledCubeMap); + Assert(enabledRect == tu->enabledRect); + + if (enabled1D) + { + crWarning("GL_TEXTURE_1D: unsupported"); + } + +// if (enabled2D) + { + GLint hwTex = 0; + VBOXVR_TEXTURE Tex; + + GLint width = 0, height = 0, depth = 0; + CRTextureObj *pTobj = tu->currentTexture2D; + + pRec->pDispatch->GetIntegerv(GL_TEXTURE_BINDING_2D, &hwTex); + if (hwTex) + { + CRTextureLevel *pTl = &pTobj->level[0][0 /* level */]; + Assert(pTobj + && pTobj->hwid == hwTex); + + pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); + pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); + pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_DEPTH, &depth); + + Assert(width == pTl->width); + Assert(height == pTl->height); + Assert(depth == pTl->depth); + + Tex.width = width; + Tex.height = height; + Tex.target = GL_TEXTURE_2D; + Tex.hwid = hwTex; + + if (g_CrDbgDumpRecTexInfo) + { + crRecDumpTexParam(pRec, ctx, GL_TEXTURE_2D); + crRecDumpTexEnv(pRec, ctx); + crRecDumpTexGen(pRec, ctx); + } + + crRecDumpTextureF(pRec, &Tex, "ctx(%d), Unit %d: TEXTURE_2D id(%d) hwid(%d), width(%d), height(%d)", ctx, i, pTobj->id, pTobj->hwid, width, height); + } +// else +// { +// Assert(!pTobj || pTobj->hwid == 0); +// crWarning("no TEXTURE_2D bound!"); +// } + } +#if 0 + if (enabled3D) + { + crWarning("GL_TEXTURE_3D: unsupported"); + } + + if (enabledCubeMap) + { + crWarning("GL_TEXTURE_CUBE_MAP_ARB: unsupported"); + } + +// if (enabledRect) + { + GLint hwTex = 0; + CR_BLITTER_IMG Img = {0}; + VBOXVR_TEXTURE Tex; + + GLint width = 0, height = 0, depth = 0; + CRTextureObj *pTobj = tu->currentTextureRect; + + pRec->pDispatch->GetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_NV, &hwTex); + if (hwTex) + { + CRTextureLevel *pTl = &pTobj->level[0][0 /* level */]; + Assert(pTobj + && pTobj->hwid == hwTex); + + pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_NV, 0, GL_TEXTURE_WIDTH, &width); + pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_NV, 0, GL_TEXTURE_HEIGHT, &height); + pRec->pDispatch->GetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_NV, 0, GL_TEXTURE_DEPTH, &depth); + + Assert(width == pTl->width); + Assert(height == pTl->height); + Assert(depth == pTl->depth); + + Tex.width = width; + Tex.height = height; + Tex.target = GL_TEXTURE_RECTANGLE_NV; + Tex.hwid = hwTex; + + rc = CrBltEnter(pRec->pBlitter); + if (RT_SUCCESS(rc)) + { + rc = CrBltImgGetTex(pRec->pBlitter, &Tex, GL_BGRA, &Img); + if (RT_SUCCESS(rc)) + { + crDmpImgF(pRec->pDumper, &Img, "Unit %d: TEXTURE_RECTANGLE data", i); + CrBltImgFree(pRec->pBlitter, &Img); + } + else + { + crWarning("CrBltImgGetTex failed, rc %d", rc); + } + CrBltLeave(pRec->pBlitter); + } + else + { + crWarning("CrBltEnter failed, rc %d", rc); + } + } +// else +// { +// Assert(!pTobj || pTobj->hwid == 0); +// crWarning("no TEXTURE_RECTANGLE bound!"); +// } + } +#endif + } + + if (curTexUnit != restoreTexUnit) + { + pRec->pDispatch->ActiveTextureARB(restoreTexUnit); + curTexUnit = restoreTexUnit; + } +} + +#ifdef RT_OS_WINDOWS +static void crDmpPrint(const char* szString, ...) +{ + char szBuffer[4096] = {0}; + va_list pArgList; + va_start(pArgList, szString); + RTStrPrintfV(szBuffer, sizeof (szBuffer), szString, pArgList); + va_end(pArgList); + + OutputDebugStringA(szBuffer); +} + +static void crDmpPrintDmlCmd(const char* pszDesc, const char* pszCmd) +{ + crDmpPrint("<?dml?><exec cmd=\"%s\">%s</exec>, ( %s )\n", pszCmd, pszDesc, pszCmd); +} + +void crDmpPrintDumpDmlCmd(const char* pszDesc, const void *pvData, uint32_t width, uint32_t height, uint32_t bpp, uint32_t pitch) +{ + char Cmd[1024]; + sprintf(Cmd, "!vbvdbg.ms 0x%p 0n%d 0n%d 0n%d 0n%d", pvData, width, height, bpp, pitch); + crDmpPrintDmlCmd(pszDesc, Cmd); +} + +DECLCALLBACK(void) crDmpDumpImgDmlBreak(struct CR_DUMPER * pDumper, CR_BLITTER_IMG *pImg, const char*pszEntryDesc) +{ + crDmpPrintDumpDmlCmd(pszEntryDesc, pImg->pvData, pImg->width, pImg->height, pImg->bpp, pImg->pitch); + RT_BREAKPOINT(); +} + +DECLCALLBACK(void) crDmpDumpStrDbgPrint(struct CR_DUMPER * pDumper, const char*pszStr) +{ + crDmpPrint("%s\n", pszStr); +} +#endif + +static void crDmpHtmlDumpStrExact(struct CR_HTML_DUMPER * pDumper, const char *pszStr) +{ + fprintf(pDumper->pFile, "%s", pszStr); + fflush(pDumper->pFile); +} + +static DECLCALLBACK(void) crDmpHtmlDumpStr(struct CR_DUMPER * pDumper, const char*pszStr) +{ + CR_HTML_DUMPER * pHtmlDumper = (CR_HTML_DUMPER*)pDumper; + fprintf(pHtmlDumper->pFile, "<pre>%s</pre>\n", pszStr); + fflush(pHtmlDumper->pFile); +} + +static DECLCALLBACK(void) crDmpHtmlDumpImg(struct CR_DUMPER * pDumper, CR_BLITTER_IMG *pImg, const char*pszEntryDesc) +{ + CR_HTML_DUMPER * pHtmlDumper = (CR_HTML_DUMPER*)pDumper; + char szBuffer[4096] = {0}; + size_t cbWritten = RTStrPrintf(szBuffer, sizeof(szBuffer), "%s/", pHtmlDumper->pszDir); + char *pszFileName = szBuffer + cbWritten; + RTStrPrintf(pszFileName, sizeof(szBuffer) - cbWritten, "img%d.bmp", ++pHtmlDumper->cImg); + crDmpImgBmp(pImg, szBuffer); + fprintf(pHtmlDumper->pFile, "<a href=\"%s\"><pre>%s</pre><img src=\"%s\" alt=\"%s\" width=\"150\" height=\"100\" /></a><br>\n", + pszFileName, pszEntryDesc, pszFileName, pszEntryDesc); + fflush(pHtmlDumper->pFile); +} + +static void crDmpHtmlPrintHeader(struct CR_HTML_DUMPER * pDumper) +{ + fprintf(pDumper->pFile, "<html><body>\n"); + fflush(pDumper->pFile); +} + +static void crDmpHtmlPrintFooter(struct CR_HTML_DUMPER * pDumper) +{ + fprintf(pDumper->pFile, "</body></html>\n"); + fflush(pDumper->pFile); +} + +DECLEXPORT(bool) crDmpHtmlIsInited(struct CR_HTML_DUMPER * pDumper) +{ + return !!pDumper->pFile; +} + +DECLEXPORT(void) crDmpHtmlTerm(struct CR_HTML_DUMPER * pDumper) +{ + crDmpHtmlPrintFooter(pDumper); + fclose (pDumper->pFile); + pDumper->pFile = NULL; +} + +DECLEXPORT(int) crDmpHtmlInit(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile) +{ + int rc = VERR_NO_MEMORY; + pDumper->Base.pfnDumpImg = crDmpHtmlDumpImg; + pDumper->Base.pfnDumpStr = crDmpHtmlDumpStr; + pDumper->cImg = 0; + pDumper->pszDir = crStrdup(pszDir); + if (pDumper->pszDir) + { + pDumper->pszFile = crStrdup(pszFile); + if (pDumper->pszFile) + { + char szBuffer[4096] = {0}; + RTStrPrintf(szBuffer, sizeof(szBuffer), "%s/%s", pszDir, pszFile); + + pDumper->pszFile = crStrdup(pszFile); + pDumper->pFile = fopen(szBuffer, "w"); + if (pDumper->pFile) + { + crDmpHtmlPrintHeader(pDumper); + return VINF_SUCCESS; + } + else + { + crWarning("open failed"); + rc = VERR_OPEN_FAILED; + } + crFree((void*)pDumper->pszFile); + } + else + { + crWarning("open failed"); + } + crFree((void*)pDumper->pszDir); + } + else + { + crWarning("open failed"); + } + return rc; +} + +DECLEXPORT(int) crDmpHtmlInitV(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile, va_list pArgList) +{ + char szBuffer[4096] = {0}; + vsprintf_s(szBuffer, sizeof (szBuffer), pszFile, pArgList); + return crDmpHtmlInit(pDumper, pszDir, szBuffer); +} + +DECLEXPORT(int) crDmpHtmlInitF(struct CR_HTML_DUMPER * pDumper, const char *pszDir, const char *pszFile, ...) +{ + int rc; + va_list pArgList; + va_start(pArgList, pszFile); + rc = crDmpHtmlInitV(pDumper, pszDir, pszFile, pArgList); + va_end(pArgList); + return rc; +} + +#endif diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/dump_gen.py b/src/VBox/GuestHost/OpenGL/state_tracker/dump_gen.py new file mode 100755 index 00000000..c4cae06e --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/dump_gen.py @@ -0,0 +1,249 @@ +from __future__ import print_function +import sys + +import apiutil + +import sys, re, string + + +line_re = re.compile(r'^(\S+)\s+(GL_\S+)\s+(.*)\s*$') +extensions_line_re = re.compile(r'^(\S+)\s+(GL_\S+)\s(\S+)\s+(.*)\s*$') + +params = {} +extended_params = {} + +input = open( sys.argv[2]+"/state_isenabled.txt", 'r' ) +for line in input.readlines(): + match = line_re.match( line ) + if match: + type = match.group(1) + pname = match.group(2) + fields = string.split( match.group(3) ) + params[pname] = ( type, fields ) + +input = open( sys.argv[2]+"/state_extensions_isenabled.txt", 'r' ) +for line in input.readlines(): + match = extensions_line_re.match( line ) + if match: + type = match.group(1) + pname = match.group(2) + ifdef = match.group(3) + fields = string.split( match.group(4) ) + extended_params[pname] = ( type, ifdef, fields ) + + +apiutil.CopyrightC() + +print("""#include "cr_blitter.h" +#include "cr_spu.h" +#include "chromium.h" +#include "cr_error.h" +#include "cr_net.h" +#include "cr_rand.h" +#include "cr_mem.h" +#include "cr_string.h" +#include <cr_dump.h> +#include "cr_pixeldata.h" + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/mem.h> + +#include <stdio.h> + +#ifdef VBOX_WITH_CRDUMPER +""") + +from get_sizes import *; + +getprops = apiutil.ParamProps("GetDoublev") +enableprops = apiutil.ParamProps("Enable") + +#print "//missing get props:" +#for prop in getprops: +# try: +# tmp = num_get_values[prop] +# except KeyError: +# try: +# keyvalues = extensions_num_get_values[prop] +# except KeyError: +# print "//%s" % prop +# +print(""" +static void crRecDumpPrintVal(CR_DUMPER *pDumper, struct nv_struct *pDesc, float *pfData) +{ + char aBuf[4096]; + crDmpFormatArray(aBuf, sizeof (aBuf), "%f", sizeof (float), pfData, pDesc->num_values); + crDmpStrF(pDumper, "%s = %s;", pDesc->pszName, aBuf); +} + + +void crRecDumpGlGetState(CR_RECORDER *pRec, CRContext *ctx) +{ + float afData[CR_MAX_GET_VALUES]; + struct nv_struct *pDesc; + + for (pDesc = num_values_array; pDesc->num_values != 0 ; pDesc++) + { + memset(afData, 0, sizeof(afData)); + pRec->pDispatch->GetFloatv(pDesc->pname, afData); + crRecDumpPrintVal(pRec->pDumper, pDesc, afData); + } +} + +void crRecDumpGlEnableState(CR_RECORDER *pRec, CRContext *ctx) +{ + GLboolean fEnabled; +""") +for pname in sorted(params.keys()): + print("\tfEnabled = pRec->pDispatch->IsEnabled(%s);" % pname) + print("\tcrDmpStrF(pRec->pDumper, \"%s = %%d;\", fEnabled);" % pname) + +for pname in sorted(extended_params.keys()): + (srctype,ifdef,fields) = extended_params[pname] + ext = ifdef[3:] # the extension name with the "GL_" prefix removed + ext = ifdef + print('#ifdef CR_%s' % ext) + print("\tfEnabled = pRec->pDispatch->IsEnabled(%s);" % pname) + print("\tcrDmpStrF(pRec->pDumper, \"%s = %%d;\", fEnabled);" % pname) + print('#endif /* CR_%s */' % ext) + +#print "//missing enable props:" +#for prop in enableprops: +# try: +# keyvalues = params[prop] +# except KeyError: +# try: +# keyvalues = extended_params[prop] +# except KeyError: +# print "//%s" % prop +# +print(""" +} +#endif +""") + +texenv_mappings = { + 'GL_TEXTURE_ENV' : [ + 'GL_TEXTURE_ENV_MODE', + 'GL_TEXTURE_ENV_COLOR', + 'GL_COMBINE_RGB', + 'GL_COMBINE_ALPHA', + 'GL_RGB_SCALE', + 'GL_ALPHA_SCALE', + 'GL_SRC0_RGB', + 'GL_SRC1_RGB', + 'GL_SRC2_RGB', + 'GL_SRC0_ALPHA', + 'GL_SRC1_ALPHA', + 'GL_SRC2_ALPHA' + ], + 'GL_TEXTURE_FILTER_CONTROL' : [ + 'GL_TEXTURE_LOD_BIAS' + ], + 'GL_POINT_SPRITE' : [ + 'GL_COORD_REPLACE' + ] +} + +texgen_coords = [ + 'GL_S', + 'GL_T', + 'GL_R', + 'GL_Q' +] + +texgen_names = [ + 'GL_TEXTURE_GEN_MODE', + 'GL_OBJECT_PLANE', + 'GL_EYE_PLANE' +] + +texparam_names = [ + 'GL_TEXTURE_MAG_FILTER', + 'GL_TEXTURE_MIN_FILTER', + 'GL_TEXTURE_MIN_LOD', + 'GL_TEXTURE_MAX_LOD', + 'GL_TEXTURE_BASE_LEVEL', + 'GL_TEXTURE_MAX_LEVEL', + 'GL_TEXTURE_WRAP_S', + 'GL_TEXTURE_WRAP_T', + 'GL_TEXTURE_WRAP_R', + 'GL_TEXTURE_BORDER_COLOR', + 'GL_TEXTURE_PRIORITY', + 'GL_TEXTURE_RESIDENT', + 'GL_TEXTURE_COMPARE_MODE', + 'GL_TEXTURE_COMPARE_FUNC', + 'GL_DEPTH_TEXTURE_MODE', + 'GL_GENERATE_MIPMAP' +] + +print(""" +void crRecDumpTexParam(CR_RECORDER *pRec, CRContext *ctx, GLenum enmTarget) +{ + GLfloat afBuf[4]; + char acBuf[1024]; + unsigned int cComponents; + crDmpStrF(pRec->pDumper, "==TEX_PARAM for target(0x%x)==", enmTarget); +""") +for pname in texparam_names: + print("\tcComponents = crStateHlpComponentsCount(%s);" % pname) + print("\tAssert(cComponents <= RT_ELEMENTS(afBuf));") + print("\tmemset(afBuf, 0, sizeof (afBuf));") + print("\tpRec->pDispatch->GetTexParameterfv(enmTarget, %s, afBuf);" % pname) + print("\tcrDmpFormatArray(acBuf, sizeof (acBuf), \"%f\", sizeof (afBuf[0]), afBuf, cComponents);") + print("\tcrDmpStrF(pRec->pDumper, \"%s = %%s;\", acBuf);" % pname) +print(""" + crDmpStrF(pRec->pDumper, "==Done TEX_PARAM for target(0x%x)==", enmTarget); +} +""") + +print(""" +void crRecDumpTexEnv(CR_RECORDER *pRec, CRContext *ctx) +{ + GLfloat afBuf[4]; + char acBuf[1024]; + unsigned int cComponents; + crDmpStrF(pRec->pDumper, "==TEX_ENV=="); +""") + +for target in sorted(texenv_mappings.keys()): + print("\tcrDmpStrF(pRec->pDumper, \"===%s===\");" % target) + values = texenv_mappings[target] + for pname in values: + print("\tcComponents = crStateHlpComponentsCount(%s);" % pname) + print("\tAssert(cComponents <= RT_ELEMENTS(afBuf));") + print("\tmemset(afBuf, 0, sizeof (afBuf));") + print("\tpRec->pDispatch->GetTexEnvfv(%s, %s, afBuf);" % (target, pname)) + print("\tcrDmpFormatArray(acBuf, sizeof (acBuf), \"%f\", sizeof (afBuf[0]), afBuf, cComponents);") + print("\tcrDmpStrF(pRec->pDumper, \"%s = %%s;\", acBuf);" % pname) + print("\tcrDmpStrF(pRec->pDumper, \"===Done %s===\");" % target) +print(""" + crDmpStrF(pRec->pDumper, "==Done TEX_ENV=="); +} +""") + + +print(""" +void crRecDumpTexGen(CR_RECORDER *pRec, CRContext *ctx) +{ + GLdouble afBuf[4]; + char acBuf[1024]; + unsigned int cComponents; + crDmpStrF(pRec->pDumper, "==TEX_GEN=="); +""") + +for coord in texgen_coords: + print("\tcrDmpStrF(pRec->pDumper, \"===%s===\");" % coord) + for pname in texgen_names: + print("\tcComponents = crStateHlpComponentsCount(%s);" % pname) + print("\tAssert(cComponents <= RT_ELEMENTS(afBuf));") + print("\tmemset(afBuf, 0, sizeof (afBuf));") + print("\tpRec->pDispatch->GetTexGendv(%s, %s, afBuf);" % (coord, pname)) + print("\tcrDmpFormatArray(acBuf, sizeof (acBuf), \"%f\", sizeof (afBuf[0]), afBuf, cComponents);") + print("\tcrDmpStrF(pRec->pDumper, \"%s = %%s;\", acBuf);" % pname) + print("\tcrDmpStrF(pRec->pDumper, \"===Done %s===\");" % coord) +print(""" + crDmpStrF(pRec->pDumper, "==Done TEX_GEN=="); +} +""") diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/gendiffcode.py b/src/VBox/GuestHost/OpenGL/state_tracker/gendiffcode.py new file mode 100755 index 00000000..6c3e91d6 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/gendiffcode.py @@ -0,0 +1,273 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software + +from __future__ import print_function +import sys + +def main(): + name = sys.argv[1] + Name = sys.argv[2] + + print("""/* This code is AUTOGENERATED!!! */ + +#include "state.h" +#include "state_internals.h\"""") + + print(""" +void crState%(Name)sDiff(CR%(Name)sBits *b, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + CR%(Name)sState *from = &(fromCtx->%(name)s); + CR%(Name)sState *to = &(toCtx->%(name)s);"""%vars()) + gendiffcode("state_%s.txt"%(name.lower()), name, docopy=1, doinvalid=0) + print("""} + +void crState%(Name)sSwitch(CR%(Name)sBits *b, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + CR%(Name)sState *from = &(fromCtx->%(name)s); + CR%(Name)sState *to = &(toCtx->%(name)s);"""%vars()) + gendiffcode("state_%s.txt"%(Name.lower()), Name, docopy=0, doinvalid=1) + print("}\n") + +def gendiffcode(fname, state_name, docopy, doinvalid): + target = "to" + current = "from" + bit = "b" + extrabit = "" + tab = "\t" + current_guard = "" + current_dependency = "" + + v_types = { + 'l': 'GLboolean', + 'b': 'GLbyte', + 'ub': 'GLubyte', + 's': 'GLshort', + 'us': 'GLushort', + 'i': 'GLint', + 'ui': 'GLuint', + 'f': 'GLfloat', + 'd': 'GLdouble' + } + + FILE = open(sys.argv[3]+"/"+fname, "r") + + print(""" unsigned int j, i; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + for (j = 0; j<CR_MAX_BITARRAY; j++) + nbitID[j] = ~bitID[j]; + i = 0; /* silence compiler */""") + + import re + for line in FILE: + line = line.rstrip() + + if re.match("#", line): + continue + +## Handle text dump + m = re.match("\+(.*)", line) + if m: + if doinvalid: + continue + line = m.group(1) + + else: + m = re.match("-(.*)", line) + if m: + if docopy: + continue + line = m.group(1) + + m = re.match(">(.*)", line) + if m: + text = m.group(1) + if re.search("}", line): + tab = tab[:-1] + print(tab+text) + if re.search("{", line): + tab = tab+"\t" + continue + +## Handle commands + + m = re.search("%target=(\w*)", line) + if m: + target = m.group(1) + m = re.search("%current=(\w*)", line) + if m: + current = m.group(1) + m = re.search("%bit=(\w*)", line) + if m: + bit = m.group(1) + m = re.search("%extrabit=(\w*)", line) + if m: + extrabit = m.group(1) + + if re.search("%flush", line): + if current_guard != "": + print(tab+"CLEARDIRTY(%(bit)s->%(current_guard)s, nbitID);"%vars()) + tab = tab[:-1] + print(tab+"}") + if docopy and current_dependency != "": + tab = tab[:-1] + print(tab+"}") + current_guard = "" + current_dependency = "" + if re.search("%", line): + continue + +## Load the line + (dependency, guardbit, members, func) = \ + (re.split(":", line) + ["", ""])[0:4] + func = func.rstrip() + +## Close the guardbit and dependency + if current_guard != "" and current_guard != guardbit: + print(tab+"CLEARDIRTY(%(bit)s->%(current_guard)s, nbitID);"%vars()) + tab = tab[:-1] + print(tab+"}") + if docopy and current_dependency != "" and current_dependency != dependency: + tab = tab[:-1] + print(tab+"}") + +## Open the dependency if + if docopy and current_dependency != dependency and dependency != "": + print(tab+"if (%(target)s->%(dependency)s)\n%(tab)s{"%vars()) + tab = tab+"\t" + current_dependency = dependency + +## Open the guard if + if docopy and current_dependency != dependency and dependency != "": + print(tab+"if ($(target)s->%(dependency)s)\n%(tab)s{"%vars()) + tab = tab+"\t" + + if current_guard != guardbit and guardbit != "": + print(tab+"if (CHECKDIRTY(%(bit)s->%(guardbit)s, bitID))\n%(tab)s{"%vars()) + tab = tab+"\t" + if members[0] != "*" and guardbit[0:6] == "enable": + print(tab+"glAble able[2];") + print(tab+"able[0] = diff_api.Disable;") + print(tab+"able[1] = diff_api.Enable;") + + current_dependency = dependency + current_guard = guardbit + +## Handle text dump + if members[0] == "*": + print(tab+members[1:]) + else: + ## Parse the members variable + mainelem = re.split(",", members) + elems = re.split("\|", members) + if len(elems) > 1: + mainelem = [""] + mainelem[0] = elems[0] + elems = re.split(",", elems[1]) + newelems = [] + for elem in elems: + elem = mainelem[0] + "." + elem + newelems += [elem] + elems = newelems + else: + elems = re.split(",", members) + + ## Check member values + if guardbit != "extensions": + sys.stdout.write(tab+"if (") + first = 1 + for elem in elems: + if first != 1: + print(" ||\n"+tab+" ", end="") + first = 0 + sys.stdout.write("%(current)s->%(elem)s != %(target)s->%(elem)s"%vars()) + print(")\n"+tab+"{") + tab = tab+"\t" + +## Handle text function + if func[0] == "*": + func = func[1:] + print(tab+func) + else: + if func != "": +## Call the glhw function + if guardbit[0:6] == "enable": + print(tab+"able["+target+"->"+elems[0]+"]("+func+");") + elif guardbit == "extensions": + print(tab+"crState$state_name",end="") + if docopy == 1: + print("Diff",end="") + else: + print("Switch",end="") + print("Extensions(from, to);") + else: + funcargs = re.split(",", func) + #print "// funcargs:",funcargs + func = funcargs.pop(0) + + if func[-1] == "v": + v_type = func[-2:-1] + num_elems = len(elems) + print(tab+v_types[v_type]+" varg["+str(num_elems)+"];") + i = 0 + for elem in elems: + print(tab+"varg["+str(i)+"] = "+target+"->"+elem+";") + i += 1 + elif func[-3:] == "vNV": + v_type = func[-4:-3] + num_elems = len(elems) + print(tab+v_types[v_type]+" varg["+str(num_elems)+"];") + i = 0 + for elem in elems: + print(tab+"varg["+str(i)+"] = "+target+"->"+elem+";") + i += 1 + + sys.stdout.write(tab+"diff_api.%(func)s("%vars()) + for funcarg in funcargs: + sys.stdout.write(funcarg+", ") + +## Handle vargs + if func[-1] == "v" or func[-3:] == "vNV": + sys.stdout.write("varg") + else: + first = 1 + for elem in elems: + if first != 1: + sys.stdout.write(",\n"+tab+" ") + first = 0 + sys.stdout.write(target+"->"+elem) + print(");") + +## Do the sync if necessary + if docopy and guardbit != "extensions": + for elem in mainelem: + print(tab+current+"->"+elem+" = "+target+"->"+elem+";") + + ## Do the clear if necessary + if doinvalid: + if guardbit != "": + print(tab+"FILLDIRTY(%(bit)s->%(guardbit)s);"%vars()) + print(tab+"FILLDIRTY(%(bit)s->dirty);"%vars()) + if extrabit != "": + print(tab+"FILLDIRTY(%(extrabit)s->dirty);"%vars()) + + ## Close the compare + if guardbit != "extensions": + tab = tab[:-1] + print(tab+"}") + +## Do final closures + if current_guard != "": + print(tab+"CLEARDIRTY(%(bit)s->%(current_guard)s, nbitID);"%vars()) + tab = tab[:-1] + print(tab+"}") + if docopy and current_dependency != "": + tab = tab[:-1] + print(tab+"} /*%(current_dependency)s*/"%vars()) + + print(tab+"CLEARDIRTY(%(bit)s->dirty, nbitID);"%vars()) + +main() diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/get_components.py b/src/VBox/GuestHost/OpenGL/state_tracker/get_components.py new file mode 100755 index 00000000..dc7da7b2 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/get_components.py @@ -0,0 +1,141 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function + +num_components = { + 'GL_AMBIENT' : 4, + 'GL_DIFFUSE' : 4, + 'GL_SPECULAR' : 4, + 'GL_POSITION' : 4, + 'GL_SPOT_DIRECTION' : 3, + 'GL_SPOT_EXPONENT' : 1, + 'GL_SPOT_CUTOFF' : 1, + 'GL_CONSTANT_ATTENUATION' : 1, + 'GL_LINEAR_ATTENUATION' : 1, + 'GL_QUADRATIC_ATTENUATION' : 1, + 'GL_EMISSION' : 4, + 'GL_SHININESS' : 1, + 'GL_COLOR_INDEXES' : 3, + 'GL_TEXTURE_ENV_MODE' : 1, + 'GL_TEXTURE_ENV_COLOR' : 4, + 'GL_TEXTURE_GEN_MODE' : 1, + 'GL_OBJECT_PLANE' : 4, + 'GL_EYE_PLANE' : 4, + 'GL_TEXTURE_MAG_FILTER' : 1, + 'GL_TEXTURE_MIN_FILTER' : 1, + 'GL_TEXTURE_WRAP_S' : 1, + 'GL_TEXTURE_WRAP_T' : 1, + 'GL_TEXTURE_BORDER_COLOR' : 4, + 'GL_TEXTURE_WIDTH': 1, + 'GL_TEXTURE_HEIGHT': 1, + 'GL_TEXTURE_DEPTH': 1, + # 'GL_TEXTURE_INTERNAL_FORMAT': 1, THIS CONFLICTS WITH GL_TEXTURE_COMPONENTS! + 'GL_TEXTURE_BORDER': 1, + 'GL_TEXTURE_RED_SIZE': 1, + 'GL_TEXTURE_GREEN_SIZE': 1, + 'GL_TEXTURE_BLUE_SIZE': 1, + 'GL_TEXTURE_ALPHA_SIZE': 1, + 'GL_TEXTURE_LUMINANCE_SIZE': 1, + 'GL_TEXTURE_INTENSITY_SIZE': 1, + 'GL_TEXTURE_COMPONENTS': 1, + 'GL_TEXTURE_RESIDENT': 1 +} + +num_extended_components = { + 'GL_TEXTURE_MAX_ANISOTROPY_EXT': ( 1, 'CR_EXT_texture_filter_anisotropic' ), + 'GL_TEXTURE_WRAP_R': ( 1, 'CR_OPENGL_VERSION_1_2'), + 'GL_TEXTURE_PRIORITY': ( 1, 'CR_OPENGL_VERSION_1_2'), + 'GL_TEXTURE_MIN_LOD': ( 1, 'CR_OPENGL_VERSION_1_2'), + 'GL_TEXTURE_MAX_LOD': ( 1, 'CR_OPENGL_VERSION_1_2'), + 'GL_TEXTURE_BASE_LEVEL': ( 1, 'CR_OPENGL_VERSION_1_2'), + 'GL_TEXTURE_MAX_LEVEL': ( 1, 'CR_OPENGL_VERSION_1_2'), + 'GL_COMBINER_INPUT_NV': ( 1, 'CR_NV_register_combiners'), + 'GL_COMBINER_MAPPING_NV': ( 1, 'CR_NV_register_combiners'), + 'GL_COMBINER_COMPONENT_USAGE_NV': ( 1, 'CR_NV_register_combiners'), + 'GL_COMBINER_AB_DOT_PRODUCT_NV': ( 1, 'CR_NV_register_combiners'), + 'GL_COMBINER_CD_DOT_PRODUCT_NV': ( 1, 'CR_NV_register_combiners'), + 'GL_COMBINER_MUX_SUM_NV': ( 1, 'CR_NV_register_combiners'), + 'GL_COMBINER_SCALE_NV': ( 1, 'CR_NV_register_combiners'), + 'GL_COMBINER_BIAS_NV': ( 1, 'CR_NV_register_combiners'), + 'GL_COMBINER_AB_OUTPUT_NV': ( 1, 'CR_NV_register_combiners'), + 'GL_COMBINER_CD_OUTPUT_NV': ( 1, 'CR_NV_register_combiners'), + 'GL_COMBINER_SUM_OUTPUT_NV': ( 1, 'CR_NV_register_combiners'), + 'GL_COMBINER_INPUT_NV': ( 1, 'CR_NV_register_combiners'), + 'GL_COMBINER_INPUT_NV': ( 1, 'CR_NV_register_combiners'), + 'GL_COMBINER_MAPPING_NV': ( 1, 'CR_NV_register_combiners'), + 'GL_COMBINER_COMPONENT_USAGE_NV': ( 1, 'CR_NV_register_combiners'), + 'GL_CONSTANT_COLOR0_NV': ( 4, 'CR_NV_register_combiners'), + 'GL_CONSTANT_COLOR1_NV': ( 4, 'CR_NV_register_combiners'), + 'GL_COMBINE_RGB_ARB': (1, 'CR_ARB_texture_env_combine'), + 'GL_COMBINE_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'), + 'GL_SOURCE0_RGB_ARB': (1, 'CR_ARB_texture_env_combine'), + 'GL_SOURCE1_RGB_ARB': (1, 'CR_ARB_texture_env_combine'), + 'GL_SOURCE2_RGB_ARB': (1, 'CR_ARB_texture_env_combine'), + 'GL_SOURCE0_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'), + 'GL_SOURCE1_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'), + 'GL_SOURCE2_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'), + 'GL_OPERAND0_RGB_ARB': (1, 'CR_ARB_texture_env_combine'), + 'GL_OPERAND1_RGB_ARB': (1, 'CR_ARB_texture_env_combine'), + 'GL_OPERAND2_RGB_ARB': (1, 'CR_ARB_texture_env_combine'), + 'GL_OPERAND0_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'), + 'GL_OPERAND1_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'), + 'GL_OPERAND2_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'), + 'GL_RGB_SCALE_ARB': (1, 'CR_ARB_texture_env_combine'), + 'GL_ALPHA_SCALE': (1, 'CR_ARB_texture_env_combine'), + 'GL_DEPTH_TEXTURE_MODE_ARB': (1, 'CR_ARB_depth_texture'), + 'GL_TEXTURE_DEPTH_SIZE_ARB': (1, 'CR_ARB_depth_texture'), + 'GL_TEXTURE_COMPARE_MODE_ARB': (1, 'CR_ARB_shadow'), + 'GL_TEXTURE_COMPARE_FUNC_ARB': (1, 'CR_ARB_shadow'), + 'GL_TEXTURE_COMPARE_FAIL_VALUE_ARB': (1, 'CR_ARB_shadow_ambient'), + 'GL_GENERATE_MIPMAP_SGIS': (1, 'CR_SGIS_generate_mipmap'), + 'GL_TEXTURE_LOD_BIAS_EXT': (1, 'CR_EXT_texture_lod_bias'), + 'GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB': (1, 'CR_any_vertex_program'), + 'GL_CURRENT_VERTEX_ATTRIB_ARB': (4, 'CR_any_vertex_program'), + 'GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB': (1, 'CR_any_vertex_program'), + 'GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB': (1, 'CR_any_vertex_program'), + 'GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB': (1, 'CR_any_vertex_program'), + 'GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB': (1, 'CR_any_vertex_program'), + 'GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB': (1, 'CR_any_vertex_program'), + 'GL_TRACK_MATRIX_NV': (24, 'CR_any_vertex_program'), + 'GL_TRACK_MATRIX_TRANSFORM_NV': (24, 'CR_any_vertex_program'), + 'GL_BUFFER_SIZE_ARB': (1, 'CR_ARB_vertex_buffer_object'), + 'GL_BUFFER_USAGE_ARB': (1, 'CR_ARB_vertex_buffer_object'), + 'GL_BUFFER_ACCESS_ARB': (1, 'CR_ARB_vertex_buffer_object'), + 'GL_BUFFER_MAPPED_ARB': (1, 'CR_ARB_vertex_buffer_object'), + 'GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB': (1, 'CR_ARB_vertex_buffer_object'), + 'GL_QUERY_COUNTER_BITS_ARB': (1, 'CR_ARB_occlusion_query'), + 'GL_QUERY_RESULT_AVAILABLE_ARB': (1, 'CR_ARB_occlusion_query'), + 'GL_QUERY_RESULT_ARB': (1, 'CR_ARB_occlusion_query'), + 'GL_CURRENT_QUERY_ARB': (1, 'CR_ARB_occlusion_query'), + 'GL_TEXTURE_COMPRESSED_IMAGE_SIZE': (1, 'CR_ARB_texture_compression'), + 'GL_TEXTURE_COMPRESSED': (1, 'CR_ARB_texture_compression'), + 'GL_COORD_REPLACE_ARB': (1, 'CR_ARB_point_sprite'), +} + +print("""unsigned int crStateHlpComponentsCount( GLenum pname ) +{ + switch( pname ) + { +""") +for comp in sorted(num_components.keys()): + print('\t\t\tcase %s: return %d;' % (comp,num_components[comp])) + +for comp in sorted(num_extended_components.keys()): + (nc, ifdef) = num_extended_components[comp] + print('#ifdef %s' % ifdef) + print('\t\t\tcase %s: return %d;' % (comp,nc)) + print('#endif /* %s */' % ifdef) + +print(""" + default: + crError( "Unknown parameter name in crStateHlpComponentsCount: %d", (int) pname ); + break; + } + /* NOTREACHED */ + return 0; +} +""") + diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state.h b/src/VBox/GuestHost/OpenGL/state_tracker/state.h new file mode 100644 index 00000000..9ba9d4c6 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state.h @@ -0,0 +1,80 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved. + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#ifndef STATE_H +#define STATE_H + +#include "cr_glstate.h" + +#define CRSTATE_CHECKERR_RET(expr, result, message, ret) \ + if (expr) { \ + crStateError(__LINE__, __FILE__, result, message); \ + return ret; \ + } + +#define CRSTATE_NO_RETURN + +#define CRSTATE_CHECKERR(expr, result, message) CRSTATE_CHECKERR_RET(expr, result, message, CRSTATE_NO_RETURN) + +typedef struct _crCheckIDHWID { + GLuint id, hwid; +} crCheckIDHWID_t; + +extern SPUDispatchTable diff_api; +extern CRStateBits *__currentBits; + +#define GetCurrentBits() __currentBits + +#ifdef CHROMIUM_THREADSAFE +#include <cr_threads.h> + +extern CRtsd __contextTSD; +#define GetCurrentContext() VBoxTlsRefGetCurrent(CRContext, &__contextTSD) + +/* NOTE: below SetCurrentContext stuff is supposed to be used only internally!! + * it is placed here only to simplify things since some code besides state_init.c + * (i.e. state_glsl.c) is using it */ +#define SetCurrentContext(_ctx) VBoxTlsRefSetCurrent(CRContext, &__contextTSD, _ctx) +#else +extern CRContext *__currentContext; +#define GetCurrentContext() __currentContext +#endif + +extern GLboolean g_bVBoxEnableDiffOnMakeCurrent; + +extern CRContext *g_pAvailableContexts[CR_MAX_CONTEXTS]; +extern uint32_t g_cContexts; + +extern void crStateTextureInitTextureObj (CRContext *ctx, CRTextureObj *tobj, GLuint name, GLenum target); +extern void crStateTextureInitTextureFormat( CRTextureLevel *tl, GLenum internalFormat ); + +/* Normally these functions would have been in cr_bufferobject.h but + * that led to a number of issues. + */ +void crStateBufferObjectInit(CRContext *ctx); + +void crStateBufferObjectDestroy (CRContext *ctx); + +void crStateBufferObjectDiff(CRBufferObjectBits *bb, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx); + +void crStateBufferObjectSwitch(CRBufferObjectBits *bb, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx); + +/* These would normally be in cr_client.h */ + +void crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID, CRContext *from, CRContext *to); + +void crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID, CRContext *from, CRContext *to); + +void crStateFreeBufferObject(void *data); +void crStateFreeFBO(void *data); +void crStateFreeRBO(void *data); + +void crStateGenNames(CRContext *g, CRHashTable *table, GLsizei n, GLuint *names); +void crStateRegNames(CRContext *g, CRHashTable *table, GLsizei n, GLuint *names); +void crStateOnTextureUsageRelease(CRSharedState *pS, CRTextureObj *pObj); +#endif diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_attrib.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_attrib.c new file mode 100644 index 00000000..a226a8d7 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_attrib.c @@ -0,0 +1,1185 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include <stdio.h> +#include "state.h" +#include "state/cr_statetypes.h" +#include "state_internals.h" +#include "cr_error.h" +#include "cr_mem.h" + +/** + * \mainpage state_tracker + * + * \section StateTrackerIntroduction Introduction + * + * Chromium consists of all the top-level files in the cr + * directory. The state_tracker module basically takes care of API dispatch, + * and OpenGL state management. + * + * + */ +void crStateAttribInit (CRAttribState *a) +{ + int i; + a->attribStackDepth = 0; + a->accumBufferStackDepth = 0; + a->colorBufferStackDepth = 0; + a->currentStackDepth = 0; + a->depthBufferStackDepth = 0; + a->enableStackDepth = 0; + for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++) + { + a->enableStack[i].clip = NULL; + a->enableStack[i].light = NULL; + a->lightingStack[i].light = NULL; + a->transformStack[i].clip = NULL; + a->transformStack[i].clipPlane = NULL; + } + a->evalStackDepth = 0; + a->fogStackDepth = 0; + a->lightingStackDepth = 0; + a->lineStackDepth = 0; + a->listStackDepth = 0; + a->pixelModeStackDepth = 0; + a->pointStackDepth = 0; + a->polygonStackDepth = 0; + a->polygonStippleStackDepth = 0; + a->scissorStackDepth = 0; + a->stencilBufferStackDepth = 0; + a->textureStackDepth = 0; + a->transformStackDepth = 0; + a->viewportStackDepth = 0; +} + +/** @todo check if NV rect needed too*/ +static void +copy_texunit(CRTextureUnit *dest, const CRTextureUnit *src) +{ + dest->enabled1D = src->enabled1D; + dest->enabled2D = src->enabled2D; + dest->enabled3D = src->enabled3D; + dest->enabledCubeMap = src->enabledCubeMap; + dest->envMode = src->envMode; + dest->envColor = src->envColor; + dest->textureGen = src->textureGen; + dest->objSCoeff = src->objSCoeff; + dest->objTCoeff = src->objTCoeff; + dest->objRCoeff = src->objRCoeff; + dest->objQCoeff = src->objQCoeff; + dest->eyeSCoeff = src->eyeSCoeff; + dest->eyeTCoeff = src->eyeTCoeff; + dest->eyeRCoeff = src->eyeRCoeff; + dest->eyeQCoeff = src->eyeQCoeff; + dest->gen = src->gen; + dest->currentTexture1D = src->currentTexture1D; + dest->currentTexture2D = src->currentTexture2D; + dest->currentTexture3D = src->currentTexture3D; + dest->currentTextureCubeMap = src->currentTextureCubeMap; +} + +static void +copy_texobj(CRTextureObj *dest, CRTextureObj *src, GLboolean copyName) +{ + if (copyName) + { + dest->id = src->id; + dest->hwid = crStateGetTextureObjHWID(src); + } + + dest->borderColor = src->borderColor; + dest->wrapS = src->wrapS; + dest->wrapT = src->wrapT; + dest->minFilter = src->minFilter; + dest->magFilter = src->magFilter; +#ifdef CR_OPENGL_VERSION_1_2 + dest->priority = src->priority; + dest->wrapR = src->wrapR; + dest->minLod = src->minLod; + dest->maxLod = src->maxLod; + dest->baseLevel = src->baseLevel; + dest->maxLevel = src->maxLevel; +#endif +#ifdef CR_EXT_texture_filter_anisotropic + dest->maxAnisotropy = src->maxAnisotropy; +#endif +} + +void STATE_APIENTRY crStatePushAttrib(GLbitfield mask) +{ + CRContext *g = GetCurrentContext(); + CRAttribState *a = &(g->attrib); + CRStateBits *sb = GetCurrentBits(); + CRAttribBits *ab = &(sb->attrib); + unsigned int i; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glPushAttrib called in Begin/End"); + return; + } + + if (a->attribStackDepth == CR_MAX_ATTRIB_STACK_DEPTH - 1) + { + crStateError(__LINE__, __FILE__, GL_STACK_OVERFLOW, "glPushAttrib called with a full stack!" ); + return; + } + + FLUSH(); + + a->pushMaskStack[a->attribStackDepth++] = mask; + + if (mask & GL_ACCUM_BUFFER_BIT) + { + a->accumBufferStack[a->accumBufferStackDepth].accumClearValue = g->buffer.accumClearValue; + a->accumBufferStackDepth++; + } + if (mask & GL_COLOR_BUFFER_BIT) + { + a->colorBufferStack[a->colorBufferStackDepth].alphaTest = g->buffer.alphaTest; + a->colorBufferStack[a->colorBufferStackDepth].alphaTestFunc = g->buffer.alphaTestFunc; + a->colorBufferStack[a->colorBufferStackDepth].alphaTestRef = g->buffer.alphaTestRef; + a->colorBufferStack[a->colorBufferStackDepth].blend = g->buffer.blend; + a->colorBufferStack[a->colorBufferStackDepth].blendSrcRGB = g->buffer.blendSrcRGB; + a->colorBufferStack[a->colorBufferStackDepth].blendDstRGB = g->buffer.blendDstRGB; +#if defined(CR_EXT_blend_func_separate) + a->colorBufferStack[a->colorBufferStackDepth].blendSrcA = g->buffer.blendSrcA; + a->colorBufferStack[a->colorBufferStackDepth].blendDstA = g->buffer.blendDstA; +#endif +#ifdef CR_EXT_blend_color + a->colorBufferStack[a->colorBufferStackDepth].blendColor = g->buffer.blendColor; +#endif +#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op) + a->colorBufferStack[a->colorBufferStackDepth].blendEquation = g->buffer.blendEquation; +#endif + a->colorBufferStack[a->colorBufferStackDepth].dither = g->buffer.dither; + a->colorBufferStack[a->colorBufferStackDepth].drawBuffer = g->buffer.drawBuffer; + a->colorBufferStack[a->colorBufferStackDepth].logicOp = g->buffer.logicOp; + a->colorBufferStack[a->colorBufferStackDepth].indexLogicOp = g->buffer.indexLogicOp; + a->colorBufferStack[a->colorBufferStackDepth].logicOpMode = g->buffer.logicOpMode; + a->colorBufferStack[a->colorBufferStackDepth].colorClearValue = g->buffer.colorClearValue; + a->colorBufferStack[a->colorBufferStackDepth].indexClearValue = g->buffer.indexClearValue; + a->colorBufferStack[a->colorBufferStackDepth].colorWriteMask = g->buffer.colorWriteMask; + a->colorBufferStack[a->colorBufferStackDepth].indexWriteMask = g->buffer.indexWriteMask; + a->colorBufferStackDepth++; + } + if (mask & GL_CURRENT_BIT) + { + for (i = 0 ; i < CR_MAX_VERTEX_ATTRIBS ; i++) + { + COPY_4V(a->currentStack[a->currentStackDepth].attrib[i] , g->current.vertexAttrib[i]); + COPY_4V(a->currentStack[a->currentStackDepth].rasterAttrib[i] , g->current.rasterAttrib[i]); + } + a->currentStack[a->currentStackDepth].rasterValid = g->current.rasterValid; + a->currentStack[a->currentStackDepth].edgeFlag = g->current.edgeFlag; + a->currentStack[a->currentStackDepth].colorIndex = g->current.colorIndex; + a->currentStackDepth++; + } + if (mask & GL_DEPTH_BUFFER_BIT) + { + a->depthBufferStack[a->depthBufferStackDepth].depthTest = g->buffer.depthTest; + a->depthBufferStack[a->depthBufferStackDepth].depthFunc = g->buffer.depthFunc; + a->depthBufferStack[a->depthBufferStackDepth].depthClearValue = g->buffer.depthClearValue; + a->depthBufferStack[a->depthBufferStackDepth].depthMask = g->buffer.depthMask; + a->depthBufferStackDepth++; + } + if (mask & GL_ENABLE_BIT) + { + if (a->enableStack[a->enableStackDepth].clip == NULL) + { + a->enableStack[a->enableStackDepth].clip = (GLboolean *) crCalloc( g->limits.maxClipPlanes * sizeof( GLboolean )); + } + if (a->enableStack[a->enableStackDepth].light == NULL) + { + a->enableStack[a->enableStackDepth].light = (GLboolean *) crCalloc( g->limits.maxLights * sizeof( GLboolean )); + } + a->enableStack[a->enableStackDepth].alphaTest = g->buffer.alphaTest; + a->enableStack[a->enableStackDepth].autoNormal = g->eval.autoNormal; + a->enableStack[a->enableStackDepth].blend = g->buffer.blend; + for (i = 0 ; i < g->limits.maxClipPlanes ; i++) + { + a->enableStack[a->enableStackDepth].clip[i] = g->transform.clip[i]; + } + a->enableStack[a->enableStackDepth].colorMaterial = g->lighting.colorMaterial; + a->enableStack[a->enableStackDepth].cullFace = g->polygon.cullFace; + a->enableStack[a->enableStackDepth].depthTest = g->buffer.depthTest; + a->enableStack[a->enableStackDepth].dither = g->buffer.dither; + a->enableStack[a->enableStackDepth].fog = g->fog.enable; + for (i = 0 ; i < g->limits.maxLights ; i++) + { + a->enableStack[a->enableStackDepth].light[i] = g->lighting.light[i].enable; + } + a->enableStack[a->enableStackDepth].lighting = g->lighting.lighting; + a->enableStack[a->enableStackDepth].lineSmooth = g->line.lineSmooth; + a->enableStack[a->enableStackDepth].lineStipple = g->line.lineStipple; + a->enableStack[a->enableStackDepth].logicOp = g->buffer.logicOp; + a->enableStack[a->enableStackDepth].indexLogicOp = g->buffer.indexLogicOp; + for (i = 0 ; i < GLEVAL_TOT ; i++) + { + a->enableStack[a->enableStackDepth].map1[i] = g->eval.enable1D[i]; + a->enableStack[a->enableStackDepth].map2[i] = g->eval.enable2D[i]; + } + a->enableStack[a->enableStackDepth].normalize = g->transform.normalize; + a->enableStack[a->enableStackDepth].pointSmooth = g->point.pointSmooth; +#if CR_ARB_point_sprite + a->enableStack[a->enableStackDepth].pointSprite = g->point.pointSprite; + for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) + a->enableStack[a->enableStackDepth].coordReplacement[i] = g->point.coordReplacement[i]; +#endif + a->enableStack[a->enableStackDepth].polygonOffsetLine = g->polygon.polygonOffsetLine; + a->enableStack[a->enableStackDepth].polygonOffsetFill = g->polygon.polygonOffsetFill; + a->enableStack[a->enableStackDepth].polygonOffsetPoint = g->polygon.polygonOffsetPoint; + a->enableStack[a->enableStackDepth].polygonSmooth = g->polygon.polygonSmooth; + a->enableStack[a->enableStackDepth].polygonStipple = g->polygon.polygonStipple; +#ifdef CR_OPENGL_VERSION_1_2 + a->enableStack[a->enableStackDepth].rescaleNormals = g->transform.rescaleNormals; +#endif + a->enableStack[a->enableStackDepth].scissorTest = g->viewport.scissorTest; + a->enableStack[a->enableStackDepth].stencilTest = g->stencil.stencilTest; + for (i = 0 ; i < g->limits.maxTextureUnits; i++) + { + a->enableStack[a->enableStackDepth].texture1D[i] = g->texture.unit[i].enabled1D; + a->enableStack[a->enableStackDepth].texture2D[i] = g->texture.unit[i].enabled2D; +#ifdef CR_OPENGL_VERSION_1_2 + a->enableStack[a->enableStackDepth].texture3D[i] = g->texture.unit[i].enabled3D; +#endif +#ifdef CR_ARB_texture_cube_map + a->enableStack[a->enableStackDepth].textureCubeMap[i] = g->texture.unit[i].enabledCubeMap; +#endif +#ifdef CR_NV_texture_rectangle + a->enableStack[a->enableStackDepth].textureRect[i] = g->texture.unit[i].enabledRect; +#endif + a->enableStack[a->enableStackDepth].textureGenS[i] = g->texture.unit[i].textureGen.s; + a->enableStack[a->enableStackDepth].textureGenT[i] = g->texture.unit[i].textureGen.t; + a->enableStack[a->enableStackDepth].textureGenR[i] = g->texture.unit[i].textureGen.r; + a->enableStack[a->enableStackDepth].textureGenQ[i] = g->texture.unit[i].textureGen.q; + } + a->enableStackDepth++; + } + if (mask & GL_EVAL_BIT) + { + for (i = 0 ; i < GLEVAL_TOT ; i++) + { + int size1 = g->eval.eval1D[i].order * gleval_sizes[i] * + sizeof (GLfloat); + int size2 = g->eval.eval2D[i].uorder * g->eval.eval2D[i].vorder * + gleval_sizes[i] * sizeof (GLfloat); + a->evalStack[a->evalStackDepth].enable1D[i] = g->eval.enable1D[i]; + a->evalStack[a->evalStackDepth].enable2D[i] = g->eval.enable2D[i]; + a->evalStack[a->evalStackDepth].eval1D[i].u1 = g->eval.eval1D[i].u1; + a->evalStack[a->evalStackDepth].eval1D[i].u2 = g->eval.eval1D[i].u2; + a->evalStack[a->evalStackDepth].eval1D[i].order = g->eval.eval1D[i].order; + a->evalStack[a->evalStackDepth].eval1D[i].coeff = (GLfloat*)crCalloc(size1); + crMemcpy(a->evalStack[a->evalStackDepth].eval1D[i].coeff, g->eval.eval1D[i].coeff, size1); + a->evalStack[a->evalStackDepth].eval2D[i].u1 = g->eval.eval2D[i].u1; + a->evalStack[a->evalStackDepth].eval2D[i].u2 = g->eval.eval2D[i].u2; + a->evalStack[a->evalStackDepth].eval2D[i].v1 = g->eval.eval2D[i].v1; + a->evalStack[a->evalStackDepth].eval2D[i].v2 = g->eval.eval2D[i].v2; + a->evalStack[a->evalStackDepth].eval2D[i].uorder = g->eval.eval2D[i].uorder; + a->evalStack[a->evalStackDepth].eval2D[i].vorder = g->eval.eval2D[i].vorder; + a->evalStack[a->evalStackDepth].eval2D[i].coeff = (GLfloat*)crCalloc(size2); + crMemcpy(a->evalStack[a->evalStackDepth].eval2D[i].coeff, g->eval.eval2D[i].coeff, size2); + } + a->evalStack[a->evalStackDepth].autoNormal = g->eval.autoNormal; + a->evalStack[a->evalStackDepth].un1D = g->eval.un1D; + a->evalStack[a->evalStackDepth].u11D = g->eval.u11D; + a->evalStack[a->evalStackDepth].u21D = g->eval.u21D; + a->evalStack[a->evalStackDepth].un2D = g->eval.un2D; + a->evalStack[a->evalStackDepth].u12D = g->eval.u12D; + a->evalStack[a->evalStackDepth].u22D = g->eval.u22D; + a->evalStack[a->evalStackDepth].vn2D = g->eval.vn2D; + a->evalStack[a->evalStackDepth].v12D = g->eval.v12D; + a->evalStack[a->evalStackDepth].v22D = g->eval.v22D; + a->evalStackDepth++; + } + if (mask & GL_FOG_BIT) + { + a->fogStack[a->fogStackDepth].enable = g->fog.enable; + a->fogStack[a->fogStackDepth].color = g->fog.color; + a->fogStack[a->fogStackDepth].density = g->fog.density; + a->fogStack[a->fogStackDepth].start = g->fog.start; + a->fogStack[a->fogStackDepth].end = g->fog.end; + a->fogStack[a->fogStackDepth].index = g->fog.index; + a->fogStack[a->fogStackDepth].mode = g->fog.mode; + a->fogStackDepth++; + } + if (mask & GL_HINT_BIT) + { + a->hintStack[a->hintStackDepth].perspectiveCorrection = g->hint.perspectiveCorrection; + a->hintStack[a->hintStackDepth].pointSmooth = g->hint.pointSmooth; + a->hintStack[a->hintStackDepth].lineSmooth = g->hint.lineSmooth; + a->hintStack[a->hintStackDepth].polygonSmooth = g->hint.polygonSmooth; + a->hintStack[a->hintStackDepth].fog = g->hint.fog; +#ifdef CR_EXT_clip_volume_hint + a->hintStack[a->hintStackDepth].clipVolumeClipping = g->hint.clipVolumeClipping; +#endif +#ifdef CR_ARB_texture_compression + a->hintStack[a->hintStackDepth].textureCompression = g->hint.textureCompression; +#endif +#ifdef CR_SGIS_generate_mipmap + a->hintStack[a->hintStackDepth].generateMipmap = g->hint.generateMipmap; +#endif + a->hintStackDepth++; + } + if (mask & GL_LIGHTING_BIT) + { + if (a->lightingStack[a->lightingStackDepth].light == NULL) + { + a->lightingStack[a->lightingStackDepth].light = (CRLight *) crCalloc( g->limits.maxLights * sizeof( CRLight )); + } + a->lightingStack[a->lightingStackDepth].lightModelAmbient = g->lighting.lightModelAmbient; + a->lightingStack[a->lightingStackDepth].lightModelLocalViewer = g->lighting.lightModelLocalViewer; + a->lightingStack[a->lightingStackDepth].lightModelTwoSide = g->lighting.lightModelTwoSide; +#if defined(CR_EXT_separate_specular_color) || defined(CR_OPENGL_VERSION_1_2) + a->lightingStack[a->lightingStackDepth].lightModelColorControlEXT = g->lighting.lightModelColorControlEXT; +#endif + a->lightingStack[a->lightingStackDepth].lighting = g->lighting.lighting; + a->lightingStack[a->lightingStackDepth].colorMaterial = g->lighting.colorMaterial; + a->lightingStack[a->lightingStackDepth].colorMaterialMode = g->lighting.colorMaterialMode; + a->lightingStack[a->lightingStackDepth].colorMaterialFace = g->lighting.colorMaterialFace; + for (i = 0 ; i < g->limits.maxLights; i++) + { + a->lightingStack[a->lightingStackDepth].light[i].enable = g->lighting.light[i].enable; + a->lightingStack[a->lightingStackDepth].light[i].ambient = g->lighting.light[i].ambient; + a->lightingStack[a->lightingStackDepth].light[i].diffuse = g->lighting.light[i].diffuse; + a->lightingStack[a->lightingStackDepth].light[i].specular = g->lighting.light[i].specular; + a->lightingStack[a->lightingStackDepth].light[i].spotDirection = g->lighting.light[i].spotDirection; + a->lightingStack[a->lightingStackDepth].light[i].position = g->lighting.light[i].position; + a->lightingStack[a->lightingStackDepth].light[i].spotExponent = g->lighting.light[i].spotExponent; + a->lightingStack[a->lightingStackDepth].light[i].spotCutoff = g->lighting.light[i].spotCutoff; + a->lightingStack[a->lightingStackDepth].light[i].constantAttenuation = g->lighting.light[i].constantAttenuation; + a->lightingStack[a->lightingStackDepth].light[i].linearAttenuation = g->lighting.light[i].linearAttenuation; + a->lightingStack[a->lightingStackDepth].light[i].quadraticAttenuation = g->lighting.light[i].quadraticAttenuation; + } + for (i = 0 ; i < 2 ; i++) + { + a->lightingStack[a->lightingStackDepth].ambient[i] = g->lighting.ambient[i]; + a->lightingStack[a->lightingStackDepth].diffuse[i] = g->lighting.diffuse[i]; + a->lightingStack[a->lightingStackDepth].specular[i] = g->lighting.specular[i]; + a->lightingStack[a->lightingStackDepth].emission[i] = g->lighting.emission[i]; + a->lightingStack[a->lightingStackDepth].shininess[i] = g->lighting.shininess[i]; + a->lightingStack[a->lightingStackDepth].indexes[i][0] = g->lighting.indexes[i][0]; + a->lightingStack[a->lightingStackDepth].indexes[i][1] = g->lighting.indexes[i][1]; + a->lightingStack[a->lightingStackDepth].indexes[i][2] = g->lighting.indexes[i][2]; + } + a->lightingStack[a->lightingStackDepth].shadeModel = g->lighting.shadeModel; + a->lightingStackDepth++; + } + if (mask & GL_LINE_BIT) + { + a->lineStack[a->lineStackDepth].lineSmooth = g->line.lineSmooth; + a->lineStack[a->lineStackDepth].lineStipple = g->line.lineStipple; + a->lineStack[a->lineStackDepth].pattern = g->line.pattern; + a->lineStack[a->lineStackDepth].repeat = g->line.repeat; + a->lineStack[a->lineStackDepth].width = g->line.width; + a->lineStackDepth++; + } + if (mask & GL_LIST_BIT) + { + a->listStack[a->listStackDepth].base = g->lists.base; + a->listStackDepth++; + } + if (mask & GL_PIXEL_MODE_BIT) + { + a->pixelModeStack[a->pixelModeStackDepth].bias = g->pixel.bias; + a->pixelModeStack[a->pixelModeStackDepth].scale = g->pixel.scale; + a->pixelModeStack[a->pixelModeStackDepth].indexOffset = g->pixel.indexOffset; + a->pixelModeStack[a->pixelModeStackDepth].indexShift = g->pixel.indexShift; + a->pixelModeStack[a->pixelModeStackDepth].mapColor = g->pixel.mapColor; + a->pixelModeStack[a->pixelModeStackDepth].mapStencil = g->pixel.mapStencil; + a->pixelModeStack[a->pixelModeStackDepth].xZoom = g->pixel.xZoom; + a->pixelModeStack[a->pixelModeStackDepth].yZoom = g->pixel.yZoom; + a->pixelModeStack[a->pixelModeStackDepth].readBuffer = g->buffer.readBuffer; + a->pixelModeStackDepth++; + } + if (mask & GL_POINT_BIT) + { + a->pointStack[a->pointStackDepth].pointSmooth = g->point.pointSmooth; +#if CR_ARB_point_sprite + a->pointStack[a->pointStackDepth].pointSprite = g->point.pointSprite; + for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) + a->pointStack[a->enableStackDepth].coordReplacement[i] = g->point.coordReplacement[i]; +#endif + a->pointStack[a->pointStackDepth].pointSize = g->point.pointSize; + a->pointStackDepth++; + } + if (mask & GL_POLYGON_BIT) + { + a->polygonStack[a->polygonStackDepth].cullFace = g->polygon.cullFace; + a->polygonStack[a->polygonStackDepth].cullFaceMode = g->polygon.cullFaceMode; + a->polygonStack[a->polygonStackDepth].frontFace = g->polygon.frontFace; + a->polygonStack[a->polygonStackDepth].frontMode = g->polygon.frontMode; + a->polygonStack[a->polygonStackDepth].backMode = g->polygon.backMode; + a->polygonStack[a->polygonStackDepth].polygonSmooth = g->polygon.polygonSmooth; + a->polygonStack[a->polygonStackDepth].polygonStipple = g->polygon.polygonStipple; + a->polygonStack[a->polygonStackDepth].polygonOffsetFill = g->polygon.polygonOffsetFill; + a->polygonStack[a->polygonStackDepth].polygonOffsetLine = g->polygon.polygonOffsetLine; + a->polygonStack[a->polygonStackDepth].polygonOffsetPoint = g->polygon.polygonOffsetPoint; + a->polygonStack[a->polygonStackDepth].offsetFactor = g->polygon.offsetFactor; + a->polygonStack[a->polygonStackDepth].offsetUnits = g->polygon.offsetUnits; + a->polygonStackDepth++; + } + if (mask & GL_POLYGON_STIPPLE_BIT) + { + crMemcpy( a->polygonStippleStack[a->polygonStippleStackDepth].pattern, g->polygon.stipple, 32*sizeof(GLint) ); + a->polygonStippleStackDepth++; + } + if (mask & GL_SCISSOR_BIT) + { + a->scissorStack[a->scissorStackDepth].scissorTest = g->viewport.scissorTest; + a->scissorStack[a->scissorStackDepth].scissorX = g->viewport.scissorX; + a->scissorStack[a->scissorStackDepth].scissorY = g->viewport.scissorY; + a->scissorStack[a->scissorStackDepth].scissorW = g->viewport.scissorW; + a->scissorStack[a->scissorStackDepth].scissorH = g->viewport.scissorH; + a->scissorStackDepth++; + } + if (mask & GL_STENCIL_BUFFER_BIT) + { + a->stencilBufferStack[a->stencilBufferStackDepth].stencilTest = g->stencil.stencilTest; + a->stencilBufferStack[a->stencilBufferStackDepth].clearValue = g->stencil.clearValue; + a->stencilBufferStack[a->stencilBufferStackDepth].writeMask = g->stencil.writeMask; + for (i = 0; i < CRSTATE_STENCIL_BUFFER_COUNT; ++i) + { + a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].func = g->stencil.buffers[i].func; + a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].mask = g->stencil.buffers[i].mask; + a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].ref = g->stencil.buffers[i].ref; + a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].fail = g->stencil.buffers[i].fail; + a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].passDepthFail = g->stencil.buffers[i].passDepthFail; + a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].passDepthPass = g->stencil.buffers[i].passDepthPass; + } + a->stencilBufferStackDepth++; + } + if (mask & GL_TEXTURE_BIT) + { + CRTextureStack *tState = a->textureStack + a->textureStackDepth; + tState->curTextureUnit = g->texture.curTextureUnit; + for (i = 0 ; i < g->limits.maxTextureUnits ; i++) + { + /* per-unit state */ + copy_texunit(&tState->unit[i], &g->texture.unit[i]); + /* texture object state */ + copy_texobj(&tState->unit[i].Saved1D, g->texture.unit[i].currentTexture1D, GL_TRUE); + copy_texobj(&tState->unit[i].Saved2D, g->texture.unit[i].currentTexture2D, GL_TRUE); +#ifdef CR_OPENGL_VERSION_1_2 + copy_texobj(&tState->unit[i].Saved3D, g->texture.unit[i].currentTexture3D, GL_TRUE); +#endif +#ifdef CR_ARB_texture_cube_map + copy_texobj(&tState->unit[i].SavedCubeMap, g->texture.unit[i].currentTextureCubeMap, GL_TRUE); +#endif +#ifdef CR_NV_texture_rectangle + copy_texobj(&tState->unit[i].SavedRect, g->texture.unit[i].currentTextureRect, GL_TRUE); +#endif + } + a->textureStackDepth++; + } + if (mask & GL_TRANSFORM_BIT) + { + if (a->transformStack[a->transformStackDepth].clip == NULL) + { + a->transformStack[a->transformStackDepth].clip = (GLboolean *) crCalloc( g->limits.maxClipPlanes * sizeof( GLboolean )); + } + if (a->transformStack[a->transformStackDepth].clipPlane == NULL) + { + a->transformStack[a->transformStackDepth].clipPlane = (GLvectord *) crCalloc( g->limits.maxClipPlanes * sizeof( GLvectord )); + } + a->transformStack[a->transformStackDepth].matrixMode = g->transform.matrixMode; + for (i = 0 ; i < g->limits.maxClipPlanes ; i++) + { + a->transformStack[a->transformStackDepth].clip[i] = g->transform.clip[i]; + a->transformStack[a->transformStackDepth].clipPlane[i] = g->transform.clipPlane[i]; + } + a->transformStack[a->transformStackDepth].normalize = g->transform.normalize; +#ifdef CR_OPENGL_VERSION_1_2 + a->transformStack[a->transformStackDepth].rescaleNormals = g->transform.rescaleNormals; +#endif + a->transformStackDepth++; + } + if (mask & GL_VIEWPORT_BIT) + { + a->viewportStack[a->viewportStackDepth].viewportX = g->viewport.viewportX; + a->viewportStack[a->viewportStackDepth].viewportY = g->viewport.viewportY; + a->viewportStack[a->viewportStackDepth].viewportW = g->viewport.viewportW; + a->viewportStack[a->viewportStackDepth].viewportH = g->viewport.viewportH; + a->viewportStack[a->viewportStackDepth].nearClip = g->viewport.nearClip; + a->viewportStack[a->viewportStackDepth].farClip = g->viewport.farClip; + a->viewportStackDepth++; + } + + DIRTY(ab->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStatePopAttrib(void) +{ + CRContext *g = GetCurrentContext(); + CRAttribState *a = &(g->attrib); + CRStateBits *sb = GetCurrentBits(); + CRAttribBits *ab = &(sb->attrib); + CRbitvalue mask; + unsigned int i; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glPopAttrib called in Begin/End"); + return; + } + + if (a->attribStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty stack!" ); + return; + } + + FLUSH(); + + mask = a->pushMaskStack[--a->attribStackDepth]; + + if (mask & GL_ACCUM_BUFFER_BIT) + { + if (a->accumBufferStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty accum buffer stack!" ); + return; + } + a->accumBufferStackDepth--; + g->buffer.accumClearValue = a->accumBufferStack[a->accumBufferStackDepth].accumClearValue; + DIRTY(sb->buffer.dirty, g->neg_bitid); + DIRTY(sb->buffer.clearAccum, g->neg_bitid); + } + if (mask & GL_COLOR_BUFFER_BIT) + { + if (a->colorBufferStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty color buffer stack!" ); + return; + } + a->colorBufferStackDepth--; + g->buffer.alphaTest = a->colorBufferStack[a->colorBufferStackDepth].alphaTest; + g->buffer.alphaTestFunc = a->colorBufferStack[a->colorBufferStackDepth].alphaTestFunc; + g->buffer.alphaTestRef = a->colorBufferStack[a->colorBufferStackDepth].alphaTestRef; + g->buffer.blend = a->colorBufferStack[a->colorBufferStackDepth].blend; + g->buffer.blendSrcRGB = a->colorBufferStack[a->colorBufferStackDepth].blendSrcRGB; + g->buffer.blendDstRGB = a->colorBufferStack[a->colorBufferStackDepth].blendDstRGB; +#if defined(CR_EXT_blend_func_separate) + g->buffer.blendSrcA = a->colorBufferStack[a->colorBufferStackDepth].blendSrcA; + g->buffer.blendDstA = a->colorBufferStack[a->colorBufferStackDepth].blendDstA; +#endif +#ifdef CR_EXT_blend_color + g->buffer.blendColor = a->colorBufferStack[a->colorBufferStackDepth].blendColor; +#endif +#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op) + g->buffer.blendEquation = a->colorBufferStack[a->colorBufferStackDepth].blendEquation; +#endif + g->buffer.dither = a->colorBufferStack[a->colorBufferStackDepth].dither; + g->buffer.drawBuffer = a->colorBufferStack[a->colorBufferStackDepth].drawBuffer; + g->buffer.logicOp = a->colorBufferStack[a->colorBufferStackDepth].logicOp; + g->buffer.indexLogicOp = a->colorBufferStack[a->colorBufferStackDepth].indexLogicOp; + g->buffer.logicOpMode = a->colorBufferStack[a->colorBufferStackDepth].logicOpMode; + g->buffer.colorClearValue = a->colorBufferStack[a->colorBufferStackDepth].colorClearValue; + g->buffer.indexClearValue = a->colorBufferStack[a->colorBufferStackDepth].indexClearValue; + g->buffer.colorWriteMask = a->colorBufferStack[a->colorBufferStackDepth].colorWriteMask; + g->buffer.indexWriteMask = a->colorBufferStack[a->colorBufferStackDepth].indexWriteMask; + DIRTY(sb->buffer.dirty, g->neg_bitid); + DIRTY(sb->buffer.enable, g->neg_bitid); + DIRTY(sb->buffer.alphaFunc, g->neg_bitid); + DIRTY(sb->buffer.blendFunc, g->neg_bitid); +#ifdef CR_EXT_blend_color + DIRTY(sb->buffer.blendColor, g->neg_bitid); +#endif +#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op) + DIRTY(sb->buffer.blendEquation, g->neg_bitid); +#endif + DIRTY(sb->buffer.drawBuffer, g->neg_bitid); + DIRTY(sb->buffer.logicOp, g->neg_bitid); + DIRTY(sb->buffer.indexLogicOp, g->neg_bitid); + DIRTY(sb->buffer.clearColor, g->neg_bitid); + DIRTY(sb->buffer.clearIndex, g->neg_bitid); + DIRTY(sb->buffer.colorWriteMask, g->neg_bitid); + DIRTY(sb->buffer.indexMask, g->neg_bitid); + } + if (mask & GL_CURRENT_BIT) + { + if (a->currentStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty current stack!" ); + return; + } + a->currentStackDepth--; + for (i = 0 ; i < CR_MAX_VERTEX_ATTRIBS ; i++) + { + COPY_4V(g->current.vertexAttrib[i], a->currentStack[a->currentStackDepth].attrib[i]); + COPY_4V(g->current.rasterAttrib[i], a->currentStack[a->currentStackDepth].rasterAttrib[i]); + DIRTY(sb->current.vertexAttrib[i], g->neg_bitid); + } + g->current.rasterValid = a->currentStack[a->currentStackDepth].rasterValid; + g->current.edgeFlag = a->currentStack[a->currentStackDepth].edgeFlag; + g->current.colorIndex = a->currentStack[a->currentStackDepth].colorIndex; + DIRTY(sb->current.dirty, g->neg_bitid); + DIRTY(sb->current.edgeFlag, g->neg_bitid); + DIRTY(sb->current.colorIndex, g->neg_bitid); + DIRTY(sb->current.rasterPos, g->neg_bitid); + } + if (mask & GL_DEPTH_BUFFER_BIT) + { + if (a->depthBufferStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty depth buffer stack!" ); + return; + } + a->depthBufferStackDepth--; + g->buffer.depthTest = a->depthBufferStack[a->depthBufferStackDepth].depthTest; + g->buffer.depthFunc = a->depthBufferStack[a->depthBufferStackDepth].depthFunc; + g->buffer.depthClearValue = a->depthBufferStack[a->depthBufferStackDepth].depthClearValue; + g->buffer.depthMask = a->depthBufferStack[a->depthBufferStackDepth].depthMask; + DIRTY(sb->buffer.dirty, g->neg_bitid); + DIRTY(sb->buffer.enable, g->neg_bitid); + DIRTY(sb->buffer.depthFunc, g->neg_bitid); + DIRTY(sb->buffer.clearDepth, g->neg_bitid); + DIRTY(sb->buffer.depthMask, g->neg_bitid); + } + if (mask & GL_ENABLE_BIT) + { + if (a->enableStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty enable stack!" ); + return; + } + a->enableStackDepth--; + g->buffer.alphaTest = a->enableStack[a->enableStackDepth].alphaTest; + g->eval.autoNormal = a->enableStack[a->enableStackDepth].autoNormal; + g->buffer.blend = a->enableStack[a->enableStackDepth].blend; + for (i = 0 ; i < g->limits.maxClipPlanes ; i++) + { + g->transform.clip[i] = a->enableStack[a->enableStackDepth].clip[i]; + } + g->lighting.colorMaterial = a->enableStack[a->enableStackDepth].colorMaterial; + g->polygon.cullFace = a->enableStack[a->enableStackDepth].cullFace; + g->buffer.depthTest = a->enableStack[a->enableStackDepth].depthTest; + g->buffer.dither = a->enableStack[a->enableStackDepth].dither; + g->fog.enable = a->enableStack[a->enableStackDepth].fog; + for (i = 0 ; i < g->limits.maxLights ; i++) + { + g->lighting.light[i].enable = a->enableStack[a->enableStackDepth].light[i]; + } + g->lighting.lighting = a->enableStack[a->enableStackDepth].lighting; + g->line.lineSmooth = a->enableStack[a->enableStackDepth].lineSmooth; + g->line.lineStipple = a->enableStack[a->enableStackDepth].lineStipple; + g->buffer.logicOp = a->enableStack[a->enableStackDepth].logicOp; + g->buffer.indexLogicOp = a->enableStack[a->enableStackDepth].indexLogicOp; + for (i = 0 ; i < GLEVAL_TOT ; i++) + { + g->eval.enable1D[i] = a->enableStack[a->enableStackDepth].map1[i]; + g->eval.enable2D[i] = a->enableStack[a->enableStackDepth].map2[i]; + } + g->transform.normalize = a->enableStack[a->enableStackDepth].normalize; + g->point.pointSmooth = a->enableStack[a->enableStackDepth].pointSmooth; +#ifdef CR_ARB_point_sprite + g->point.pointSprite = a->enableStack[a->enableStackDepth].pointSprite; + for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) + g->point.coordReplacement[i] = a->enableStack[a->enableStackDepth].coordReplacement[i]; +#endif + g->polygon.polygonOffsetLine = a->enableStack[a->enableStackDepth].polygonOffsetLine; + g->polygon.polygonOffsetFill = a->enableStack[a->enableStackDepth].polygonOffsetFill; + g->polygon.polygonOffsetPoint = a->enableStack[a->enableStackDepth].polygonOffsetPoint; + g->polygon.polygonSmooth = a->enableStack[a->enableStackDepth].polygonSmooth; + g->polygon.polygonStipple = a->enableStack[a->enableStackDepth].polygonStipple; +#ifdef CR_OPENGL_VERSION_1_2 + g->transform.rescaleNormals = a->enableStack[a->enableStackDepth].rescaleNormals; +#endif + g->viewport.scissorTest = a->enableStack[a->enableStackDepth].scissorTest; + g->stencil.stencilTest = a->enableStack[a->enableStackDepth].stencilTest; + for (i = 0 ; i < g->limits.maxTextureUnits; i++) + { + g->texture.unit[i].enabled1D = a->enableStack[a->enableStackDepth].texture1D[i]; + g->texture.unit[i].enabled2D = a->enableStack[a->enableStackDepth].texture2D[i]; +#ifdef CR_OPENGL_VERSION_1_2 + g->texture.unit[i].enabled3D = a->enableStack[a->enableStackDepth].texture3D[i]; +#endif +#ifdef CR_ARB_texture_cube_map + g->texture.unit[i].enabledCubeMap = a->enableStack[a->enableStackDepth].textureCubeMap[i]; +#endif +#ifdef CR_NV_texture_rectangle + g->texture.unit[i].enabledRect = a->enableStack[a->enableStackDepth].textureRect[i]; +#endif + g->texture.unit[i].textureGen.s = a->enableStack[a->enableStackDepth].textureGenS[i]; + g->texture.unit[i].textureGen.t = a->enableStack[a->enableStackDepth].textureGenT[i]; + g->texture.unit[i].textureGen.r = a->enableStack[a->enableStackDepth].textureGenR[i]; + g->texture.unit[i].textureGen.q = a->enableStack[a->enableStackDepth].textureGenQ[i]; + } + DIRTY(sb->buffer.dirty, g->neg_bitid); + DIRTY(sb->eval.dirty, g->neg_bitid); + DIRTY(sb->transform.dirty, g->neg_bitid); + DIRTY(sb->lighting.dirty, g->neg_bitid); + DIRTY(sb->fog.dirty, g->neg_bitid); + DIRTY(sb->line.dirty, g->neg_bitid); + DIRTY(sb->polygon.dirty, g->neg_bitid); + DIRTY(sb->viewport.dirty, g->neg_bitid); + DIRTY(sb->stencil.dirty, g->neg_bitid); + DIRTY(sb->texture.dirty, g->neg_bitid); + + DIRTY(sb->buffer.enable, g->neg_bitid); + DIRTY(sb->eval.enable, g->neg_bitid); + DIRTY(sb->transform.enable, g->neg_bitid); + DIRTY(sb->lighting.enable, g->neg_bitid); + DIRTY(sb->fog.enable, g->neg_bitid); + DIRTY(sb->line.enable, g->neg_bitid); + DIRTY(sb->polygon.enable, g->neg_bitid); + DIRTY(sb->viewport.enable, g->neg_bitid); + DIRTY(sb->stencil.enable, g->neg_bitid); + for (i = 0 ; i < g->limits.maxTextureUnits ; i++) + { + DIRTY(sb->texture.enable[i], g->neg_bitid); + } + } + if (mask & GL_EVAL_BIT) + { + if (a->evalStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty eval stack!" ); + return; + } + a->evalStackDepth--; + for (i = 0 ; i < GLEVAL_TOT ; i++) + { + int size1 = a->evalStack[a->evalStackDepth].eval1D[i].order * gleval_sizes[i] * sizeof(GLfloat); + int size2 = a->evalStack[a->evalStackDepth].eval2D[i].uorder * a->evalStack[a->evalStackDepth].eval2D[i].vorder * gleval_sizes[i] * sizeof (GLfloat); + g->eval.enable1D[i] = a->evalStack[a->evalStackDepth].enable1D[i]; + g->eval.enable2D[i] = a->evalStack[a->evalStackDepth].enable2D[i]; + g->eval.eval1D[i].u1 = a->evalStack[a->evalStackDepth].eval1D[i].u1; + g->eval.eval1D[i].u2 = a->evalStack[a->evalStackDepth].eval1D[i].u2; + g->eval.eval1D[i].order = a->evalStack[a->evalStackDepth].eval1D[i].order; + crMemcpy((char*)g->eval.eval1D[i].coeff, a->evalStack[a->evalStackDepth].eval1D[i].coeff, size1); + crFree(a->evalStack[a->evalStackDepth].eval1D[i].coeff); + a->evalStack[a->evalStackDepth].eval1D[i].coeff = NULL; + g->eval.eval2D[i].u1 = a->evalStack[a->evalStackDepth].eval2D[i].u1; + g->eval.eval2D[i].u2 = a->evalStack[a->evalStackDepth].eval2D[i].u2; + g->eval.eval2D[i].v1 = a->evalStack[a->evalStackDepth].eval2D[i].v1; + g->eval.eval2D[i].v2 = a->evalStack[a->evalStackDepth].eval2D[i].v2; + g->eval.eval2D[i].uorder = a->evalStack[a->evalStackDepth].eval2D[i].uorder; + g->eval.eval2D[i].vorder = a->evalStack[a->evalStackDepth].eval2D[i].vorder; + crMemcpy((char*)g->eval.eval2D[i].coeff, a->evalStack[a->evalStackDepth].eval2D[i].coeff, size2); + crFree(a->evalStack[a->evalStackDepth].eval2D[i].coeff); + a->evalStack[a->evalStackDepth].eval2D[i].coeff = NULL; + } + g->eval.autoNormal = a->evalStack[a->evalStackDepth].autoNormal; + g->eval.un1D = a->evalStack[a->evalStackDepth].un1D; + g->eval.u11D = a->evalStack[a->evalStackDepth].u11D; + g->eval.u21D = a->evalStack[a->evalStackDepth].u21D; + g->eval.un2D = a->evalStack[a->evalStackDepth].un2D; + g->eval.u12D = a->evalStack[a->evalStackDepth].u12D; + g->eval.u22D = a->evalStack[a->evalStackDepth].u22D; + g->eval.vn2D = a->evalStack[a->evalStackDepth].vn2D; + g->eval.v12D = a->evalStack[a->evalStackDepth].v12D; + g->eval.v22D = a->evalStack[a->evalStackDepth].v22D; + for (i = 0; i < GLEVAL_TOT; i++) { + DIRTY(sb->eval.eval1D[i], g->neg_bitid); + DIRTY(sb->eval.eval2D[i], g->neg_bitid); + } + DIRTY(sb->eval.dirty, g->neg_bitid); + DIRTY(sb->eval.grid1D, g->neg_bitid); + DIRTY(sb->eval.grid2D, g->neg_bitid); + DIRTY(sb->eval.enable, g->neg_bitid); + } + if (mask & GL_FOG_BIT) + { + if (a->fogStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty fog stack!" ); + return; + } + a->fogStackDepth--; + g->fog.enable = a->fogStack[a->fogStackDepth].enable; + g->fog.color = a->fogStack[a->fogStackDepth].color; + g->fog.density = a->fogStack[a->fogStackDepth].density; + g->fog.start = a->fogStack[a->fogStackDepth].start; + g->fog.end = a->fogStack[a->fogStackDepth].end; + g->fog.index = a->fogStack[a->fogStackDepth].index; + g->fog.mode = a->fogStack[a->fogStackDepth].mode; + DIRTY(sb->fog.dirty, g->neg_bitid); + DIRTY(sb->fog.color, g->neg_bitid); + DIRTY(sb->fog.index, g->neg_bitid); + DIRTY(sb->fog.density, g->neg_bitid); + DIRTY(sb->fog.start, g->neg_bitid); + DIRTY(sb->fog.end, g->neg_bitid); + DIRTY(sb->fog.mode, g->neg_bitid); + DIRTY(sb->fog.enable, g->neg_bitid); + } + if (mask & GL_HINT_BIT) + { + if (a->hintStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty hint stack!" ); + return; + } + a->hintStackDepth--; + g->hint.perspectiveCorrection = a->hintStack[a->hintStackDepth].perspectiveCorrection; + g->hint.pointSmooth = a->hintStack[a->hintStackDepth].pointSmooth; + g->hint.lineSmooth = a->hintStack[a->hintStackDepth].lineSmooth; + g->hint.polygonSmooth = a->hintStack[a->hintStackDepth].polygonSmooth; + g->hint.fog = a->hintStack[a->hintStackDepth].fog; + DIRTY(sb->hint.dirty, g->neg_bitid); + DIRTY(sb->hint.perspectiveCorrection, g->neg_bitid); + DIRTY(sb->hint.pointSmooth, g->neg_bitid); + DIRTY(sb->hint.lineSmooth, g->neg_bitid); + DIRTY(sb->hint.polygonSmooth, g->neg_bitid); +#ifdef CR_EXT_clip_volume_hint + g->hint.clipVolumeClipping = a->hintStack[a->hintStackDepth].clipVolumeClipping; + DIRTY(sb->hint.clipVolumeClipping, g->neg_bitid); +#endif +#ifdef CR_ARB_texture_compression + g->hint.textureCompression = a->hintStack[a->hintStackDepth].textureCompression; + DIRTY(sb->hint.textureCompression, g->neg_bitid); +#endif +#ifdef CR_SGIS_generate_mipmap + g->hint.generateMipmap = a->hintStack[a->hintStackDepth].generateMipmap; + DIRTY(sb->hint.generateMipmap, g->neg_bitid); +#endif + } + if (mask & GL_LIGHTING_BIT) + { + if (a->lightingStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty lighting stack!" ); + return; + } + a->lightingStackDepth--; + g->lighting.lightModelAmbient = a->lightingStack[a->lightingStackDepth].lightModelAmbient; + g->lighting.lightModelLocalViewer = a->lightingStack[a->lightingStackDepth].lightModelLocalViewer; + g->lighting.lightModelTwoSide = a->lightingStack[a->lightingStackDepth].lightModelTwoSide; +#if defined(CR_EXT_separate_specular_color) || defined(CR_OPENGL_VERSION_1_2) + g->lighting.lightModelColorControlEXT = a->lightingStack[a->lightingStackDepth].lightModelColorControlEXT; +#endif + g->lighting.lighting = a->lightingStack[a->lightingStackDepth].lighting; + g->lighting.colorMaterial = a->lightingStack[a->lightingStackDepth].colorMaterial; + g->lighting.colorMaterialMode = a->lightingStack[a->lightingStackDepth].colorMaterialMode; + g->lighting.colorMaterialFace = a->lightingStack[a->lightingStackDepth].colorMaterialFace; + for (i = 0 ; i < g->limits.maxLights; i++) + { + g->lighting.light[i].enable = a->lightingStack[a->lightingStackDepth].light[i].enable; + g->lighting.light[i].ambient = a->lightingStack[a->lightingStackDepth].light[i].ambient; + g->lighting.light[i].diffuse = a->lightingStack[a->lightingStackDepth].light[i].diffuse; + g->lighting.light[i].specular = a->lightingStack[a->lightingStackDepth].light[i].specular; + g->lighting.light[i].spotDirection = a->lightingStack[a->lightingStackDepth].light[i].spotDirection; + g->lighting.light[i].position = a->lightingStack[a->lightingStackDepth].light[i].position; + g->lighting.light[i].spotExponent = a->lightingStack[a->lightingStackDepth].light[i].spotExponent; + g->lighting.light[i].spotCutoff = a->lightingStack[a->lightingStackDepth].light[i].spotCutoff; + g->lighting.light[i].constantAttenuation = a->lightingStack[a->lightingStackDepth].light[i].constantAttenuation; + g->lighting.light[i].linearAttenuation = a->lightingStack[a->lightingStackDepth].light[i].linearAttenuation; + g->lighting.light[i].quadraticAttenuation = a->lightingStack[a->lightingStackDepth].light[i].quadraticAttenuation; + } + for (i = 0 ; i < 2 ; i++) + { + g->lighting.ambient[i] = a->lightingStack[a->lightingStackDepth].ambient[i]; + g->lighting.diffuse[i] = a->lightingStack[a->lightingStackDepth].diffuse[i]; + g->lighting.specular[i] = a->lightingStack[a->lightingStackDepth].specular[i]; + g->lighting.emission[i] = a->lightingStack[a->lightingStackDepth].emission[i]; + g->lighting.shininess[i] = a->lightingStack[a->lightingStackDepth].shininess[i]; + g->lighting.indexes[i][0] = a->lightingStack[a->lightingStackDepth].indexes[i][0]; + g->lighting.indexes[i][1] = a->lightingStack[a->lightingStackDepth].indexes[i][1]; + g->lighting.indexes[i][2] = a->lightingStack[a->lightingStackDepth].indexes[i][2]; + } + g->lighting.shadeModel = a->lightingStack[a->lightingStackDepth].shadeModel; + DIRTY(sb->lighting.dirty, g->neg_bitid); + DIRTY(sb->lighting.shadeModel, g->neg_bitid); + DIRTY(sb->lighting.lightModel, g->neg_bitid); + DIRTY(sb->lighting.material, g->neg_bitid); + DIRTY(sb->lighting.enable, g->neg_bitid); + for (i = 0 ; i < g->limits.maxLights; i++) + { + DIRTY(sb->lighting.light[i].dirty, g->neg_bitid); + DIRTY(sb->lighting.light[i].enable, g->neg_bitid); + DIRTY(sb->lighting.light[i].ambient, g->neg_bitid); + DIRTY(sb->lighting.light[i].diffuse, g->neg_bitid); + DIRTY(sb->lighting.light[i].specular, g->neg_bitid); + DIRTY(sb->lighting.light[i].position, g->neg_bitid); + DIRTY(sb->lighting.light[i].attenuation, g->neg_bitid); + DIRTY(sb->lighting.light[i].spot, g->neg_bitid); + } + } + if (mask & GL_LINE_BIT) + { + if (a->lineStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty line stack!" ); + return; + } + a->lineStackDepth--; + g->line.lineSmooth = a->lineStack[a->lineStackDepth].lineSmooth; + g->line.lineStipple = a->lineStack[a->lineStackDepth].lineStipple; + g->line.pattern = a->lineStack[a->lineStackDepth].pattern; + g->line.repeat = a->lineStack[a->lineStackDepth].repeat; + g->line.width = a->lineStack[a->lineStackDepth].width; + DIRTY(sb->line.dirty, g->neg_bitid); + DIRTY(sb->line.enable, g->neg_bitid); + DIRTY(sb->line.width, g->neg_bitid); + DIRTY(sb->line.stipple, g->neg_bitid); + } + if (mask & GL_LIST_BIT) + { + if (a->listStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty list stack!" ); + return; + } + a->listStackDepth--; + g->lists.base = a->listStack[a->listStackDepth].base; + DIRTY(sb->lists.dirty, g->neg_bitid); + } + if (mask & GL_PIXEL_MODE_BIT) + { + if (a->pixelModeStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty pixel mode stack!" ); + return; + } + a->pixelModeStackDepth--; + g->pixel.bias = a->pixelModeStack[a->pixelModeStackDepth].bias; + g->pixel.scale = a->pixelModeStack[a->pixelModeStackDepth].scale; + g->pixel.indexOffset = a->pixelModeStack[a->pixelModeStackDepth].indexOffset; + g->pixel.indexShift = a->pixelModeStack[a->pixelModeStackDepth].indexShift; + g->pixel.mapColor = a->pixelModeStack[a->pixelModeStackDepth].mapColor; + g->pixel.mapStencil = a->pixelModeStack[a->pixelModeStackDepth].mapStencil; + g->pixel.xZoom = a->pixelModeStack[a->pixelModeStackDepth].xZoom; + g->pixel.yZoom = a->pixelModeStack[a->pixelModeStackDepth].yZoom; + g->buffer.readBuffer = a->pixelModeStack[a->pixelModeStackDepth].readBuffer; + DIRTY(sb->pixel.dirty, g->neg_bitid); + DIRTY(sb->pixel.transfer, g->neg_bitid); + DIRTY(sb->pixel.zoom, g->neg_bitid); + DIRTY(sb->buffer.dirty, g->neg_bitid); + DIRTY(sb->buffer.readBuffer, g->neg_bitid); + } + if (mask & GL_POINT_BIT) + { + if (a->pointStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty point stack!" ); + return; + } + a->pointStackDepth--; + g->point.pointSmooth = a->pointStack[a->pointStackDepth].pointSmooth; + g->point.pointSize = a->pointStack[a->pointStackDepth].pointSize; +#if GL_ARB_point_sprite + g->point.pointSprite = a->pointStack[a->pointStackDepth].pointSprite; + DIRTY(sb->point.enableSprite, g->neg_bitid); + for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) { + g->point.coordReplacement[i] = a->enableStack[a->enableStackDepth].coordReplacement[i]; + DIRTY(sb->point.coordReplacement[i], g->neg_bitid); + } +#endif + DIRTY(sb->point.dirty, g->neg_bitid); + DIRTY(sb->point.size, g->neg_bitid); + DIRTY(sb->point.enableSmooth, g->neg_bitid); + } + if (mask & GL_POLYGON_BIT) + { + if (a->polygonStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty polygon stack!" ); + return; + } + a->polygonStackDepth--; + g->polygon.cullFace = a->polygonStack[a->polygonStackDepth].cullFace; + g->polygon.cullFaceMode = a->polygonStack[a->polygonStackDepth].cullFaceMode; + g->polygon.frontFace = a->polygonStack[a->polygonStackDepth].frontFace; + g->polygon.frontMode = a->polygonStack[a->polygonStackDepth].frontMode; + g->polygon.backMode = a->polygonStack[a->polygonStackDepth].backMode; + g->polygon.polygonSmooth = a->polygonStack[a->polygonStackDepth].polygonSmooth; + g->polygon.polygonStipple = a->polygonStack[a->polygonStackDepth].polygonStipple; + g->polygon.polygonOffsetFill = a->polygonStack[a->polygonStackDepth].polygonOffsetFill; + g->polygon.polygonOffsetLine = a->polygonStack[a->polygonStackDepth].polygonOffsetLine; + g->polygon.polygonOffsetPoint = a->polygonStack[a->polygonStackDepth].polygonOffsetPoint; + g->polygon.offsetFactor = a->polygonStack[a->polygonStackDepth].offsetFactor; + g->polygon.offsetUnits = a->polygonStack[a->polygonStackDepth].offsetUnits; + DIRTY(sb->polygon.dirty, g->neg_bitid); + DIRTY(sb->polygon.enable, g->neg_bitid); + DIRTY(sb->polygon.offset, g->neg_bitid); + DIRTY(sb->polygon.mode, g->neg_bitid); + DIRTY(sb->polygon.stipple, g->neg_bitid); + } + if (mask & GL_POLYGON_STIPPLE_BIT) + { + if (a->polygonStippleStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty polygon stipple stack!" ); + return; + } + a->polygonStippleStackDepth--; + crMemcpy( g->polygon.stipple, a->polygonStippleStack[a->polygonStippleStackDepth].pattern, 32*sizeof(GLint) ); + DIRTY(sb->polygon.dirty, g->neg_bitid); + DIRTY(sb->polygon.stipple, g->neg_bitid); + } + if (mask & GL_SCISSOR_BIT) + { + if (a->scissorStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty scissor stack!" ); + return; + } + a->scissorStackDepth--; + g->viewport.scissorTest = a->scissorStack[a->scissorStackDepth].scissorTest; + g->viewport.scissorX = a->scissorStack[a->scissorStackDepth].scissorX; + g->viewport.scissorY = a->scissorStack[a->scissorStackDepth].scissorY; + g->viewport.scissorW = a->scissorStack[a->scissorStackDepth].scissorW; + g->viewport.scissorH = a->scissorStack[a->scissorStackDepth].scissorH; + DIRTY(sb->viewport.dirty, g->neg_bitid); + DIRTY(sb->viewport.enable, g->neg_bitid); + DIRTY(sb->viewport.s_dims, g->neg_bitid); + } + if (mask & GL_STENCIL_BUFFER_BIT) + { + if (a->stencilBufferStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty stencil stack!" ); + return; + } + a->stencilBufferStackDepth--; + g->stencil.stencilTest = a->stencilBufferStack[a->stencilBufferStackDepth].stencilTest; + g->stencil.clearValue = a->stencilBufferStack[a->stencilBufferStackDepth].clearValue; + g->stencil.writeMask = a->stencilBufferStack[a->stencilBufferStackDepth].writeMask; + for (i = 0; i < CRSTATE_STENCIL_BUFFER_COUNT; ++i) + { + g->stencil.buffers[i].func = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].func; + g->stencil.buffers[i].mask = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].mask; + g->stencil.buffers[i].ref = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].ref; + g->stencil.buffers[i].fail = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].fail; + g->stencil.buffers[i].passDepthFail = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].passDepthFail; + g->stencil.buffers[i].passDepthPass = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].passDepthPass; + } + + DIRTY(sb->stencil.dirty, g->neg_bitid); + DIRTY(sb->stencil.enable, g->neg_bitid); + DIRTY(sb->stencil.clearValue, g->neg_bitid); + DIRTY(sb->stencil.writeMask, g->neg_bitid); + + for (i = 0; i < CRSTATE_STENCIL_BUFFER_REF_COUNT; ++i) + { + DIRTY(sb->stencil.bufferRefs[i].func, g->neg_bitid); + DIRTY(sb->stencil.bufferRefs[i].op, g->neg_bitid); + } + } + if (mask & GL_TEXTURE_BIT) + { + CRTextureStack *tState; + if (a->textureStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty texture stack!" ); + return; + } + a->textureStackDepth--; + tState = a->textureStack + a->textureStackDepth; + + g->texture.curTextureUnit = tState->curTextureUnit; + for (i = 0 ; i < g->limits.maxTextureUnits ; i++) + { + copy_texunit(&g->texture.unit[i], &tState->unit[i]); + /* first, restore the bindings! */ + g->texture.unit[i].currentTexture1D = crStateTextureGet(GL_TEXTURE_1D, tState->unit[i].Saved1D.id); + copy_texobj(g->texture.unit[i].currentTexture1D, &tState->unit[i].Saved1D, GL_FALSE); + g->texture.unit[i].currentTexture2D = crStateTextureGet(GL_TEXTURE_2D, tState->unit[i].Saved2D.id); + copy_texobj(g->texture.unit[i].currentTexture2D, &tState->unit[i].Saved2D, GL_FALSE); +#ifdef CR_OPENGL_VERSION_1_2 + g->texture.unit[i].currentTexture3D = crStateTextureGet(GL_TEXTURE_3D, tState->unit[i].Saved3D.id); + copy_texobj(g->texture.unit[i].currentTexture3D, &tState->unit[i].Saved3D, GL_FALSE); +#endif +#ifdef CR_ARB_texture_cube_map + g->texture.unit[i].currentTextureCubeMap = crStateTextureGet(GL_TEXTURE_CUBE_MAP_ARB, tState->unit[i].SavedCubeMap.id); + copy_texobj(g->texture.unit[i].currentTextureCubeMap, &tState->unit[i].SavedCubeMap, GL_FALSE); +#endif +#ifdef CR_NV_texture_rectangle + g->texture.unit[i].currentTextureRect = crStateTextureGet(GL_TEXTURE_CUBE_MAP_ARB, tState->unit[i].SavedRect.id); + copy_texobj(g->texture.unit[i].currentTextureRect, &tState->unit[i].SavedRect, GL_FALSE); +#endif + } + DIRTY(sb->texture.dirty, g->neg_bitid); + for (i = 0 ; i < g->limits.maxTextureUnits ; i++) + { + DIRTY(sb->texture.enable[i], g->neg_bitid); + DIRTY(sb->texture.current[i], g->neg_bitid); + DIRTY(sb->texture.objGen[i], g->neg_bitid); + DIRTY(sb->texture.eyeGen[i], g->neg_bitid); + DIRTY(sb->texture.envBit[i], g->neg_bitid); + DIRTY(sb->texture.genMode[i], g->neg_bitid); + } + + for (i = 0 ; i < g->limits.maxTextureUnits ; i++) + { + DIRTY(g->texture.unit[i].currentTexture1D->dirty, g->neg_bitid); + DIRTY(g->texture.unit[i].currentTexture2D->dirty, g->neg_bitid); + DIRTY(g->texture.unit[i].currentTexture3D->dirty, g->neg_bitid); +#ifdef CR_ARB_texture_cube_map + DIRTY(g->texture.unit[i].currentTextureCubeMap->dirty, g->neg_bitid); +#endif +#ifdef CR_NV_texture_rectangle + DIRTY(g->texture.unit[i].currentTextureRect->dirty, g->neg_bitid); +#endif + DIRTY(g->texture.unit[i].currentTexture1D->paramsBit[i], g->neg_bitid); + DIRTY(g->texture.unit[i].currentTexture2D->paramsBit[i], g->neg_bitid); + DIRTY(g->texture.unit[i].currentTexture3D->paramsBit[i], g->neg_bitid); +#ifdef CR_ARB_texture_cube_map + DIRTY(g->texture.unit[i].currentTextureCubeMap->paramsBit[i], g->neg_bitid); +#endif +#ifdef CR_NV_texture_rectangle + DIRTY(g->texture.unit[i].currentTextureRect->paramsBit[i], g->neg_bitid); +#endif + } + } + if (mask & GL_TRANSFORM_BIT) + { + if (a->transformStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty transform stack!" ); + return; + } + a->transformStackDepth--; + g->transform.matrixMode = a->transformStack[a->transformStackDepth].matrixMode; + crStateMatrixMode(g->transform.matrixMode); + for (i = 0 ; i < g->limits.maxClipPlanes ; i++) + { + g->transform.clip[i] = a->transformStack[a->transformStackDepth].clip[i]; + g->transform.clipPlane[i] = a->transformStack[a->transformStackDepth].clipPlane[i]; + } + g->transform.normalize = a->transformStack[a->transformStackDepth].normalize; +#ifdef CR_OPENGL_VERSION_1_2 + g->transform.rescaleNormals = a->transformStack[a->transformStackDepth].rescaleNormals; +#endif + DIRTY(sb->transform.dirty, g->neg_bitid); + DIRTY(sb->transform.matrixMode, g->neg_bitid); + DIRTY(sb->transform.clipPlane, g->neg_bitid); + DIRTY(sb->transform.enable, g->neg_bitid); + } + if (mask & GL_VIEWPORT_BIT) + { + if (a->viewportStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty viewport stack!" ); + return; + } + a->viewportStackDepth--; + g->viewport.viewportX = a->viewportStack[a->viewportStackDepth].viewportX; + g->viewport.viewportY = a->viewportStack[a->viewportStackDepth].viewportY; + g->viewport.viewportW = a->viewportStack[a->viewportStackDepth].viewportW; + g->viewport.viewportH = a->viewportStack[a->viewportStackDepth].viewportH; + g->viewport.nearClip = a->viewportStack[a->viewportStackDepth].nearClip; + g->viewport.farClip = a->viewportStack[a->viewportStackDepth].farClip; + DIRTY(sb->viewport.dirty, g->neg_bitid); + DIRTY(sb->viewport.v_dims, g->neg_bitid); + DIRTY(sb->viewport.depth, g->neg_bitid); + } + DIRTY(ab->dirty, g->neg_bitid); +} + +void crStateAttribSwitch( CRAttribBits *bb, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx ) +{ + CRAttribState *to = &(toCtx->attrib); + CRAttribState *from = &(fromCtx->attrib); + if (to->attribStackDepth != 0 || from->attribStackDepth != 0) + { + crWarning( "Trying to switch contexts when the attribute stacks " + "weren't empty. Currently, this is not supported." ); + } + (void) bb; + (void) bitID; +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_bits_globalop.h b/src/VBox/GuestHost/OpenGL/state_tracker/state_bits_globalop.h new file mode 100644 index 00000000..506da3c5 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_bits_globalop.h @@ -0,0 +1,338 @@ +/* $Id: state_bits_globalop.h $ */ + +/** @file + * Global State bits operation + */ + +/* + * Copyright (C) 2013-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#include <iprt/cdefs.h> + +#include <cr_version.h> + +#ifndef CRSTATE_BITS_OP +# error "CRSTATE_BITS_OP must be defined!" +#endif + +#define _CRSTATE_BITS_OP_SIZEOF(_val) CRSTATE_BITS_OP(_val, RT_SIZEOFMEMB(CRStateBits, _val)) + +#ifndef CRSTATE_BITS_OP_VERSION +# define CRSTATE_BITS_OP_VERSION SHCROGL_SSM_VERSION +#endif + +do { +int i; +#ifdef _CRSTATE_BITS_OP_STENCIL_V_33 +# error "_CRSTATE_BITS_OP_STENCIL_V_33 must no be defined!" +#endif +#if CRSTATE_BITS_OP_VERSION < SHCROGL_SSM_VERSION_WITH_FIXED_STENCIL +# define _CRSTATE_BITS_OP_STENCIL_V_33 +#endif + +#ifdef _CRSTATE_BITS_OP_STENCIL_V_33 +# ifndef CRSTATE_BITS_OP_STENCIL_OP_V_33 +# error "CRSTATE_BITS_OP_STENCIL_OP_V_33 undefined!" +# endif +# ifndef CRSTATE_BITS_OP_STENCIL_FUNC_V_33 +# error "CRSTATE_BITS_OP_STENCIL_FUNC_V_33 undefined!" +# endif +#endif + +_CRSTATE_BITS_OP_SIZEOF(attrib.dirty); + +_CRSTATE_BITS_OP_SIZEOF(buffer.dirty); +_CRSTATE_BITS_OP_SIZEOF(buffer.enable); +_CRSTATE_BITS_OP_SIZEOF(buffer.alphaFunc); +_CRSTATE_BITS_OP_SIZEOF(buffer.depthFunc); +_CRSTATE_BITS_OP_SIZEOF(buffer.blendFunc); +_CRSTATE_BITS_OP_SIZEOF(buffer.logicOp); +_CRSTATE_BITS_OP_SIZEOF(buffer.indexLogicOp); +_CRSTATE_BITS_OP_SIZEOF(buffer.drawBuffer); +_CRSTATE_BITS_OP_SIZEOF(buffer.readBuffer); +_CRSTATE_BITS_OP_SIZEOF(buffer.indexMask); +_CRSTATE_BITS_OP_SIZEOF(buffer.colorWriteMask); +_CRSTATE_BITS_OP_SIZEOF(buffer.clearColor); +_CRSTATE_BITS_OP_SIZEOF(buffer.clearIndex); +_CRSTATE_BITS_OP_SIZEOF(buffer.clearDepth); +_CRSTATE_BITS_OP_SIZEOF(buffer.clearAccum); +_CRSTATE_BITS_OP_SIZEOF(buffer.depthMask); +#ifdef CR_EXT_blend_color +_CRSTATE_BITS_OP_SIZEOF(buffer.blendColor); +#endif +#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op) +_CRSTATE_BITS_OP_SIZEOF(buffer.blendEquation); +#endif +#if defined(CR_EXT_blend_func_separate) +_CRSTATE_BITS_OP_SIZEOF(buffer.blendFuncSeparate); +#endif + +#ifdef CR_ARB_vertex_buffer_object +_CRSTATE_BITS_OP_SIZEOF(bufferobject.dirty); +_CRSTATE_BITS_OP_SIZEOF(bufferobject.arrayBinding); +_CRSTATE_BITS_OP_SIZEOF(bufferobject.elementsBinding); +# ifdef CR_ARB_pixel_buffer_object +_CRSTATE_BITS_OP_SIZEOF(bufferobject.packBinding); +_CRSTATE_BITS_OP_SIZEOF(bufferobject.unpackBinding); +# endif +#endif + +_CRSTATE_BITS_OP_SIZEOF(client.dirty); +_CRSTATE_BITS_OP_SIZEOF(client.pack); +_CRSTATE_BITS_OP_SIZEOF(client.unpack); +_CRSTATE_BITS_OP_SIZEOF(client.enableClientState); +_CRSTATE_BITS_OP_SIZEOF(client.clientPointer); +CRSTATE_BITS_OP(client.v, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); +CRSTATE_BITS_OP(client.n, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); +CRSTATE_BITS_OP(client.c, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); +CRSTATE_BITS_OP(client.i, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); +CRSTATE_BITS_OP(client.e, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); +CRSTATE_BITS_OP(client.s, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); +CRSTATE_BITS_OP(client.f, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); +for (i=0; i<CR_MAX_TEXTURE_UNITS; i++) +{ + CRSTATE_BITS_OP(client.t[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); +} +#ifdef CR_NV_vertex_program +for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++) +{ + CRSTATE_BITS_OP(client.a[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); +} +#endif + +_CRSTATE_BITS_OP_SIZEOF(current.dirty); +for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++) +{ + _CRSTATE_BITS_OP_SIZEOF(current.vertexAttrib[i]); +} +_CRSTATE_BITS_OP_SIZEOF(current.edgeFlag); +_CRSTATE_BITS_OP_SIZEOF(current.colorIndex); +_CRSTATE_BITS_OP_SIZEOF(current.rasterPos); + + +_CRSTATE_BITS_OP_SIZEOF(eval.dirty); +for (i=0; i<GLEVAL_TOT; i++) +{ + _CRSTATE_BITS_OP_SIZEOF(eval.eval1D[i]); + _CRSTATE_BITS_OP_SIZEOF(eval.eval2D[i]); + _CRSTATE_BITS_OP_SIZEOF(eval.enable1D[i]); + _CRSTATE_BITS_OP_SIZEOF(eval.enable2D[i]); +} +_CRSTATE_BITS_OP_SIZEOF(eval.enable); +_CRSTATE_BITS_OP_SIZEOF(eval.grid1D); +_CRSTATE_BITS_OP_SIZEOF(eval.grid2D); +#ifdef CR_NV_vertex_program + /*@todo Those seems to be unused? +_CRSTATE_BITS_OP_SIZEOF(eval.enableAttrib1D); +_CRSTATE_BITS_OP_SIZEOF(eval.enableAttrib2D); + */ +#endif + +_CRSTATE_BITS_OP_SIZEOF(feedback.dirty); +_CRSTATE_BITS_OP_SIZEOF(selection.dirty); + +_CRSTATE_BITS_OP_SIZEOF(fog.dirty); +_CRSTATE_BITS_OP_SIZEOF(fog.color); +_CRSTATE_BITS_OP_SIZEOF(fog.index); +_CRSTATE_BITS_OP_SIZEOF(fog.density); +_CRSTATE_BITS_OP_SIZEOF(fog.start); +_CRSTATE_BITS_OP_SIZEOF(fog.end); +_CRSTATE_BITS_OP_SIZEOF(fog.mode); +_CRSTATE_BITS_OP_SIZEOF(fog.enable); +#ifdef CR_NV_fog_distance +_CRSTATE_BITS_OP_SIZEOF(fog.fogDistanceMode); +#endif +#ifdef CR_EXT_fog_coord +_CRSTATE_BITS_OP_SIZEOF(fog.fogCoordinateSource); +#endif + +_CRSTATE_BITS_OP_SIZEOF(hint.dirty); +_CRSTATE_BITS_OP_SIZEOF(hint.perspectiveCorrection); +_CRSTATE_BITS_OP_SIZEOF(hint.pointSmooth); +_CRSTATE_BITS_OP_SIZEOF(hint.lineSmooth); +_CRSTATE_BITS_OP_SIZEOF(hint.polygonSmooth); +_CRSTATE_BITS_OP_SIZEOF(hint.fog); +#ifdef CR_EXT_clip_volume_hint +_CRSTATE_BITS_OP_SIZEOF(hint.clipVolumeClipping); + +#endif +#ifdef CR_ARB_texture_compression +_CRSTATE_BITS_OP_SIZEOF(hint.textureCompression); +#endif +#ifdef CR_SGIS_generate_mipmap +_CRSTATE_BITS_OP_SIZEOF(hint.generateMipmap); +#endif + +_CRSTATE_BITS_OP_SIZEOF(lighting.dirty); +_CRSTATE_BITS_OP_SIZEOF(lighting.shadeModel); +_CRSTATE_BITS_OP_SIZEOF(lighting.colorMaterial); +_CRSTATE_BITS_OP_SIZEOF(lighting.lightModel); +_CRSTATE_BITS_OP_SIZEOF(lighting.material); +_CRSTATE_BITS_OP_SIZEOF(lighting.enable); +for (i=0; i<CR_MAX_LIGHTS; ++i) +{ + _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].dirty); + _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].enable); + _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].ambient); + _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].diffuse); + _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].specular); + _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].position); + _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].attenuation); + _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].spot); +} + +_CRSTATE_BITS_OP_SIZEOF(line.dirty); +_CRSTATE_BITS_OP_SIZEOF(line.enable); +_CRSTATE_BITS_OP_SIZEOF(line.width); +_CRSTATE_BITS_OP_SIZEOF(line.stipple); + +_CRSTATE_BITS_OP_SIZEOF(lists.dirty); +_CRSTATE_BITS_OP_SIZEOF(lists.base); + +_CRSTATE_BITS_OP_SIZEOF(multisample.dirty); +_CRSTATE_BITS_OP_SIZEOF(multisample.enable); +_CRSTATE_BITS_OP_SIZEOF(multisample.sampleAlphaToCoverage); +_CRSTATE_BITS_OP_SIZEOF(multisample.sampleAlphaToOne); +_CRSTATE_BITS_OP_SIZEOF(multisample.sampleCoverage); +_CRSTATE_BITS_OP_SIZEOF(multisample.sampleCoverageValue); + +#if CR_ARB_occlusion_query +_CRSTATE_BITS_OP_SIZEOF(occlusion.dirty); +#endif + +_CRSTATE_BITS_OP_SIZEOF(pixel.dirty); +_CRSTATE_BITS_OP_SIZEOF(pixel.transfer); +_CRSTATE_BITS_OP_SIZEOF(pixel.zoom); +_CRSTATE_BITS_OP_SIZEOF(pixel.maps); + +_CRSTATE_BITS_OP_SIZEOF(point.dirty); +_CRSTATE_BITS_OP_SIZEOF(point.enableSmooth); +_CRSTATE_BITS_OP_SIZEOF(point.size); +#ifdef CR_ARB_point_parameters +_CRSTATE_BITS_OP_SIZEOF(point.minSize); +_CRSTATE_BITS_OP_SIZEOF(point.maxSize); +_CRSTATE_BITS_OP_SIZEOF(point.fadeThresholdSize); +_CRSTATE_BITS_OP_SIZEOF(point.distanceAttenuation); +#endif +#ifdef CR_ARB_point_sprite +_CRSTATE_BITS_OP_SIZEOF(point.enableSprite); +for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i) +{ + _CRSTATE_BITS_OP_SIZEOF(point.coordReplacement[i]); +} +#endif +#if CRSTATE_BITS_OP_VERSION >= SHCROGL_SSM_VERSION_WITH_SPRITE_COORD_ORIGIN +_CRSTATE_BITS_OP_SIZEOF(point.spriteCoordOrigin); +#endif + +_CRSTATE_BITS_OP_SIZEOF(polygon.dirty); +_CRSTATE_BITS_OP_SIZEOF(polygon.enable); +_CRSTATE_BITS_OP_SIZEOF(polygon.offset); +_CRSTATE_BITS_OP_SIZEOF(polygon.mode); +_CRSTATE_BITS_OP_SIZEOF(polygon.stipple); + +_CRSTATE_BITS_OP_SIZEOF(program.dirty); +_CRSTATE_BITS_OP_SIZEOF(program.vpEnable); +_CRSTATE_BITS_OP_SIZEOF(program.fpEnable); +_CRSTATE_BITS_OP_SIZEOF(program.vpBinding); +_CRSTATE_BITS_OP_SIZEOF(program.fpBinding); +for (i=0; i<CR_MAX_VERTEX_ATTRIBS; ++i) +{ + _CRSTATE_BITS_OP_SIZEOF(program.vertexAttribArrayEnable[i]); + _CRSTATE_BITS_OP_SIZEOF(program.map1AttribArrayEnable[i]); + _CRSTATE_BITS_OP_SIZEOF(program.map2AttribArrayEnable[i]); +} +for (i=0; i<CR_MAX_VERTEX_PROGRAM_ENV_PARAMS; ++i) +{ + _CRSTATE_BITS_OP_SIZEOF(program.vertexEnvParameter[i]); +} +for (i=0; i<CR_MAX_FRAGMENT_PROGRAM_ENV_PARAMS; ++i) +{ + _CRSTATE_BITS_OP_SIZEOF(program.fragmentEnvParameter[i]); +} +_CRSTATE_BITS_OP_SIZEOF(program.vertexEnvParameters); +_CRSTATE_BITS_OP_SIZEOF(program.fragmentEnvParameters); +for (i=0; i<CR_MAX_VERTEX_PROGRAM_ENV_PARAMS/4; ++i) +{ + _CRSTATE_BITS_OP_SIZEOF(program.trackMatrix[i]); +} + +_CRSTATE_BITS_OP_SIZEOF(regcombiner.dirty); +_CRSTATE_BITS_OP_SIZEOF(regcombiner.enable); +_CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerVars); +_CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerColor0); +_CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerColor1); +for (i=0; i<CR_MAX_GENERAL_COMBINERS; ++i) +{ + _CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerStageColor0[i]); + _CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerStageColor1[i]); + _CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerInput[i]); + _CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerOutput[i]); +} +_CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerFinalInput); + +_CRSTATE_BITS_OP_SIZEOF(stencil.dirty); +_CRSTATE_BITS_OP_SIZEOF(stencil.enable); +#ifdef _CRSTATE_BITS_OP_STENCIL_V_33 +_CRSTATE_BITS_OP_SIZEOF(stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func); +_CRSTATE_BITS_OP_SIZEOF(stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op); +for (i = CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK + 1; i < CRSTATE_STENCIL_BUFFER_REF_COUNT; ++i) +{ + CRSTATE_BITS_OP_STENCIL_FUNC_V_33(i, stencil.bufferRefs[i].func); + CRSTATE_BITS_OP_STENCIL_OP_V_33(i, stencil.bufferRefs[i].op); +} +_CRSTATE_BITS_OP_SIZEOF(stencil.clearValue); +_CRSTATE_BITS_OP_SIZEOF(stencil.writeMask); +#else +_CRSTATE_BITS_OP_SIZEOF(stencil.enableTwoSideEXT); +_CRSTATE_BITS_OP_SIZEOF(stencil.activeStencilFace); +_CRSTATE_BITS_OP_SIZEOF(stencil.clearValue); +_CRSTATE_BITS_OP_SIZEOF(stencil.writeMask); +for (i = 0; i < CRSTATE_STENCIL_BUFFER_REF_COUNT; ++i) +{ + _CRSTATE_BITS_OP_SIZEOF(stencil.bufferRefs[i].func); + _CRSTATE_BITS_OP_SIZEOF(stencil.bufferRefs[i].op); +} +#endif + +_CRSTATE_BITS_OP_SIZEOF(texture.dirty); +for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i) +{ + _CRSTATE_BITS_OP_SIZEOF(texture.enable[i]); + _CRSTATE_BITS_OP_SIZEOF(texture.current[i]); + _CRSTATE_BITS_OP_SIZEOF(texture.objGen[i]); + _CRSTATE_BITS_OP_SIZEOF(texture.eyeGen[i]); + _CRSTATE_BITS_OP_SIZEOF(texture.genMode[i]); + _CRSTATE_BITS_OP_SIZEOF(texture.envBit[i]); +} + +_CRSTATE_BITS_OP_SIZEOF(transform.dirty); +_CRSTATE_BITS_OP_SIZEOF(transform.matrixMode); +_CRSTATE_BITS_OP_SIZEOF(transform.modelviewMatrix); +_CRSTATE_BITS_OP_SIZEOF(transform.projectionMatrix); +_CRSTATE_BITS_OP_SIZEOF(transform.colorMatrix); +_CRSTATE_BITS_OP_SIZEOF(transform.textureMatrix); +_CRSTATE_BITS_OP_SIZEOF(transform.programMatrix); +_CRSTATE_BITS_OP_SIZEOF(transform.clipPlane); +_CRSTATE_BITS_OP_SIZEOF(transform.enable); +_CRSTATE_BITS_OP_SIZEOF(transform.base); + +_CRSTATE_BITS_OP_SIZEOF(viewport.dirty); +_CRSTATE_BITS_OP_SIZEOF(viewport.v_dims); +_CRSTATE_BITS_OP_SIZEOF(viewport.s_dims); +_CRSTATE_BITS_OP_SIZEOF(viewport.enable); +_CRSTATE_BITS_OP_SIZEOF(viewport.depth); + +} while (0); + +#undef CRSTATE_BITS_OP_VERSION +#undef _CRSTATE_BITS_OP_STENCIL_V_33 diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c new file mode 100644 index 00000000..75090f84 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c @@ -0,0 +1,776 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include <stdio.h> +#include "state.h" +#include "state/cr_statetypes.h" +#include "state_internals.h" + +void crStateBufferInit (CRContext *ctx) +{ + CRBufferState *b = &ctx->buffer; + CRStateBits *sb = GetCurrentBits(); + CRBufferBits *bb = &(sb->buffer); + GLcolorf zero_colorf = {0.0f, 0.0f, 0.0f, 0.0f}; + + b->width = 640; + b->height = 480; + b->storedWidth = 0; + b->storedHeight = 0; + b->pFrontImg = NULL; + b->pBackImg = NULL; + + b->depthTest = GL_FALSE; + b->blend = GL_FALSE; + b->alphaTest = GL_FALSE; + b->dither = GL_TRUE; + RESET(bb->enable, ctx->bitid); + + b->logicOp = GL_FALSE; + RESET(bb->logicOp, ctx->bitid); + b->indexLogicOp = GL_FALSE; + RESET(bb->indexLogicOp, ctx->bitid); + b->depthMask = GL_TRUE; + RESET(bb->depthMask, ctx->bitid); + + b->alphaTestFunc = GL_ALWAYS; + b->alphaTestRef = 0; + RESET(bb->alphaFunc, ctx->bitid); + b->depthFunc = GL_LESS; + RESET(bb->depthFunc, ctx->bitid); + b->blendSrcRGB = GL_ONE; + b->blendDstRGB = GL_ZERO; + RESET(bb->blendFunc, ctx->bitid); +#ifdef CR_EXT_blend_func_separate + b->blendSrcA = GL_ONE; + b->blendDstA = GL_ZERO; + RESET(bb->blendFuncSeparate, ctx->bitid); +#endif + b->logicOpMode = GL_COPY; + b->drawBuffer = GL_BACK; + RESET(bb->drawBuffer, ctx->bitid); + b->readBuffer = GL_BACK; + RESET(bb->readBuffer, ctx->bitid); + b->indexWriteMask = 0xffffffff; + RESET(bb->indexMask, ctx->bitid); + b->colorWriteMask.r = GL_TRUE; + b->colorWriteMask.g = GL_TRUE; + b->colorWriteMask.b = GL_TRUE; + b->colorWriteMask.a = GL_TRUE; + RESET(bb->colorWriteMask, ctx->bitid); + b->colorClearValue = zero_colorf; + RESET(bb->clearColor, ctx->bitid); + b->indexClearValue = 0; + RESET(bb->clearIndex, ctx->bitid); + b->depthClearValue = (GLdefault) 1.0; + RESET(bb->clearDepth, ctx->bitid); + b->accumClearValue = zero_colorf; + RESET(bb->clearAccum, ctx->bitid); + +#ifdef CR_EXT_blend_color + b->blendColor = zero_colorf; + RESET(bb->blendColor, ctx->bitid); +#endif +#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op) + b->blendEquation = GL_FUNC_ADD_EXT; + RESET(bb->blendEquation, ctx->bitid); +#endif + + RESET(bb->dirty, ctx->bitid); +} + +void STATE_APIENTRY crStateAlphaFunc (GLenum func, GLclampf ref) +{ + CRContext *g = GetCurrentContext(); + CRBufferState *b = &(g->buffer); + CRStateBits *sb = GetCurrentBits(); + CRBufferBits *bb = &(sb->buffer); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glAlphaFunc called in begin/end"); + return; + } + + FLUSH(); + + switch (func) + { + case GL_NEVER: + case GL_LESS: + case GL_EQUAL: + case GL_LEQUAL: + case GL_GREATER: + case GL_GEQUAL: + case GL_NOTEQUAL: + case GL_ALWAYS: + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glAlphaFunc: Invalid func: %d", func); + return; + } + + if (ref < 0.0f) ref = 0.0f; + if (ref > 1.0f) ref = 1.0f; + + b->alphaTestFunc = func; + b->alphaTestRef = ref; + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(bb->alphaFunc, g->neg_bitid); +} + +void STATE_APIENTRY crStateDepthFunc (GLenum func) +{ + CRContext *g = GetCurrentContext(); + CRBufferState *b = &(g->buffer); + CRStateBits *sb = GetCurrentBits(); + CRBufferBits *bb = &(sb->buffer); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glDepthFunc called in begin/end"); + return; + } + + FLUSH(); + + switch (func) + { + case GL_NEVER: + case GL_LESS: + case GL_EQUAL: + case GL_LEQUAL: + case GL_GREATER: + case GL_NOTEQUAL: + case GL_GEQUAL: + case GL_ALWAYS: + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glDepthFunc: Invalid func: %d", func); + return; + } + + + b->depthFunc = func; + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(bb->depthFunc, g->neg_bitid); +} + +void STATE_APIENTRY crStateBlendFunc (GLenum sfactor, GLenum dfactor) +{ + CRContext *g = GetCurrentContext(); + CRBufferState *b = &(g->buffer); + CRStateBits *sb = GetCurrentBits(); + CRBufferBits *bb = &(sb->buffer); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glBlendFunc called in begin/end"); + return; + } + + FLUSH(); + + switch (sfactor) + { + case GL_ZERO: + case GL_ONE: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_SRC_ALPHA_SATURATE: + break; /* OK */ +#ifdef CR_EXT_blend_color + case GL_CONSTANT_COLOR_EXT: + case GL_ONE_MINUS_CONSTANT_COLOR_EXT: + case GL_CONSTANT_ALPHA_EXT: + case GL_ONE_MINUS_CONSTANT_ALPHA_EXT: + if (g->extensions.EXT_blend_color) + break; /* OK */ +#endif + RT_FALL_THRU(); + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid sfactor passed to glBlendFunc: %d", sfactor); + return; + } + + switch (dfactor) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + break; /* OK */ +#ifdef CR_EXT_blend_color + case GL_CONSTANT_COLOR_EXT: + case GL_ONE_MINUS_CONSTANT_COLOR_EXT: + case GL_CONSTANT_ALPHA_EXT: + case GL_ONE_MINUS_CONSTANT_ALPHA_EXT: + if (g->extensions.EXT_blend_color) + break; /* OK */ +#endif + RT_FALL_THRU(); + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid dfactor passed to glBlendFunc: %d", dfactor); + return; + } + + b->blendSrcRGB = sfactor; + b->blendDstRGB = dfactor; + b->blendSrcA = sfactor; + b->blendDstA = dfactor; + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(bb->blendFunc, g->neg_bitid); +} + +void STATE_APIENTRY crStateBlendColorEXT( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) +{ + CRContext *g = GetCurrentContext(); + CRBufferState *b = &(g->buffer); + CRStateBits *sb = GetCurrentBits(); + CRBufferBits *bb = &(sb->buffer); + + if (g->current.inBeginEnd) + { + crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "BlendColorEXT called inside a Begin/End" ); + return; + } + + b->blendColor.r = red; + b->blendColor.g = green; + b->blendColor.b = blue; + b->blendColor.a = alpha; + DIRTY(bb->blendColor, g->neg_bitid); + DIRTY(bb->dirty, g->neg_bitid); +} + +#ifdef CR_EXT_blend_func_separate +void STATE_APIENTRY crStateBlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA ) +{ + CRContext *g = GetCurrentContext(); + CRBufferState *b = &(g->buffer); + CRStateBits *sb = GetCurrentBits(); + CRBufferBits *bb = &(sb->buffer); + + if (g->current.inBeginEnd) + { + crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "BlendFuncSeparateEXT called inside a Begin/End" ); + return; + } + + FLUSH(); + + switch (sfactorRGB) + { + case GL_ZERO: + case GL_ONE: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_SRC_ALPHA_SATURATE: + break; /* OK */ +#ifdef CR_EXT_blend_color + case GL_CONSTANT_COLOR_EXT: + case GL_ONE_MINUS_CONSTANT_COLOR_EXT: + case GL_CONSTANT_ALPHA_EXT: + case GL_ONE_MINUS_CONSTANT_ALPHA_EXT: + if (g->extensions.EXT_blend_color) + break; /* OK */ +#endif + RT_FALL_THRU(); + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid sfactorRGB passed to glBlendFuncSeparateEXT: %d", sfactorRGB); + return; + } + + switch (sfactorA) + { + case GL_ZERO: + case GL_ONE: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_SRC_ALPHA_SATURATE: + break; /* OK */ +#ifdef CR_EXT_blend_color + case GL_CONSTANT_COLOR_EXT: + case GL_ONE_MINUS_CONSTANT_COLOR_EXT: + case GL_CONSTANT_ALPHA_EXT: + case GL_ONE_MINUS_CONSTANT_ALPHA_EXT: + if (g->extensions.EXT_blend_color) + break; /* OK */ +#endif + RT_FALL_THRU(); + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid sfactorA passed to glBlendFuncSeparateEXT: %d", sfactorA); + return; + } + + switch (dfactorRGB) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_SRC_ALPHA_SATURATE: + break; /* OK */ +#ifdef CR_EXT_blend_color + case GL_CONSTANT_COLOR_EXT: + case GL_ONE_MINUS_CONSTANT_COLOR_EXT: + case GL_CONSTANT_ALPHA_EXT: + case GL_ONE_MINUS_CONSTANT_ALPHA_EXT: + if (g->extensions.EXT_blend_color) + break; /* OK */ +#endif + RT_FALL_THRU(); + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid dfactorRGB passed to glBlendFuncSeparateEXT: %d", dfactorRGB); + return; + } + + switch (dfactorA) + { + case GL_ZERO: + case GL_ONE: + case GL_DST_COLOR: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_SRC_ALPHA_SATURATE: + break; /* OK */ +#ifdef CR_EXT_blend_color + case GL_CONSTANT_COLOR_EXT: + case GL_ONE_MINUS_CONSTANT_COLOR_EXT: + case GL_CONSTANT_ALPHA_EXT: + case GL_ONE_MINUS_CONSTANT_ALPHA_EXT: + if (g->extensions.EXT_blend_color) + break; /* OK */ +#endif + RT_FALL_THRU(); + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid dfactorA passed to glBlendFuncSeparateEXT: %d", dfactorA); + return; + } + + b->blendSrcRGB = sfactorRGB; + b->blendDstRGB = dfactorRGB; + b->blendSrcA = sfactorA; + b->blendDstA = dfactorA; + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(bb->blendFuncSeparate, g->neg_bitid); +} +#endif + +void STATE_APIENTRY crStateBlendEquationEXT( GLenum mode ) +{ + CRContext *g = GetCurrentContext(); + CRBufferState *b = &(g->buffer); + CRStateBits *sb = GetCurrentBits(); + CRBufferBits *bb = &(sb->buffer); + + if( g->current.inBeginEnd ) + { + crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "BlendEquationEXT called inside a Begin/End" ); + return; + } + switch( mode ) + { +#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op) + case GL_FUNC_ADD_EXT: +#ifdef CR_EXT_blend_subtract + case GL_FUNC_SUBTRACT_EXT: + case GL_FUNC_REVERSE_SUBTRACT_EXT: +#endif /* CR_EXT_blend_subtract */ +#ifdef CR_EXT_blend_minmax + case GL_MIN_EXT: + case GL_MAX_EXT: +#endif /* CR_EXT_blend_minmax */ +#ifdef CR_EXT_blend_logic_op + case GL_LOGIC_OP: +#endif /* CR_EXT_blend_logic_op */ + b->blendEquation = mode; + break; +#endif /* defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op) */ + default: + crStateError( __LINE__, __FILE__, GL_INVALID_ENUM, + "BlendEquationEXT: mode called with illegal parameter: 0x%x", (GLenum) mode ); + return; + } + DIRTY(bb->blendEquation, g->neg_bitid); + DIRTY(bb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateLogicOp (GLenum opcode) +{ + CRContext *g = GetCurrentContext(); + CRBufferState *b = &(g->buffer); + CRStateBits *sb = GetCurrentBits(); + CRBufferBits *bb = &(sb->buffer); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glLogicOp called in begin/end"); + return; + } + + FLUSH(); + + switch (opcode) + { + case GL_CLEAR: + case GL_SET: + case GL_COPY: + case GL_COPY_INVERTED: + case GL_NOOP: + case GL_INVERT: + case GL_AND: + case GL_NAND: + case GL_OR: + case GL_NOR: + case GL_XOR: + case GL_EQUIV: + case GL_AND_REVERSE: + case GL_AND_INVERTED: + case GL_OR_REVERSE: + case GL_OR_INVERTED: + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glLogicOp called with bogus opcode: %d", opcode); + return; + } + + b->logicOpMode = opcode; + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(bb->logicOp, g->neg_bitid); + DIRTY(bb->indexLogicOp, g->neg_bitid); +} + +void STATE_APIENTRY crStateDrawBuffer (GLenum mode) +{ + CRContext *g = GetCurrentContext(); + CRBufferState *b = &(g->buffer); + CRStateBits *sb = GetCurrentBits(); + CRBufferBits *bb = &(sb->buffer); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glDrawBuffer called in begin/end"); + return; + } + + FLUSH(); + + switch (mode) + { + case GL_NONE: + break; + case GL_FRONT_LEFT: + case GL_FRONT_RIGHT: + case GL_BACK_LEFT: + case GL_BACK_RIGHT: + case GL_FRONT: + case GL_BACK: + case GL_LEFT: + case GL_RIGHT: + case GL_FRONT_AND_BACK: + case GL_AUX0: + case GL_AUX1: + case GL_AUX2: + case GL_AUX3: + if (g->framebufferobject.drawFB) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glDrawBuffer invalid mode while fbo is active"); + return; + } + break; + default: + if (mode>=GL_COLOR_ATTACHMENT0_EXT && mode<=GL_COLOR_ATTACHMENT15_EXT) + { + if (!g->framebufferobject.drawFB) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glDrawBuffer invalid mode while fbo is inactive"); + return; + } + } + else + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glDrawBuffer called with bogus mode: %d", mode); + return; + } + } + + if (g->framebufferobject.drawFB) + { + g->framebufferobject.drawFB->drawbuffer[0] = mode; + } + else + { + b->drawBuffer = mode; + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(bb->drawBuffer, g->neg_bitid); + } +} + +void STATE_APIENTRY crStateReadBuffer (GLenum mode) +{ + CRContext *g = GetCurrentContext(); + CRBufferState *b = &(g->buffer); + CRStateBits *sb = GetCurrentBits(); + CRBufferBits *bb = &(sb->buffer); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glReadBuffer called in begin/end"); + return; + } + + FLUSH(); + + switch (mode) + { + case GL_NONE: + break; + case GL_FRONT_LEFT: + case GL_FRONT_RIGHT: + case GL_BACK_LEFT: + case GL_BACK_RIGHT: + case GL_FRONT: + case GL_BACK: + case GL_LEFT: + case GL_RIGHT: + case GL_FRONT_AND_BACK: + case GL_AUX0: + case GL_AUX1: + case GL_AUX2: + case GL_AUX3: + if (g->framebufferobject.readFB) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glReadBuffer invalid mode while fbo is active"); + return; + } + break; + default: + if (mode>=GL_COLOR_ATTACHMENT0_EXT && mode<=GL_COLOR_ATTACHMENT15_EXT) + { + if (!g->framebufferobject.readFB) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glReadBuffer invalid mode while fbo is inactive"); + return; + } + else + { + /*@todo, check if fbo binding is complete*/ + } + } + else + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glReadBuffer called with bogus mode: %d", mode); + return; + } + } + + if (g->framebufferobject.readFB) + { + g->framebufferobject.readFB->readbuffer = mode; + } + else + { + b->readBuffer = mode; + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(bb->readBuffer, g->neg_bitid); + } +} + +void STATE_APIENTRY crStateIndexMask (GLuint mask) +{ + CRContext *g = GetCurrentContext(); + CRBufferState *b = &(g->buffer); + CRStateBits *sp = GetCurrentBits(); + CRBufferBits *bb = &(sp->buffer); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glReadBuffer called in begin/end"); + return; + } + + FLUSH(); + + b->indexWriteMask = mask; + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(bb->indexMask, g->neg_bitid); +} + +void STATE_APIENTRY crStateColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) +{ + CRContext *g = GetCurrentContext(); + CRBufferState *b = &(g->buffer); + CRStateBits *sp = GetCurrentBits(); + CRBufferBits *bb = &(sp->buffer); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glReadBuffer called in begin/end"); + return; + } + + FLUSH(); + + b->colorWriteMask.r = red; + b->colorWriteMask.g = green; + b->colorWriteMask.b = blue; + b->colorWriteMask.a = alpha; + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(bb->colorWriteMask, g->neg_bitid); +} + +void STATE_APIENTRY crStateClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + CRContext *g = GetCurrentContext(); + CRBufferState *b = &(g->buffer); + CRStateBits *sp = GetCurrentBits(); + CRBufferBits *bb = &(sp->buffer); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glClearColor called in begin/end"); + return; + } + + FLUSH(); + + if (red < 0.0f) red = 0.0f; + if (red > 1.0f) red = 1.0f; + if (green < 0.0f) green = 0.0f; + if (green > 1.0f) green = 1.0f; + if (blue < 0.0f) blue = 0.0f; + if (blue > 1.0f) blue = 1.0f; + if (alpha < 0.0f) alpha = 0.0f; + if (alpha > 1.0f) alpha = 1.0f; + + b->colorClearValue.r = red; + b->colorClearValue.g = green; + b->colorClearValue.b = blue; + b->colorClearValue.a = alpha; + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(bb->clearColor, g->neg_bitid); +} + +void STATE_APIENTRY crStateClearIndex (GLfloat c) +{ + CRContext *g = GetCurrentContext(); + CRBufferState *b = &(g->buffer); + CRStateBits *sp = GetCurrentBits(); + CRBufferBits *bb = &(sp->buffer); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glClearIndex called in begin/end"); + return; + } + + b->indexClearValue = c; + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(bb->clearIndex, g->neg_bitid); +} + +void STATE_APIENTRY crStateClearDepth (GLclampd depth) +{ + CRContext *g = GetCurrentContext(); + CRBufferState *b = &(g->buffer); + CRStateBits *sp = GetCurrentBits(); + CRBufferBits *bb = &(sp->buffer); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glClearDepth called in begin/end"); + return; + } + + FLUSH(); + + if (depth < 0.0) depth = 0.0; + if (depth > 1.0) depth = 1.0; + + b->depthClearValue = (GLdefault) depth; + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(bb->clearDepth, g->neg_bitid); +} + +void STATE_APIENTRY crStateClearAccum (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + CRContext *g = GetCurrentContext(); + CRBufferState *b = &(g->buffer); + CRStateBits *sp = GetCurrentBits(); + CRBufferBits *bb = &(sp->buffer); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glClearAccum called in begin/end"); + return; + } + + FLUSH(); + + if (red < -1.0f) red = 0.0f; + if (red > 1.0f) red = 1.0f; + if (green < -1.0f) green = 0.0f; + if (green > 1.0f) green = 1.0f; + if (blue < -1.0f) blue = 0.0f; + if (blue > 1.0f) blue = 1.0f; + if (alpha < -1.0f) alpha = 0.0f; + if (alpha > 1.0f) alpha = 1.0f; + + b->accumClearValue.r = red; + b->accumClearValue.g = green; + b->accumClearValue.b = blue; + b->accumClearValue.a = alpha; + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(bb->clearAccum, g->neg_bitid); +} + +void STATE_APIENTRY crStateDepthMask (GLboolean b) +{ + CRContext *g = GetCurrentContext(); + CRBufferState *bs = &(g->buffer); + CRStateBits *sp = GetCurrentBits(); + CRBufferBits *bb = &(sp->buffer); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "DepthMask called in begin/end"); + return; + } + + FLUSH(); + + bs->depthMask = b; + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(bb->depthMask, g->neg_bitid); +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.txt new file mode 100644 index 00000000..768a205b --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.txt @@ -0,0 +1,34 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +#-:enable:*glAble able[2]; +#-:enable:*able[0] = diff_api.Disable; +#-:enable:*able[1] = diff_api.Enable; +#-:enable:*able[to->depthTest](GL_DEPTH_TEST); +#-:enable:*FILLDIRTY(b->enable); +#-:enable:*FILLDIRTY(b->dirty); +#+:enable:depthTest:GL_DEPTH_TEST +:enable:depthTest:GL_DEPTH_TEST +:enable:blend:GL_BLEND +:enable:alphaTest:GL_ALPHA_TEST +:enable:logicOp:GL_COLOR_LOGIC_OP +:enable:indexLogicOp:GL_INDEX_LOGIC_OP +:enable:dither:GL_DITHER +:alphaFunc:alphaTestFunc,alphaTestRef:AlphaFunc +:depthFunc:depthFunc:DepthFunc +:blendFunc:blendSrcRGB,blendDstRGB:BlendFunc +:blendFuncSeparate:blendSrcRGB,blendDstRGB,blendSrcA,blendDstA:BlendFuncSeparateEXT +:logicOp:logicOpMode:LogicOp +:indexLogicOp:logicOpMode:LogicOp +:drawBuffer:drawBuffer:DrawBuffer +:readBuffer:readBuffer:ReadBuffer +:indexMask:indexWriteMask:IndexMask +:colorWriteMask:colorWriteMask|r,g,b,a:ColorMask +:clearColor:colorClearValue|r,g,b,a:ClearColor +:clearIndex:indexClearValue:ClearIndex +:clearDepth:depthClearValue:ClearDepth +:clearAccum:accumClearValue|r,g,b,a:ClearAccum +:depthMask:depthMask:DepthMask +:blendEquation:blendEquation:BlendEquationEXT +:blendColor:blendColor|r,g,b,a:BlendColorEXT diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c new file mode 100644 index 00000000..373b24f8 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c @@ -0,0 +1,1126 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "state.h" +#include "state/cr_statetypes.h" +#include "state/cr_statefuncs.h" +#include "state_internals.h" +#include "cr_mem.h" +#include "cr_string.h" + + +static CRBufferObject *AllocBufferObject(GLuint name) +{ + CRBufferObject *b = crCalloc(sizeof(CRBufferObject)); + if (b) { + b->refCount = 1; + b->id = name; + b->hwid = name; + b->usage = GL_STATIC_DRAW_ARB; + b->access = GL_READ_WRITE_ARB; + b->bResyncOnRead = GL_FALSE; + CR_STATE_SHAREDOBJ_USAGE_INIT(b); + } + return b; +} + +void STATE_APIENTRY crStateGenBuffersARB(GLsizei n, GLuint *buffers) +{ + CRContext *g = GetCurrentContext(); + crStateGenNames(g, g->shared->buffersTable, n, buffers); +} + +void crStateRegBuffers(GLsizei n, GLuint *buffers) +{ + CRContext *g = GetCurrentContext(); + crStateRegNames(g, g->shared->buffersTable, n, buffers); +} + +GLboolean crStateIsBufferBoundForCtx(CRContext *g, GLenum target) +{ + CRBufferObjectState *b = &(g->bufferobject); + + switch (target) + { + case GL_ARRAY_BUFFER_ARB: + return b->arrayBuffer->id!=0; + case GL_ELEMENT_ARRAY_BUFFER_ARB: + return b->elementsBuffer->id!=0; +#ifdef CR_ARB_pixel_buffer_object + case GL_PIXEL_PACK_BUFFER_ARB: + return b->packBuffer->id!=0; + case GL_PIXEL_UNPACK_BUFFER_ARB: + return b->unpackBuffer->id!=0; +#endif + default: + return GL_FALSE; + } +} + +GLboolean crStateIsBufferBound(GLenum target) +{ + CRContext *g = GetCurrentContext(); + return crStateIsBufferBoundForCtx(g, target); +} + +CRBufferObject *crStateGetBoundBufferObject(GLenum target, CRBufferObjectState *b) +{ + switch (target) + { + case GL_ARRAY_BUFFER_ARB: + return b->arrayBuffer; + case GL_ELEMENT_ARRAY_BUFFER_ARB: + return b->elementsBuffer; +#ifdef CR_ARB_pixel_buffer_object + case GL_PIXEL_PACK_BUFFER_ARB: + return b->packBuffer; + case GL_PIXEL_UNPACK_BUFFER_ARB: + return b->unpackBuffer; +#endif + default: + return NULL; + } +} + +DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsBufferARB( GLuint buffer ) +{ + CRContext *g = GetCurrentContext(); + + FLUSH(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glIsBufferARB called in begin/end"); + return GL_FALSE; + } + + return buffer ? crHashtableIsKeyUsed(g->shared->buffersTable, buffer) : GL_FALSE; +} + +void crStateBufferObjectInit (CRContext *ctx) +{ + CRStateBits *sb = GetCurrentBits(); + CRBufferObjectBits *bb = &sb->bufferobject; + CRBufferObjectState *b = &ctx->bufferobject; + + RESET(bb->dirty, ctx->bitid); + RESET(bb->arrayBinding, ctx->bitid); + RESET(bb->elementsBinding, ctx->bitid); +#ifdef CR_ARB_pixel_buffer_object + RESET(bb->unpackBinding, ctx->bitid); + RESET(bb->packBinding, ctx->bitid); +#endif + +#ifdef IN_GUEST + b->retainBufferData = GL_TRUE; +#else + b->retainBufferData = GL_FALSE; +#endif + + b->nullBuffer = AllocBufferObject(0); + b->arrayBuffer = b->nullBuffer; + b->elementsBuffer = b->nullBuffer; + b->nullBuffer->refCount += 2; +#ifdef CR_ARB_pixel_buffer_object + b->packBuffer = b->nullBuffer; + b->unpackBuffer = b->nullBuffer; + b->nullBuffer->refCount += 2; +#endif + + ctx->shared->bVBOResyncNeeded = GL_FALSE; +} + +void crStateFreeBufferObject(void *data) +{ + CRBufferObject *pObj = (CRBufferObject *)data; + if (pObj->data) crFree(pObj->data); + +#ifndef IN_GUEST + if (diff_api.DeleteBuffersARB) + { + diff_api.DeleteBuffersARB(1, &pObj->hwid); + } +#endif + + crFree(pObj); +} + +void crStateBufferObjectDestroy (CRContext *ctx) +{ + CRBufferObjectState *b = &ctx->bufferobject; + crFree(b->nullBuffer); +} + +static void crStateCheckBufferHWIDCB(unsigned long key, void *data1, void *data2) +{ + CRBufferObject *pObj = (CRBufferObject *) data1; + crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2; + (void) key; + + if (pObj->hwid==pParms->hwid) + pParms->id = pObj->id; +} + +DECLEXPORT(GLuint) STATE_APIENTRY crStateBufferHWIDtoID(GLuint hwid) +{ + CRContext *g = GetCurrentContext(); + crCheckIDHWID_t parms; + + parms.id = hwid; + parms.hwid = hwid; + + crHashtableWalk(g->shared->buffersTable, crStateCheckBufferHWIDCB, &parms); + return parms.id; +} + +DECLEXPORT(GLuint) STATE_APIENTRY crStateGetBufferHWID(GLuint id) +{ + CRContext *g = GetCurrentContext(); + CRBufferObject *pObj = (CRBufferObject *) crHashtableSearch(g->shared->buffersTable, id); + + return pObj ? pObj->hwid : 0; +} + +void STATE_APIENTRY +crStateBindBufferARB (GLenum target, GLuint buffer) +{ + CRContext *g = GetCurrentContext(); + CRBufferObjectState *b = &(g->bufferobject); + CRStateBits *sb = GetCurrentBits(); + CRBufferObjectBits *bb = &(sb->bufferobject); + CRBufferObject *oldObj, *newObj; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glBindBufferARB called in begin/end"); + return; + } + + FLUSH(); + + oldObj = crStateGetBoundBufferObject(target, b); + if (!oldObj) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glBindBufferARB(target)"); + return; + } + + if (buffer == 0) { + newObj = b->nullBuffer; + } + else { + newObj = (CRBufferObject *) crHashtableSearch(g->shared->buffersTable, buffer); + if (!newObj) { + CRSTATE_CHECKERR(!crHashtableIsKeyUsed(g->shared->buffersTable, buffer), GL_INVALID_OPERATION, "name is not a buffer object"); + newObj = AllocBufferObject(buffer); + CRSTATE_CHECKERR(!newObj, GL_OUT_OF_MEMORY, "glBindBuffer"); +#ifndef IN_GUEST + diff_api.GenBuffersARB(1, &newObj->hwid); + if (!newObj->hwid) + { + crWarning("GenBuffersARB failed!"); + crFree(newObj); + return; + } +#endif + crHashtableAdd( g->shared->buffersTable, buffer, newObj ); + } + + CR_STATE_SHAREDOBJ_USAGE_SET(newObj, g); + } + + newObj->refCount++; + oldObj->refCount--; + + switch (target) + { + case GL_ARRAY_BUFFER_ARB: + b->arrayBuffer = newObj; + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(bb->arrayBinding, g->neg_bitid); + break; + case GL_ELEMENT_ARRAY_BUFFER_ARB: + b->elementsBuffer = newObj; + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(bb->elementsBinding, g->neg_bitid); + break; +#ifdef CR_ARB_pixel_buffer_object + case GL_PIXEL_PACK_BUFFER_ARB: + b->packBuffer = newObj; + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(bb->packBinding, g->neg_bitid); + break; + case GL_PIXEL_UNPACK_BUFFER_ARB: + b->unpackBuffer = newObj; + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(bb->unpackBinding, g->neg_bitid); + break; +#endif + default: /*can't get here*/ + CRASSERT(false); + return; + } + + if (oldObj->refCount <= 0) { + /*we shouldn't reach this point*/ + CRASSERT(false); + crHashtableDelete(g->shared->buffersTable, (unsigned long) oldObj->id, crStateFreeBufferObject); + } + +#ifdef IN_GUEST + if (target == GL_PIXEL_PACK_BUFFER_ARB) + { + newObj->bResyncOnRead = GL_TRUE; + } +#endif +} + +static void ctStateBuffersRefsCleanup(CRContext *ctx, CRBufferObject *obj, CRbitvalue *neg_bitid) +{ + CRBufferObjectState *b = &(ctx->bufferobject); + CRStateBits *sb = GetCurrentBits(); + CRBufferObjectBits *bb = &(sb->bufferobject); + int j, k; + + if (obj == b->arrayBuffer) + { + b->arrayBuffer = b->nullBuffer; + b->arrayBuffer->refCount++; + DIRTY(bb->dirty, neg_bitid); + DIRTY(bb->arrayBinding, neg_bitid); + } + if (obj == b->elementsBuffer) + { + b->elementsBuffer = b->nullBuffer; + b->elementsBuffer->refCount++; + DIRTY(bb->dirty, neg_bitid); + DIRTY(bb->elementsBinding, neg_bitid); + } +#ifdef CR_ARB_pixel_buffer_object + if (obj == b->packBuffer) + { + b->packBuffer = b->nullBuffer; + b->packBuffer->refCount++; + DIRTY(bb->dirty, neg_bitid); + DIRTY(bb->packBinding, neg_bitid); + } + if (obj == b->unpackBuffer) + { + b->unpackBuffer = b->nullBuffer; + b->unpackBuffer->refCount++; + DIRTY(bb->dirty, neg_bitid); + DIRTY(bb->unpackBinding, neg_bitid); + } +#endif + +#ifdef CR_ARB_vertex_buffer_object + for (j=0; j<CRSTATECLIENT_MAX_VERTEXARRAYS; ++j) + { + CRClientPointer *cp = crStateGetClientPointerByIndex(j, &ctx->client.array); + if (obj == cp->buffer) + { + cp->buffer = b->nullBuffer; + ++b->nullBuffer->refCount; + } + } + + for (k=0; k<ctx->client.vertexArrayStackDepth; ++k) + { + CRVertexArrays *pArray = &ctx->client.vertexArrayStack[k]; + for (j=0; j<CRSTATECLIENT_MAX_VERTEXARRAYS; ++j) + { + CRClientPointer *cp = crStateGetClientPointerByIndex(j, pArray); + if (obj == cp->buffer) + { + cp->buffer = b->nullBuffer; + ++b->nullBuffer->refCount; + } + } + } +#endif + + CR_STATE_SHAREDOBJ_USAGE_CLEAR(obj, ctx); +} + +void STATE_APIENTRY +crStateDeleteBuffersARB(GLsizei n, const GLuint *buffers) +{ + CRContext *g = GetCurrentContext(); + int i; + + FLUSH(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glDeleteBuffersARB called in Begin/End"); + return; + } + + if (n < 0) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glDeleteBuffersARB(n < 0)"); + return; + } + + for (i = 0; i < n; i++) { + if (buffers[i]) { + CRBufferObject *obj = (CRBufferObject *) + crHashtableSearch(g->shared->buffersTable, buffers[i]); + if (obj) { + int j; + + ctStateBuffersRefsCleanup(g, obj, g->neg_bitid); + + CR_STATE_SHAREDOBJ_USAGE_FOREACH_USED_IDX(obj, j) + { + /* saved state version <= SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS does not have usage bits info, + * so on restore, we set mark bits as used. + * This is why g_pAvailableContexts[j] could be NULL + * also g_pAvailableContexts[0] will hold default context, which we should discard */ + CRContext *ctx = g_pAvailableContexts[j]; + if (j && ctx) + { + ctStateBuffersRefsCleanup(ctx, obj, g->neg_bitid); /* <- yes, use g->neg_bitid, i.e. neg_bitid of the current context to ensure others bits get dirtified, + * but not the current context ones*/ + } + else + CR_STATE_SHAREDOBJ_USAGE_CLEAR_IDX(obj, j); + } + + crHashtableDelete(g->shared->buffersTable, buffers[i], crStateFreeBufferObject); + } + } + } +} + +void STATE_APIENTRY +crStateBufferDataARB(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage) +{ + CRContext *g = GetCurrentContext(); + CRBufferObjectState *b = &g->bufferobject; + CRBufferObject *obj; + CRStateBits *sb = GetCurrentBits(); + CRBufferObjectBits *bb = &sb->bufferobject; + + FLUSH(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glBufferDataARB called in begin/end"); + return; + } + + if (size < 0) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glBufferDataARB(size < 0)"); + return; + } + + switch (usage) { + case GL_STREAM_DRAW_ARB: + case GL_STREAM_READ_ARB: + case GL_STREAM_COPY_ARB: + case GL_STATIC_DRAW_ARB: + case GL_STATIC_READ_ARB: + case GL_STATIC_COPY_ARB: + case GL_DYNAMIC_DRAW_ARB: + case GL_DYNAMIC_READ_ARB: + case GL_DYNAMIC_COPY_ARB: + /* OK */ + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glBufferDataARB(usage)"); + return; + } + + obj = crStateGetBoundBufferObject(target, b); + if (!obj) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glBufferDataARB(target)"); + return; + } + + if (obj->id == 0) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glBufferDataARB"); + return; + } + + if (obj->pointer) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glBufferDataARB(buffer is mapped)"); + return; + } + + obj->usage = usage; + obj->size = size; + + /* The user of the state tracker should set the retainBufferData field + * during context initialization, if needed. + */ + if (b->retainBufferData) { + if (obj->data) { + crFree(obj->data); + } + + obj->data = crAlloc(size); + if (!obj->data) { + crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glBufferDataARB"); + return; + } + if (data) + crMemcpy(obj->data, data, size); + } + + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(obj->dirty, g->neg_bitid); + obj->dirtyStart = 0; + obj->dirtyLength = size; +} + + +void STATE_APIENTRY +crStateBufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data) +{ + CRContext *g = GetCurrentContext(); + CRBufferObjectState *b = &g->bufferobject; + CRBufferObject *obj; + CRStateBits *sb = GetCurrentBits(); + CRBufferObjectBits *bb = &sb->bufferobject; + + FLUSH(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glBufferSubDataARB called in begin/end"); + return; + } + + obj = crStateGetBoundBufferObject(target, b); + if (!obj) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glBufferSubDataARB(target)"); + return; + } + + if (obj->id == 0) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glBufferSubDataARB"); + return; + } + + if (obj->pointer) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glBufferSubDataARB(buffer is mapped)"); + return; + } + + if (size < 0 || offset < 0 || (unsigned int)offset + size > obj->size) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glBufferSubDataARB(bad offset and/or size)"); + return; + } + + if (b->retainBufferData && obj->data) { + crMemcpy((char *) obj->data + offset, data, size); + } + + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(obj->dirty, g->neg_bitid); + /* grow dirty region */ + if (offset + size > obj->dirtyStart + obj->dirtyLength) + obj->dirtyLength = offset + size; + if (offset < obj->dirtyStart) + obj->dirtyStart = offset; +} + + +void STATE_APIENTRY +crStateGetBufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, void * data) +{ + CRContext *g = GetCurrentContext(); + CRBufferObjectState *b = &g->bufferobject; + CRBufferObject *obj; + + FLUSH(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetBufferSubDataARB called in begin/end"); + return; + } + + obj = crStateGetBoundBufferObject(target, b); + if (!obj) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetBufferSubDataARB(target)"); + return; + } + + if (obj->id == 0) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetBufferSubDataARB"); + return; + } + + if (obj->pointer) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetBufferSubDataARB(buffer is mapped)"); + return; + } + + if (size < 0 || offset < 0 || (unsigned int)offset + size > obj->size) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetBufferSubDataARB(bad offset and/or size)"); + return; + } + + if (b->retainBufferData && obj->data) { + crMemcpy(data, (char *) obj->data + offset, size); + } +} + + +void * STATE_APIENTRY +crStateMapBufferARB(GLenum target, GLenum access) +{ + CRContext *g = GetCurrentContext(); + CRBufferObjectState *b = &g->bufferobject; + CRBufferObject *obj; + + FLUSH(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glMapBufferARB called in begin/end"); + return NULL; + } + + obj = crStateGetBoundBufferObject(target, b); + if (!obj) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMapBufferARB(target)"); + return NULL; + } + + if (obj->id == 0) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glMapBufferARB"); + return GL_FALSE; + } + + switch (access) { + case GL_READ_ONLY_ARB: + case GL_WRITE_ONLY_ARB: + case GL_READ_WRITE_ARB: + obj->access = access; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glMapBufferARB(access)"); + return NULL; + } + + if (b->retainBufferData && obj->data) + obj->pointer = obj->data; + + return obj->pointer; +} + + +GLboolean STATE_APIENTRY +crStateUnmapBufferARB(GLenum target) +{ + CRContext *g = GetCurrentContext(); + CRBufferObjectState *b = &g->bufferobject; + CRBufferObject *obj; + CRStateBits *sb = GetCurrentBits(); + CRBufferObjectBits *bb = &sb->bufferobject; + + FLUSH(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glUnmapBufferARB called in begin/end"); + return GL_FALSE; + } + + obj = crStateGetBoundBufferObject(target, b); + if (!obj) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glUnmapBufferARB(target)"); + return GL_FALSE; + } + + if (obj->id == 0) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glUnmapBufferARB"); + return GL_FALSE; + } + + if (!obj->pointer) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glUnmapBufferARB"); + return GL_FALSE; + } + + obj->pointer = NULL; + + if (obj->access != GL_READ_ONLY_ARB) { + /* the data was most likely modified */ + DIRTY(bb->dirty, g->neg_bitid); + DIRTY(obj->dirty, g->neg_bitid); + obj->dirtyStart = 0; + obj->dirtyLength = obj->size; + } + + return GL_TRUE; +} + + +void STATE_APIENTRY +crStateGetBufferParameterivARB(GLenum target, GLenum pname, GLint *params) +{ + CRContext *g = GetCurrentContext(); + CRBufferObjectState *b = &g->bufferobject; + CRBufferObject *obj; + + FLUSH(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetBufferParameterivARB called in begin/end"); + return; + } + + obj = crStateGetBoundBufferObject(target, b); + if (!obj) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetBufferParameterivARB(target)"); + return; + } + + switch (pname) { + case GL_BUFFER_SIZE_ARB: + *params = obj->size; + break; + case GL_BUFFER_USAGE_ARB: + *params = obj->usage; + break; + case GL_BUFFER_ACCESS_ARB: + *params = obj->access; + break; + case GL_BUFFER_MAPPED_ARB: + *params = (obj->pointer != NULL); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetBufferParameterivARB(pname)"); + return; + } +} + + +void STATE_APIENTRY +crStateGetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params) +{ + CRContext *g = GetCurrentContext(); + CRBufferObjectState *b = &g->bufferobject; + CRBufferObject *obj; + + FLUSH(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetBufferPointervARB called in begin/end"); + return; + } + + obj = crStateGetBoundBufferObject(target, b); + if (!obj) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetBufferPointervARB(target)"); + return; + } + + if (pname != GL_BUFFER_MAP_POINTER_ARB) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetBufferPointervARB(pname)"); + return; + } + + *params = obj->pointer; +} + + +/** + * We need to check if the GL_EXT_vertex/pixel_buffer_object extensions + * are supported before calling any of the diff_api functions. + * This flag indicates if the extensions is available (1), not available (0) + * or needs to be tested for (-1). + * If we don't do this, we can segfault inside OpenGL. + * Ideally, the render SPU should no-op unsupported GL functions, but + * that's a bit complicated. + */ +static GLboolean +HaveBufferObjectExtension(void) +{ + static GLint haveBufferObjectExt = -1; + + if (haveBufferObjectExt == -1) { + const char *ext; + /* XXX this check is temporary. We need to make the tilesort SPU plug + * GetString into the diff'ing table in order for this to really work. + */ + if (!diff_api.GetString) { + haveBufferObjectExt = 0; + return 0; + } + CRASSERT(diff_api.GetString); + ext = (const char *) diff_api.GetString(GL_EXTENSIONS); + if (crStrstr(ext, "GL_ARB_vertex_buffer_object") || + crStrstr(ext, "GL_ARB_pixel_buffer_object")) { + haveBufferObjectExt = 1; + } + else { + haveBufferObjectExt = 0; + } + } + return haveBufferObjectExt; +} + +static void crStateBufferObjectIntCmp(CRBufferObjectBits *bb, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx, + GLboolean bSwitch) +{ + CRBufferObjectState *from = &(fromCtx->bufferobject); + const CRBufferObjectState *to = &(toCtx->bufferobject); + + /* ARRAY_BUFFER */ + if (CHECKDIRTY(bb->arrayBinding, bitID)) + { + if (from->arrayBuffer != to->arrayBuffer) + { + GLuint bufferID = to->arrayBuffer ? to->arrayBuffer->hwid : 0; + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, bufferID); + if (bSwitch) + { + FILLDIRTY(bb->arrayBinding); + FILLDIRTY(bb->dirty); + } + else + { + CLEARDIRTY2(bb->arrayBinding, bitID); + from->arrayBuffer = to->arrayBuffer; + } + } + if (bSwitch) CLEARDIRTY2(bb->arrayBinding, bitID); + } + + if (to->arrayBuffer && CHECKDIRTY(to->arrayBuffer->dirty, bitID)) + { + /* update array buffer data */ + CRBufferObject *bufObj = to->arrayBuffer; + CRASSERT(bufObj); + if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size) + { + /* update whole buffer */ + diff_api.BufferDataARB(GL_ARRAY_BUFFER_ARB, bufObj->size, + bufObj->data, bufObj->usage); + } + else + { + /* update sub buffer */ + diff_api.BufferSubDataARB(GL_ARRAY_BUFFER_ARB, + bufObj->dirtyStart, bufObj->dirtyLength, + (char *) bufObj->data + bufObj->dirtyStart); + } + if (bSwitch) FILLDIRTY(bufObj->dirty); + CLEARDIRTY2(bufObj->dirty, bitID); + } + + /* ELEMENTS_BUFFER */ + if (CHECKDIRTY(bb->elementsBinding, bitID)) + { + if (from->elementsBuffer != to->elementsBuffer) + { + GLuint bufferID = to->elementsBuffer ? to->elementsBuffer->hwid : 0; + diff_api.BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferID); + if (bSwitch) + { + FILLDIRTY(bb->elementsBinding); + FILLDIRTY(bb->dirty); + } + else + { + CLEARDIRTY2(bb->elementsBinding, bitID); + from->elementsBuffer = to->elementsBuffer; + } + } + if (bSwitch) CLEARDIRTY2(bb->elementsBinding, bitID); + } + + if (to->elementsBuffer && CHECKDIRTY(to->elementsBuffer->dirty, bitID)) + { + /* update array buffer data */ + CRBufferObject *bufObj = to->elementsBuffer; + CRASSERT(bufObj); + if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size) + { + /* update whole buffer */ + diff_api.BufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufObj->size, + bufObj->data, bufObj->usage); + } + else + { + /* update sub buffer */ + diff_api.BufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, + bufObj->dirtyStart, bufObj->dirtyLength, + (char *) bufObj->data + bufObj->dirtyStart); + } + if (bSwitch) FILLDIRTY(bufObj->dirty); + CLEARDIRTY2(bufObj->dirty, bitID); + } + +#ifdef CR_ARB_pixel_buffer_object + /* PIXEL_PACK_BUFFER */ + if (CHECKDIRTY(bb->packBinding, bitID)) + { + if (from->packBuffer != to->packBuffer) + { + GLuint bufferID = to->packBuffer ? to->packBuffer->hwid : 0; + diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, bufferID); + if (bSwitch) + { + FILLDIRTY(bb->packBinding); + FILLDIRTY(bb->dirty); + } + else + { + CLEARDIRTY2(bb->packBinding, bitID); + from->packBuffer = to->packBuffer; + } + } + if (bSwitch) CLEARDIRTY2(bb->packBinding, bitID); + } + + if (to->packBuffer && CHECKDIRTY(to->packBuffer->dirty, bitID)) + { + /* update array buffer data */ + CRBufferObject *bufObj = to->packBuffer; + CRASSERT(bufObj); + if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size) + { + /* update whole buffer */ + diff_api.BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, bufObj->size, + bufObj->data, bufObj->usage); + } + else + { + /* update sub buffer */ + diff_api.BufferSubDataARB(GL_PIXEL_PACK_BUFFER_ARB, + bufObj->dirtyStart, bufObj->dirtyLength, + (char *) bufObj->data + bufObj->dirtyStart); + } + if (bSwitch) FILLDIRTY(bufObj->dirty); + CLEARDIRTY2(bufObj->dirty, bitID); + } + + /* PIXEL_UNPACK_BUFFER */ + if (CHECKDIRTY(bb->unpackBinding, bitID)) + { + if (from->unpackBuffer != to->unpackBuffer) + { + GLuint bufferID = to->unpackBuffer ? to->unpackBuffer->hwid : 0; + diff_api.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, bufferID); + if (bSwitch) + { + FILLDIRTY(bb->unpackBinding); + FILLDIRTY(bb->dirty); + } + else + { + CLEARDIRTY2(bb->unpackBinding, bitID); + from->unpackBuffer = to->unpackBuffer; + } + } + if (bSwitch) CLEARDIRTY2(bb->unpackBinding, bitID); + } + + if (to->unpackBuffer && CHECKDIRTY(to->unpackBuffer->dirty, bitID)) + { + /* update array buffer data */ + CRBufferObject *bufObj = to->unpackBuffer; + CRASSERT(bufObj); + if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size) + { + /* update whole buffer */ + diff_api.BufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, bufObj->size, + bufObj->data, bufObj->usage); + } + else + { + /* update sub buffer */ + diff_api.BufferSubDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, + bufObj->dirtyStart, bufObj->dirtyLength, + (char *) bufObj->data + bufObj->dirtyStart); + } + if (bSwitch) FILLDIRTY(bufObj->dirty); + CLEARDIRTY2(bufObj->dirty, bitID); + } +#endif /*ifdef CR_ARB_pixel_buffer_object*/ +} + +void crStateBufferObjectDiff(CRBufferObjectBits *bb, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + /*CRBufferObjectState *from = &(fromCtx->bufferobject); - unused + const CRBufferObjectState *to = &(toCtx->bufferobject); - unused */ + + if (!HaveBufferObjectExtension()) + return; + + crStateBufferObjectIntCmp(bb, bitID, fromCtx, toCtx, GL_FALSE); +} + +static void crStateBufferObjectSyncCB(unsigned long key, void *data1, void *data2) +{ + CRBufferObject *pBufferObj = (CRBufferObject *) data1; + CRBufferObjectState *pState = (CRBufferObjectState *) data2; + (void)key; + + if (pBufferObj->id && !pBufferObj->hwid) + { + diff_api.GenBuffersARB(1, &pBufferObj->hwid); + CRASSERT(pBufferObj->hwid); + } + + if (pBufferObj->data) + { + /** @todo http://www.opengl.org/registry/specs/ARB/pixel_buffer_object.txt + "While it is entirely legal to create a buffer object by binding + it to GL_ARRAY_BUFFER and loading it with data, then using it + with the GL_PIXEL_UNPACK_BUFFER_ARB or GL_PIXEL_PACK_BUFFER_ARB + binding, such behavior is liable to confuse the driver and may + hurt performance." + */ + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, pBufferObj->hwid); + diff_api.BufferDataARB(GL_ARRAY_BUFFER_ARB, pBufferObj->size, pBufferObj->data, pBufferObj->usage); + + if (!pState->retainBufferData) + { + crFree(pBufferObj->data); + pBufferObj->data = NULL; + } + } +} + +/* + * XXX this function might need some testing/fixing. + */ +void crStateBufferObjectSwitch(CRBufferObjectBits *bb, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + /*const CRBufferObjectState *from = &(fromCtx->bufferobject); - unused */ + CRBufferObjectState *to = &(toCtx->bufferobject); + int i; + + if (!HaveBufferObjectExtension()) + return; + + if (toCtx->shared->bVBOResyncNeeded) + { + CRClientPointer *cp; + GLboolean locked = toCtx->client.array.locked; + + crHashtableWalk(toCtx->shared->buffersTable, crStateBufferObjectSyncCB, to); + toCtx->shared->bVBOResyncNeeded = GL_FALSE; + + /*@todo, move to state_client.c*/ + cp = &toCtx->client.array.v; + if (cp->buffer && (cp->buffer->id || locked)) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid); + diff_api.VertexPointer(cp->size, cp->type, cp->stride, cp->p); + } + + cp = &toCtx->client.array.c; + if (cp->buffer && (cp->buffer->id || locked)) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid); + diff_api.ColorPointer(cp->size, cp->type, cp->stride, cp->p); + } + + cp = &toCtx->client.array.f; + if (cp->buffer && (cp->buffer->id || locked)) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid); + diff_api.FogCoordPointerEXT(cp->type, cp->stride, cp->p); + } + + cp = &toCtx->client.array.s; + if (cp->buffer && (cp->buffer->id || locked)) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid); + diff_api.SecondaryColorPointerEXT(cp->size, cp->type, cp->stride, cp->p); + } + + cp = &toCtx->client.array.e; + if (cp->buffer && (cp->buffer->id || locked)) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid); + diff_api.EdgeFlagPointer(cp->stride, cp->p); + } + + cp = &toCtx->client.array.i; + if (cp->buffer && (cp->buffer->id || locked)) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid); + diff_api.IndexPointer(cp->type, cp->stride, cp->p); + } + + cp = &toCtx->client.array.n; + if (cp->buffer && (cp->buffer->id || locked)) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid); + diff_api.NormalPointer(cp->type, cp->stride, cp->p); + } + + for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) + { + cp = &toCtx->client.array.t[i]; + if (cp->buffer && (cp->buffer->id || locked)) + { + if (diff_api.ActiveTextureARB) + diff_api.ActiveTextureARB(i+GL_TEXTURE0_ARB); + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid); + diff_api.TexCoordPointer(cp->size, cp->type, cp->stride, cp->p); + } + } + + if (diff_api.ActiveTextureARB) + diff_api.ActiveTextureARB(toCtx->client.curClientTextureUnit+GL_TEXTURE0_ARB); + +#ifdef CR_NV_vertex_program + for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++) + { + cp = &toCtx->client.array.a[i]; + if (cp->buffer && (cp->buffer->id || locked)) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, cp->buffer->hwid); + diff_api.VertexAttribPointerARB(i, cp->size, cp->type, cp->normalized, cp->stride, cp->p); + } + } +#endif + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, to->arrayBuffer->hwid); + diff_api.BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, to->elementsBuffer->hwid); +#ifdef CR_ARB_pixel_buffer_object + diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, to->packBuffer->hwid); + diff_api.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, to->unpackBuffer->hwid); +#endif + } + else + { + crStateBufferObjectIntCmp(bb, bitID, fromCtx, toCtx, GL_TRUE); + } +} + diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_client.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_client.c new file mode 100644 index 00000000..6ca6e159 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_client.c @@ -0,0 +1,2433 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +/* + * This file manages all the client-side state including: + * Pixel pack/unpack parameters + * Vertex arrays + */ + + +#include "cr_mem.h" +#include "state.h" +#include "state/cr_statetypes.h" +#include "state/cr_statefuncs.h" +#include "state_internals.h" + +const CRPixelPackState crStateNativePixelPacking = { + 0, /* rowLength */ + 0, /* skipRows */ + 0, /* skipPixels */ + 1, /* alignment */ + 0, /* imageHeight */ + 0, /* skipImages */ + GL_FALSE, /* swapBytes */ + GL_FALSE, /* psLSBFirst */ +}; + + +void crStateClientInitBits (CRClientBits *c) +{ + int i; + + /* XXX why GLCLIENT_BIT_ALLOC? */ + c->v = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + c->n = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + c->c = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + c->s = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + c->i = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + for ( i = 0; i < CR_MAX_TEXTURE_UNITS; i++ ) + c->t[i] = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + c->e = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + c->f = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + +#ifdef CR_NV_vertex_program + for ( i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++ ) + c->a[i] = (CRbitvalue *) crCalloc(GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); +#endif +} + +void crStateClientDestroyBits (CRClientBits *c) +{ + int i; + + crFree(c->v); + crFree(c->n); + crFree(c->c); + crFree(c->s); + crFree(c->i); + + for ( i = 0; i < CR_MAX_TEXTURE_UNITS; i++ ) + crFree(c->t[i]); + + crFree(c->e); + crFree(c->f); + +#ifdef CR_NV_vertex_program + for ( i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++ ) + crFree(c->a[i]); +#endif +} + +static void crStateUnlockClientPointer(CRClientPointer* cp) +{ + if (cp->locked) + { +#ifndef IN_GUEST + if (cp->p) crFree(cp->p); +#endif + cp->locked = GL_FALSE; + } +} + +void crStateClientDestroy(CRContext *g) +{ + CRClientState *c = &(g->client); +#ifdef CR_EXT_compiled_vertex_array + if (c->array.locked) + { + unsigned int i; + + crStateUnlockClientPointer(&c->array.v); + crStateUnlockClientPointer(&c->array.c); + crStateUnlockClientPointer(&c->array.f); + crStateUnlockClientPointer(&c->array.s); + crStateUnlockClientPointer(&c->array.e); + crStateUnlockClientPointer(&c->array.i); + crStateUnlockClientPointer(&c->array.n); + for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++) + { + crStateUnlockClientPointer(&c->array.t[i]); + } + for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++) + { + crStateUnlockClientPointer(&c->array.a[i]); + } + } +#endif +} + +void crStateClientInit(CRContext *ctx) +{ + CRClientState *c = &(ctx->client); + unsigned int i; + + /* pixel pack/unpack */ + c->unpack.rowLength = 0; + c->unpack.skipRows = 0; + c->unpack.skipPixels = 0; + c->unpack.skipImages = 0; + c->unpack.alignment = 4; + c->unpack.imageHeight = 0; + c->unpack.swapBytes = GL_FALSE; + c->unpack.psLSBFirst = GL_FALSE; + c->pack.rowLength = 0; + c->pack.skipRows = 0; + c->pack.skipPixels = 0; + c->pack.skipImages = 0; + c->pack.alignment = 4; + c->pack.imageHeight = 0; + c->pack.swapBytes = GL_FALSE; + c->pack.psLSBFirst = GL_FALSE; + + /* ARB multitexture */ + c->curClientTextureUnit = 0; + +#ifdef CR_EXT_compiled_vertex_array + c->array.lockFirst = 0; + c->array.lockCount = 0; + c->array.locked = GL_FALSE; +# ifdef IN_GUEST + c->array.synced = GL_FALSE; +# endif +#endif + + /* vertex array */ + c->array.v.p = NULL; + c->array.v.size = 4; + c->array.v.type = GL_FLOAT; + c->array.v.stride = 0; + c->array.v.enabled = 0; +#ifdef CR_ARB_vertex_buffer_object + c->array.v.buffer = ctx->bufferobject.arrayBuffer; + if (c->array.v.buffer) + ++c->array.v.buffer->refCount; +#endif +#ifdef CR_EXT_compiled_vertex_array + c->array.v.locked = GL_FALSE; + c->array.v.prevPtr = NULL; + c->array.v.prevStride = 0; +#endif + + /* color array */ + c->array.c.p = NULL; + c->array.c.size = 4; + c->array.c.type = GL_FLOAT; + c->array.c.stride = 0; + c->array.c.enabled = 0; +#ifdef CR_ARB_vertex_buffer_object + c->array.c.buffer = ctx->bufferobject.arrayBuffer; + if (c->array.c.buffer) + ++c->array.c.buffer->refCount; +#endif +#ifdef CR_EXT_compiled_vertex_array + c->array.c.locked = GL_FALSE; + c->array.c.prevPtr = NULL; + c->array.c.prevStride = 0; +#endif + + /* fog array */ + c->array.f.p = NULL; + c->array.f.size = 0; + c->array.f.type = GL_FLOAT; + c->array.f.stride = 0; + c->array.f.enabled = 0; +#ifdef CR_ARB_vertex_buffer_object + c->array.f.buffer = ctx->bufferobject.arrayBuffer; + if (c->array.f.buffer) + ++c->array.f.buffer->refCount; +#endif +#ifdef CR_EXT_compiled_vertex_array + c->array.f.locked = GL_FALSE; + c->array.f.prevPtr = NULL; + c->array.f.prevStride = 0; +#endif + + /* secondary color array */ + c->array.s.p = NULL; + c->array.s.size = 3; + c->array.s.type = GL_FLOAT; + c->array.s.stride = 0; + c->array.s.enabled = 0; +#ifdef CR_ARB_vertex_buffer_object + c->array.s.buffer = ctx->bufferobject.arrayBuffer; + if (c->array.s.buffer) + ++c->array.s.buffer->refCount; +#endif +#ifdef CR_EXT_compiled_vertex_array + c->array.s.locked = GL_FALSE; + c->array.s.prevPtr = NULL; + c->array.s.prevStride = 0; +#endif + + /* edge flag array */ + c->array.e.p = NULL; + c->array.e.size = 0; + c->array.e.type = GL_FLOAT; + c->array.e.stride = 0; + c->array.e.enabled = 0; +#ifdef CR_ARB_vertex_buffer_object + c->array.e.buffer = ctx->bufferobject.arrayBuffer; + if (c->array.e.buffer) + ++c->array.e.buffer->refCount; +#endif +#ifdef CR_EXT_compiled_vertex_array + c->array.e.locked = GL_FALSE; + c->array.e.prevPtr = NULL; + c->array.e.prevStride = 0; +#endif + + /* color index array */ + c->array.i.p = NULL; + c->array.i.size = 0; + c->array.i.type = GL_FLOAT; + c->array.i.stride = 0; + c->array.i.enabled = 0; +#ifdef CR_ARB_vertex_buffer_object + c->array.i.buffer = ctx->bufferobject.arrayBuffer; + if (c->array.i.buffer) + ++c->array.i.buffer->refCount; +#endif +#ifdef CR_EXT_compiled_vertex_array + c->array.i.locked = GL_FALSE; + c->array.i.prevPtr = NULL; + c->array.i.prevStride = 0; +#endif + + /* normal array */ + c->array.n.p = NULL; + c->array.n.size = 4; + c->array.n.type = GL_FLOAT; + c->array.n.stride = 0; + c->array.n.enabled = 0; +#ifdef CR_ARB_vertex_buffer_object + c->array.n.buffer = ctx->bufferobject.arrayBuffer; + if (c->array.n.buffer) + ++c->array.n.buffer->refCount; +#endif +#ifdef CR_EXT_compiled_vertex_array + c->array.n.locked = GL_FALSE; + c->array.n.prevPtr = NULL; + c->array.n.prevStride = 0; +#endif + + /* texcoord arrays */ + for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++) + { + c->array.t[i].p = NULL; + c->array.t[i].size = 4; + c->array.t[i].type = GL_FLOAT; + c->array.t[i].stride = 0; + c->array.t[i].enabled = 0; +#ifdef CR_ARB_vertex_buffer_object + c->array.t[i].buffer = ctx->bufferobject.arrayBuffer; + if (c->array.t[i].buffer) + ++c->array.t[i].buffer->refCount; +#endif +#ifdef CR_EXT_compiled_vertex_array + c->array.t[i].locked = GL_FALSE; + c->array.t[i].prevPtr = NULL; + c->array.t[i].prevStride = 0; +#endif + } + + /* generic vertex attributes */ +#ifdef CR_NV_vertex_program + for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++) { + c->array.a[i].enabled = GL_FALSE; + c->array.a[i].type = GL_FLOAT; + c->array.a[i].size = 4; + c->array.a[i].stride = 0; +#ifdef CR_ARB_vertex_buffer_object + c->array.a[i].buffer = ctx->bufferobject.arrayBuffer; + if (c->array.a[i].buffer) + ++c->array.a[i].buffer->refCount; +#endif +#ifdef CR_EXT_compiled_vertex_array + c->array.a[i].locked = GL_FALSE; + c->array.a[i].prevPtr = NULL; + c->array.a[i].prevStride = 0; +#endif + } +#endif +} + + +/* + * PixelStore functions are here, not in state_pixel.c because this + * is client-side state, like vertex arrays. + */ + +void STATE_APIENTRY crStatePixelStoref (GLenum pname, GLfloat param) +{ + + /* The GL SPEC says I can do this on page 76. */ + switch( pname ) + { + case GL_PACK_SWAP_BYTES: + case GL_PACK_LSB_FIRST: + case GL_UNPACK_SWAP_BYTES: + case GL_UNPACK_LSB_FIRST: + crStatePixelStorei( pname, param == 0.0f ? 0: 1 ); + break; + default: + crStatePixelStorei( pname, (GLint) param ); + break; + } +} + +void STATE_APIENTRY crStatePixelStorei (GLenum pname, GLint param) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + CRStateBits *sb = GetCurrentBits(); + CRClientBits *cb = &(sb->client); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "PixelStore{if} called in Begin/End"); + return; + } + + FLUSH(); + + switch(pname) { + case GL_PACK_SWAP_BYTES: + c->pack.swapBytes = (GLboolean) param; + DIRTY(cb->pack, g->neg_bitid); + break; + case GL_PACK_LSB_FIRST: + c->pack.psLSBFirst = (GLboolean) param; + DIRTY(cb->pack, g->neg_bitid); + break; + case GL_PACK_ROW_LENGTH: + if (param < 0.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Row Length: %f", param); + return; + } + c->pack.rowLength = param; + DIRTY(cb->pack, g->neg_bitid); + break; +#ifdef CR_OPENGL_VERSION_1_2 + case GL_PACK_IMAGE_HEIGHT: + if (param < 0.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Image Height: %f", param); + return; + } + c->pack.imageHeight = param; + DIRTY(cb->pack, g->neg_bitid); + break; +#endif + case GL_PACK_SKIP_IMAGES: + if (param < 0.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Skip Images: %f", param); + return; + } + c->pack.skipImages = param; + DIRTY(cb->pack, g->neg_bitid); + break; + case GL_PACK_SKIP_PIXELS: + if (param < 0.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Skip Pixels: %f", param); + return; + } + c->pack.skipPixels = param; + DIRTY(cb->pack, g->neg_bitid); + break; + case GL_PACK_SKIP_ROWS: + if (param < 0.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Row Skip: %f", param); + return; + } + c->pack.skipRows = param; + DIRTY(cb->pack, g->neg_bitid); + break; + case GL_PACK_ALIGNMENT: + if (((GLint) param) != 1 && + ((GLint) param) != 2 && + ((GLint) param) != 4 && + ((GLint) param) != 8) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Invalid Alignment: %f", param); + return; + } + c->pack.alignment = param; + DIRTY(cb->pack, g->neg_bitid); + break; + + case GL_UNPACK_SWAP_BYTES: + c->unpack.swapBytes = (GLboolean) param; + DIRTY(cb->unpack, g->neg_bitid); + break; + case GL_UNPACK_LSB_FIRST: + c->unpack.psLSBFirst = (GLboolean) param; + DIRTY(cb->unpack, g->neg_bitid); + break; + case GL_UNPACK_ROW_LENGTH: + if (param < 0.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Row Length: %f", param); + return; + } + c->unpack.rowLength = param; + DIRTY(cb->unpack, g->neg_bitid); + break; +#ifdef CR_OPENGL_VERSION_1_2 + case GL_UNPACK_IMAGE_HEIGHT: + if (param < 0.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Image Height: %f", param); + return; + } + c->unpack.imageHeight = param; + DIRTY(cb->unpack, g->neg_bitid); + break; +#endif + case GL_UNPACK_SKIP_IMAGES: + if (param < 0.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Skip Images: %f", param); + return; + } + c->unpack.skipImages = param; + DIRTY(cb->unpack, g->neg_bitid); + break; + case GL_UNPACK_SKIP_PIXELS: + if (param < 0.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Skip Pixels: %f", param); + return; + } + c->unpack.skipPixels = param; + DIRTY(cb->unpack, g->neg_bitid); + break; + case GL_UNPACK_SKIP_ROWS: + if (param < 0.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative Row Skip: %f", param); + return; + } + c->unpack.skipRows = param; + DIRTY(cb->unpack, g->neg_bitid); + break; + case GL_UNPACK_ALIGNMENT: + if (((GLint) param) != 1 && + ((GLint) param) != 2 && + ((GLint) param) != 4 && + ((GLint) param) != 8) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Invalid Alignment: %f", param); + return; + } + c->unpack.alignment = param; + DIRTY(cb->unpack, g->neg_bitid); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Unknown glPixelStore Pname: %d", pname); + return; + } + DIRTY(cb->dirty, g->neg_bitid); +} + + +static void setClientState(CRClientState *c, CRClientBits *cb, + CRbitvalue *neg_bitid, GLenum array, GLboolean state) +{ + CRContext *g = GetCurrentContext(); + + switch (array) + { +#ifdef CR_NV_vertex_program + case GL_VERTEX_ATTRIB_ARRAY0_NV: + case GL_VERTEX_ATTRIB_ARRAY1_NV: + case GL_VERTEX_ATTRIB_ARRAY2_NV: + case GL_VERTEX_ATTRIB_ARRAY3_NV: + case GL_VERTEX_ATTRIB_ARRAY4_NV: + case GL_VERTEX_ATTRIB_ARRAY5_NV: + case GL_VERTEX_ATTRIB_ARRAY6_NV: + case GL_VERTEX_ATTRIB_ARRAY7_NV: + case GL_VERTEX_ATTRIB_ARRAY8_NV: + case GL_VERTEX_ATTRIB_ARRAY9_NV: + case GL_VERTEX_ATTRIB_ARRAY10_NV: + case GL_VERTEX_ATTRIB_ARRAY11_NV: + case GL_VERTEX_ATTRIB_ARRAY12_NV: + case GL_VERTEX_ATTRIB_ARRAY13_NV: + case GL_VERTEX_ATTRIB_ARRAY14_NV: + case GL_VERTEX_ATTRIB_ARRAY15_NV: + { + const GLuint i = array - GL_VERTEX_ATTRIB_ARRAY0_NV; + c->array.a[i].enabled = state; + } + break; +#endif + case GL_VERTEX_ARRAY: + c->array.v.enabled = state; + break; + case GL_COLOR_ARRAY: + c->array.c.enabled = state; + break; + case GL_NORMAL_ARRAY: + c->array.n.enabled = state; + break; + case GL_INDEX_ARRAY: + c->array.i.enabled = state; + break; + case GL_TEXTURE_COORD_ARRAY: + c->array.t[c->curClientTextureUnit].enabled = state; + break; + case GL_EDGE_FLAG_ARRAY: + c->array.e.enabled = state; + break; +#ifdef CR_EXT_fog_coord + case GL_FOG_COORDINATE_ARRAY_EXT: + c->array.f.enabled = state; + break; +#endif +#ifdef CR_EXT_secondary_color + case GL_SECONDARY_COLOR_ARRAY_EXT: + if( g->extensions.EXT_secondary_color ){ + c->array.s.enabled = state; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid Enum passed to Enable/Disable Client State: SECONDARY_COLOR_ARRAY_EXT - EXT_secondary_color is not enabled." ); + return; + } + break; +#endif + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid Enum passed to Enable/Disable Client State: 0x%x", array ); + return; + } + DIRTY(cb->dirty, neg_bitid); + DIRTY(cb->enableClientState, neg_bitid); +} + +void STATE_APIENTRY crStateEnableClientState (GLenum array) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + CRStateBits *sb = GetCurrentBits(); + CRClientBits *cb = &(sb->client); + + FLUSH(); + + setClientState(c, cb, g->neg_bitid, array, GL_TRUE); +} + +void STATE_APIENTRY crStateDisableClientState (GLenum array) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + CRStateBits *sb = GetCurrentBits(); + CRClientBits *cb = &(sb->client); + + FLUSH(); + + setClientState(c, cb, g->neg_bitid, array, GL_FALSE); +} + +static void +crStateClientSetPointer(CRClientPointer *cp, GLint size, + GLenum type, GLboolean normalized, + GLsizei stride, const GLvoid *pointer) +{ + CRContext *g = GetCurrentContext(); + +#ifdef CR_EXT_compiled_vertex_array + crStateUnlockClientPointer(cp); + cp->prevPtr = cp->p; + cp->prevStride = cp->stride; +#endif + + cp->p = (unsigned char *) pointer; + cp->size = size; + cp->type = type; + cp->normalized = normalized; + + /* Calculate the bytes per index for address calculation */ + cp->bytesPerIndex = size; + switch (type) + { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + break; + case GL_SHORT: + case GL_UNSIGNED_SHORT: + cp->bytesPerIndex *= sizeof(GLshort); + break; + case GL_INT: + case GL_UNSIGNED_INT: + cp->bytesPerIndex *= sizeof(GLint); + break; + case GL_FLOAT: + cp->bytesPerIndex *= sizeof(GLfloat); + break; + case GL_DOUBLE: + cp->bytesPerIndex *= sizeof(GLdouble); + break; + default: + crStateError( __LINE__, __FILE__, GL_INVALID_VALUE, + "Unknown type of vertex array: %d", type ); + return; + } + + /* + ** Note: If stride==0 then we set the + ** stride equal address offset + ** therefore stride can never equal + ** zero. + */ + if (stride) + cp->stride = stride; + else + cp->stride = cp->bytesPerIndex; + +#ifdef CR_ARB_vertex_buffer_object + if (cp->buffer) + { + --cp->buffer->refCount; + CRASSERT(cp->buffer->refCount && cp->buffer->refCount < UINT32_MAX/2); + } + cp->buffer = g->bufferobject.arrayBuffer; + if (cp->buffer) + ++cp->buffer->refCount; +#endif +} + +void STATE_APIENTRY crStateVertexPointer(GLint size, GLenum type, + GLsizei stride, const GLvoid *p) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + CRStateBits *sb = GetCurrentBits(); + CRClientBits *cb = &(sb->client); + + FLUSH(); + + if (size != 2 && size != 3 && size != 4) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glVertexPointer: invalid size: %d", size); + return; + } + if (type != GL_SHORT && type != GL_INT && + type != GL_FLOAT && type != GL_DOUBLE) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glVertexPointer: invalid type: 0x%x", type); + return; + } + if (stride < 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glVertexPointer: stride was negative: %d", stride); + return; + } + + crStateClientSetPointer(&(c->array.v), size, type, GL_FALSE, stride, p); + DIRTY(cb->dirty, g->neg_bitid); + DIRTY(cb->clientPointer, g->neg_bitid); + DIRTY(cb->v, g->neg_bitid); +} + +void STATE_APIENTRY crStateColorPointer(GLint size, GLenum type, + GLsizei stride, const GLvoid *p) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + CRStateBits *sb = GetCurrentBits(); + CRClientBits *cb = &(sb->client); + + FLUSH(); + + if (size != 3 && size != 4) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glColorPointer: invalid size: %d", size); + return; + } + if (type != GL_BYTE && type != GL_UNSIGNED_BYTE && + type != GL_SHORT && type != GL_UNSIGNED_SHORT && + type != GL_INT && type != GL_UNSIGNED_INT && + type != GL_FLOAT && type != GL_DOUBLE) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glColorPointer: invalid type: 0x%x", type); + return; + } + if (stride < 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glColorPointer: stride was negative: %d", stride); + return; + } + + crStateClientSetPointer(&(c->array.c), size, type, GL_TRUE, stride, p); + DIRTY(cb->dirty, g->neg_bitid); + DIRTY(cb->clientPointer, g->neg_bitid); + DIRTY(cb->c, g->neg_bitid); +} + +void STATE_APIENTRY crStateSecondaryColorPointerEXT(GLint size, + GLenum type, GLsizei stride, const GLvoid *p) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + CRStateBits *sb = GetCurrentBits(); + CRClientBits *cb = &(sb->client); + + FLUSH(); + + if ( !g->extensions.EXT_secondary_color ) + { + crError( "glSecondaryColorPointerEXT called but EXT_secondary_color is disabled." ); + return; + } + + /*Note: According to opengl spec, only size==3 should be accepted here. + *But it turns out that most drivers accept size==4 here as well, and 4th value + *could even be accessed in shaders code. + *Having a strict check here, leads to difference between guest and host gpu states, which + *in turn could lead to crashes when using server side VBOs. + *@todo: add error reporting to state's VBO related functions and abort dispatching to + *real gpu on any failure to prevent other possible issues. + */ + + if ((size != 3) && (size != 4)) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glSecondaryColorPointerEXT: invalid size: %d", size); + return; + } + if (type != GL_BYTE && type != GL_UNSIGNED_BYTE && + type != GL_SHORT && type != GL_UNSIGNED_SHORT && + type != GL_INT && type != GL_UNSIGNED_INT && + type != GL_FLOAT && type != GL_DOUBLE) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glSecondaryColorPointerEXT: invalid type: 0x%x", type); + return; + } + if (stride < 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glSecondaryColorPointerEXT: stride was negative: %d", stride); + return; + } + + crStateClientSetPointer(&(c->array.s), size, type, GL_TRUE, stride, p); + DIRTY(cb->dirty, g->neg_bitid); + DIRTY(cb->clientPointer, g->neg_bitid); + DIRTY(cb->s, g->neg_bitid); +} + +void STATE_APIENTRY crStateIndexPointer(GLenum type, GLsizei stride, + const GLvoid *p) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + CRStateBits *sb = GetCurrentBits(); + CRClientBits *cb = &(sb->client); + + FLUSH(); + + if (type != GL_SHORT && type != GL_INT && type != GL_UNSIGNED_BYTE && + type != GL_FLOAT && type != GL_DOUBLE) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glIndexPointer: invalid type: 0x%x", type); + return; + } + if (stride < 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glIndexPointer: stride was negative: %d", stride); + return; + } + + crStateClientSetPointer(&(c->array.i), 1, type, GL_TRUE, stride, p); + DIRTY(cb->dirty, g->neg_bitid); + DIRTY(cb->clientPointer, g->neg_bitid); + DIRTY(cb->i, g->neg_bitid); +} + +void STATE_APIENTRY crStateNormalPointer(GLenum type, GLsizei stride, + const GLvoid *p) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + CRStateBits *sb = GetCurrentBits(); + CRClientBits *cb = &(sb->client); + + FLUSH(); + + if (type != GL_BYTE && type != GL_SHORT && + type != GL_INT && type != GL_FLOAT && + type != GL_DOUBLE) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glNormalPointer: invalid type: 0x%x", type); + return; + } + if (stride < 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glNormalPointer: stride was negative: %d", stride); + return; + } + + crStateClientSetPointer(&(c->array.n), 3, type, GL_TRUE, stride, p); + DIRTY(cb->dirty, g->neg_bitid); + DIRTY(cb->clientPointer, g->neg_bitid); + DIRTY(cb->n, g->neg_bitid); +} + +void STATE_APIENTRY crStateTexCoordPointer(GLint size, GLenum type, + GLsizei stride, const GLvoid *p) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + CRStateBits *sb = GetCurrentBits(); + CRClientBits *cb = &(sb->client); + + FLUSH(); + + if (size != 1 && size != 2 && size != 3 && size != 4) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glTexCoordPointer: invalid size: %d", size); + return; + } + if (type != GL_SHORT && type != GL_INT && + type != GL_FLOAT && type != GL_DOUBLE) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexCoordPointer: invalid type: 0x%x", type); + return; + } + if (stride < 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glTexCoordPointer: stride was negative: %d", stride); + return; + } + + crStateClientSetPointer(&(c->array.t[c->curClientTextureUnit]), size, type, GL_FALSE, stride, p); + DIRTY(cb->dirty, g->neg_bitid); + DIRTY(cb->clientPointer, g->neg_bitid); + DIRTY(cb->t[c->curClientTextureUnit], g->neg_bitid); +} + +void STATE_APIENTRY crStateEdgeFlagPointer(GLsizei stride, const GLvoid *p) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + CRStateBits *sb = GetCurrentBits(); + CRClientBits *cb = &(sb->client); + + FLUSH(); + + if (stride < 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glTexCoordPointer: stride was negative: %d", stride); + return; + } + + crStateClientSetPointer(&(c->array.e), 1, GL_UNSIGNED_BYTE, GL_FALSE, stride, p); + DIRTY(cb->dirty, g->neg_bitid); + DIRTY(cb->clientPointer, g->neg_bitid); + DIRTY(cb->e, g->neg_bitid); +} + +void STATE_APIENTRY crStateFogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *p) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + CRStateBits *sb = GetCurrentBits(); + CRClientBits *cb = &(sb->client); + + FLUSH(); + + if (type != GL_BYTE && type != GL_UNSIGNED_BYTE && + type != GL_SHORT && type != GL_UNSIGNED_SHORT && + type != GL_INT && type != GL_UNSIGNED_INT && + type != GL_FLOAT && type != GL_DOUBLE) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glFogCoordPointerEXT: invalid type: 0x%x", type); + return; + } + if (stride < 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glFogCoordPointerEXT: stride was negative: %d", stride); + return; + } + + crStateClientSetPointer(&(c->array.f), 1, type, GL_FALSE, stride, p); + DIRTY(cb->dirty, g->neg_bitid); + DIRTY(cb->clientPointer, g->neg_bitid); + DIRTY(cb->f, g->neg_bitid); +} + + +void STATE_APIENTRY crStateVertexAttribPointerNV(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *p) +{ + GLboolean normalized = GL_FALSE; + /* Extra error checking for NV arrays */ + if (type != GL_UNSIGNED_BYTE && type != GL_SHORT && + type != GL_FLOAT && type != GL_DOUBLE) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glVertexAttribPointerNV: invalid type: 0x%x", type); + return; + } + crStateVertexAttribPointerARB(index, size, type, normalized, stride, p); +} + + +void STATE_APIENTRY crStateVertexAttribPointerARB(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *p) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + CRStateBits *sb = GetCurrentBits(); + CRClientBits *cb = &(sb->client); + + FLUSH(); + + if (index >= CR_MAX_VERTEX_ATTRIBS) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glVertexAttribPointerARB: invalid index: %d", (int) index); + return; + } + if (size != 1 && size != 2 && size != 3 && size != 4) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glVertexAttribPointerARB: invalid size: %d", size); + return; + } + if (type != GL_BYTE && type != GL_UNSIGNED_BYTE && + type != GL_SHORT && type != GL_UNSIGNED_SHORT && + type != GL_INT && type != GL_UNSIGNED_INT && + type != GL_FLOAT && type != GL_DOUBLE) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glVertexAttribPointerARB: invalid type: 0x%x", type); + return; + } + if (stride < 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glVertexAttribPointerARB: stride was negative: %d", stride); + return; + } + + crStateClientSetPointer(&(c->array.a[index]), size, type, normalized, stride, p); + DIRTY(cb->dirty, g->neg_bitid); + DIRTY(cb->clientPointer, g->neg_bitid); + DIRTY(cb->a[index], g->neg_bitid); +} + + +void STATE_APIENTRY crStateGetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer) +{ + CRContext *g = GetCurrentContext(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetVertexAttribPointervNV called in Begin/End"); + return; + } + + if (index >= CR_MAX_VERTEX_ATTRIBS) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glGetVertexAttribPointervNV(index)"); + return; + } + + if (pname != GL_ATTRIB_ARRAY_POINTER_NV) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetVertexAttribPointervNV(pname)"); + return; + } + + *pointer = g->client.array.a[index].p; +} + + +void STATE_APIENTRY crStateGetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer) +{ + crStateGetVertexAttribPointervNV(index, pname, pointer); +} + + + +/* +** Currently I treat Interleaved Arrays as if the +** user uses them as separate arrays. +** Certainly not the most efficient method but it +** lets me use the same glDrawArrays method. +*/ +void STATE_APIENTRY crStateInterleavedArrays(GLenum format, GLsizei stride, const GLvoid *p) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + CRStateBits *sb = GetCurrentBits(); + CRClientBits *cb = &(sb->client); + CRClientPointer *cp; + unsigned char *base = (unsigned char *) p; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glInterleavedArrays called in begin/end"); + return; + } + + FLUSH(); + + if (stride < 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glInterleavedArrays: stride < 0: %d", stride); + return; + } + + switch (format) + { + case GL_T4F_C4F_N3F_V4F: + case GL_T2F_C4F_N3F_V3F: + case GL_C4F_N3F_V3F: + case GL_T4F_V4F: + case GL_T2F_C3F_V3F: + case GL_T2F_N3F_V3F: + case GL_C3F_V3F: + case GL_N3F_V3F: + case GL_T2F_C4UB_V3F: + case GL_T2F_V3F: + case GL_C4UB_V3F: + case GL_V3F: + case GL_C4UB_V2F: + case GL_V2F: + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glInterleavedArrays: Unrecognized format: %d", format); + return; + } + + DIRTY(cb->dirty, g->neg_bitid); + DIRTY(cb->clientPointer, g->neg_bitid); + +/* p, size, type, stride, enabled, bytesPerIndex */ +/* +** VertexPointer +*/ + + cp = &(c->array.v); + cp->type = GL_FLOAT; + cp->enabled = GL_TRUE; + +#ifdef CR_EXT_compiled_vertex_array + crStateUnlockClientPointer(cp); +#endif + + switch (format) + { + case GL_T4F_C4F_N3F_V4F: + cp->p = base+4*sizeof(GLfloat)+4*sizeof(GLfloat)+3*sizeof(GLfloat); + cp->size = 4; + break; + case GL_T2F_C4F_N3F_V3F: + cp->p = base+2*sizeof(GLfloat)+4*sizeof(GLfloat)+3*sizeof(GLfloat); + cp->size = 3; + break; + case GL_C4F_N3F_V3F: + cp->p = base+4*sizeof(GLfloat)+3*sizeof(GLfloat); + cp->size = 3; + break; + case GL_T4F_V4F: + cp->p = base+4*sizeof(GLfloat); + cp->size = 4; + break; + case GL_T2F_C3F_V3F: + cp->p = base+2*sizeof(GLfloat)+3*sizeof(GLfloat); + cp->size = 3; + break; + case GL_T2F_N3F_V3F: + cp->p = base+2*sizeof(GLfloat)+3*sizeof(GLfloat); + cp->size = 3; + break; + case GL_C3F_V3F: + cp->p = base+3*sizeof(GLfloat); + cp->size = 3; + break; + case GL_N3F_V3F: + cp->p = base+3*sizeof(GLfloat); + cp->size = 3; + break; + case GL_T2F_C4UB_V3F: + cp->p = base+2*sizeof(GLfloat)+4*sizeof(GLubyte); + cp->size = 3; + break; + case GL_T2F_V3F: + cp->p = base+2*sizeof(GLfloat); + cp->size = 3; + break; + case GL_C4UB_V3F: + cp->p = base+4*sizeof(GLubyte); + cp->size = 3; + break; + case GL_V3F: + cp->p = base; + cp->size = 3; + break; + case GL_C4UB_V2F: + cp->p = base+4*sizeof(GLubyte); + cp->size = 2; + break; + case GL_V2F: + cp->p = base; + cp->size = 2; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glInterleavedArrays: Unrecognized format: %d", format); + return; + } + + cp->bytesPerIndex = cp->size * sizeof (GLfloat); + + if (stride==0) + stride = cp->bytesPerIndex + (cp->p - base); + cp->stride = stride; + +/* +** NormalPointer +*/ + + cp = &(c->array.n); + cp->enabled = GL_TRUE; + cp->stride = stride; +#ifdef CR_EXT_compiled_vertex_array + crStateUnlockClientPointer(cp); +#endif + + switch (format) + { + case GL_T4F_C4F_N3F_V4F: + cp->p = base+4*sizeof(GLfloat)+4*sizeof(GLfloat); + break; + case GL_T2F_C4F_N3F_V3F: + cp->p = base+2*sizeof(GLfloat)+4*sizeof(GLfloat); + break; + case GL_C4F_N3F_V3F: + cp->p = base+4*sizeof(GLfloat); + break; + case GL_T2F_N3F_V3F: + cp->p = base+2*sizeof(GLfloat); + break; + case GL_N3F_V3F: + cp->p = base; + break; + case GL_T4F_V4F: + case GL_T2F_C3F_V3F: + case GL_C3F_V3F: + case GL_T2F_C4UB_V3F: + case GL_T2F_V3F: + case GL_C4UB_V3F: + case GL_V3F: + case GL_C4UB_V2F: + case GL_V2F: + cp->enabled = GL_FALSE; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glInterleavedArrays: Unrecognized format: %d", format); + return; + } + + if (cp->enabled) + { + cp->type = GL_FLOAT; + cp->size = 3; + cp->bytesPerIndex = cp->size * sizeof (GLfloat); + } + +/* +** ColorPointer +*/ + + cp = &(c->array.c); + cp->enabled = GL_TRUE; + cp->stride = stride; +#ifdef CR_EXT_compiled_vertex_array + crStateUnlockClientPointer(cp); +#endif + + switch (format) + { + case GL_T4F_C4F_N3F_V4F: + cp->size = 4; + cp->type = GL_FLOAT; + cp->bytesPerIndex = cp->size * sizeof(GLfloat); + cp->p = base+4*sizeof(GLfloat); + break; + case GL_T2F_C4F_N3F_V3F: + cp->size = 4; + cp->type = GL_FLOAT; + cp->bytesPerIndex = cp->size * sizeof(GLfloat); + cp->p = base+2*sizeof(GLfloat); + break; + case GL_C4F_N3F_V3F: + cp->size = 4; + cp->type = GL_FLOAT; + cp->bytesPerIndex = cp->size * sizeof(GLfloat); + cp->p = base; + break; + case GL_T2F_C3F_V3F: + cp->size = 3; + cp->type = GL_FLOAT; + cp->bytesPerIndex = cp->size * sizeof(GLfloat); + cp->p = base+2*sizeof(GLfloat); + break; + case GL_C3F_V3F: + cp->size = 3; + cp->type = GL_FLOAT; + cp->bytesPerIndex = cp->size * sizeof(GLfloat); + cp->p = base; + break; + case GL_T2F_C4UB_V3F: + cp->size = 4; + cp->type = GL_UNSIGNED_BYTE; + cp->bytesPerIndex = cp->size * sizeof(GLubyte); + cp->p = base+2*sizeof(GLfloat); + break; + case GL_C4UB_V3F: + cp->size = 4; + cp->type = GL_UNSIGNED_BYTE; + cp->bytesPerIndex = cp->size * sizeof(GLubyte); + cp->p = base; + break; + case GL_C4UB_V2F: + cp->size = 4; + cp->type = GL_UNSIGNED_BYTE; + cp->bytesPerIndex = cp->size * sizeof(GLubyte); + cp->p = base; + break; + case GL_T2F_N3F_V3F: + case GL_N3F_V3F: + case GL_T4F_V4F: + case GL_T2F_V3F: + case GL_V3F: + case GL_V2F: + cp->enabled = GL_FALSE; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glInterleavedArrays: Unrecognized format: %d", format); + return; + } + +/* +** TexturePointer +*/ + + cp = &(c->array.t[c->curClientTextureUnit]); + cp->enabled = GL_TRUE; + cp->stride = stride; +#ifdef CR_EXT_compiled_vertex_array + crStateUnlockClientPointer(cp); +#endif + + switch (format) + { + case GL_T4F_C4F_N3F_V4F: + cp->size = 4; + cp->p = base; + break; + case GL_T2F_C4F_N3F_V3F: + cp->size = 3; + cp->p = base; + break; + case GL_T2F_C3F_V3F: + case GL_T2F_N3F_V3F: + cp->size = 3; + cp->p = base; + break; + case GL_T2F_C4UB_V3F: + cp->size = 3; + cp->p = base; + break; + case GL_T4F_V4F: + cp->size = 4; + cp->p = base; + break; + case GL_T2F_V3F: + cp->size = 3; + cp->p = base; + break; + case GL_C4UB_V3F: + case GL_C4UB_V2F: + case GL_C3F_V3F: + case GL_C4F_N3F_V3F: + case GL_N3F_V3F: + case GL_V3F: + case GL_V2F: + cp->enabled = GL_FALSE; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glInterleavedArrays: Unrecognized format: %d", format); + return; + } + + if (cp->enabled) + { + cp->type = GL_FLOAT; + cp->bytesPerIndex = cp->size * sizeof (GLfloat); + } +} + +void STATE_APIENTRY crStateGetPointerv(GLenum pname, GLvoid * * params) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "GetPointerv called in begin/end"); + return; + } + + switch (pname) + { + case GL_VERTEX_ARRAY_POINTER: + *params = (GLvoid *) c->array.v.p; + break; + case GL_COLOR_ARRAY_POINTER: + *params = (GLvoid *) c->array.c.p; + break; + case GL_NORMAL_ARRAY_POINTER: + *params = (GLvoid *) c->array.n.p; + break; + case GL_INDEX_ARRAY_POINTER: + *params = (GLvoid *) c->array.i.p; + break; + case GL_TEXTURE_COORD_ARRAY_POINTER: + *params = (GLvoid *) c->array.t[c->curClientTextureUnit].p; + break; + case GL_EDGE_FLAG_ARRAY_POINTER: + *params = (GLvoid *) c->array.e.p; + break; +#ifdef CR_EXT_fog_coord + case GL_FOG_COORDINATE_ARRAY_POINTER_EXT: + *params = (GLvoid *) c->array.f.p; + break; +#endif +#ifdef CR_EXT_secondary_color + case GL_SECONDARY_COLOR_ARRAY_POINTER_EXT: + if( g->extensions.EXT_secondary_color ){ + *params = (GLvoid *) c->array.s.p; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid Enum passed to glGetPointerv: SECONDARY_COLOR_ARRAY_EXT - EXT_secondary_color is not enabled." ); + return; + } + break; +#endif + case GL_FEEDBACK_BUFFER_POINTER: + case GL_SELECTION_BUFFER_POINTER: + /* do nothing - API switching should pick this up */ + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetPointerv: invalid pname: %d", pname); + return; + } +} + + +void STATE_APIENTRY crStatePushClientAttrib( GLbitfield mask ) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glPushClientAttrib called in Begin/End"); + return; + } + + if (c->attribStackDepth == CR_MAX_CLIENT_ATTRIB_STACK_DEPTH - 1) { + crStateError(__LINE__, __FILE__, GL_STACK_OVERFLOW, + "glPushClientAttrib called with a full stack!" ); + return; + } + + FLUSH(); + + c->pushMaskStack[c->attribStackDepth++] = mask; + + if (mask & GL_CLIENT_PIXEL_STORE_BIT) { + c->pixelPackStoreStack[c->pixelStoreStackDepth] = c->pack; + c->pixelUnpackStoreStack[c->pixelStoreStackDepth] = c->unpack; + c->pixelStoreStackDepth++; + } + if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) { + c->vertexArrayStack[c->vertexArrayStackDepth] = c->array; + c->vertexArrayStackDepth++; + } + + /* dirty? - no, because we haven't really changed any state */ +} + + +void STATE_APIENTRY crStatePopClientAttrib( void ) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + CRStateBits *sb = GetCurrentBits(); + CRClientBits *cb = &(sb->client); + CRbitvalue mask; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glPopClientAttrib called in Begin/End"); + return; + } + + if (c->attribStackDepth == 0) { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, + "glPopClientAttrib called with an empty stack!" ); + return; + } + + FLUSH(); + + mask = c->pushMaskStack[--c->attribStackDepth]; + + if (mask & GL_CLIENT_PIXEL_STORE_BIT) { + if (c->pixelStoreStackDepth == 0) { + crError("bug in glPopClientAttrib (pixel store) "); + return; + } + c->pixelStoreStackDepth--; + c->pack = c->pixelPackStoreStack[c->pixelStoreStackDepth]; + c->unpack = c->pixelUnpackStoreStack[c->pixelStoreStackDepth]; + DIRTY(cb->pack, g->neg_bitid); + } + + if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) { + if (c->vertexArrayStackDepth == 0) { + crError("bug in glPopClientAttrib (vertex array) "); + return; + } + c->vertexArrayStackDepth--; + c->array = c->vertexArrayStack[c->vertexArrayStackDepth]; + DIRTY(cb->clientPointer, g->neg_bitid); + } + + DIRTY(cb->dirty, g->neg_bitid); +} + +static void crStateLockClientPointer(CRClientPointer* cp) +{ + crStateUnlockClientPointer(cp); + if (cp->enabled) + { + cp->locked = GL_TRUE; + } +} + +static GLboolean crStateCanLockClientPointer(CRClientPointer* cp) +{ + return !(cp->enabled && cp->buffer && cp->buffer->id); +} + +void STATE_APIENTRY crStateLockArraysEXT(GLint first, GLint count) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + int i; + + for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i) + { + if (!crStateCanLockClientPointer(crStateGetClientPointerByIndex(i, &c->array))) + { + break; + } + } + if (i<CRSTATECLIENT_MAX_VERTEXARRAYS) + { + crDebug("crStateLockArraysEXT ignored because array %i have a bound VBO", i); + return; + } + + c->array.locked = GL_TRUE; + c->array.lockFirst = first; + c->array.lockCount = count; +#ifdef IN_GUEST + c->array.synced = GL_FALSE; +#endif + + for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i) + { + crStateLockClientPointer(crStateGetClientPointerByIndex(i, &c->array)); + } +} + +void STATE_APIENTRY crStateUnlockArraysEXT() +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + int i; + + if (!c->array.locked) + { + crDebug("crStateUnlockArraysEXT ignored because arrays aren't locked"); + return; + } + + c->array.locked = GL_FALSE; +#ifdef IN_GUEST + c->array.synced = GL_FALSE; +#endif + + for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i) + { + crStateUnlockClientPointer(crStateGetClientPointerByIndex(i, &c->array)); + } +} + +void STATE_APIENTRY crStateVertexArrayRangeNV(GLsizei length, const GLvoid *pointer) +{ + /* XXX todo */ + crWarning("crStateVertexArrayRangeNV not implemented"); + (void)length; (void)pointer; +} + + +void STATE_APIENTRY crStateFlushVertexArrayRangeNV(void) +{ + /* XXX todo */ + crWarning("crStateFlushVertexArrayRangeNV not implemented"); +} + +/*Returns if the given clientpointer could be used on server side directly*/ +#define CRSTATE_IS_SERVER_CP(cp) (!(cp).enabled || !(cp).p || ((cp).buffer && (cp).buffer->id) || ((cp).locked)) + +#if defined(DEBUG) && 0 +static void crStateDumpClientPointer(CRClientPointer *cp, const char *name, int i) +{ + if (i<0 && cp->enabled) + { + crDebug("CP(%s): enabled:%d ptr:%p buffer:%p buffer.name:%i locked: %i %s", + name, cp->enabled, cp->p, cp->buffer, cp->buffer ? cp->buffer->id : ~(GLuint)0, (int)cp->locked, + CRSTATE_IS_SERVER_CP(*cp) ? "":"!FAIL!"); + } + else if (0==i || cp->enabled) + { + crDebug("CP(%s%i): enabled:%d ptr:%p buffer:%p buffer.name:%i locked: %i %s", + name, i, cp->enabled, cp->p, cp->buffer, cp->buffer ? cp->buffer->id : ~(GLuint)0, (int)cp->locked, + CRSTATE_IS_SERVER_CP(*cp) ? "":"!FAIL!"); + } +} +#endif + +#ifdef DEBUG_misha +/* debugging */ +/*# define CR_NO_SERVER_ARRAYS*/ +#endif + +/* + * Determine if the enabled arrays all live on the server + * (via GL_ARB_vertex_buffer_object). + */ +GLboolean crStateUseServerArrays(void) +{ +#if defined(CR_ARB_vertex_buffer_object) && !defined(CR_NO_SERVER_ARRAYS) + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + int i; + GLboolean res; + + res = CRSTATE_IS_SERVER_CP(c->array.v) + && CRSTATE_IS_SERVER_CP(c->array.n) + && CRSTATE_IS_SERVER_CP(c->array.c) + && CRSTATE_IS_SERVER_CP(c->array.i) + && CRSTATE_IS_SERVER_CP(c->array.e) + && CRSTATE_IS_SERVER_CP(c->array.s) + && CRSTATE_IS_SERVER_CP(c->array.f); + + if (res) + { + for (i = 0; (unsigned int)i < g->limits.maxTextureUnits; i++) + if (!CRSTATE_IS_SERVER_CP(c->array.t[i])) + { + res = GL_FALSE; + break; + } + } + + if (res) + { + for (i = 0; (unsigned int)i < g->limits.maxVertexProgramAttribs; i++) + if (!CRSTATE_IS_SERVER_CP(c->array.a[i])) + { + res = GL_FALSE; + break; + } + } + +#if defined(DEBUG) && 0 + if (!res) + { + crStateDumpClientPointer(&c->array.v, "v", -1); + crStateDumpClientPointer(&c->array.n, "n", -1); + crStateDumpClientPointer(&c->array.c, "c", -1); + crStateDumpClientPointer(&c->array.i, "i", -1); + crStateDumpClientPointer(&c->array.e, "e", -1); + crStateDumpClientPointer(&c->array.s, "s", -1); + crStateDumpClientPointer(&c->array.f, "f", -1); + for (i = 0; (unsigned int)i < g->limits.maxTextureUnits; i++) + crStateDumpClientPointer(&c->array.t[i], "tex", i); + for (i = 0; (unsigned int)i < g->limits.maxVertexProgramAttribs; i++) + crStateDumpClientPointer(&c->array.a[i], "attrib", i); + crDebug("crStateUseServerArrays->%d", res); + } +#endif + + return res; +#else + return GL_FALSE; +#endif +} + +GLuint crStateNeedDummyZeroVertexArray(CRContext *g, CRCurrentStatePointers *current, GLfloat *pZva) +{ +#if defined(CR_ARB_vertex_buffer_object) + CRClientState *c = &(g->client); + int i; + GLuint zvMax = 0; + + if (c->array.a[0].enabled) + return 0; + + for (i = 1; (unsigned int)i < g->limits.maxVertexProgramAttribs; i++) + { + if (c->array.a[i].enabled) + { + if (c->array.a[i].buffer && c->array.a[i].buffer->id) + { + GLuint cElements = c->array.a[i].buffer->size / c->array.a[i].stride; + if (zvMax < cElements) + zvMax = cElements; + } + else + { + zvMax = ~0; + break; + } + } + } + + if (zvMax) + { + Assert(!c->array.v.enabled); + + crStateCurrentRecoverNew(g, current); + + crMemcpy(pZva, &g->current.vertexAttrib[0][0], sizeof (*pZva) * 4); + } + + return zvMax; +#else + return GL_FALSE; +#endif +} + + +/** + * Determine if there's a server-side array element buffer. + * Called by glDrawElements() in packing SPUs to determine if glDrawElements + * should be evaluated (unrolled) locally or if glDrawElements should be + * packed and sent to the server. + */ +GLboolean +crStateUseServerArrayElements(void) +{ +#ifdef CR_ARB_vertex_buffer_object + CRContext *g = GetCurrentContext(); + if (g->bufferobject.elementsBuffer && + g->bufferobject.elementsBuffer->id > 0) + return GL_TRUE; + else + return GL_FALSE; +#else + return GL_FALSE; +#endif +} + +#define CR_BUFFER_HWID(_p) ((_p) ? (_p)->hwid : 0) + +void +crStateClientDiff(CRClientBits *cb, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + CRClientState *from = &(fromCtx->client); + const CRClientState *to = &(toCtx->client); + GLint curClientTextureUnit = from->curClientTextureUnit; + int i; + GLint idHwArrayBuffer = CR_BUFFER_HWID(toCtx->bufferobject.arrayBuffer); + const GLint idHwInitialBuffer = idHwArrayBuffer; + +#ifdef DEBUG_misha + { + GLint tstHwBuffer = -1; + diff_api.GetIntegerv(GL_ARRAY_BUFFER_BINDING, &tstHwBuffer); + CRASSERT(idHwInitialBuffer == tstHwBuffer); + } +#endif + + + if (CHECKDIRTY(cb->clientPointer, bitID)) { + /* one or more vertex pointers is dirty */ + if (CHECKDIRTY(cb->v, bitID)) { + if (from->array.v.size != to->array.v.size || + from->array.v.type != to->array.v.type || + from->array.v.stride != to->array.v.stride || + from->array.v.p != to->array.v.p || + from->array.v.buffer != to->array.v.buffer) { + GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.v.buffer); + if (idHwArrayBufferUsed != idHwArrayBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed); + idHwArrayBuffer = idHwArrayBufferUsed; + } + diff_api.VertexPointer(to->array.v.size, to->array.v.type, + to->array.v.stride, to->array.v.p); + from->array.v.size = to->array.v.size; + from->array.v.type = to->array.v.type; + from->array.v.stride = to->array.v.stride; + from->array.v.p = to->array.v.p; + from->array.v.buffer = to->array.v.buffer; + } + CLEARDIRTY2(cb->v, bitID); + } + /* normal */ + if (CHECKDIRTY(cb->n, bitID)) { + if (from->array.n.type != to->array.n.type || + from->array.n.stride != to->array.n.stride || + from->array.n.p != to->array.n.p || + from->array.n.buffer != to->array.n.buffer) { + GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.n.buffer); + if (idHwArrayBufferUsed != idHwArrayBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed); + idHwArrayBuffer = idHwArrayBufferUsed; + } + diff_api.NormalPointer(to->array.n.type, + to->array.n.stride, to->array.n.p); + from->array.n.type = to->array.n.type; + from->array.n.stride = to->array.n.stride; + from->array.n.p = to->array.n.p; + from->array.n.buffer = to->array.n.buffer; + } + CLEARDIRTY2(cb->n, bitID); + } + /* color */ + if (CHECKDIRTY(cb->c, bitID)) { + if (from->array.c.size != to->array.c.size || + from->array.c.type != to->array.c.type || + from->array.c.stride != to->array.c.stride || + from->array.c.p != to->array.c.p || + from->array.c.buffer != to->array.c.buffer) { + GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.c.buffer); + if (idHwArrayBufferUsed != idHwArrayBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed); + idHwArrayBuffer = idHwArrayBufferUsed; + } + diff_api.ColorPointer(to->array.c.size, to->array.c.type, + to->array.c.stride, to->array.c.p); + from->array.c.size = to->array.c.size; + from->array.c.type = to->array.c.type; + from->array.c.stride = to->array.c.stride; + from->array.c.p = to->array.c.p; + from->array.c.buffer = to->array.c.buffer; + } + CLEARDIRTY2(cb->c, bitID); + } + /* index */ + if (CHECKDIRTY(cb->i, bitID)) { + if (from->array.i.type != to->array.i.type || + from->array.i.stride != to->array.i.stride || + from->array.i.p != to->array.i.p || + from->array.i.buffer != to->array.i.buffer) { + GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.i.buffer); + if (idHwArrayBufferUsed != idHwArrayBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed); + idHwArrayBuffer = idHwArrayBufferUsed; + } + diff_api.IndexPointer(to->array.i.type, + to->array.i.stride, to->array.i.p); + from->array.i.type = to->array.i.type; + from->array.i.stride = to->array.i.stride; + from->array.i.p = to->array.i.p; + from->array.i.buffer = to->array.i.buffer; + } + CLEARDIRTY2(cb->i, bitID); + } + /* texcoords */ + for (i = 0; (unsigned int)i < toCtx->limits.maxTextureUnits; i++) { + if (CHECKDIRTY(cb->t[i], bitID)) { + if (from->array.t[i].size != to->array.t[i].size || + from->array.t[i].type != to->array.t[i].type || + from->array.t[i].stride != to->array.t[i].stride || + from->array.t[i].p != to->array.t[i].p || + from->array.t[i].buffer != to->array.t[i].buffer) { + GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.t[i].buffer); + if (idHwArrayBufferUsed != idHwArrayBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed); + idHwArrayBuffer = idHwArrayBufferUsed; + } + diff_api.ClientActiveTextureARB(GL_TEXTURE0_ARB + i); + curClientTextureUnit = i; + diff_api.TexCoordPointer(to->array.t[i].size, to->array.t[i].type, + to->array.t[i].stride, to->array.t[i].p); + from->array.t[i].size = to->array.t[i].size; + from->array.t[i].type = to->array.t[i].type; + from->array.t[i].stride = to->array.t[i].stride; + from->array.t[i].p = to->array.t[i].p; + from->array.t[i].buffer = to->array.t[i].buffer; + } + CLEARDIRTY2(cb->t[i], bitID); + } + } + /* edge flag */ + if (CHECKDIRTY(cb->e, bitID)) { + if (from->array.e.stride != to->array.e.stride || + from->array.e.p != to->array.e.p || + from->array.e.buffer != to->array.e.buffer) { + GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.e.buffer); + if (idHwArrayBufferUsed != idHwArrayBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed); + idHwArrayBuffer = idHwArrayBufferUsed; + } + diff_api.EdgeFlagPointer(to->array.e.stride, to->array.e.p); + from->array.e.stride = to->array.e.stride; + from->array.e.p = to->array.e.p; + from->array.e.buffer = to->array.e.buffer; + } + CLEARDIRTY2(cb->e, bitID); + } + /* secondary color */ + if (CHECKDIRTY(cb->s, bitID)) { + if (from->array.s.size != to->array.s.size || + from->array.s.type != to->array.s.type || + from->array.s.stride != to->array.s.stride || + from->array.s.p != to->array.s.p || + from->array.s.buffer != to->array.s.buffer) { + GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.s.buffer); + if (idHwArrayBufferUsed != idHwArrayBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed); + idHwArrayBuffer = idHwArrayBufferUsed; + } + diff_api.SecondaryColorPointerEXT(to->array.s.size, to->array.s.type, + to->array.s.stride, to->array.s.p); + from->array.s.size = to->array.s.size; + from->array.s.type = to->array.s.type; + from->array.s.stride = to->array.s.stride; + from->array.s.p = to->array.s.p; + from->array.s.buffer = to->array.s.buffer; + } + CLEARDIRTY2(cb->s, bitID); + } + /* fog coord */ + if (CHECKDIRTY(cb->f, bitID)) { + if (from->array.f.type != to->array.f.type || + from->array.f.stride != to->array.f.stride || + from->array.f.p != to->array.f.p || + from->array.f.buffer != to->array.f.buffer) { + GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.f.buffer); + if (idHwArrayBufferUsed != idHwArrayBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed); + idHwArrayBuffer = idHwArrayBufferUsed; + } + diff_api.FogCoordPointerEXT(to->array.f.type, + to->array.f.stride, to->array.f.p); + from->array.f.type = to->array.f.type; + from->array.f.stride = to->array.f.stride; + from->array.f.p = to->array.f.p; + from->array.f.buffer = to->array.f.buffer; + } + CLEARDIRTY2(cb->f, bitID); + } +#if defined(CR_NV_vertex_program) || defined(CR_ARB_vertex_program) + /* vertex attributes */ + for (i = 0; (unsigned int)i < toCtx->limits.maxVertexProgramAttribs; i++) { + if (CHECKDIRTY(cb->a[i], bitID)) { + if (from->array.a[i].size != to->array.a[i].size || + from->array.a[i].type != to->array.a[i].type || + from->array.a[i].stride != to->array.a[i].stride || + from->array.a[i].normalized != to->array.a[i].normalized || + from->array.a[i].p != to->array.a[i].p || + from->array.a[i].buffer != to->array.a[i].buffer) { + GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.a[i].buffer); + if (idHwArrayBufferUsed != idHwArrayBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed); + idHwArrayBuffer = idHwArrayBufferUsed; + } + diff_api.VertexAttribPointerARB(i, to->array.a[i].size, + to->array.a[i].type, + to->array.a[i].normalized, + to->array.a[i].stride, + to->array.a[i].p); + from->array.a[i].size = to->array.a[i].size; + from->array.a[i].type = to->array.a[i].type; + from->array.a[i].stride = to->array.a[i].stride; + from->array.a[i].normalized = to->array.a[i].normalized; + from->array.a[i].p = to->array.a[i].p; + from->array.a[i].buffer = to->array.a[i].buffer; + } + CLEARDIRTY2(cb->a[i], bitID); + } + } +#endif + } + + if (idHwArrayBuffer != idHwInitialBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwInitialBuffer); + } + + if (CHECKDIRTY(cb->enableClientState, bitID)) { + /* update vertex array enable/disable flags */ + glAble able[2]; + able[0] = diff_api.DisableClientState; + able[1] = diff_api.EnableClientState; + if (from->array.v.enabled != to->array.v.enabled) { + able[to->array.v.enabled](GL_VERTEX_ARRAY); + from->array.v.enabled = to->array.v.enabled; + } + if (from->array.n.enabled != to->array.n.enabled) { + able[to->array.n.enabled](GL_NORMAL_ARRAY); + from->array.n.enabled = to->array.n.enabled; + } + if (from->array.c.enabled != to->array.c.enabled) { + able[to->array.c.enabled](GL_COLOR_ARRAY); + from->array.c.enabled = to->array.c.enabled; + } + if (from->array.i.enabled != to->array.i.enabled) { + able[to->array.i.enabled](GL_INDEX_ARRAY); + from->array.i.enabled = to->array.i.enabled; + } + for (i = 0; (unsigned int)i < toCtx->limits.maxTextureUnits; i++) { + if (from->array.t[i].enabled != to->array.t[i].enabled) { + diff_api.ClientActiveTextureARB(GL_TEXTURE0_ARB + i); + curClientTextureUnit = i; + able[to->array.t[i].enabled](GL_TEXTURE_COORD_ARRAY); + from->array.t[i].enabled = to->array.t[i].enabled; + } + } + if (from->array.e.enabled != to->array.e.enabled) { + able[to->array.e.enabled](GL_EDGE_FLAG_ARRAY); + from->array.e.enabled = to->array.e.enabled; + } + if (from->array.s.enabled != to->array.s.enabled) { + able[to->array.s.enabled](GL_SECONDARY_COLOR_ARRAY_EXT); + from->array.s.enabled = to->array.s.enabled; + } + if (from->array.f.enabled != to->array.f.enabled) { + able[to->array.f.enabled](GL_FOG_COORDINATE_ARRAY_EXT); + from->array.f.enabled = to->array.f.enabled; + } + for (i = 0; (unsigned int)i < toCtx->limits.maxVertexProgramAttribs; i++) { + if (from->array.a[i].enabled != to->array.a[i].enabled) { + if (to->array.a[i].enabled) + diff_api.EnableVertexAttribArrayARB(i); + else + diff_api.DisableVertexAttribArrayARB(i); + from->array.a[i].enabled = to->array.a[i].enabled; + } + } + CLEARDIRTY2(cb->enableClientState, bitID); + } + + if (to->curClientTextureUnit != curClientTextureUnit) + { + diff_api.ClientActiveTextureARB(GL_TEXTURE0_ARB + to->curClientTextureUnit); + } +} + + +void +crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + const CRClientState *from = &(fromCtx->client); + const CRClientState *to = &(toCtx->client); + GLint curClientTextureUnit = from->curClientTextureUnit; + int i; + GLint idHwArrayBuffer = CR_BUFFER_HWID(toCtx->bufferobject.arrayBuffer); + const GLint idHwInitialBuffer = idHwArrayBuffer; + +#ifdef DEBUG_misha + { + GLint tstHwBuffer = -1; + diff_api.GetIntegerv(GL_ARRAY_BUFFER_BINDING, &tstHwBuffer); + CRASSERT(idHwInitialBuffer == tstHwBuffer); + } +#endif + + if (CHECKDIRTY(cb->clientPointer, bitID)) { + /* one or more vertex pointers is dirty */ + if (CHECKDIRTY(cb->v, bitID)) { + if (from->array.v.size != to->array.v.size || + from->array.v.type != to->array.v.type || + from->array.v.stride != to->array.v.stride || + from->array.v.p != to->array.v.p || + from->array.v.buffer != to->array.v.buffer) { + GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.v.buffer); + if (idHwArrayBufferUsed != idHwArrayBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed); + idHwArrayBuffer = idHwArrayBufferUsed; + } + diff_api.VertexPointer(to->array.v.size, to->array.v.type, + to->array.v.stride, to->array.v.p); + FILLDIRTY(cb->v); + FILLDIRTY(cb->clientPointer); + FILLDIRTY(cb->dirty); + } + CLEARDIRTY2(cb->v, bitID); + } + /* normal */ + if (CHECKDIRTY(cb->n, bitID)) { + if (from->array.n.type != to->array.n.type || + from->array.n.stride != to->array.n.stride || + from->array.n.p != to->array.n.p || + from->array.n.buffer != to->array.n.buffer) { + GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.n.buffer); + if (idHwArrayBufferUsed != idHwArrayBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed); + idHwArrayBuffer = idHwArrayBufferUsed; + } + diff_api.NormalPointer(to->array.n.type, + to->array.n.stride, to->array.n.p); + FILLDIRTY(cb->n); + FILLDIRTY(cb->clientPointer); + FILLDIRTY(cb->dirty); + } + CLEARDIRTY2(cb->n, bitID); + } + /* color */ + if (CHECKDIRTY(cb->c, bitID)) { + if (from->array.c.size != to->array.c.size || + from->array.c.type != to->array.c.type || + from->array.c.stride != to->array.c.stride || + from->array.c.p != to->array.c.p || + from->array.c.buffer != to->array.c.buffer) { + GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.c.buffer); + if (idHwArrayBufferUsed != idHwArrayBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed); + idHwArrayBuffer = idHwArrayBufferUsed; + } + diff_api.ColorPointer(to->array.c.size, to->array.c.type, + to->array.c.stride, to->array.c.p); + FILLDIRTY(cb->c); + FILLDIRTY(cb->clientPointer); + FILLDIRTY(cb->dirty); + } + CLEARDIRTY2(cb->c, bitID); + } + /* index */ + if (CHECKDIRTY(cb->i, bitID)) { + if (from->array.i.type != to->array.i.type || + from->array.i.stride != to->array.i.stride || + from->array.i.p != to->array.i.p || + from->array.i.buffer != to->array.i.buffer) { + GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.i.buffer); + if (idHwArrayBufferUsed != idHwArrayBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed); + idHwArrayBuffer = idHwArrayBufferUsed; + } + diff_api.IndexPointer(to->array.i.type, + to->array.i.stride, to->array.i.p); + FILLDIRTY(cb->i); + FILLDIRTY(cb->dirty); + FILLDIRTY(cb->clientPointer); + } + CLEARDIRTY2(cb->i, bitID); + } + /* texcoords */ + for (i = 0; (unsigned int)i < toCtx->limits.maxTextureUnits; i++) { + if (CHECKDIRTY(cb->t[i], bitID)) { + if (from->array.t[i].size != to->array.t[i].size || + from->array.t[i].type != to->array.t[i].type || + from->array.t[i].stride != to->array.t[i].stride || + from->array.t[i].p != to->array.t[i].p || + from->array.t[i].buffer != to->array.t[i].buffer) { + GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.t[i].buffer); + if (idHwArrayBufferUsed != idHwArrayBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed); + idHwArrayBuffer = idHwArrayBufferUsed; + } + diff_api.ClientActiveTextureARB(GL_TEXTURE0_ARB + i); + curClientTextureUnit = i; + diff_api.TexCoordPointer(to->array.t[i].size, to->array.t[i].type, + to->array.t[i].stride, to->array.t[i].p); + FILLDIRTY(cb->t[i]); + FILLDIRTY(cb->clientPointer); + FILLDIRTY(cb->dirty); + } + CLEARDIRTY2(cb->t[i], bitID); + } + } + /* edge flag */ + if (CHECKDIRTY(cb->e, bitID)) { + if (from->array.e.stride != to->array.e.stride || + from->array.e.p != to->array.e.p || + from->array.e.buffer != to->array.e.buffer) { + GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.e.buffer); + if (idHwArrayBufferUsed != idHwArrayBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed); + idHwArrayBuffer = idHwArrayBufferUsed; + } + diff_api.EdgeFlagPointer(to->array.e.stride, to->array.e.p); + FILLDIRTY(cb->e); + FILLDIRTY(cb->clientPointer); + FILLDIRTY(cb->dirty); + } + CLEARDIRTY2(cb->e, bitID); + } + /* secondary color */ + if (CHECKDIRTY(cb->s, bitID)) { + if (from->array.s.size != to->array.s.size || + from->array.s.type != to->array.s.type || + from->array.s.stride != to->array.s.stride || + from->array.s.p != to->array.s.p || + from->array.s.buffer != to->array.s.buffer) { + GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.s.buffer); + if (idHwArrayBufferUsed != idHwArrayBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed); + idHwArrayBuffer = idHwArrayBufferUsed; + } + diff_api.SecondaryColorPointerEXT(to->array.s.size, to->array.s.type, + to->array.s.stride, to->array.s.p); + FILLDIRTY(cb->s); + FILLDIRTY(cb->clientPointer); + FILLDIRTY(cb->dirty); + } + CLEARDIRTY2(cb->s, bitID); + } + /* fog coord */ + if (CHECKDIRTY(cb->f, bitID)) { + if (from->array.f.type != to->array.f.type || + from->array.f.stride != to->array.f.stride || + from->array.f.p != to->array.f.p || + from->array.f.buffer != to->array.f.buffer) { + GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.f.buffer); + if (idHwArrayBufferUsed != idHwArrayBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed); + idHwArrayBuffer = idHwArrayBufferUsed; + } + diff_api.FogCoordPointerEXT(to->array.f.type, + to->array.f.stride, to->array.f.p); + FILLDIRTY(cb->f); + FILLDIRTY(cb->clientPointer); + FILLDIRTY(cb->dirty); + } + CLEARDIRTY2(cb->f, bitID); + } +#if defined(CR_NV_vertex_program) || defined(CR_ARB_vertex_program) + /* vertex attributes */ + for (i = 0; (unsigned int)i < toCtx->limits.maxVertexProgramAttribs; i++) { + if (CHECKDIRTY(cb->a[i], bitID)) { + if (from->array.a[i].size != to->array.a[i].size || + from->array.a[i].type != to->array.a[i].type || + from->array.a[i].stride != to->array.a[i].stride || + from->array.a[i].normalized != to->array.a[i].normalized || + from->array.a[i].p != to->array.a[i].p || + from->array.a[i].buffer != to->array.a[i].buffer) { + GLint idHwArrayBufferUsed = CR_BUFFER_HWID(to->array.a[i].buffer); + if (idHwArrayBufferUsed != idHwArrayBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwArrayBufferUsed); + idHwArrayBuffer = idHwArrayBufferUsed; + } + diff_api.VertexAttribPointerARB(i, to->array.a[i].size, + to->array.a[i].type, + to->array.a[i].normalized, + to->array.a[i].stride, + to->array.a[i].p); + FILLDIRTY(cb->a[i]); + FILLDIRTY(cb->clientPointer); + FILLDIRTY(cb->dirty); + } + CLEARDIRTY2(cb->a[i], bitID); + } + } +#endif + } + + if (idHwArrayBuffer != idHwInitialBuffer) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, idHwInitialBuffer); + } + + if (CHECKDIRTY(cb->enableClientState, bitID)) { + /* update vertex array enable/disable flags */ + glAble able[2]; + able[0] = diff_api.DisableClientState; + able[1] = diff_api.EnableClientState; + if (from->array.v.enabled != to->array.v.enabled) { + able[to->array.v.enabled](GL_VERTEX_ARRAY); + FILLDIRTY(cb->enableClientState); + FILLDIRTY(cb->dirty); + } + if (from->array.n.enabled != to->array.n.enabled) { + able[to->array.n.enabled](GL_NORMAL_ARRAY); + FILLDIRTY(cb->enableClientState); + FILLDIRTY(cb->dirty); + } + if (from->array.c.enabled != to->array.c.enabled) { + able[to->array.c.enabled](GL_COLOR_ARRAY); + FILLDIRTY(cb->enableClientState); + FILLDIRTY(cb->dirty); + } + if (from->array.i.enabled != to->array.i.enabled) { + able[to->array.i.enabled](GL_INDEX_ARRAY); + FILLDIRTY(cb->enableClientState); + FILLDIRTY(cb->dirty); + } + for (i = 0; (unsigned int)i < toCtx->limits.maxTextureUnits; i++) { + if (from->array.t[i].enabled != to->array.t[i].enabled) { + diff_api.ClientActiveTextureARB(GL_TEXTURE0_ARB + i); + curClientTextureUnit = i; + able[to->array.t[i].enabled](GL_TEXTURE_COORD_ARRAY); + FILLDIRTY(cb->enableClientState); + FILLDIRTY(cb->dirty); + } + } + if (from->array.e.enabled != to->array.e.enabled) { + able[to->array.e.enabled](GL_EDGE_FLAG_ARRAY); + FILLDIRTY(cb->enableClientState); + FILLDIRTY(cb->dirty); + } + if (from->array.s.enabled != to->array.s.enabled) { + able[to->array.s.enabled](GL_SECONDARY_COLOR_ARRAY_EXT); + FILLDIRTY(cb->enableClientState); + FILLDIRTY(cb->dirty); + } + if (from->array.f.enabled != to->array.f.enabled) { + able[to->array.f.enabled](GL_FOG_COORDINATE_ARRAY_EXT); + FILLDIRTY(cb->enableClientState); + FILLDIRTY(cb->dirty); + } + for (i = 0; (unsigned int)i < toCtx->limits.maxVertexProgramAttribs; i++) { + if (from->array.a[i].enabled != to->array.a[i].enabled) { + if (to->array.a[i].enabled) + diff_api.EnableVertexAttribArrayARB(i); + else + diff_api.DisableVertexAttribArrayARB(i); + FILLDIRTY(cb->enableClientState); + FILLDIRTY(cb->dirty); + } + } + CLEARDIRTY2(cb->enableClientState, bitID); + } + + if (to->curClientTextureUnit != curClientTextureUnit) + { + diff_api.ClientActiveTextureARB(GL_TEXTURE0_ARB + to->curClientTextureUnit); + } + + if (CHECKDIRTY(cb->unpack, bitID)) + { + if (from->unpack.rowLength != to->unpack.rowLength) + { + diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, to->unpack.rowLength); + FILLDIRTY(cb->unpack); + FILLDIRTY(cb->dirty); + } + if (from->unpack.skipRows != to->unpack.skipRows) + { + diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, to->unpack.skipRows); + FILLDIRTY(cb->unpack); + FILLDIRTY(cb->dirty); + } + if (from->unpack.skipPixels != to->unpack.skipPixels) + { + diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, to->unpack.skipPixels); + FILLDIRTY(cb->unpack); + FILLDIRTY(cb->dirty); + } + if (from->unpack.alignment != to->unpack.alignment) + { + diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, to->unpack.alignment); + FILLDIRTY(cb->unpack); + FILLDIRTY(cb->dirty); + } + if (from->unpack.imageHeight != to->unpack.imageHeight) + { + diff_api.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, to->unpack.imageHeight); + FILLDIRTY(cb->unpack); + FILLDIRTY(cb->dirty); + } + if (from->unpack.skipImages != to->unpack.skipImages) + { + diff_api.PixelStorei(GL_UNPACK_SKIP_IMAGES, to->unpack.skipImages); + FILLDIRTY(cb->unpack); + FILLDIRTY(cb->dirty); + } + if (from->unpack.swapBytes != to->unpack.swapBytes) + { + diff_api.PixelStorei(GL_UNPACK_SWAP_BYTES, to->unpack.swapBytes); + FILLDIRTY(cb->unpack); + FILLDIRTY(cb->dirty); + } + if (from->unpack.psLSBFirst != to->unpack.psLSBFirst) + { + diff_api.PixelStorei(GL_UNPACK_LSB_FIRST, to->unpack.psLSBFirst); + FILLDIRTY(cb->unpack); + FILLDIRTY(cb->dirty); + } + CLEARDIRTY2(cb->unpack, bitID); + } + + if (CHECKDIRTY(cb->pack, bitID)) + { + if (from->pack.rowLength != to->pack.rowLength) + { + diff_api.PixelStorei(GL_PACK_ROW_LENGTH, to->pack.rowLength); + FILLDIRTY(cb->pack); + FILLDIRTY(cb->dirty); + } + if (from->pack.skipRows != to->pack.skipRows) + { + diff_api.PixelStorei(GL_PACK_SKIP_ROWS, to->pack.skipRows); + FILLDIRTY(cb->pack); + FILLDIRTY(cb->dirty); + } + if (from->pack.skipPixels != to->pack.skipPixels) + { + diff_api.PixelStorei(GL_PACK_SKIP_PIXELS, to->pack.skipPixels); + FILLDIRTY(cb->pack); + FILLDIRTY(cb->dirty); + } + if (from->pack.alignment != to->pack.alignment) + { + diff_api.PixelStorei(GL_PACK_ALIGNMENT, to->pack.alignment); + FILLDIRTY(cb->pack); + FILLDIRTY(cb->dirty); + } + if (from->pack.imageHeight != to->pack.imageHeight) + { + diff_api.PixelStorei(GL_PACK_IMAGE_HEIGHT, to->pack.imageHeight); + FILLDIRTY(cb->pack); + FILLDIRTY(cb->dirty); + } + if (from->pack.skipImages != to->pack.skipImages) + { + diff_api.PixelStorei(GL_PACK_SKIP_IMAGES, to->pack.skipImages); + FILLDIRTY(cb->pack); + FILLDIRTY(cb->dirty); + } + if (from->pack.swapBytes != to->pack.swapBytes) + { + diff_api.PixelStorei(GL_PACK_SWAP_BYTES, to->pack.swapBytes); + FILLDIRTY(cb->pack); + FILLDIRTY(cb->dirty); + } + if (from->pack.psLSBFirst != to->pack.psLSBFirst) + { + diff_api.PixelStorei(GL_PACK_LSB_FIRST, to->pack.psLSBFirst); + FILLDIRTY(cb->pack); + FILLDIRTY(cb->dirty); + } + CLEARDIRTY2(cb->pack, bitID); + } + + CLEARDIRTY2(cb->dirty, bitID); +} + +CRClientPointer* crStateGetClientPointerByIndex(int index, CRVertexArrays *array) +{ + CRASSERT(array && index>=0 && index<CRSTATECLIENT_MAX_VERTEXARRAYS); + + if (array == NULL || index < 0 || index >= CRSTATECLIENT_MAX_VERTEXARRAYS) + { + return NULL; + } + + if (index < 7) + { + switch (index) + { + case 0: return &array->v; + case 1: return &array->c; + case 2: return &array->f; + case 3: return &array->s; + case 4: return &array->e; + case 5: return &array->i; + case 6: return &array->n; + } + } + else if (index<(7+CR_MAX_TEXTURE_UNITS)) + { + return &array->t[index-7]; + } + else + { + return &array->a[index-7-CR_MAX_TEXTURE_UNITS]; + } + + /*silence the compiler warning*/ + CRASSERT(false); + return NULL; +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_client.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_client.txt new file mode 100644 index 00000000..bdf7a729 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_client.txt @@ -0,0 +1,32 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +:unpack:unpack.rowLength:PixelStorei,GL_UNPACK_ROW_LENGTH +#:unpack:unpack.skipImages:PixelStorei,GL_UNPACK_SKIP_IMAGES +:unpack:unpack.skipRows:PixelStorei,GL_UNPACK_SKIP_ROWS +:unpack:unpack.skipPixels:PixelStorei,GL_UNPACK_SKIP_PIXELS +#:unpack:unpack.imageHeight:PixelStorei,GL_UNPACK_IMAGE_HEIGHT +:pack:pack.rowLength:PixelStorei,GL_PACK_ROW_LENGTH +#:pack:pack.skipImages:PixelStorei,GL_PACK_SKIP_IMAGES +:pack:pack.skipRows:PixelStorei,GL_PACK_SKIP_ROWS +:pack:pack.skipPixels:PixelStorei,GL_PACK_SKIP_PIXELS +#:pack:pack.imageHeight:PixelStorei,GL_PACK_IMAGE_HEIGHT +#:clientPointer:v.size,v.type,v.stride,v.p:VertexPointer +#:clientPointer:c.size,c.type,c.stride,c.p:ColorPointer +#:clientPointer:s.size,s.type,s.stride,s.p:SecondaryColorPointerEXT +#:clientPointer:i.type,i.stride,i.p:IndexPointer +#:clientPointer:n.type,n.stride,n.p:NormalPointer +#:clientPointer:t.size,t.type,t.stride,t.p:TexCoordPointer +#:clientPointer:e.stride,e.p:EdgeFlagPointer +#:enableClientState:*glAble able[2]; +#:enableClientState:*able[0] = diff_api.DisableClientState; +#:enableClientState:*able[1] = diff_api.EnableClientState; +#:enableClientState:v.enabled:*able[to->v.enabled](GL_VERTEX_ARRAY); +#:enableClientState:c.enabled:*able[to->c.enabled](GL_COLOR_ARRAY); +#:enableClientState:i.enabled:*able[to->i.enabled](GL_INDEX_ARRAY); +#:enableClientState:n.enabled:*able[to->n.enabled](GL_NORMAL_ARRAY); +#:enableClientState:t.enabled:*able[to->t.enabled](GL_TEXTURE_COORD_ARRAY); +#:enableClientState:e.enabled:*able[to->e.enabled](GL_EDGE_FLAG_ARRAY); +#:enableClientState:s.enabled:*able[to->s.enabled](GL_SECONDARY_COLOR_ARRAY_EXT); +#+:element:*crError( "element in client state DiffContext!" ); /* __glclient_SendUpdates(b, bitID, from, to); */ diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_current.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_current.c new file mode 100644 index 00000000..511f997d --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_current.c @@ -0,0 +1,435 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "cr_mem.h" +#include "state.h" +#include "state_internals.h" + +/* + * Note: regardless of GL_NV_vertex_program, we store all per-vertex + * attributes in an array now, instead of specially named attributes + * like color, normal, texcoord, etc. + */ + + +void crStateCurrentInit( CRContext *ctx ) +{ + CRCurrentState *c = &ctx->current; + CRStateBits *sb = GetCurrentBits(); + CRCurrentBits *cb = &(sb->current); + static const GLfloat default_normal[4] = {0.0f, 0.0f, 1.0f, 1.0f}; + static const GLfloat default_color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + static const GLfloat default_secondaryColor[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + static const GLfloat default_attrib[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + unsigned int i; + + /* + * initialize all vertex attributes to <0,0,0,1> for starters + */ + for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++) { + COPY_4V(c->vertexAttrib[i], default_attrib); + COPY_4V(c->vertexAttribPre[i], default_attrib); + } + /* now re-do the exceptions */ + COPY_4V(c->vertexAttrib[VERT_ATTRIB_COLOR0], default_color); + COPY_4V(c->vertexAttrib[VERT_ATTRIB_COLOR1], default_secondaryColor); + COPY_4V(c->vertexAttrib[VERT_ATTRIB_NORMAL], default_normal); + + c->rasterIndex = 1.0f; + c->colorIndex = c->colorIndexPre = 1.0; + c->edgeFlag = c->edgeFlagPre = GL_TRUE; + + /* Set the "pre" values and raster position attributes */ + for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++) { + COPY_4V(c->vertexAttribPre[i], c->vertexAttrib[i]); + COPY_4V(c->rasterAttrib[i], c->vertexAttrib[i]); + COPY_4V(c->rasterAttribPre[i], c->vertexAttrib[i]); + } + + c->rasterValid = GL_TRUE; + + c->inBeginEnd = GL_FALSE; + c->beginEndNum = 0; + /*c->beginEndMax = cfg->beginend_max;*/ + c->mode = 0x10; /* Undefined Mode */ + c->flushOnEnd = 0; + + c->current = 0; /* picked up by crStateSetCurrentPointers() */ + + /* init dirty bits */ + RESET(cb->dirty, ctx->bitid); + for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++) { + RESET(cb->vertexAttrib[i], ctx->bitid); + } + RESET(cb->edgeFlag, ctx->bitid); + RESET(cb->colorIndex, ctx->bitid); + RESET(cb->rasterPos, ctx->bitid); +} + +void STATE_APIENTRY crStateColor3f( GLfloat r, GLfloat g, GLfloat b ) +{ + crStateColor4f(r, g, b, 1.0F); +} + +void STATE_APIENTRY crStateColor3fv( const GLfloat *color ) +{ + crStateColor4f( color[0], color[1], color[2], 1.0F ); +} + +void STATE_APIENTRY crStateColor4f( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ) +{ + CRContext *g = GetCurrentContext(); + CRCurrentState *c = &(g->current); + CRStateBits *sb = GetCurrentBits(); + CRCurrentBits *cb = &(sb->current); + + FLUSH(); + + c->vertexAttrib[VERT_ATTRIB_COLOR0][0] = red; + c->vertexAttrib[VERT_ATTRIB_COLOR0][1] = green; + c->vertexAttrib[VERT_ATTRIB_COLOR0][2] = blue; + c->vertexAttrib[VERT_ATTRIB_COLOR0][3] = alpha; + + DIRTY(cb->dirty, g->neg_bitid); + DIRTY(cb->vertexAttrib[VERT_ATTRIB_COLOR0], g->neg_bitid); +} + +void STATE_APIENTRY crStateColor4fv( const GLfloat *color ) +{ + crStateColor4f( color[0], color[1], color[2], color[3] ); +} + +void crStateSetCurrentPointers( CRContext *ctx, CRCurrentStatePointers *current ) +{ + CRCurrentState *c = &(ctx->current); + c->current = current; +} + +void crStateResetCurrentPointers( CRCurrentStatePointers *current ) +{ + uint32_t attribsUsedMask = current->attribsUsedMask; + + crMemset(current, 0, sizeof (*current)); + + current->attribsUsedMask = attribsUsedMask; +} + +void STATE_APIENTRY crStateBegin( GLenum mode ) +{ + CRContext *g = GetCurrentContext(); + CRCurrentState *c = &(g->current); + + if (mode > GL_POLYGON) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Begin called with invalid mode: %d", mode); + return; + } + + if (c->inBeginEnd) + { + crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "glBegin called inside Begin/End"); + return; + } + + c->attribsUsedMask = 0; + c->inBeginEnd = GL_TRUE; + c->mode = mode; + c->beginEndNum++; +} + +void STATE_APIENTRY crStateEnd( void ) +{ + CRContext *g = GetCurrentContext(); + CRCurrentState *c = &(g->current); + + if (!c->inBeginEnd) + { + crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "glEnd called outside Begin/End" ); + return; + } + + c->inBeginEnd = GL_FALSE; +} + +void crStateCurrentSwitch( CRCurrentBits *c, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx ) +{ + const CRCurrentState *from = &(fromCtx->current); + const CRCurrentState *to = &(toCtx->current); + const GLuint maxTextureUnits = fromCtx->limits.maxTextureUnits; + unsigned int i, j; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + + for (j=0;j<CR_MAX_BITARRAY;j++) + nbitID[j] = ~bitID[j]; + + if (CHECKDIRTY(c->rasterPos, bitID)) { + if (to->rasterValid) { + const GLfloat fromX = from->rasterAttrib[VERT_ATTRIB_POS][0]; + const GLfloat fromY = from->rasterAttrib[VERT_ATTRIB_POS][1]; + const GLfloat fromZ = from->rasterAttrib[VERT_ATTRIB_POS][2]; + const GLfloat toX = to->rasterAttrib[VERT_ATTRIB_POS][0]; + const GLfloat toY = to->rasterAttrib[VERT_ATTRIB_POS][1]; + const GLfloat toZ = to->rasterAttrib[VERT_ATTRIB_POS][2]; + if (toX != fromX || toY != fromY || toZ != fromZ) { + /* Use glWindowPos (which updates raster color) */ + diff_api.WindowPos3fvARB(to->rasterAttrib[VERT_ATTRIB_POS]); + FILLDIRTY(c->rasterPos); + FILLDIRTY(c->dirty); + } + } + CLEARDIRTY(c->rasterPos, nbitID); + } + + /* Vertex Current State Switch Code */ + + /* Its important that we don't do a value check here because + ** current may not actually have the correct values, I think... + ** We also need to restore the current state tracking pointer + ** since the packing functions will set it. + */ + + if (CHECKDIRTY(c->colorIndex, bitID)) { + if (to->colorIndex != from->colorIndex) { + diff_api.Indexf(to->colorIndex); + FILLDIRTY(c->colorIndex); + FILLDIRTY(c->dirty); + } + CLEARDIRTY(c->colorIndex, nbitID); + } + + if (CHECKDIRTY(c->edgeFlag, bitID)) { + if (to->edgeFlag != from->edgeFlag) { + diff_api.EdgeFlag(to->edgeFlag); + FILLDIRTY(c->edgeFlag); + FILLDIRTY(c->dirty); + } + CLEARDIRTY(c->edgeFlag, nbitID); + } + + /* If using a vertex program, update the generic vertex attributes, + * which may or may not be aliased with conventional attributes. + */ +#if defined(CR_ARB_vertex_program) || defined(CR_NV_vertex_progra) + if (toCtx->program.vpEnabled && + (toCtx->extensions.ARB_vertex_program || + (toCtx->extensions.NV_vertex_program))) { + const unsigned attribsUsedMask = toCtx->current.attribsUsedMask; + for (i = 1; i < CR_MAX_VERTEX_ATTRIBS; i++) { /* skip zero */ + if ((attribsUsedMask & (1 << i)) + && CHECKDIRTY(c->vertexAttrib[i], bitID)) { + if (COMPARE_VECTOR (from->vertexAttrib[i], to->vertexAttribPre[i])) { + diff_api.VertexAttrib4fvARB(i, &(to->vertexAttrib[i][0])); + FILLDIRTY(c->vertexAttrib[i]); + FILLDIRTY(c->dirty); + } + CLEARDIRTY(c->vertexAttrib[i], nbitID); + } + } + } + /* Fall-through so that attributes which don't have their bit set in the + * attribsUsedMask get handled via the conventional attribute functions. + */ +#endif + + { + /* use conventional attribute functions */ + + /* NEED TO FIX THIS!!!!!! */ + if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR0], bitID)) { + if (COMPARE_COLOR(from->vertexAttrib[VERT_ATTRIB_COLOR0],to->vertexAttrib[VERT_ATTRIB_COLOR0])) { + diff_api.Color4fv ((GLfloat *) &(to->vertexAttrib[VERT_ATTRIB_COLOR0])); + FILLDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR0]); + FILLDIRTY(c->dirty); + } + CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR0], nbitID); + } + + /* NEED TO FIX THIS, ALSO?!!!!! */ +#ifdef CR_EXT_secondary_color + if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR1], bitID)) { + if (COMPARE_COLOR(from->vertexAttrib[VERT_ATTRIB_COLOR1],to->vertexAttrib[VERT_ATTRIB_COLOR1])) { + diff_api.SecondaryColor3fvEXT ((GLfloat *) &(to->vertexAttrib[VERT_ATTRIB_COLOR1])); + FILLDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR1]); + FILLDIRTY(c->dirty); + } + CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR1], nbitID); + } +#endif + + /* NEED TO FIX THIS, ALSO?!!!!! */ +#ifdef CR_EXT_fog_coord + if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_FOG], bitID)) { + if (from->vertexAttrib[VERT_ATTRIB_FOG][0] != to->vertexAttrib[VERT_ATTRIB_FOG][0] ) { + diff_api.FogCoordfvEXT ((GLfloat *) &(to->vertexAttrib[VERT_ATTRIB_FOG][0] )); + FILLDIRTY(c->vertexAttrib[VERT_ATTRIB_FOG]); + FILLDIRTY(c->dirty); + } + CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_FOG], nbitID); + } +#endif + + if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_NORMAL], bitID)) { + if (COMPARE_VECTOR (from->vertexAttrib[VERT_ATTRIB_NORMAL], to->vertexAttrib[VERT_ATTRIB_NORMAL])) { + diff_api.Normal3fv ((GLfloat *) &(to->vertexAttrib[VERT_ATTRIB_NORMAL][0])); + FILLDIRTY(c->vertexAttrib[VERT_ATTRIB_NORMAL]); + FILLDIRTY(c->dirty); + } + CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_NORMAL], nbitID); + } + + for (i = 0; i < maxTextureUnits; i++) { + if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_TEX0 + i], bitID)) { + if (COMPARE_TEXCOORD (from->vertexAttrib[VERT_ATTRIB_TEX0 + i], to->vertexAttribPre[VERT_ATTRIB_TEX0 + i])) { + diff_api.MultiTexCoord4fvARB (i+GL_TEXTURE0_ARB, (GLfloat *) &(to->vertexAttrib[VERT_ATTRIB_TEX0+ i][0])); + FILLDIRTY(c->vertexAttrib[VERT_ATTRIB_TEX0 + i]); + FILLDIRTY(c->dirty); + } + CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_TEX0 + i], nbitID); + } + } + } + + CLEARDIRTY(c->dirty, nbitID); +} + +void +crStateCurrentDiff( CRCurrentBits *c, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx ) +{ + CRCurrentState *from = &(fromCtx->current); + const CRCurrentState *to = &(toCtx->current); + unsigned int i, j; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + + for (j=0;j<CR_MAX_BITARRAY;j++) + nbitID[j] = ~bitID[j]; + + if (CHECKDIRTY(c->rasterPos, bitID)) { + from->rasterValid = to->rasterValid; + if (to->rasterValid) { + const GLfloat fromX = from->rasterAttrib[VERT_ATTRIB_POS][0]; + const GLfloat fromY = from->rasterAttrib[VERT_ATTRIB_POS][1]; + const GLfloat fromZ = from->rasterAttrib[VERT_ATTRIB_POS][2]; + const GLfloat toX = to->rasterAttrib[VERT_ATTRIB_POS][0]; + const GLfloat toY = to->rasterAttrib[VERT_ATTRIB_POS][1]; + const GLfloat toZ = to->rasterAttrib[VERT_ATTRIB_POS][2]; + if (toX != fromX || toY != fromY || toZ != fromZ) { + /* Use glWindowPos (which updates raster color) */ + diff_api.WindowPos3fvARB(to->rasterAttrib[VERT_ATTRIB_POS]); + from->rasterAttrib[VERT_ATTRIB_POS][0] = toX; + from->rasterAttrib[VERT_ATTRIB_POS][1] = toY; + from->rasterAttrib[VERT_ATTRIB_POS][2] = toZ; + } + } + CLEARDIRTY(c->rasterPos, nbitID); + } + + /* Vertex Current State Sync Code */ + /* Some things to note here: + ** 1) Compare is done against the pre value since the + ** current value includes the geometry info. + ** 2) Update is done with the current value since + ** the server will be getting the geometry block + ** 3) Copy is done outside of the compare to ensure + ** that it happens. + */ + + /* edge flag */ + if (CHECKDIRTY(c->edgeFlag, bitID)) { + if (from->edgeFlag != to->edgeFlagPre) { + diff_api.EdgeFlag (to->edgeFlagPre); + } + from->edgeFlag = to->edgeFlag; + CLEARDIRTY(c->edgeFlag, nbitID); + } + + /* color index */ + if (CHECKDIRTY(c->colorIndex, bitID)) { + if (from->colorIndex != to->colorIndexPre) { + diff_api.Indexf (to->colorIndex); + } + from->colorIndex = to->colorIndex; + CLEARDIRTY(c->colorIndex, nbitID); + } + + + /* If using a vertex program, update the generic vertex attributes, + * which may or may not be aliased with conventional attributes. + */ +#if defined(CR_ARB_vertex_program) || defined(CR_NV_vertex_progra) + if (toCtx->program.vpEnabled && + (toCtx->extensions.ARB_vertex_program || + (toCtx->extensions.NV_vertex_program))) { + const unsigned attribsUsedMask = toCtx->current.attribsUsedMask; + for (i = 1; i < CR_MAX_VERTEX_ATTRIBS; i++) { /* skip zero */ + if ((attribsUsedMask & (1 << i)) + && CHECKDIRTY(c->vertexAttrib[i], bitID)) { + if (COMPARE_VECTOR (from->vertexAttrib[i], to->vertexAttribPre[i])) { + diff_api.VertexAttrib4fvARB(i, &(to->vertexAttribPre[i][0])); + } + COPY_4V(from->vertexAttrib[i] , to->vertexAttrib[i]); + CLEARDIRTY(c->vertexAttrib[i], nbitID); + } + } + } + /* Fall-through so that attributes which don't have their bit set in the + * attribsUsedMask get handled via the conventional attribute functions. + */ +#endif + + { + /* use conventional attribute functions */ + if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR0], bitID)) { + if (COMPARE_COLOR(from->vertexAttrib[VERT_ATTRIB_COLOR0],to->vertexAttribPre[VERT_ATTRIB_COLOR0])) { + diff_api.Color4fv ((GLfloat *) &(to->vertexAttribPre[VERT_ATTRIB_COLOR0])); + } + COPY_4V(from->vertexAttrib[VERT_ATTRIB_COLOR0] , to->vertexAttrib[VERT_ATTRIB_COLOR0]); + CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR0], nbitID); + } + +#ifdef CR_EXT_secondary_color + if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR1], bitID)) { + if (COMPARE_COLOR(from->vertexAttrib[VERT_ATTRIB_COLOR1],to->vertexAttribPre[VERT_ATTRIB_COLOR1])) { + diff_api.SecondaryColor3fvEXT ((GLfloat *) &(to->vertexAttribPre[VERT_ATTRIB_COLOR1])); + } + COPY_4V(from->vertexAttrib[VERT_ATTRIB_COLOR1] , to->vertexAttrib[VERT_ATTRIB_COLOR1]); + CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR1], nbitID); + } +#endif + +#ifdef CR_EXT_fog_coord + if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_FOG], bitID)) { + if (from->vertexAttrib[VERT_ATTRIB_FOG] != to->vertexAttribPre[VERT_ATTRIB_FOG]) { + diff_api.FogCoordfvEXT ((GLfloat *) &(to->vertexAttribPre[VERT_ATTRIB_FOG])); + } + COPY_4V(from->vertexAttrib[VERT_ATTRIB_FOG] , to->vertexAttrib[VERT_ATTRIB_FOG]); + CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_FOG], nbitID); + } +#endif + + if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_NORMAL], bitID)) { + if (COMPARE_VECTOR (from->vertexAttrib[VERT_ATTRIB_NORMAL], to->vertexAttribPre[VERT_ATTRIB_NORMAL])) { + diff_api.Normal3fv ((GLfloat *) &(to->vertexAttribPre[VERT_ATTRIB_NORMAL])); + } + COPY_4V(from->vertexAttrib[VERT_ATTRIB_NORMAL] , to->vertexAttrib[VERT_ATTRIB_NORMAL]); + CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_NORMAL], nbitID); + } + + for ( i = 0 ; i < fromCtx->limits.maxTextureUnits ; i++) + { + if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_TEX0 + i], bitID)) { + if (COMPARE_TEXCOORD (from->vertexAttrib[VERT_ATTRIB_TEX0 + i], to->vertexAttribPre[VERT_ATTRIB_TEX0 + i])) { + diff_api.MultiTexCoord4fvARB (GL_TEXTURE0_ARB + i, (GLfloat *) &(to->vertexAttribPre[VERT_ATTRIB_TEX0 + i])); + } + COPY_4V(from->vertexAttrib[VERT_ATTRIB_TEX0 + i] , to->vertexAttrib[VERT_ATTRIB_TEX0 + i]); + CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_TEX0 + i], nbitID); + } + } + } + + CLEARDIRTY(c->dirty, nbitID); +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_current.py b/src/VBox/GuestHost/OpenGL/state_tracker/state_current.py new file mode 100755 index 00000000..49a54aed --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_current.py @@ -0,0 +1,485 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys + +from pack_currenttypes import * +import apiutil + +apiutil.CopyrightC() + +print(''' +#include "state/cr_currentpointers.h" +#include "state.h" + +#include <stdio.h> + +#ifdef WINDOWS +#pragma warning( disable : 4127 ) +#endif + +typedef void (*convert_func) (GLfloat *, const unsigned char *); +''') + +import convert + +for k in sorted(current_fns.keys()): + name = k + name = '%s%s' % (k[:1].lower(),k[1:]) + ucname = k.upper() + num_members = len(current_fns[k]['default']) + 1 + + print('#define VPINCH_CONVERT_%s(op,data,dst) \\' % ucname) + print('{\\') + print('\tGLfloat vdata[%d] = {' % num_members, end=' ') + +## Copy dst data into vdata + i = 0; + for defaultvar in current_fns[k]['default']: + print('%d' % defaultvar, end=' ') + if i != num_members: + print(',', end=' ') + i += 1 + print('};\\') + + print('\tswitch (op) { \\') + for type in current_fns[k]['types']: + if type[0:1] == "N": + normalize = 1 + type = type[1:] + else: + normalize = 0 + for size in current_fns[k]['sizes']: + uctype = type.upper() + if ucname == 'EDGEFLAG': + print('\tcase CR_%s_OPCODE: \\' % ucname) + else: + print('\tcase CR_%s%d%s_OPCODE: \\' % (ucname,size,uctype)) + + if (ucname == 'COLOR' or ucname == 'NORMAL' or ucname == 'SECONDARYCOLOR' or normalize) and type != 'f' and type != 'd': + print('\t\t__convert_rescale_%s%d (vdata, (%s *) (data)); \\' % (type,size,gltypes[type]['type'])) + else: + print('\t\t__convert_%s%d (vdata, (%s *) (data)); \\' % (type,size,gltypes[type]['type'])) + print('\t\tbreak; \\') + + print('\tdefault: \\') + print('\t\tcrSimpleError ( "Unknown opcode in VPINCH_CONVERT_%s" ); \\' % ucname) + print('\t}\\') + + i = 0 + for member in current_fns[k]['members']: + print('\t(dst).%s = vdata[%d];\\' % (member,i)) + i += 1 + + print('}\n') + +print(''' + +void crStateCurrentRecover( void ) +{ + const unsigned char *v; + convert_func convert=NULL; + CRContext *g = GetCurrentContext(); + CRCurrentState *c = &(g->current); + CRStateBits *sb = GetCurrentBits(); + CRCurrentBits *cb = &(sb->current); + static const GLfloat color_default[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + static const GLfloat secondaryColor_default[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + static const GLfloat texCoord_default[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + static const GLfloat normal_default[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + static const GLfloat index_default = 0.0f; + static const GLboolean edgeFlag_default = GL_TRUE; + static const GLfloat vertexAttrib_default[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + static const GLfloat fogCoord_default = 0.0f; + GLnormal_p *normal = &(c->current->c.normal); + GLcolor_p *color = &(c->current->c.color); + GLsecondarycolor_p *secondaryColor = &(c->current->c.secondaryColor); + GLtexcoord_p *texCoord = &(c->current->c.texCoord); + GLindex_p *index = &(c->current->c.index); + GLedgeflag_p *edgeFlag = &(c->current->c.edgeFlag); + GLvertexattrib_p *vertexAttrib = &(c->current->c.vertexAttrib); + GLfogcoord_p *fogCoord = &(c->current->c.fogCoord); + unsigned int i; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + + /* + * If the calling SPU hasn't called crStateSetCurrentPointers() + * we can't recover anything, so abort now. (i.e. we don't have + * a pincher, oh, and just emit the message once). + */ + if (!c->current) { + static int donewarning = 0; + if (!donewarning) + crWarning("No pincher, please call crStateSetCurrentPointers() in your SPU"); + donewarning = 1; + return; /* never get here */ + } + + c->attribsUsedMask = c->current->attribsUsedMask; + + /* silence warnings */ + (void) __convert_b1; + (void) __convert_b2; + (void) __convert_b3; + (void) __convert_b4; + (void) __convert_ui1; + (void) __convert_ui2; + (void) __convert_ui3; + (void) __convert_ui4; + (void) __convert_l1; + (void) __convert_l2; + (void) __convert_l3; + (void) __convert_l4; + (void) __convert_us1; + (void) __convert_us2; + (void) __convert_us3; + (void) __convert_us4; + (void) __convert_ub1; + (void) __convert_ub2; + (void) __convert_ub3; + (void) __convert_ub4; + (void) __convert_rescale_s1; + (void) __convert_rescale_s2; + (void) __convert_rescale_b1; + (void) __convert_rescale_b2; + (void) __convert_rescale_ui1; + (void) __convert_rescale_ui2; + (void) __convert_rescale_i1; + (void) __convert_rescale_i2; + (void) __convert_rescale_us1; + (void) __convert_rescale_us2; + (void) __convert_rescale_ub1; + (void) __convert_rescale_ub2; + (void) __convert_Ni1; + (void) __convert_Ni2; + (void) __convert_Ni3; + (void) __convert_Ni4; + (void) __convert_Nb1; + (void) __convert_Nb2; + (void) __convert_Nb3; + (void) __convert_Nb4; + (void) __convert_Nus1; + (void) __convert_Nus2; + (void) __convert_Nus3; + (void) __convert_Nus4; + (void) __convert_Nui1; + (void) __convert_Nui2; + (void) __convert_Nui3; + (void) __convert_Nui4; + (void) __convert_Ns1; + (void) __convert_Ns2; + (void) __convert_Ns3; + (void) __convert_Ns4; + (void) __convert_Nub1; + (void) __convert_Nub2; + (void) __convert_Nub3; + (void) __convert_Nub4; + + DIRTY(nbitID, g->neg_bitid); + + /* Save pre state */ + for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++) { + COPY_4V(c->vertexAttribPre[i] , c->vertexAttrib[i]); + } + c->edgeFlagPre = c->edgeFlag; + c->colorIndexPre = c->colorIndex; + +''') + +for k in sorted(current_fns.keys()): + print('\t/* %s */' % k) + print('\tv = NULL;') + name = '%s%s' % (k[:1].lower(),k[1:]) + + indent = "" + if 'array' in current_fns[k]: + print('\tfor (i = 0; i < %s; i++)' % current_fns[k]['array']) + print('\t{') + indent += "\t" + for type in current_fns[k]['types']: + if type[0:1] == "N": + normalized = 1 + type2 = type[1:] + else: + normalized = 0 + type2 = type + for size in current_fns[k]['sizes']: + ptr = '%s->%s%d' % (name, type, size ) + if 'array' in current_fns[k]: + ptr += "[i]" + print('%s\tif (v < %s)' % (indent, ptr)) + print('%s\t{' % indent) + print('%s\t\tv = %s;' % (indent, ptr)) + if (k == 'Color' or k == 'Normal' or k == 'SecondaryColor' or normalized) and type != 'f' and type != 'd' and type != 'l': + print('%s\t\tconvert = (convert_func) __convert_rescale_%s%d;' % (indent,type,size)) + else: + print('%s\t\tconvert = (convert_func) __convert_%s%d;' % (indent,type,size)) + print('%s\t}' % indent) + print('') + print('%s\tif (v != NULL) {' % indent) + if 'array' in current_fns[k]: + if k == 'TexCoord': + print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_TEX0 + i], %s_default);' % (indent,name)) + else: + print('%s\t\tCOPY_4V(c->%s[i], %s_default);' % (indent,name,name)) + else: + if k == 'Normal': + print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_NORMAL], %s_default);' % (indent,name)) + elif k == 'FogCoord': + print('%s\t\tc->vertexAttrib[VERT_ATTRIB_FOG][0] = %s_default;' % (indent,name)) + elif k == 'Color': + print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_COLOR0], %s_default);' % (indent,name)) + elif k == 'SecondaryColor': + print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_COLOR1], %s_default);' % (indent,name)) + elif k == 'TexCoord': + print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_TEX0], %s_default);' % (indent,name)) + elif k == 'Index': + print('%s\t\tc->colorIndex = %s_default;' % (indent,name)) + elif k == 'EdgeFlag': + print('%s\t\tc->edgeFlag = %s_default;' % (indent,name)) + else: + print('%s\t\tc->%s = %s_default;' % (indent,name,name)) + if k == 'EdgeFlag': + print('%s\t\t__convert_boolean (&c->edgeFlag, v);' % (indent)) + dirtyVar = 'cb->edgeFlag' + elif k == 'Normal': + print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_NORMAL][0]), v);' % (indent)) + dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_NORMAL]' + elif k == 'TexCoord': + print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_TEX0 + i][0]), v);' % (indent)) + dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_TEX0 + i]' + elif k == 'Color': + print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_COLOR0][0]), v);' % (indent)) + dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_COLOR0]' + elif k == 'Index': + print('%s\t\tconvert(&(c->colorIndex), v);' % (indent)) + dirtyVar = 'cb->colorIndex' + elif k == 'SecondaryColor': + print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_COLOR1][0]), v);' % (indent)) + dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_COLOR1]' + elif k == 'FogCoord': + print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_FOG][0]), v);' % (indent)) + dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_FOG]' + elif k == 'VertexAttrib': + print('%s\t\tconvert(&(c->vertexAttrib[i][0]), v);' % (indent)) + dirtyVar = 'cb->vertexAttrib[i]' + else: + assert 0 # should never get here + + print('%s\t\tDIRTY(%s, nbitID);' % (indent, dirtyVar)) + +# if current_fns[k].has_key( 'array' ): +# print '%s\t\tDIRTY(cb->%s[i], nbitID);' % (indent,name) +# else: +# print '%s\t\tDIRTY(cb->%s, nbitID);' % (indent,name) + + + + print('%s\t\tDIRTY(cb->dirty, nbitID);' % indent) + print('%s\t}' % indent) + if 'array' in current_fns[k]: + print('%s\t%s->ptr[i] = v;' % (indent, name )) + else: + print('%s\t%s->ptr = v;' % (indent, name )) + if 'array' in current_fns[k]: + print('\t}') +print('}') + +print(''' + +void crStateCurrentRecoverNew(CRContext *g, CRCurrentStatePointers *current) +{ + const unsigned char *v; + convert_func convert=NULL; + CRCurrentState *c = &(g->current); + CRStateBits *sb = GetCurrentBits(); + CRCurrentBits *cb = &(sb->current); + + static const GLfloat vertexAttrib_default[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + + GLvertexattrib_p *vertexAttrib = &(current->c.vertexAttrib); + + unsigned int i; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + + /* Invalid parameters, do nothing */ + if (!g || !current) + return; + + /* silence warnings */ + (void) __convert_b1; + (void) __convert_b2; + (void) __convert_b3; + (void) __convert_b4; + (void) __convert_ui1; + (void) __convert_ui2; + (void) __convert_ui3; + (void) __convert_ui4; + (void) __convert_l1; + (void) __convert_l2; + (void) __convert_l3; + (void) __convert_l4; + (void) __convert_us1; + (void) __convert_us2; + (void) __convert_us3; + (void) __convert_us4; + (void) __convert_ub1; + (void) __convert_ub2; + (void) __convert_ub3; + (void) __convert_ub4; + (void) __convert_rescale_s1; + (void) __convert_rescale_s2; + (void) __convert_rescale_b1; + (void) __convert_rescale_b2; + (void) __convert_rescale_ui1; + (void) __convert_rescale_ui2; + (void) __convert_rescale_i1; + (void) __convert_rescale_i2; + (void) __convert_rescale_us1; + (void) __convert_rescale_us2; + (void) __convert_rescale_ub1; + (void) __convert_rescale_ub2; + (void) __convert_Ni1; + (void) __convert_Ni2; + (void) __convert_Ni3; + (void) __convert_Ni4; + (void) __convert_Nb1; + (void) __convert_Nb2; + (void) __convert_Nb3; + (void) __convert_Nb4; + (void) __convert_Nus1; + (void) __convert_Nus2; + (void) __convert_Nus3; + (void) __convert_Nus4; + (void) __convert_Nui1; + (void) __convert_Nui2; + (void) __convert_Nui3; + (void) __convert_Nui4; + (void) __convert_Ns1; + (void) __convert_Ns2; + (void) __convert_Ns3; + (void) __convert_Ns4; + (void) __convert_Nub1; + (void) __convert_Nub2; + (void) __convert_Nub3; + (void) __convert_Nub4; + + DIRTY(nbitID, g->neg_bitid); + +''') + +for k in sorted(current_fns_new.keys()): + print('\t/* %s */' % k) + print('\tif (current->changed%s)' % k) + print('\t{') + print('\t\tv=NULL;') + name = '%s%s' % (k[:1].lower(),k[1:]) + + indent = "" + if 'array' in current_fns_new[k]: + print('\t\tfor (i = 0; i < %s; i++)' % current_fns_new[k]['array']) + print('\t\t{') + indent += "\t\t" + print('\t\tif (!(current->changed%s & (1 << i))) continue;' % k) + for type in current_fns_new[k]['types']: + if type[0:1] == "N": + normalized = 1 + type2 = type[1:] + else: + normalized = 0 + type2 = type + for size in current_fns_new[k]['sizes']: + ptr = '%s->%s%d' % (name, type, size ) + if 'array' in current_fns_new[k]: + ptr += "[i]" + print('#ifdef DEBUG_misha') + print('%s\tif (%s)' % (indent, ptr)) + print('%s\t{' % (indent)) + print('%s\t\tuint32_t *pTst = (uint32_t*)(%s);' % (indent, ptr)) + print('%s\t\t--pTst;' % (indent)) + print('%s\t\tAssert((*pTst) == i);' % (indent)) + print('%s\t}' % (indent)) + print('#endif') + print('%s\tif (v < %s)' % (indent, ptr)) + print('%s\t{' % indent) + print('%s\t\tv = %s;' % (indent, ptr)) + if (k == 'Color' or k == 'Normal' or k == 'SecondaryColor' or normalized) and type != 'f' and type != 'd' and type != 'l': + print('%s\t\tconvert = (convert_func) __convert_rescale_%s%d;' % (indent,type,size)) + else: + print('%s\t\tconvert = (convert_func) __convert_%s%d;' % (indent,type,size)) + print('%s\t}' % indent) + print('') + print('%s\tif (v != NULL) {' % indent) + if 'array' in current_fns_new[k]: + if k == 'TexCoord': + print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_TEX0 + i], %s_default);' % (indent,name)) + else: + print('%s\t\tCOPY_4V(c->%s[i], %s_default);' % (indent,name,name)) + else: + if k == 'Normal': + print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_NORMAL], %s_default);' % (indent,name)) + elif k == 'FogCoord': + print('%s\t\tc->vertexAttrib[VERT_ATTRIB_FOG][0] = %s_default;' % (indent,name)) + elif k == 'Color': + print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_COLOR0], %s_default);' % (indent,name)) + elif k == 'SecondaryColor': + print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_COLOR1], %s_default);' % (indent,name)) + elif k == 'TexCoord': + print('%s\t\tCOPY_4V(c->vertexAttrib[VERT_ATTRIB_TEX0], %s_default);' % (indent,name)) + elif k == 'Index': + print('%s\t\tc->colorIndex = %s_default;' % (indent,name)) + elif k == 'EdgeFlag': + print('%s\t\tc->edgeFlag = %s_default;' % (indent,name)) + else: + print('%s\t\tc->%s = %s_default;' % (indent,name,name)) + if k == 'EdgeFlag': + print('%s\t\t__convert_boolean (&c->edgeFlag, v);' % (indent)) + dirtyVar = 'cb->edgeFlag' + elif k == 'Normal': + print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_NORMAL][0]), v);' % (indent)) + dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_NORMAL]' + elif k == 'TexCoord': + print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_TEX0 + i][0]), v);' % (indent)) + dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_TEX0 + i]' + elif k == 'Color': + print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_COLOR0][0]), v);' % (indent)) + dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_COLOR0]' + elif k == 'Index': + print('%s\t\tconvert(&(c->colorIndex), v);' % (indent)) + dirtyVar = 'cb->colorIndex' + elif k == 'SecondaryColor': + print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_COLOR1][0]), v);' % (indent)) + dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_COLOR1]' + elif k == 'FogCoord': + print('%s\t\tconvert(&(c->vertexAttrib[VERT_ATTRIB_FOG][0]), v);' % (indent)) + dirtyVar = 'cb->vertexAttrib[VERT_ATTRIB_FOG]' + elif k == 'VertexAttrib': + print('%s\t\tconvert(&(c->vertexAttrib[i][0]), v);' % (indent)) + dirtyVar = 'cb->vertexAttrib[i]' + else: + assert 0 # should never get here + + print('%s\t\tDIRTY(%s, nbitID);' % (indent, dirtyVar)) + +# if current_fns_new[k].has_key( 'array' ): +# print '%s\t\tDIRTY(cb->%s[i], nbitID);' % (indent,name) +# else: +# print '%s\t\tDIRTY(cb->%s, nbitID);' % (indent,name) + + + + print('%s\t\tDIRTY(cb->dirty, nbitID);' % indent) + print('%s\t}' % indent) + if 'array' in current_fns_new[k]: + print('%s\t%s->ptr[i] = v;' % (indent, name )) + else: + print('%s\t%s->ptr = v;' % (indent, name )) + if 'array' in current_fns_new[k]: + print('\t\t}') + print('\t\tcurrent->changed%s = 0;' % k) + print('\t}') +print('\tcrStateResetCurrentPointers(current);') +print('}') diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_defs.py b/src/VBox/GuestHost/OpenGL/state_tracker/state_defs.py new file mode 100644 index 00000000..1fb1a384 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_defs.py @@ -0,0 +1,64 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + + +import sys + +import apiutil + +apiutil.CopyrightDef() + +print """DESCRIPTION "" +EXPORTS +""" + +keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt") + +for func_name in apiutil.AllSpecials( 'state' ): + print "crState%s" % func_name + +for func_name in apiutil.AllSpecials( 'state_feedback' ): + print "crStateFeedback%s" % func_name + +for func_name in apiutil.AllSpecials( 'state_select' ): + print "crStateSelect%s" % func_name + +print """crStateInit +crStateReadPixels +crStateGetChromiumParametervCR +crStateCreateContext +crStateCreateContextEx +crStateDestroyContext +crStateDiffContext +crStateSwitchContext +crStateMakeCurrent +crStateSetCurrent +crStateFlushFunc +crStateFlushArg +crStateDiffAPI +crStateSetCurrentPointers +crStateResetCurrentPointers +crStateCurrentRecover +crStateTransformUpdateTransform +crStateColorMaterialRecover +crStateError +crStateUpdateColorBits +crStateClientInit +crStateGetCurrent +crStateLimitsInit +crStateMergeExtensions +crStateRasterPosUpdate +crStateTextureCheckDirtyImages +crStateExtensionsInit +crStateSetExtensionString +crStateUseServerArrays +crStateUseServerArrayElements +crStateComputeVersion +crStateTransformXformPointMatrixf +crStateTransformXformPointMatrixd +crStateInitMatrixStack +crStateLoadMatrix +__currentBits +""" diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c new file mode 100644 index 00000000..daf22565 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c @@ -0,0 +1,644 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "state.h" +#include "cr_error.h" +#include "cr_mem.h" +#include "cr_pixeldata.h" +#include <iprt/errcore.h> +#include <stdio.h> + +void crStateDiffContext( CRContext *from, CRContext *to ) +{ + CRbitvalue *bitID = from->bitid; + CRStateBits *sb = GetCurrentBits(); + + /*crDebug( "Diffing two contexts!" ); */ + + if (CHECKDIRTY(sb->transform.dirty, bitID)) + { + crStateTransformDiff( &(sb->transform), bitID, from, to ); + } + if (CHECKDIRTY(sb->pixel.dirty, bitID)) + { + crStatePixelDiff( &(sb->pixel), bitID, from, to ); + } + if (CHECKDIRTY(sb->viewport.dirty, bitID)) + { + crStateViewportDiff( &(sb->viewport), bitID, from, to ); + } + if (CHECKDIRTY(sb->fog.dirty, bitID)) + { + crStateFogDiff( &(sb->fog), bitID, from, to ); + } + if (CHECKDIRTY(sb->texture.dirty, bitID)) + { + crStateTextureDiff( &(sb->texture), bitID, from, to ); + } + if (CHECKDIRTY(sb->lists.dirty, bitID)) + { + crStateListsDiff( &(sb->lists), bitID, from, to ); + } + if (CHECKDIRTY(sb->buffer.dirty, bitID)) + { + crStateBufferDiff( &(sb->buffer), bitID, from, to ); + } +#ifdef CR_ARB_vertex_buffer_object + if (CHECKDIRTY(sb->bufferobject.dirty, bitID)) + { + crStateBufferObjectDiff( &(sb->bufferobject), bitID, from, to ); + } +#endif + if (CHECKDIRTY(sb->client.dirty, bitID)) + { + crStateClientDiff(&(sb->client), bitID, from, to ); + } + if (CHECKDIRTY(sb->hint.dirty, bitID)) + { + crStateHintDiff( &(sb->hint), bitID, from, to ); + } + if (CHECKDIRTY(sb->lighting.dirty, bitID)) + { + crStateLightingDiff( &(sb->lighting), bitID, from, to ); + } + if (CHECKDIRTY(sb->line.dirty, bitID)) + { + crStateLineDiff( &(sb->line), bitID, from, to ); + } + if (CHECKDIRTY(sb->occlusion.dirty, bitID)) + { + crStateOcclusionDiff( &(sb->occlusion), bitID, from, to ); + } + if (CHECKDIRTY(sb->point.dirty, bitID)) + { + crStatePointDiff( &(sb->point), bitID, from, to ); + } + if (CHECKDIRTY(sb->polygon.dirty, bitID)) + { + crStatePolygonDiff( &(sb->polygon), bitID, from, to ); + } + if (CHECKDIRTY(sb->program.dirty, bitID)) + { + crStateProgramDiff( &(sb->program), bitID, from, to ); + } + if (CHECKDIRTY(sb->stencil.dirty, bitID)) + { + crStateStencilDiff( &(sb->stencil), bitID, from, to ); + } + if (CHECKDIRTY(sb->eval.dirty, bitID)) + { + crStateEvaluatorDiff( &(sb->eval), bitID, from, to ); + } +#ifdef CR_ARB_imaging + if (CHECKDIRTY(sb->imaging.dirty, bitID)) + { + crStateImagingDiff( &(sb->imaging), bitID, from, to ); + } +#endif +#if 0 + if (CHECKDIRTY(sb->selection.dirty, bitID)) + { + crStateSelectionDiff( &(sb->selection), bitID, from, to ); + } +#endif +#ifdef CR_NV_register_combiners + if (CHECKDIRTY(sb->regcombiner.dirty, bitID) && to->extensions.NV_register_combiners) + { + crStateRegCombinerDiff( &(sb->regcombiner), bitID, from, to ); + } +#endif +#ifdef CR_ARB_multisample + if (CHECKDIRTY(sb->multisample.dirty, bitID) && + from->extensions.ARB_multisample) + { + crStateMultisampleDiff( &(sb->multisample), bitID, from, to ); + } +#endif + if (CHECKDIRTY(sb->current.dirty, bitID)) + { + crStateCurrentDiff( &(sb->current), bitID, from, to ); + } +} + +void crStateFreeFBImageLegacy(CRContext *to) +{ + if (to->buffer.pFrontImg) + { + crFree(to->buffer.pFrontImg); + to->buffer.pFrontImg = NULL; + } + if (to->buffer.pBackImg) + { + crFree(to->buffer.pBackImg); + to->buffer.pBackImg = NULL; + } + + to->buffer.storedWidth = 0; + to->buffer.storedHeight = 0; +} + +int crStateAcquireFBImage(CRContext *to, CRFBData *data) +{ + /*CRBufferState *pBuf = &to->buffer; - unused */ + CRPixelPackState packing = to->client.pack; + uint32_t i; + + diff_api.PixelStorei(GL_PACK_SKIP_ROWS, 0); + diff_api.PixelStorei(GL_PACK_SKIP_PIXELS, 0); + diff_api.PixelStorei(GL_PACK_ALIGNMENT, 1); + diff_api.PixelStorei(GL_PACK_ROW_LENGTH, 0); + diff_api.PixelStorei(GL_PACK_IMAGE_HEIGHT, 0); + diff_api.PixelStorei(GL_PACK_SKIP_IMAGES, 0); + diff_api.PixelStorei(GL_PACK_SWAP_BYTES, 0); + diff_api.PixelStorei(GL_PACK_LSB_FIRST, 0); + + if (to->bufferobject.packBuffer->hwid>0) + { + diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); + } + + for (i = 0; i < data->cElements; ++i) + { + CRFBDataElement *el = &data->aElements[i]; + + if (el->enmFormat == GL_DEPTH_COMPONENT || el->enmFormat == GL_DEPTH_STENCIL) + { + if (!to->buffer.depthTest) + { + diff_api.Enable(GL_DEPTH_TEST); + } + if (to->pixel.depthScale != 1.0f) + { + diff_api.PixelTransferf (GL_DEPTH_SCALE, 1.0f); + } + if (to->pixel.depthBias != 0.0f) + { + diff_api.PixelTransferf (GL_DEPTH_BIAS, 0.0f); + } + } + if (el->enmFormat == GL_STENCIL_INDEX || el->enmFormat == GL_DEPTH_STENCIL) + { + if (!to->stencil.stencilTest) + { + diff_api.Enable(GL_STENCIL_TEST); + } + if (to->pixel.mapStencil) + { + diff_api.PixelTransferi (GL_MAP_STENCIL, GL_FALSE); + } + if (to->pixel.indexOffset) + { + diff_api.PixelTransferi (GL_INDEX_OFFSET, 0); + } + if (to->pixel.indexShift) + { + diff_api.PixelTransferi (GL_INDEX_SHIFT, 0); + } + } + + diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, el->idFBO); + + if (el->enmBuffer) + diff_api.ReadBuffer(el->enmBuffer); + + diff_api.ReadPixels(el->posX, el->posY, el->width, el->height, el->enmFormat, el->enmType, el->pvData); + crDebug("Acquired %d;%d;%d;%d;%d;0x%p fb image", el->enmBuffer, el->width, el->height, el->enmFormat, el->enmType, el->pvData); + + if (el->enmFormat == GL_DEPTH_COMPONENT || el->enmFormat == GL_DEPTH_STENCIL) + { + if (to->pixel.depthScale != 1.0f) + { + diff_api.PixelTransferf (GL_DEPTH_SCALE, to->pixel.depthScale); + } + if (to->pixel.depthBias != 0.0f) + { + diff_api.PixelTransferf (GL_DEPTH_BIAS, to->pixel.depthBias); + } + if (!to->buffer.depthTest) + { + diff_api.Disable(GL_DEPTH_TEST); + } + } + if (el->enmFormat == GL_STENCIL_INDEX || el->enmFormat == GL_DEPTH_STENCIL) + { + if (to->pixel.indexOffset) + { + diff_api.PixelTransferi (GL_INDEX_OFFSET, to->pixel.indexOffset); + } + if (to->pixel.indexShift) + { + diff_api.PixelTransferi (GL_INDEX_SHIFT, to->pixel.indexShift); + } + if (to->pixel.mapStencil) + { + diff_api.PixelTransferi (GL_MAP_STENCIL, GL_TRUE); + } + if (!to->stencil.stencilTest) + { + diff_api.Disable(GL_STENCIL_TEST); + } + } + } + + if (to->bufferobject.packBuffer->hwid>0) + { + diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, to->bufferobject.packBuffer->hwid); + } + if (to->framebufferobject.readFB) + { + CRASSERT(to->framebufferobject.readFB->hwid); + diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, to->framebufferobject.readFB->hwid); + diff_api.ReadBuffer(to->framebufferobject.readFB->readbuffer); + + } + else if (data->idOverrrideFBO) + { + diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, data->idOverrrideFBO); + diff_api.ReadBuffer(GL_COLOR_ATTACHMENT0); + } + else + { + diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0); + diff_api.ReadBuffer(to->buffer.readBuffer); + } + + diff_api.PixelStorei(GL_PACK_SKIP_ROWS, packing.skipRows); + diff_api.PixelStorei(GL_PACK_SKIP_PIXELS, packing.skipPixels); + diff_api.PixelStorei(GL_PACK_ALIGNMENT, packing.alignment); + diff_api.PixelStorei(GL_PACK_ROW_LENGTH, packing.rowLength); + diff_api.PixelStorei(GL_PACK_IMAGE_HEIGHT, packing.imageHeight); + diff_api.PixelStorei(GL_PACK_SKIP_IMAGES, packing.skipImages); + diff_api.PixelStorei(GL_PACK_SWAP_BYTES, packing.swapBytes); + diff_api.PixelStorei(GL_PACK_LSB_FIRST, packing.psLSBFirst); + return VINF_SUCCESS; +} + +void crStateApplyFBImage(CRContext *to, CRFBData *data) +{ + { + /*CRBufferState *pBuf = &to->buffer; - unused */ + CRPixelPackState unpack = to->client.unpack; + uint32_t i; + + diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, 0); + diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, 1); + diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, 0); + diff_api.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0); + diff_api.PixelStorei(GL_UNPACK_SKIP_IMAGES, 0); + diff_api.PixelStorei(GL_UNPACK_SWAP_BYTES, 0); + diff_api.PixelStorei(GL_UNPACK_LSB_FIRST, 0); + + if (to->bufferobject.unpackBuffer->hwid>0) + { + diff_api.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); + } + + diff_api.Disable(GL_ALPHA_TEST); + diff_api.Disable(GL_SCISSOR_TEST); + diff_api.Disable(GL_BLEND); + diff_api.Disable(GL_COLOR_LOGIC_OP); + diff_api.Disable(GL_DEPTH_TEST); + diff_api.Disable(GL_STENCIL_TEST); + + for (i = 0; i < data->cElements; ++i) + { + CRFBDataElement *el = &data->aElements[i]; +#if 0 + char fname[200]; + sprintf(fname, "./img_apply_%p_%d_%d.tga", to, i, el->enmFormat); + crDumpNamedTGA(fname, el->width, el->height, el->pvData); +#endif + + /* Before SSM version SHCROGL_SSM_VERSION_WITH_SEPARATE_DEPTH_STENCIL_BUFFERS + * saved state file contined invalid DEPTH/STENCIL data. In order to prevent + * crashes and improper guest App behavior, this data should be ignored. */ + if ( data->u32Version < SHCROGL_SSM_VERSION_WITH_SEPARATE_DEPTH_STENCIL_BUFFERS + && ( el->enmFormat == GL_DEPTH_COMPONENT + || el->enmFormat == GL_STENCIL_INDEX + || el->enmFormat == GL_DEPTH_STENCIL)) + continue; + + if (el->enmFormat == GL_DEPTH_COMPONENT || el->enmFormat == GL_DEPTH_STENCIL) + { + diff_api.Enable(GL_DEPTH_TEST); + if (to->pixel.depthScale != 1.0f) + { + diff_api.PixelTransferf (GL_DEPTH_SCALE, 1.0f); + } + if (to->pixel.depthBias != 0.0f) + { + diff_api.PixelTransferf (GL_DEPTH_BIAS, 0.0f); + } + } + if (el->enmFormat == GL_STENCIL_INDEX || el->enmFormat == GL_DEPTH_STENCIL) + { + diff_api.Enable(GL_STENCIL_TEST); + if (to->pixel.mapStencil) + { + diff_api.PixelTransferi (GL_MAP_STENCIL, GL_FALSE); + } + if (to->pixel.indexOffset) + { + diff_api.PixelTransferi (GL_INDEX_OFFSET, 0); + } + if (to->pixel.indexShift) + { + diff_api.PixelTransferi (GL_INDEX_SHIFT, 0); + } + } + + diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, el->idFBO); + + if (el->enmBuffer) + diff_api.DrawBuffer(el->enmBuffer); + + diff_api.WindowPos2iARB(el->posX, el->posY); + diff_api.DrawPixels(el->width, el->height, el->enmFormat, el->enmType, el->pvData); + crDebug("Applied %d;%d;%d;%d;%d;0x%p fb image", el->enmBuffer, el->width, el->height, el->enmFormat, el->enmType, el->pvData); + + if (el->enmFormat == GL_DEPTH_COMPONENT || el->enmFormat == GL_DEPTH_STENCIL) + { + if (to->pixel.depthScale != 1.0f) + { + diff_api.PixelTransferf (GL_DEPTH_SCALE, to->pixel.depthScale); + } + if (to->pixel.depthBias != 0.0f) + { + diff_api.PixelTransferf (GL_DEPTH_BIAS, to->pixel.depthBias); + } + diff_api.Disable(GL_DEPTH_TEST); + } + if (el->enmFormat == GL_STENCIL_INDEX || el->enmFormat == GL_DEPTH_STENCIL) + { + if (to->pixel.indexOffset) + { + diff_api.PixelTransferi (GL_INDEX_OFFSET, to->pixel.indexOffset); + } + if (to->pixel.indexShift) + { + diff_api.PixelTransferi (GL_INDEX_SHIFT, to->pixel.indexShift); + } + if (to->pixel.mapStencil) + { + diff_api.PixelTransferi (GL_MAP_STENCIL, GL_TRUE); + } + diff_api.Disable(GL_STENCIL_TEST); + } + } + + diff_api.WindowPos3fvARB(to->current.rasterAttrib[VERT_ATTRIB_POS]); + if (to->bufferobject.unpackBuffer->hwid>0) + { + diff_api.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, to->bufferobject.unpackBuffer->hwid); + } + if (to->framebufferobject.drawFB) + { + CRASSERT(to->framebufferobject.drawFB->hwid); + diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, to->framebufferobject.drawFB->hwid); + diff_api.DrawBuffer(to->framebufferobject.drawFB->drawbuffer[0]); + } + else if (data->idOverrrideFBO) + { + diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, data->idOverrrideFBO); + diff_api.DrawBuffer(GL_COLOR_ATTACHMENT0); + } + else + { + diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0); + diff_api.DrawBuffer(to->buffer.drawBuffer); + } + if (to->buffer.alphaTest) + { + diff_api.Enable(GL_ALPHA_TEST); + } + if (to->viewport.scissorTest) + { + diff_api.Enable(GL_SCISSOR_TEST); + } + if (to->buffer.blend) + { + diff_api.Enable(GL_BLEND); + } + if (to->buffer.logicOp) + { + diff_api.Enable(GL_COLOR_LOGIC_OP); + } + if (to->buffer.depthTest) + { + diff_api.Enable(GL_DEPTH_TEST); + } + if (to->stencil.stencilTest) + { + diff_api.Enable(GL_STENCIL_TEST); + } + + diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, unpack.skipRows); + diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, unpack.skipPixels); + diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, unpack.alignment); + diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, unpack.rowLength); + diff_api.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, unpack.imageHeight); + diff_api.PixelStorei(GL_UNPACK_SKIP_IMAGES, unpack.skipImages); + diff_api.PixelStorei(GL_UNPACK_SWAP_BYTES, unpack.swapBytes); + diff_api.PixelStorei(GL_UNPACK_LSB_FIRST, unpack.psLSBFirst); + + diff_api.Finish(); + } +} + +void crStateSwitchContext( CRContext *from, CRContext *to ) +{ + CRbitvalue *bitID = to->bitid; + CRStateBits *sb = GetCurrentBits(); + + if (CHECKDIRTY(sb->attrib.dirty, bitID)) + { + crStateAttribSwitch(&(sb->attrib), bitID, from, to ); + } + if (CHECKDIRTY(sb->transform.dirty, bitID)) + { + crStateTransformSwitch( &(sb->transform), bitID, from, to ); + } + if (CHECKDIRTY(sb->pixel.dirty, bitID)) + { + crStatePixelSwitch(&(sb->pixel), bitID, from, to ); + } + if (CHECKDIRTY(sb->viewport.dirty, bitID)) + { + crStateViewportSwitch(&(sb->viewport), bitID, from, to ); + } + if (CHECKDIRTY(sb->fog.dirty, bitID)) + { + crStateFogSwitch(&(sb->fog), bitID, from, to ); + } + if (CHECKDIRTY(sb->texture.dirty, bitID)) + { + crStateTextureSwitch( &(sb->texture), bitID, from, to ); + } + if (CHECKDIRTY(sb->lists.dirty, bitID)) + { + crStateListsSwitch(&(sb->lists), bitID, from, to ); + } + if (CHECKDIRTY(sb->buffer.dirty, bitID)) + { + crStateBufferSwitch( &(sb->buffer), bitID, from, to ); + } +#ifdef CR_ARB_vertex_buffer_object + if (CHECKDIRTY(sb->bufferobject.dirty, bitID)) + { + crStateBufferObjectSwitch( &(sb->bufferobject), bitID, from, to ); + } +#endif + if (CHECKDIRTY(sb->client.dirty, bitID)) + { + crStateClientSwitch( &(sb->client), bitID, from, to ); + } +#if 0 + if (CHECKDIRTY(sb->hint.dirty, bitID)) + { + crStateHintSwitch( &(sb->hint), bitID, from, to ); + } +#endif + if (CHECKDIRTY(sb->lighting.dirty, bitID)) + { + crStateLightingSwitch( &(sb->lighting), bitID, from, to ); + } + if (CHECKDIRTY(sb->occlusion.dirty, bitID)) + { + crStateOcclusionSwitch( &(sb->occlusion), bitID, from, to ); + } + if (CHECKDIRTY(sb->line.dirty, bitID)) + { + crStateLineSwitch( &(sb->line), bitID, from, to ); + } + if (CHECKDIRTY(sb->point.dirty, bitID)) + { + crStatePointSwitch( &(sb->point), bitID, from, to ); + } + if (CHECKDIRTY(sb->polygon.dirty, bitID)) + { + crStatePolygonSwitch( &(sb->polygon), bitID, from, to ); + } + if (CHECKDIRTY(sb->program.dirty, bitID)) + { + crStateProgramSwitch( &(sb->program), bitID, from, to ); + } + if (CHECKDIRTY(sb->stencil.dirty, bitID)) + { + crStateStencilSwitch( &(sb->stencil), bitID, from, to ); + } + if (CHECKDIRTY(sb->eval.dirty, bitID)) + { + crStateEvaluatorSwitch( &(sb->eval), bitID, from, to ); + } +#ifdef CR_ARB_imaging + if (CHECKDIRTY(sb->imaging.dirty, bitID)) + { + crStateImagingSwitch( &(sb->imaging), bitID, from, to ); + } +#endif +#if 0 + if (CHECKDIRTY(sb->selection.dirty, bitID)) + { + crStateSelectionSwitch( &(sb->selection), bitID, from, to ); + } +#endif +#ifdef CR_NV_register_combiners + if (CHECKDIRTY(sb->regcombiner.dirty, bitID) && to->extensions.NV_register_combiners) + { + crStateRegCombinerSwitch( &(sb->regcombiner), bitID, from, to ); + } +#endif +#ifdef CR_ARB_multisample + if (CHECKDIRTY(sb->multisample.dirty, bitID)) + { + crStateMultisampleSwitch( &(sb->multisample), bitID, from, to ); + } +#endif +#ifdef CR_ARB_multisample + if (CHECKDIRTY(sb->multisample.dirty, bitID)) + { + crStateMultisampleSwitch(&(sb->multisample), bitID, from, to ); + } +#endif +#ifdef CR_EXT_framebuffer_object + /*Note, this should go after crStateTextureSwitch*/ + crStateFramebufferObjectSwitch(from, to); +#endif +#ifdef CR_OPENGL_VERSION_2_0 + crStateGLSLSwitch(from, to); +#endif + if (CHECKDIRTY(sb->current.dirty, bitID)) + { + crStateCurrentSwitch( &(sb->current), bitID, from, to ); + } + +#ifdef WINDOWS + if (to->buffer.pFrontImg) + { + CRFBData *pLazyData = (CRFBData *)to->buffer.pFrontImg; + crStateApplyFBImage(to, pLazyData); + crStateFreeFBImageLegacy(to); + } +#endif +} + +void crStateSyncHWErrorState(CRContext *ctx) +{ + GLenum err; + while ((err = diff_api.GetError()) != GL_NO_ERROR) + { + if (ctx->error != GL_NO_ERROR) + ctx->error = err; + } +} + +GLenum crStateCleanHWErrorState(void) +{ + GLenum err; + while ((err = diff_api.GetError()) != GL_NO_ERROR) + { + static int cErrPrints = 0; +#ifndef DEBUG_misha + if (cErrPrints < 5) +#endif + { + ++cErrPrints; + WARN(("cleaning gl error (0x%x), ignoring.. (%d out of 5) ..", err, cErrPrints)); + } + } + + return err; +} + + +void crStateSwitchPrepare(CRContext *toCtx, CRContext *fromCtx, GLuint idDrawFBO, GLuint idReadFBO) +{ + if (!fromCtx) + return; + + if (g_bVBoxEnableDiffOnMakeCurrent && toCtx && toCtx != fromCtx) + crStateSyncHWErrorState(fromCtx); + +#ifdef CR_EXT_framebuffer_object + crStateFramebufferObjectDisableHW(fromCtx, idDrawFBO, idReadFBO); +#endif +} + +void crStateSwitchPostprocess(CRContext *toCtx, CRContext *fromCtx, GLuint idDrawFBO, GLuint idReadFBO) +{ + if (!toCtx) + return; + +#ifdef CR_EXT_framebuffer_object + crStateFramebufferObjectReenableHW(fromCtx, toCtx, idDrawFBO, idReadFBO); +#endif + + if (g_bVBoxEnableDiffOnMakeCurrent && fromCtx && toCtx != fromCtx) + { + CR_STATE_CLEAN_HW_ERR_WARN("error on make current"); + } +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_enable.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_enable.c new file mode 100644 index 00000000..dca7d98d --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_enable.c @@ -0,0 +1,544 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include <stdio.h> +#include "state.h" +#include "state/cr_statetypes.h" +#include "state_internals.h" + +static void __enableSet (CRContext *g, CRStateBits *sb, CRbitvalue *neg_bitid, + GLenum cap, GLboolean val) +{ + unsigned int i; + i = cap - GL_CLIP_PLANE0; + if (i < g->limits.maxClipPlanes) { + g->transform.clip[i] = val; + DIRTY(sb->transform.enable, neg_bitid); + DIRTY(sb->transform.dirty, neg_bitid); + return; + } + i = cap - GL_LIGHT0; + if (i < g->limits.maxLights) { + g->lighting.light[i].enable = val; + DIRTY(sb->lighting.light[i].dirty, neg_bitid); + DIRTY(sb->lighting.light[i].enable, neg_bitid); + DIRTY(sb->lighting.dirty, neg_bitid); + return; + } + + switch (cap) { + case GL_AUTO_NORMAL: + g->eval.autoNormal = val; + DIRTY(sb->eval.enable, neg_bitid); + DIRTY(sb->eval.dirty, neg_bitid); + break; + case GL_ALPHA_TEST: + g->buffer.alphaTest = val; + DIRTY(sb->buffer.enable, neg_bitid); + DIRTY(sb->buffer.dirty, neg_bitid); + break; + case GL_BLEND: + g->buffer.blend = val; + DIRTY(sb->buffer.enable, neg_bitid); + DIRTY(sb->buffer.dirty, neg_bitid); + break; + case GL_COLOR_MATERIAL : + if (!val) + { + /* We're TURNING OFF color material. In this case, + * we should make sure that the very very latest + * color that was specified gets copied into the + * material parameters, since this might be our + * last chance (see frame 1 of progs/kirchner + * for an example of why). */ + + crStateCurrentRecover( ); + crStateColorMaterialRecover( ); + } + g->lighting.colorMaterial = val; + DIRTY(sb->lighting.enable, neg_bitid); + DIRTY(sb->lighting.dirty, neg_bitid); + break; +#ifdef CR_EXT_secondary_color + case GL_COLOR_SUM_EXT : + if (g->extensions.EXT_secondary_color) { /* XXX does EXT_separate_specular color support this enable, too? */ + g->lighting.colorSumEXT = val; + DIRTY(sb->lighting.enable, neg_bitid); + DIRTY(sb->lighting.dirty, neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(GL_COLOR_SUM_EXT) - No support for secondary color!"); + return; + } + break; +#endif + case GL_CULL_FACE : + g->polygon.cullFace = val; + DIRTY(sb->polygon.enable, neg_bitid); + DIRTY(sb->polygon.dirty, neg_bitid); + break; + case GL_DEPTH_TEST : + g->buffer.depthTest = val; + DIRTY(sb->buffer.enable, neg_bitid); + DIRTY(sb->buffer.dirty, neg_bitid); + break; + case GL_DITHER : + g->buffer.dither = val; + DIRTY(sb->buffer.enable, neg_bitid); + DIRTY(sb->buffer.dirty, neg_bitid); + break; + case GL_FOG : + g->fog.enable = val; + DIRTY(sb->fog.enable, neg_bitid); + DIRTY(sb->fog.dirty, neg_bitid); + break; + case GL_LIGHTING : + g->lighting.lighting = val; + DIRTY(sb->lighting.enable, neg_bitid); + DIRTY(sb->lighting.dirty, neg_bitid); + break; + case GL_LINE_SMOOTH : + g->line.lineSmooth = val; + DIRTY(sb->line.enable, neg_bitid); + DIRTY(sb->line.dirty, neg_bitid); + break; + case GL_LINE_STIPPLE : + g->line.lineStipple = val; + DIRTY(sb->line.enable, neg_bitid); + DIRTY(sb->line.dirty, neg_bitid); + break; + case GL_COLOR_LOGIC_OP : + g->buffer.logicOp = val; + DIRTY(sb->buffer.enable, neg_bitid); + DIRTY(sb->buffer.dirty, neg_bitid); + break; + case GL_INDEX_LOGIC_OP : + g->buffer.indexLogicOp = val; + DIRTY(sb->buffer.enable, neg_bitid); + DIRTY(sb->buffer.dirty, neg_bitid); + break; + case GL_NORMALIZE : + g->transform.normalize = val; + DIRTY(sb->transform.enable, neg_bitid); + DIRTY(sb->transform.dirty, neg_bitid); + break; + case GL_POINT_SMOOTH : + g->point.pointSmooth = val; + DIRTY(sb->point.enableSmooth, neg_bitid); + DIRTY(sb->point.dirty, neg_bitid); + break; + case GL_POLYGON_OFFSET_FILL: + g->polygon.polygonOffsetFill = val; + DIRTY(sb->polygon.enable, neg_bitid); + DIRTY(sb->polygon.dirty, neg_bitid); + break; + case GL_POLYGON_OFFSET_LINE: + g->polygon.polygonOffsetLine = val; + DIRTY(sb->polygon.enable, neg_bitid); + DIRTY(sb->polygon.dirty, neg_bitid); + break; + case GL_POLYGON_OFFSET_POINT: + g->polygon.polygonOffsetPoint = val; + DIRTY(sb->polygon.enable, neg_bitid); + DIRTY(sb->polygon.dirty, neg_bitid); + break; + case GL_POLYGON_SMOOTH : + g->polygon.polygonSmooth = val; + DIRTY(sb->polygon.enable, neg_bitid); + DIRTY(sb->polygon.dirty, neg_bitid); + break; + case GL_POLYGON_STIPPLE : + g->polygon.polygonStipple = val; + DIRTY(sb->polygon.enable, neg_bitid); + DIRTY(sb->polygon.dirty, neg_bitid); + break; +#ifdef CR_NV_register_combiners + case GL_REGISTER_COMBINERS_NV : + if (g->extensions.NV_register_combiners) { + g->regcombiner.enabledRegCombiners = val; + DIRTY(sb->regcombiner.enable, neg_bitid); + DIRTY(sb->regcombiner.dirty, neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(GL_REGISTER_COMBINERS_NV) - No support for NV_register_combiners"); + return; + } + break; +#endif +#ifdef CR_NV_register_combiners2 + case GL_PER_STAGE_CONSTANTS_NV : + if (g->extensions.NV_register_combiners2) { + g->regcombiner.enabledPerStageConstants = val; + DIRTY(sb->regcombiner.enable, neg_bitid); + DIRTY(sb->regcombiner.dirty, neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(GL_PER_STAGE_CONSTANTS_NV) - No support for NV_register_combiners2"); + return; + } + break; +#endif +#ifdef CR_NV_texture_rectangle + case GL_TEXTURE_RECTANGLE_NV: + if (g->extensions.NV_texture_rectangle) { + g->texture.unit[g->texture.curTextureUnit].enabledRect = val; + DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid); + DIRTY(sb->texture.dirty, neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap); + return; + } + break; +#endif /* CR_NV_texture_rectangle */ +#ifdef CR_OPENGL_VERSION_1_2 + case GL_RESCALE_NORMAL : + g->transform.rescaleNormals = val; + DIRTY(sb->transform.enable, neg_bitid); + DIRTY(sb->transform.dirty, neg_bitid); + break; +#endif + case GL_SCISSOR_TEST : + g->viewport.scissorTest = val; + DIRTY(sb->viewport.enable, neg_bitid); + DIRTY(sb->viewport.dirty, neg_bitid); + break; + case GL_STENCIL_TEST : + g->stencil.stencilTest= val; + DIRTY(sb->stencil.enable, neg_bitid); + DIRTY(sb->stencil.dirty, neg_bitid); + break; + case GL_TEXTURE_1D : + g->texture.unit[g->texture.curTextureUnit].enabled1D = val; + DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid); + DIRTY(sb->texture.dirty, neg_bitid); + break; + case GL_TEXTURE_2D : + g->texture.unit[g->texture.curTextureUnit].enabled2D = val; + DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid); + DIRTY(sb->texture.dirty, neg_bitid); + break; +#ifdef CR_OPENGL_VERSION_1_2 + case GL_TEXTURE_3D : + g->texture.unit[g->texture.curTextureUnit].enabled3D = val; + DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid); + DIRTY(sb->texture.dirty, neg_bitid); + break; +#endif +#ifdef CR_ARB_texture_cube_map + case GL_TEXTURE_CUBE_MAP_ARB: + if (g->extensions.ARB_texture_cube_map) { + g->texture.unit[g->texture.curTextureUnit].enabledCubeMap = val; + DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid); + DIRTY(sb->texture.dirty, neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap); + return; + } + break; +#endif /* CR_ARB_texture_cube_map */ + case GL_TEXTURE_GEN_Q : + g->texture.unit[g->texture.curTextureUnit].textureGen.q = val; + DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid); + DIRTY(sb->texture.dirty, neg_bitid); + break; + case GL_TEXTURE_GEN_R : + g->texture.unit[g->texture.curTextureUnit].textureGen.r = val; + DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid); + DIRTY(sb->texture.dirty, neg_bitid); + break; + case GL_TEXTURE_GEN_S : + g->texture.unit[g->texture.curTextureUnit].textureGen.s = val; + DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid); + DIRTY(sb->texture.dirty, neg_bitid); + break; + case GL_TEXTURE_GEN_T : + g->texture.unit[g->texture.curTextureUnit].textureGen.t = val; + DIRTY(sb->texture.enable[g->texture.curTextureUnit], neg_bitid); + DIRTY(sb->texture.dirty, neg_bitid); + break; + case GL_MAP1_COLOR_4 : + case GL_MAP1_INDEX : + case GL_MAP1_NORMAL : + case GL_MAP1_TEXTURE_COORD_1 : + case GL_MAP1_TEXTURE_COORD_2 : + case GL_MAP1_TEXTURE_COORD_3 : + case GL_MAP1_TEXTURE_COORD_4 : + case GL_MAP1_VERTEX_3 : + case GL_MAP1_VERTEX_4 : + if (g->texture.curTextureUnit != 0) + { + crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "Map stuff was enabled while the current texture unit was not GL_TEXTURE0_ARB!" ); + return; + } + g->eval.enable1D[cap - GL_MAP1_COLOR_4] = val; + DIRTY(sb->eval.enable1D[cap - GL_MAP1_COLOR_4], neg_bitid); + DIRTY(sb->eval.dirty, neg_bitid); + break; + case GL_MAP2_COLOR_4 : + case GL_MAP2_INDEX : + case GL_MAP2_NORMAL : + case GL_MAP2_TEXTURE_COORD_1 : + case GL_MAP2_TEXTURE_COORD_2 : + case GL_MAP2_TEXTURE_COORD_3 : + case GL_MAP2_TEXTURE_COORD_4 : + case GL_MAP2_VERTEX_3 : + case GL_MAP2_VERTEX_4 : +#if 0 + if (g->texture.curTextureUnit != 0) + { + crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "Map stuff was enabled while the current texture unit was not GL_TEXTURE0_ARB!" ); + return; + } +#endif + g->eval.enable2D[cap - GL_MAP2_COLOR_4] = val; + DIRTY(sb->eval.enable2D[cap - GL_MAP2_COLOR_4], neg_bitid); + DIRTY(sb->eval.dirty, neg_bitid); + break; +#ifdef CR_ARB_multisample + case GL_MULTISAMPLE_ARB: + g->multisample.enabled = val; + DIRTY(sb->multisample.enable, neg_bitid); + DIRTY(sb->multisample.dirty, neg_bitid); + break; + case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB: + g->multisample.sampleAlphaToCoverage = val; + DIRTY(sb->multisample.sampleAlphaToCoverage, neg_bitid); + DIRTY(sb->multisample.dirty, neg_bitid); + break; + case GL_SAMPLE_ALPHA_TO_ONE_ARB: + g->multisample.sampleAlphaToOne = val; + DIRTY(sb->multisample.sampleAlphaToOne, neg_bitid); + DIRTY(sb->multisample.dirty, neg_bitid); + break; + case GL_SAMPLE_COVERAGE_ARB: + g->multisample.sampleCoverage = val; + DIRTY(sb->multisample.sampleCoverage, neg_bitid); + DIRTY(sb->multisample.dirty, neg_bitid); + break; +#endif +#ifdef CR_NV_vertex_program + case GL_VERTEX_PROGRAM_NV: + if (g->extensions.NV_vertex_program) { + g->program.vpEnabled = val; + DIRTY(sb->program.vpEnable, neg_bitid); + DIRTY(sb->program.dirty, neg_bitid); + } + else if (g->extensions.ARB_vertex_program) { + g->program.vpEnabled = val; + DIRTY(sb->program.vpEnable, neg_bitid); + DIRTY(sb->program.dirty, neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap); + return; + } + break; + case GL_VERTEX_PROGRAM_POINT_SIZE_NV: + if (g->extensions.NV_vertex_program) { + g->program.vpPointSize = val; + DIRTY(sb->program.vpEnable, neg_bitid); + DIRTY(sb->program.dirty, neg_bitid); + } + else if (g->extensions.ARB_vertex_program) { + g->program.vpPointSize = val; + DIRTY(sb->program.vpEnable, neg_bitid); + DIRTY(sb->program.dirty, neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap); + return; + } + break; + case GL_VERTEX_PROGRAM_TWO_SIDE_NV: + if (g->extensions.NV_vertex_program) { + g->program.vpTwoSide = val; + DIRTY(sb->program.vpEnable, neg_bitid); + DIRTY(sb->program.dirty, neg_bitid); + } + else if (g->extensions.ARB_vertex_program) { + g->program.vpTwoSide = val; + DIRTY(sb->program.vpEnable, neg_bitid); + DIRTY(sb->program.dirty, neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap); + return; + } + break; + + case GL_MAP1_VERTEX_ATTRIB0_4_NV: + case GL_MAP1_VERTEX_ATTRIB1_4_NV: + case GL_MAP1_VERTEX_ATTRIB2_4_NV: + case GL_MAP1_VERTEX_ATTRIB3_4_NV: + case GL_MAP1_VERTEX_ATTRIB4_4_NV: + case GL_MAP1_VERTEX_ATTRIB5_4_NV: + case GL_MAP1_VERTEX_ATTRIB6_4_NV: + case GL_MAP1_VERTEX_ATTRIB7_4_NV: + case GL_MAP1_VERTEX_ATTRIB8_4_NV: + case GL_MAP1_VERTEX_ATTRIB9_4_NV: + case GL_MAP1_VERTEX_ATTRIB10_4_NV: + case GL_MAP1_VERTEX_ATTRIB11_4_NV: + case GL_MAP1_VERTEX_ATTRIB12_4_NV: + case GL_MAP1_VERTEX_ATTRIB13_4_NV: + case GL_MAP1_VERTEX_ATTRIB14_4_NV: + case GL_MAP1_VERTEX_ATTRIB15_4_NV: + { + const GLint idx = cap - GL_MAP1_VERTEX_ATTRIB0_4_NV; + g->eval.enableAttrib1D[idx] = val; + DIRTY(sb->program.map1AttribArrayEnable[idx], neg_bitid); + DIRTY(sb->program.dirty, neg_bitid); + } + break; + case GL_MAP2_VERTEX_ATTRIB0_4_NV: + case GL_MAP2_VERTEX_ATTRIB1_4_NV: + case GL_MAP2_VERTEX_ATTRIB2_4_NV: + case GL_MAP2_VERTEX_ATTRIB3_4_NV: + case GL_MAP2_VERTEX_ATTRIB4_4_NV: + case GL_MAP2_VERTEX_ATTRIB5_4_NV: + case GL_MAP2_VERTEX_ATTRIB6_4_NV: + case GL_MAP2_VERTEX_ATTRIB7_4_NV: + case GL_MAP2_VERTEX_ATTRIB8_4_NV: + case GL_MAP2_VERTEX_ATTRIB9_4_NV: + case GL_MAP2_VERTEX_ATTRIB10_4_NV: + case GL_MAP2_VERTEX_ATTRIB11_4_NV: + case GL_MAP2_VERTEX_ATTRIB12_4_NV: + case GL_MAP2_VERTEX_ATTRIB13_4_NV: + case GL_MAP2_VERTEX_ATTRIB14_4_NV: + case GL_MAP2_VERTEX_ATTRIB15_4_NV: + { + const GLint idx = cap - GL_MAP2_VERTEX_ATTRIB0_4_NV; + g->eval.enableAttrib2D[idx] = val; + DIRTY(sb->program.map2AttribArrayEnable[idx], neg_bitid); + DIRTY(sb->program.dirty, neg_bitid); + } + break; +#endif +#ifdef CR_NV_fragment_program + case GL_FRAGMENT_PROGRAM_NV: + if (g->extensions.NV_fragment_program) { + g->program.fpEnabled = val; + DIRTY(sb->program.fpEnable, neg_bitid); + DIRTY(sb->program.dirty, neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap); + return; + } + break; +#endif +#ifdef CR_ARB_fragment_program + case GL_FRAGMENT_PROGRAM_ARB: + if (g->extensions.ARB_fragment_program) { + g->program.fpEnabledARB = val; + DIRTY(sb->program.fpEnable, neg_bitid); + DIRTY(sb->program.dirty, neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable(0x%x)", cap); + return; + } + break; +#endif +#ifdef CR_IBM_rasterpos_clip + case GL_RASTER_POSITION_UNCLIPPED_IBM: + g->transform.rasterPositionUnclipped = val; + DIRTY(sb->transform.enable, neg_bitid); + DIRTY(sb->transform.dirty, neg_bitid); + break; +#endif + +#ifdef CR_ARB_point_sprite + case GL_POINT_SPRITE_ARB: + g->point.pointSprite = val; + DIRTY(sb->point.enableSprite, neg_bitid); + DIRTY(sb->point.dirty, neg_bitid); + break; +#endif + + /* Client-side enables */ + case GL_VERTEX_ARRAY: + case GL_COLOR_ARRAY: + case GL_NORMAL_ARRAY: + case GL_INDEX_ARRAY: + case GL_TEXTURE_COORD_ARRAY: + case GL_EDGE_FLAG_ARRAY: +#ifdef CR_EXT_fog_coord + case GL_FOG_COORDINATE_ARRAY_POINTER_EXT: +#endif +#ifdef CR_EXT_secondary_color + case GL_SECONDARY_COLOR_ARRAY_EXT: +#endif +#ifdef CR_NV_vertex_program + case GL_VERTEX_ATTRIB_ARRAY0_NV: + case GL_VERTEX_ATTRIB_ARRAY1_NV: + case GL_VERTEX_ATTRIB_ARRAY2_NV: + case GL_VERTEX_ATTRIB_ARRAY3_NV: + case GL_VERTEX_ATTRIB_ARRAY4_NV: + case GL_VERTEX_ATTRIB_ARRAY5_NV: + case GL_VERTEX_ATTRIB_ARRAY6_NV: + case GL_VERTEX_ATTRIB_ARRAY7_NV: + case GL_VERTEX_ATTRIB_ARRAY8_NV: + case GL_VERTEX_ATTRIB_ARRAY9_NV: + case GL_VERTEX_ATTRIB_ARRAY10_NV: + case GL_VERTEX_ATTRIB_ARRAY11_NV: + case GL_VERTEX_ATTRIB_ARRAY12_NV: + case GL_VERTEX_ATTRIB_ARRAY13_NV: + case GL_VERTEX_ATTRIB_ARRAY14_NV: + case GL_VERTEX_ATTRIB_ARRAY15_NV: +#endif + if (val) + crStateEnableClientState(cap); + else + crStateDisableClientState(cap); + break; +#ifdef CR_EXT_stencil_two_side + case GL_STENCIL_TEST_TWO_SIDE_EXT: + g->stencil.stencilTwoSideEXT= val; + DIRTY(sb->stencil.enableTwoSideEXT, neg_bitid); + DIRTY(sb->stencil.dirty, neg_bitid); + break; +#endif + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEnable/glDisable called with bogus cap: 0x%x", cap); + return; + } +} + + +void STATE_APIENTRY crStateEnable (GLenum cap) +{ + CRContext *g = GetCurrentContext(); + CRStateBits *sb = GetCurrentBits(); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glEnable called in begin/end"); + return; + } + + FLUSH(); + + __enableSet(g, sb, g->neg_bitid, cap, GL_TRUE); +} + + +void STATE_APIENTRY crStateDisable (GLenum cap) +{ + CRContext *g = GetCurrentContext(); + CRStateBits *sb = GetCurrentBits(); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glDisable called in begin/end"); + return; + } + + FLUSH(); + + __enableSet(g, sb, g->neg_bitid, cap, GL_FALSE); +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_error.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_error.c new file mode 100644 index 00000000..07a7b494 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_error.c @@ -0,0 +1,86 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "state/cr_stateerror.h" +#include "state/cr_statetypes.h" +#include "state.h" +#include "cr_error.h" +#include "cr_environment.h" +#include <stdarg.h> +#include <stdio.h> + +void crStateError( int line, const char *file, GLenum error, const char *format, ... ) +{ + CRContext *g = GetCurrentContext(); + char errstr[8096]; + va_list args; + + CRASSERT(error != GL_NO_ERROR); + + if (g->error == GL_NO_ERROR) + g->error = error; + +#ifndef DEBUG_misha + if (crGetenv("CR_DEBUG")) +#endif + { + char *glerr; + va_start( args, format ); + vsprintf( errstr, format, args ); + va_end( args ); + + switch (error) { + case GL_NO_ERROR: + glerr = "GL_NO_ERROR"; + break; + case GL_INVALID_VALUE: + glerr = "GL_INVALID_VALUE"; + break; + case GL_INVALID_ENUM: + glerr = "GL_INVALID_ENUM"; + break; + case GL_INVALID_OPERATION: + glerr = "GL_INVALID_OPERATION"; + break; + case GL_STACK_OVERFLOW: + glerr = "GL_STACK_OVERFLOW"; + break; + case GL_STACK_UNDERFLOW: + glerr = "GL_STACK_UNDERFLOW"; + break; + case GL_OUT_OF_MEMORY: + glerr = "GL_OUT_OF_MEMORY"; + break; + case GL_TABLE_TOO_LARGE: + glerr = "GL_TABLE_TOO_LARGE"; + break; + default: + glerr = "unknown"; + break; + } + + crWarning( "OpenGL error in %s, line %d: %s: %s\n", + file, line, glerr, errstr ); + } +} + + +GLenum STATE_APIENTRY crStateGetError(void) +{ + CRContext *g = GetCurrentContext(); + GLenum e = g->error; + + if (g->current.inBeginEnd) + { + crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, + "glStateGetError() called between glBegin/glEnd" ); + return 0; + } + + g->error = GL_NO_ERROR; + + return e; +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_evaluators.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_evaluators.c new file mode 100644 index 00000000..0219994d --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_evaluators.c @@ -0,0 +1,1084 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +/* + * The majority of this file is pulled from Mesa 4.0.x with the + * permission of Brian Paul + */ + +#include <stdio.h> +#include "cr_mem.h" +#include "state.h" +#include "state/cr_statetypes.h" +#include "state_internals.h" + +/* free the 1-D evaluator map */ +static void +free_1d_map(CRContext *ctx, GLenum map) +{ + CREvaluatorState *e = &ctx->eval; + const GLint k = map - GL_MAP1_COLOR_4; + + crFree( e->eval1D[k].coeff ); +} + +/* free the 2-D evaluator map */ +static void +free_2d_map(CRContext *ctx, GLenum map) +{ + CREvaluatorState *e = &ctx->eval; + const GLint k = map - GL_MAP2_COLOR_4; + + crFree( e->eval2D[k].coeff ); +} + +/* Initialize a 1-D evaluator map */ +static void +init_1d_map(CRContext *ctx, GLenum map, int n, const float *initial) +{ + CREvaluatorState *e = &ctx->eval; + CRStateBits *sb = GetCurrentBits(); + CREvaluatorBits *eb = &(sb->eval); + GLint i; + const GLint k = map - GL_MAP1_COLOR_4; + CRASSERT(k >= 0); + CRASSERT(k < GLEVAL_TOT); + e->eval1D[k].u1 = 0.0; + e->eval1D[k].u2 = 1.0; + e->eval1D[k].du = 0.0; + e->eval1D[k].order = 1; + e->eval1D[k].coeff = (GLfloat *) crAlloc(n * sizeof(GLfloat)); + for (i = 0; i < n; i++) + e->eval1D[k].coeff[i] = initial[i]; + RESET(eb->eval1D[i], ctx->bitid); +} + + +/* Initialize a 2-D evaluator map */ +static void +init_2d_map(CRContext *ctx, GLenum map, int n, const float *initial) +{ + CREvaluatorState *e = &ctx->eval; + CRStateBits *sb = GetCurrentBits(); + CREvaluatorBits *eb = &(sb->eval); + GLint i; + const GLint k = map - GL_MAP2_COLOR_4; + CRASSERT(k >= 0); + CRASSERT(k < GLEVAL_TOT); + e->eval2D[k].u1 = 0.0; + e->eval2D[k].u2 = 1.0; + e->eval2D[k].du = 0.0; + e->eval2D[k].v1 = 0.0; + e->eval2D[k].v2 = 1.0; + e->eval2D[k].dv = 0.0; + e->eval2D[k].uorder = 1; + e->eval2D[k].vorder = 1; + e->eval2D[k].coeff = (GLfloat *) crAlloc(n * sizeof(GLfloat)); + for (i = 0; i < n; i++) + e->eval2D[k].coeff[i] = initial[i]; + RESET(eb->eval2D[i], ctx->bitid); +} + +void +crStateEvaluatorDestroy(CRContext *ctx) +{ + free_1d_map(ctx, GL_MAP1_VERTEX_3); + free_1d_map(ctx, GL_MAP1_VERTEX_4); + free_1d_map(ctx, GL_MAP1_INDEX); + free_1d_map(ctx, GL_MAP1_COLOR_4); + free_1d_map(ctx, GL_MAP1_NORMAL); + free_1d_map(ctx, GL_MAP1_TEXTURE_COORD_1); + free_1d_map(ctx, GL_MAP1_TEXTURE_COORD_2); + free_1d_map(ctx, GL_MAP1_TEXTURE_COORD_3); + free_1d_map(ctx, GL_MAP1_TEXTURE_COORD_4); + + free_2d_map(ctx, GL_MAP2_VERTEX_3); + free_2d_map(ctx, GL_MAP2_VERTEX_4); + free_2d_map(ctx, GL_MAP2_INDEX); + free_2d_map(ctx, GL_MAP2_COLOR_4); + free_2d_map(ctx, GL_MAP2_NORMAL); + free_2d_map(ctx, GL_MAP2_TEXTURE_COORD_1); + free_2d_map(ctx, GL_MAP2_TEXTURE_COORD_2); + free_2d_map(ctx, GL_MAP2_TEXTURE_COORD_3); + free_2d_map(ctx, GL_MAP2_TEXTURE_COORD_4); +} + +void +crStateEvaluatorInit(CRContext *ctx) +{ + CREvaluatorState *e = &ctx->eval; + CRStateBits *sb = GetCurrentBits(); + CREvaluatorBits *eb = &(sb->eval); + static GLfloat vertex[4] = { 0.0, 0.0, 0.0, 1.0 }; + static GLfloat normal[3] = { 0.0, 0.0, 1.0 }; + static GLfloat index[1] = { 1.0 }; + static GLfloat color[4] = { 1.0, 1.0, 1.0, 1.0 }; + static GLfloat texcoord[4] = { 0.0, 0.0, 0.0, 1.0 }; + + e->autoNormal = GL_FALSE; + RESET(eb->enable, ctx->bitid); + + init_1d_map(ctx, GL_MAP1_VERTEX_3, 3, vertex); + init_1d_map(ctx, GL_MAP1_VERTEX_4, 4, vertex); + init_1d_map(ctx, GL_MAP1_INDEX, 1, index); + init_1d_map(ctx, GL_MAP1_COLOR_4, 4, color); + init_1d_map(ctx, GL_MAP1_NORMAL, 3, normal); + init_1d_map(ctx, GL_MAP1_TEXTURE_COORD_1, 1, texcoord); + init_1d_map(ctx, GL_MAP1_TEXTURE_COORD_2, 2, texcoord); + init_1d_map(ctx, GL_MAP1_TEXTURE_COORD_3, 3, texcoord); + init_1d_map(ctx, GL_MAP1_TEXTURE_COORD_4, 4, texcoord); + + init_2d_map(ctx, GL_MAP2_VERTEX_3, 3, vertex); + init_2d_map(ctx, GL_MAP2_VERTEX_4, 4, vertex); + init_2d_map(ctx, GL_MAP2_INDEX, 1, index); + init_2d_map(ctx, GL_MAP2_COLOR_4, 4, color); + init_2d_map(ctx, GL_MAP2_NORMAL, 3, normal); + init_2d_map(ctx, GL_MAP2_TEXTURE_COORD_1, 1, texcoord); + init_2d_map(ctx, GL_MAP2_TEXTURE_COORD_2, 2, texcoord); + init_2d_map(ctx, GL_MAP2_TEXTURE_COORD_3, 3, texcoord); + init_2d_map(ctx, GL_MAP2_TEXTURE_COORD_4, 4, texcoord); + + e->un1D = 1; + e->u11D = 0.0; + e->u21D = 1.0; + RESET(eb->grid1D, ctx->bitid); + + e->un2D = 1; + e->vn2D = 1; + e->u12D = 0.0; + e->u22D = 1.0; + e->v12D = 0.0; + e->v22D = 1.0; + RESET(eb->grid1D, ctx->bitid); + + RESET(eb->dirty, ctx->bitid); +} + +const int gleval_sizes[] = { 4, 1, 3, 1, 2, 3, 4, 3, 4 }; + +/**********************************************************************/ +/*** Copy and deallocate control points ***/ +/**********************************************************************/ + + +/* + * Copy 1-parametric evaluator control points from user-specified + * memory space to a buffer of contiguous control points. + * Input: see glMap1f for details + * Return: pointer to buffer of contiguous control points or NULL if out + * of memory. + */ +static GLfloat * +_copy_map_points1f(GLint size, GLint ustride, GLint uorder, + const GLfloat * points) +{ + GLfloat *buffer, *p; + GLint i, k; + + if (!points || size == 0) { + return NULL; + } + + buffer = (GLfloat *) crAlloc(uorder * size * sizeof(GLfloat)); + + if (buffer) + for (i = 0, p = buffer; i < uorder; i++, points += ustride) + for (k = 0; k < size; k++) + *p++ = points[k]; + + return buffer; +} + + + +/* + * Same as above but convert doubles to floats. + */ +static GLfloat * +_copy_map_points1d(GLint size, GLint ustride, GLint uorder, + const GLdouble * points) +{ + GLfloat *buffer, *p; + GLint i, k; + + if (!points || size == 0) { + return NULL; + } + + buffer = (GLfloat *) crAlloc(uorder * size * sizeof(GLfloat)); + + if (buffer) + for (i = 0, p = buffer; i < uorder; i++, points += ustride) + for (k = 0; k < size; k++) + *p++ = (GLfloat) points[k]; + + return buffer; +} + + + +/* + * Copy 2-parametric evaluator control points from user-specified + * memory space to a buffer of contiguous control points. + * Additional memory is allocated to be used by the Horner and + * de Casteljau evaluation schemes. + * + * Input: see glMap2f for details + * Return: pointer to buffer of contiguous control points or NULL if out + * of memory. + */ +static GLfloat * +_copy_map_points2f(GLint size, + GLint ustride, GLint uorder, + GLint vstride, GLint vorder, const GLfloat * points) +{ + GLfloat *buffer, *p; + GLint i, j, k, dsize, hsize; + GLint uinc; + + if (!points || size == 0) { + return NULL; + } + + /* max(uorder, vorder) additional points are used in */ + /* Horner evaluation and uorder*vorder additional */ + /* values are needed for de Casteljau */ + dsize = (uorder == 2 && vorder == 2) ? 0 : uorder * vorder; + hsize = (uorder > vorder ? uorder : vorder) * size; + + if (hsize > dsize) + buffer = + (GLfloat *) crAlloc((uorder * vorder * size + hsize) * sizeof(GLfloat)); + else + buffer = + (GLfloat *) crAlloc((uorder * vorder * size + dsize) * sizeof(GLfloat)); + + /* compute the increment value for the u-loop */ + uinc = ustride - vorder * vstride; + + if (buffer) + for (i = 0, p = buffer; i < uorder; i++, points += uinc) + for (j = 0; j < vorder; j++, points += vstride) + for (k = 0; k < size; k++) + *p++ = points[k]; + + return buffer; +} + + + +/* + * Same as above but convert doubles to floats. + */ +static GLfloat * +_copy_map_points2d(GLint size, + GLint ustride, GLint uorder, + GLint vstride, GLint vorder, const GLdouble * points) +{ + GLfloat *buffer, *p; + GLint i, j, k, hsize, dsize; + GLint uinc; + + if (!points || size == 0) { + return NULL; + } + + /* max(uorder, vorder) additional points are used in */ + /* Horner evaluation and uorder*vorder additional */ + /* values are needed for de Casteljau */ + dsize = (uorder == 2 && vorder == 2) ? 0 : uorder * vorder; + hsize = (uorder > vorder ? uorder : vorder) * size; + + if (hsize > dsize) + buffer = + (GLfloat *) crAlloc((uorder * vorder * size + hsize) * sizeof(GLfloat)); + else + buffer = + (GLfloat *) crAlloc((uorder * vorder * size + dsize) * sizeof(GLfloat)); + + /* compute the increment value for the u-loop */ + uinc = ustride - vorder * vstride; + + if (buffer) + for (i = 0, p = buffer; i < uorder; i++, points += uinc) + for (j = 0; j < vorder; j++, points += vstride) + for (k = 0; k < size; k++) + *p++ = (GLfloat) points[k]; + + return buffer; +} + + + + +/**********************************************************************/ +/*** API entry points ***/ +/**********************************************************************/ + + +/* + * This does the work of glMap1[fd]. + */ +static void +map1(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, + GLint uorder, const GLvoid * points, GLenum type) +{ + CRContext *g = GetCurrentContext(); + CREvaluatorState *e = &(g->eval); + CRStateBits *sb = GetCurrentBits(); + CREvaluatorBits *eb = &(sb->eval); + CRTextureState *t = &(g->texture); + GLint i; + GLint k; + GLfloat *pnts; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "Map1d called in begin/end"); + return; + } + + FLUSH(); + + CRASSERT(type == GL_FLOAT || type == GL_DOUBLE); + + if (u1 == u2) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMap1d(u1==u2)"); + return; + } + if (uorder < 1 || uorder > MAX_EVAL_ORDER) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMap1d(bad uorder)"); + return; + } + if (!points) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glMap1d(null points)"); + return; + } + + i = target - GL_MAP1_COLOR_4; + + k = gleval_sizes[i]; + + if (k == 0) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMap1d(k=0)"); + return; + } + + if (ustride < k) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMap1d(bad ustride"); + return; + } + + if (t->curTextureUnit != 0) { + /* See OpenGL 1.2.1 spec, section F.2.13 */ + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glMap1d(current texture unit must be zero)"); + return; + } + + switch (target) { + case GL_MAP1_VERTEX_3: + case GL_MAP1_VERTEX_4: + case GL_MAP1_INDEX: + case GL_MAP1_COLOR_4: + case GL_MAP1_NORMAL: + case GL_MAP1_TEXTURE_COORD_1: + case GL_MAP1_TEXTURE_COORD_2: + case GL_MAP1_TEXTURE_COORD_3: + case GL_MAP1_TEXTURE_COORD_4: + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMap1d(bad target)"); + return; + } + + /* make copy of the control points */ + if (type == GL_FLOAT) + pnts = _copy_map_points1f(k, ustride, uorder, (GLfloat *) points); + else + pnts = _copy_map_points1d(k, ustride, uorder, (GLdouble *) points); + + e->eval1D[i].order = uorder; + e->eval1D[i].u1 = u1; + e->eval1D[i].u2 = u2; + e->eval1D[i].du = 1.0f / (u2 - u1); + if (e->eval1D[i].coeff) + crFree(e->eval1D[i].coeff); + e->eval1D[i].coeff = pnts; + + DIRTY(eb->dirty, g->neg_bitid); + DIRTY(eb->eval1D[i], g->neg_bitid); +} + + + +void STATE_APIENTRY +crStateMap1f(GLenum target, GLfloat u1, GLfloat u2, + GLint stride, GLint order, const GLfloat * points) +{ + map1(target, u1, u2, stride, order, points, GL_FLOAT); +} + +void STATE_APIENTRY +crStateMap1d(GLenum target, GLdouble u1, GLdouble u2, GLint stride, + GLint order, const GLdouble * points) +{ + map1(target, (GLfloat) u1, (GLfloat) u2, stride, order, points, GL_DOUBLE); +} + +static void +map2(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, + GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, + const GLvoid * points, GLenum type) +{ + CRContext *g = GetCurrentContext(); + CRStateBits *sb = GetCurrentBits(); + CREvaluatorState *e = &(g->eval); + CREvaluatorBits *eb = &(sb->eval); +#if 0 + CRTextureState *t = &(g->texture); +#endif + GLint i; + GLint k; + GLfloat *pnts; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glMap2d()"); + return; + } + + FLUSH(); + + if (u1 == u2) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMap2d()"); + return; + } + + if (v1 == v2) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMap2d()"); + return; + } + + if (uorder < 1 || uorder > MAX_EVAL_ORDER) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMap2d()"); + return; + } + + if (vorder < 1 || vorder > MAX_EVAL_ORDER) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMap2d()"); + return; + } + + if (g->extensions.NV_vertex_program) { +/* XXX FIXME */ + i = target - GL_MAP2_COLOR_4; + } else { + i = target - GL_MAP2_COLOR_4; + } + + k = gleval_sizes[i]; + + if (k == 0) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMap2d()"); + return; + } + + if (ustride < k) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMap2d()"); + return; + } + if (vstride < k) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMap2d()"); + return; + } + +#if 00 + /* Disable this check for now - it looks like various OpenGL drivers + * don't do this error check. So, a bunch of the NVIDIA demos + * generate errors/warnings. + */ + if (t->curTextureUnit != 0) { + /* See OpenGL 1.2.1 spec, section F.2.13 */ + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glMap2d()"); + return; + } +#endif + + switch (target) { + case GL_MAP2_VERTEX_3: + case GL_MAP2_VERTEX_4: + case GL_MAP2_INDEX: + case GL_MAP2_COLOR_4: + case GL_MAP2_NORMAL: + case GL_MAP2_TEXTURE_COORD_1: + case GL_MAP2_TEXTURE_COORD_2: + case GL_MAP2_TEXTURE_COORD_3: + case GL_MAP2_TEXTURE_COORD_4: + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMap2d()"); + return; + } + + /* make copy of the control points */ + if (type == GL_FLOAT) + pnts = _copy_map_points2f(k, ustride, uorder, + vstride, vorder, (GLfloat *) points); + else + pnts = _copy_map_points2d(k, ustride, uorder, + vstride, vorder, (GLdouble *) points); + + e->eval2D[i].uorder = uorder; + e->eval2D[i].u1 = u1; + e->eval2D[i].u2 = u2; + e->eval2D[i].du = 1.0f / (u2 - u1); + e->eval2D[i].vorder = vorder; + e->eval2D[i].v1 = v1; + e->eval2D[i].v2 = v2; + e->eval2D[i].dv = 1.0f / (v2 - v1); + if (e->eval2D[i].coeff) + crFree(e->eval2D[i].coeff); + e->eval2D[i].coeff = pnts; + + DIRTY(eb->dirty, g->neg_bitid); + DIRTY(eb->eval2D[i], g->neg_bitid); +} + +void STATE_APIENTRY +crStateMap2f(GLenum target, GLfloat u1, GLfloat u2, + GLint ustride, GLint uorder, + GLfloat v1, GLfloat v2, + GLint vstride, GLint vorder, const GLfloat * points) +{ + map2(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, + points, GL_FLOAT); +} + + +void STATE_APIENTRY +crStateMap2d(GLenum target, GLdouble u1, GLdouble u2, + GLint ustride, GLint uorder, + GLdouble v1, GLdouble v2, + GLint vstride, GLint vorder, const GLdouble * points) +{ + map2(target, (GLfloat) u1, (GLfloat) u2, ustride, uorder, + (GLfloat) v1, (GLfloat) v2, vstride, vorder, points, GL_DOUBLE); +} + +void STATE_APIENTRY +crStateGetMapdv(GLenum target, GLenum query, GLdouble * v) +{ + CRContext *g = GetCurrentContext(); + CRStateBits *sb = GetCurrentBits(); + CREvaluatorState *e = &(g->eval); + GLint size; + GLint i, j; + (void) sb; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "Map1d called in begin/end"); + return; + } + + FLUSH(); + + i = target - GL_MAP1_COLOR_4; + + if (i < 0 || i >= GLEVAL_TOT) { + i = target - GL_MAP2_COLOR_4; + + if (i < 0 || i >= GLEVAL_TOT) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "GetMapdv: invalid target: %d", target); + return; + } + + switch (query) { + case GL_COEFF: + size = gleval_sizes[i] * e->eval2D[i].uorder * e->eval2D[i].vorder; + for (j = 0; j < size; j++) { + v[j] = e->eval2D[i].coeff[j]; + } + break; + case GL_ORDER: + v[0] = (GLdouble) e->eval2D[i].uorder; + v[1] = (GLdouble) e->eval2D[i].vorder; + break; + case GL_DOMAIN: + v[0] = e->eval2D[i].u1; + v[1] = e->eval2D[i].u2; + v[2] = e->eval2D[i].v1; + v[3] = e->eval2D[i].v2; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "GetMapdv: invalid target: %d", target); + return; + } + } + else { + switch (query) { + case GL_COEFF: + size = gleval_sizes[i] * e->eval1D[i].order; + for (j = 0; j < size; j++) { + v[j] = e->eval1D[i].coeff[j]; + } + break; + case GL_ORDER: + *v = (GLdouble) e->eval1D[i].order; + break; + case GL_DOMAIN: + v[0] = e->eval1D[i].u1; + v[1] = e->eval1D[i].u2; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "GetMapdv: invalid target: %d", target); + return; + } + } +} + +void STATE_APIENTRY +crStateGetMapfv(GLenum target, GLenum query, GLfloat * v) +{ + CRContext *g = GetCurrentContext(); + CRStateBits *sb = GetCurrentBits(); + CREvaluatorState *e = &(g->eval); + GLint size; + GLint i, j; + (void) sb; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "Map1d called in begin/end"); + return; + } + + FLUSH(); + + i = target - GL_MAP1_COLOR_4; + if (i < 0 || i >= GLEVAL_TOT) { + i = target - GL_MAP2_COLOR_4; + if (i < 0 || i >= GLEVAL_TOT) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "GetMapfv: invalid target: %d", target); + return; + } + switch (query) { + case GL_COEFF: + size = gleval_sizes[i] * e->eval2D[i].uorder * e->eval2D[i].vorder; + for (j = 0; j < size; j++) { + v[j] = (GLfloat) e->eval2D[i].coeff[j]; + } + break; + case GL_ORDER: + v[0] = (GLfloat) e->eval2D[i].uorder; + v[1] = (GLfloat) e->eval2D[i].vorder; + break; + case GL_DOMAIN: + v[0] = (GLfloat) e->eval2D[i].u1; + v[1] = (GLfloat) e->eval2D[i].u2; + v[2] = (GLfloat) e->eval2D[i].v1; + v[3] = (GLfloat) e->eval2D[i].v2; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "GetMapfv: invalid target: %d", target); + return; + } + } + else { + switch (query) { + case GL_COEFF: + size = gleval_sizes[i] * e->eval1D[i].order; + for (j = 0; j < size; j++) { + v[j] = (GLfloat) e->eval1D[i].coeff[j]; + } + break; + case GL_ORDER: + *v = (GLfloat) e->eval1D[i].order; + break; + case GL_DOMAIN: + v[0] = (GLfloat) e->eval1D[i].u1; + v[1] = (GLfloat) e->eval1D[i].u2; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "GetMapfv: invalid target: %d", target); + return; + } + } +} + +void STATE_APIENTRY +crStateGetMapiv(GLenum target, GLenum query, GLint * v) +{ + CRContext *g = GetCurrentContext(); + CRStateBits *sb = GetCurrentBits(); + CREvaluatorState *e = &(g->eval); + GLint size; + GLint i, j; + (void) sb; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "Map1d called in begin/end"); + return; + } + + FLUSH(); + + i = target - GL_MAP1_COLOR_4; + if (i < 0 || i >= GLEVAL_TOT) { + i = target - GL_MAP2_COLOR_4; + if (i < 0 || i >= GLEVAL_TOT) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "GetMapiv: invalid target: %d", target); + return; + } + switch (query) { + case GL_COEFF: + size = gleval_sizes[i] * e->eval2D[i].uorder * e->eval2D[i].vorder; + for (j = 0; j < size; j++) { + v[j] = (GLint) e->eval2D[i].coeff[j]; + } + break; + case GL_ORDER: + v[0] = e->eval2D[i].uorder; + v[1] = e->eval2D[i].vorder; + break; + case GL_DOMAIN: + v[0] = (GLint) e->eval2D[i].u1; + v[1] = (GLint) e->eval2D[i].u2; + v[2] = (GLint) e->eval2D[i].v1; + v[3] = (GLint) e->eval2D[i].v2; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "GetMapiv: invalid target: %d", target); + return; + } + } + else { + switch (query) { + case GL_COEFF: + size = gleval_sizes[i] * e->eval1D[i].order; + for (j = 0; j < size; j++) { + v[j] = (GLint) e->eval1D[i].coeff[j]; + } + break; + case GL_ORDER: + *v = e->eval1D[i].order; + break; + case GL_DOMAIN: + v[0] = (GLint) e->eval1D[i].u1; + v[1] = (GLint) e->eval1D[i].u2; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "GetMapiv: invalid target: %d", target); + return; + } + } +} + +void STATE_APIENTRY +crStateMapGrid1f(GLint un, GLfloat u1, GLfloat u2) +{ + CRContext *g = GetCurrentContext(); + CRStateBits *sb = GetCurrentBits(); + CREvaluatorState *e = &(g->eval); + CREvaluatorBits *eb = &(sb->eval); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "Map1d called in begin/end"); + return; + } + + FLUSH(); + + if (un < 1) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMapGrid1f(bad un)"); + return; + } + + e->un1D = un; + e->u11D = u1; + e->u21D = u2; + + DIRTY(eb->dirty, g->neg_bitid); + DIRTY(eb->grid1D, g->neg_bitid); +} + +void STATE_APIENTRY +crStateMapGrid1d(GLint un, GLdouble u1, GLdouble u2) +{ + crStateMapGrid1f(un, (GLfloat) u1, (GLfloat) u2); +} + + +void STATE_APIENTRY +crStateMapGrid2f(GLint un, GLfloat u1, GLfloat u2, + GLint vn, GLfloat v1, GLfloat v2) +{ + CRContext *g = GetCurrentContext(); + CRStateBits *sb = GetCurrentBits(); + CREvaluatorState *e = &(g->eval); + CREvaluatorBits *eb = &(sb->eval); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "Map1d called in begin/end"); + return; + } + + FLUSH(); + + if (un < 1) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMapGrid2f(bad un)"); + return; + } + if (vn < 1) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMapGrid2f(bad vn)"); + return; + } + + e->un2D = un; + e->vn2D = vn; + e->u12D = u1; + e->u22D = u2; + e->v12D = v1; + e->v22D = v2; + + DIRTY(eb->dirty, g->neg_bitid); + DIRTY(eb->grid2D, g->neg_bitid); +} + +void STATE_APIENTRY +crStateMapGrid2d(GLint un, GLdouble u1, GLdouble u2, + GLint vn, GLdouble v1, GLdouble v2) +{ + crStateMapGrid2f(un, (GLfloat) u1, (GLfloat) u2, + vn, (GLfloat) v1, (GLfloat) v2); +} + +void +crStateEvaluatorSwitch(CREvaluatorBits *e, CRbitvalue * bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + CREvaluatorState *from = &(fromCtx->eval); + CREvaluatorState *to = &(toCtx->eval); + int i, j; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + + for (j = 0; j < CR_MAX_BITARRAY; j++) + nbitID[j] = ~bitID[j]; + + if (CHECKDIRTY(e->enable, bitID)) { + if (from->autoNormal != to->autoNormal) { + glAble able[2]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + able[to->autoNormal] (GL_AUTO_NORMAL); + FILLDIRTY(e->enable); + FILLDIRTY(e->dirty); + } + CLEARDIRTY(e->enable, nbitID); + } + for (i = 0; i < GLEVAL_TOT; i++) { + if (CHECKDIRTY(e->eval1D[i], bitID)) { + int size = from->eval1D[i].order * gleval_sizes[i] * + sizeof(*from->eval1D[i].coeff); + if (from->eval1D[i].order != to->eval1D[i].order || + from->eval1D[i].u1 != to->eval1D[i].u1 || + from->eval1D[i].u2 != to->eval1D[i].u2 || + crMemcmp((const void *) from->eval1D[i].coeff, + (const void *) to->eval1D[i].coeff, size)) { + diff_api.Map1f(i + GL_MAP1_COLOR_4, to->eval1D[i].u1, + to->eval1D[i].u2, gleval_sizes[i], to->eval1D[i].order, + to->eval1D[i].coeff); + FILLDIRTY(e->dirty); + FILLDIRTY(e->eval1D[i]); + } + CLEARDIRTY(e->eval1D[i], nbitID); + } + } + + for (i = 0; i < GLEVAL_TOT; i++) { + if (CHECKDIRTY(e->eval2D[i], bitID)) { + int size = from->eval2D[i].uorder * from->eval2D[i].vorder + * gleval_sizes[i] * sizeof(*from->eval2D[i].coeff); + if (from->eval2D[i].uorder != to->eval2D[i].uorder || + from->eval2D[i].vorder != to->eval2D[i].vorder || + from->eval2D[i].u1 != to->eval2D[i].u1 || + from->eval2D[i].u2 != to->eval2D[i].u2 || + from->eval2D[i].v1 != to->eval2D[i].v1 || + from->eval2D[i].v2 != to->eval2D[i].v2 || + crMemcmp((const void *) from->eval2D[i].coeff, + (const void *) to->eval2D[i].coeff, size)) { + diff_api.Map2f(i + GL_MAP2_COLOR_4, + to->eval2D[i].u1, to->eval2D[i].u2, + gleval_sizes[i], to->eval2D[i].uorder, + to->eval2D[i].v1, to->eval2D[i].v2, + gleval_sizes[i], to->eval2D[i].vorder, + to->eval2D[i].coeff); + FILLDIRTY(e->dirty); + FILLDIRTY(e->eval2D[i]); + } + CLEARDIRTY(e->eval2D[i], nbitID); + } + } + if (CHECKDIRTY(e->grid1D, bitID)) { + if (from->u11D != to->u11D || + from->u21D != to->u21D || + from->un1D != to->un1D) { + diff_api.MapGrid1d(to->un1D, to->u11D, to->u21D); + FILLDIRTY(e->dirty); + FILLDIRTY(e->grid1D); + } + CLEARDIRTY(e->grid1D, nbitID); + } + if (CHECKDIRTY(e->grid2D, bitID)) { + if (from->u12D != to->u12D || + from->u22D != to->u22D || + from->un2D != to->un2D || + from->v12D != to->v12D || + from->v22D != to->v22D || + from->vn2D != to->vn2D) { + diff_api.MapGrid2d(to->un2D, to->u12D, to->u22D, + to->vn2D, to->v12D, to->v22D); + FILLDIRTY(e->dirty); + FILLDIRTY(e->grid1D); + } + CLEARDIRTY(e->grid1D, nbitID); + } + CLEARDIRTY(e->dirty, nbitID); +} + +void +crStateEvaluatorDiff(CREvaluatorBits *e, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + CREvaluatorState *from = &(fromCtx->eval); + CREvaluatorState *to = &(toCtx->eval); + glAble able[2]; + int i, j; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + + for (j = 0; j < CR_MAX_BITARRAY; j++) + nbitID[j] = ~bitID[j]; + + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + + if (CHECKDIRTY(e->enable, bitID)) { + if (from->autoNormal != to->autoNormal) { + able[to->autoNormal] (GL_AUTO_NORMAL); + from->autoNormal = to->autoNormal; + } + CLEARDIRTY(e->enable, nbitID); + } + for (i = 0; i < GLEVAL_TOT; i++) { + if (CHECKDIRTY(e->enable1D[i], bitID)) { + if (from->enable1D[i] != to->enable1D[i]) { + able[to->enable1D[i]] (i + GL_MAP1_COLOR_4); + from->enable1D[i] = to->enable1D[i]; + } + CLEARDIRTY(e->enable1D[i], nbitID); + } + if (to->enable1D[i] && CHECKDIRTY(e->eval1D[i], bitID)) { + int size = from->eval1D[i].order * gleval_sizes[i] * + sizeof(*from->eval1D[i].coeff); + if (from->eval1D[i].order != to->eval1D[i].order || + from->eval1D[i].u1 != to->eval1D[i].u1 || + from->eval1D[i].u2 != to->eval1D[i].u2 || + crMemcmp((const void *) from->eval1D[i].coeff, + (const void *) to->eval1D[i].coeff, size)) { + diff_api.Map1f(i + GL_MAP1_COLOR_4, to->eval1D[i].u1, + to->eval1D[i].u2, gleval_sizes[i], to->eval1D[i].order, + to->eval1D[i].coeff); + from->eval1D[i].order = to->eval1D[i].order; + from->eval1D[i].u1 = to->eval1D[i].u1; + from->eval1D[i].u2 = to->eval1D[i].u2; + crMemcpy((void *) from->eval1D[i].coeff, + (const void *) to->eval1D[i].coeff, size); + } + CLEARDIRTY(e->eval1D[i], nbitID); + } + } + + for (i = 0; i < GLEVAL_TOT; i++) { + if (CHECKDIRTY(e->enable2D[i], bitID)) { + if (from->enable2D[i] != to->enable2D[i]) { + able[to->enable2D[i]] (i + GL_MAP2_COLOR_4); + from->enable2D[i] = to->enable2D[i]; + } + CLEARDIRTY(e->enable2D[i], nbitID); + } + if (to->enable2D[i] && CHECKDIRTY(e->eval2D[i], bitID)) { + int size = from->eval2D[i].uorder * from->eval2D[i].vorder + * gleval_sizes[i] * sizeof(*from->eval2D[i].coeff); + if (from->eval2D[i].uorder != to->eval2D[i].uorder || + from->eval2D[i].vorder != to->eval2D[i].vorder || + from->eval2D[i].u1 != to->eval2D[i].u1 || + from->eval2D[i].u2 != to->eval2D[i].u2 || + from->eval2D[i].v1 != to->eval2D[i].v1 || + from->eval2D[i].v2 != to->eval2D[i].v2 || + crMemcmp((const void *) from->eval2D[i].coeff, + (const void *) to->eval2D[i].coeff, size)) { + diff_api.Map2f(i + GL_MAP2_COLOR_4, + to->eval2D[i].u1, to->eval2D[i].u2, + gleval_sizes[i], to->eval2D[i].uorder, + to->eval2D[i].v1, to->eval2D[i].v2, + gleval_sizes[i], to->eval2D[i].vorder, + to->eval2D[i].coeff); + from->eval2D[i].uorder = to->eval2D[i].uorder; + from->eval2D[i].vorder = to->eval2D[i].vorder; + from->eval2D[i].u1 = to->eval2D[i].u1; + from->eval2D[i].u2 = to->eval2D[i].u2; + from->eval2D[i].v1 = to->eval2D[i].v1; + from->eval2D[i].v2 = to->eval2D[i].v2; + crMemcpy((void *) from->eval2D[i].coeff, + (const void *) to->eval2D[i].coeff, size); + } + CLEARDIRTY(e->eval2D[i], nbitID); + } + } + if (CHECKDIRTY(e->grid1D, bitID)) { + if (from->u11D != to->u11D || + from->u21D != to->u21D || + from->un1D != to->un1D) { + diff_api.MapGrid1d(to->un1D, to->u11D, to->u21D); + from->u11D = to->u11D; + from->u21D = to->u21D; + from->un1D = to->un1D; + } + CLEARDIRTY(e->grid1D, nbitID); + } + if (CHECKDIRTY(e->grid2D, bitID)) { + if (from->u12D != to->u12D || + from->u22D != to->u22D || + from->un2D != to->un2D || + from->v12D != to->v12D || + from->v22D != to->v22D || + from->vn2D != to->vn2D) { + diff_api.MapGrid2d(to->un2D, to->u12D, to->u22D, + to->vn2D, to->v12D, to->v22D); + from->u12D = to->u12D; + from->u22D = to->u22D; + from->un2D = to->un2D; + from->v12D = to->v12D; + from->v22D = to->v22D; + from->vn2D = to->vn2D; + } + CLEARDIRTY(e->grid1D, nbitID); + } + CLEARDIRTY(e->dirty, nbitID); +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_extensions_get.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_extensions_get.txt new file mode 100644 index 00000000..7eb5ec35 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_extensions_get.txt @@ -0,0 +1,138 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +# GL_NV_fog_distance + +GLenum GL_FOG_DISTANCE_MODE_NV GL_NV_fog_distance g->fog.fogDistanceMode + + +# GL_EXT_texture_filter_anisotropic + +GLenum GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT GL_EXT_texture_filter_anisotropic g->limits.maxTextureAnisotropy + + +# GL_EXT_blend_color + +GLclampf GL_BLEND_COLOR_EXT GL_EXT_blend_color g->buffer.blendColor.r g->buffer.blendColor.g g->buffer.blendColor.b g->buffer.blendColor.a + +# GL_OPENGL_VERSION_1_2 + +GLboolean GL_RESCALE_NORMAL GL_OPENGL_VERSION_1_2 g->transform.rescaleNormals +GLenum GL_LIGHT_MODEL_COLOR_CONTROL GL_OPENGL_VERSION_1_2 g->lighting.lightModelColorControlEXT + +# GL_EXT_separate_specular_color + +GLenum GL_LIGHT_MODEL_COLOR_CONTROL_EXT GL_EXT_separate_specular_color g->lighting.lightModelColorControlEXT + +# GL_EXT_blend_minmax + +GLenum GL_BLEND_EQUATION_EXT GL_EXT_blend_minmax g->buffer.blendEquation + +# GL_EXT_blend_func_separate + +GLenum GL_BLEND_SRC_RGB_EXT GL_EXT_blend_func_separate g->buffer.blendSrcRGB +GLenum GL_BLEND_DST_RGB_EXT GL_EXT_blend_func_separate g->buffer.blendDstRGB +GLenum GL_BLEND_SRC_ALPHA_EXT GL_EXT_blend_func_separate g->buffer.blendSrcA +GLenum GL_BLEND_DST_ALPHA_EXT GL_EXT_blend_func_separate g->buffer.blendDstA + +# GL_NV_register_combiners + +GLint GL_NUM_GENERAL_COMBINERS_NV GL_NV_register_combiners g->regcombiner.numGeneralCombiners +GLboolean GL_REGISTER_COMBINERS_NV GL_NV_register_combiners g->regcombiner.enabledRegCombiners +GLboolean GL_COLOR_SUM_CLAMP_NV GL_NV_register_combiners g->regcombiner.colorSumClamp +GLfloat GL_CONSTANT_COLOR0_NV GL_NV_register_combiners g->regcombiner.constantColor0.r g->regcombiner.constantColor0.g g->regcombiner.constantColor0.b g->regcombiner.constantColor0.a +GLfloat GL_CONSTANT_COLOR1_NV GL_NV_register_combiners g->regcombiner.constantColor1.r g->regcombiner.constantColor1.g g->regcombiner.constantColor1.b g->regcombiner.constantColor1.a +GLint GL_MAX_GENERAL_COMBINERS_NV GL_NV_register_combiners g->limits.maxGeneralCombiners + + +# GL_NV_register_combiners2 + +GLboolean GL_PER_STAGE_CONSTANTS_NV GL_NV_register_combiners2 g->regcombiner.enabledPerStageConstants + + +# GL_ARB_texture_cube_map + +GLboolean GL_TEXTURE_CUBE_MAP_ARB GL_ARB_texture_cube_map g->texture.unit[g->texture.curTextureUnit].enabledCubeMap +GLint GL_TEXTURE_BINDING_CUBE_MAP_ARB GL_ARB_texture_cube_map g->texture.unit[g->texture.curTextureUnit].currentTextureCubeMap->id +GLint GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB GL_ARB_texture_cube_map g->limits.maxCubeMapTextureSize + +# GL_NV_texture_rectangle +GLboolean GL_TEXTURE_RECTANGLE_NV GL_NV_texture_rectangle g->texture.unit[g->texture.curTextureUnit].enabledRect +GLint GL_TEXTURE_BINDING_RECTANGLE_NV GL_NV_texture_rectangle g->texture.unit[g->texture.curTextureUnit].currentTextureRect->id +GLint GL_MAX_RECTANGLE_TEXTURE_SIZE_NV GL_NV_texture_rectangle g->limits.maxRectTextureSize + +# GL_NV_fragment_program +GLboolean GL_FRAGMENT_PROGRAM_NV GL_NV_fragment_program g->program.fpEnabled +GLuint GL_MAX_TEXTURE_COORDS_NV GL_NV_fragment_program g->limits.maxTextureCoords +GLuint GL_MAX_TEXTURE_IMAGE_UNITS_NV GL_NV_fragment_program g->limits.maxTextureImageUnits +GLuint GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV GL_NV_fragment_program g->limits.maxFragmentProgramLocalParams +# GLint GL_PROGRAM_ERROR_POSITION_NV GL_NV_fragment_program g->program.errorPos +GLuint GL_FRAGMENT_PROGRAM_BINDING_NV GL_NV_fragment_program g->program.fpProgramBinding + +# GL_NV_vertex_program +GLboolean GL_VERTEX_PROGRAM_NV GL_any_vertex_program g->program.vpEnabled +GLint GL_PROGRAM_ERROR_POSITION_NV GL_any_program g->program.errorPos +GLuint GL_VERTEX_PROGRAM_BINDING_NV GL_NV_vertex_program g->program.vpProgramBinding +GLboolean GL_VERTEX_PROGRAM_POINT_SIZE_NV GL_any_vertex_program g->program.vpPointSize +GLboolean GL_VERTEX_PROGRAM_TWO_SIDE_NV GL_any_vertex_program g->program.vpTwoSide + + +# GL_ARB_fragment_program +GLboolean GL_FRAGMENT_PROGRAM_ARB GL_ARB_fragment_program g->program.fpEnabledARB + + +# GL_ARB_transpose_matrix +GLdefault GL_TRANSPOSE_MODELVIEW_MATRIX GL_ARB_transpose_matrix g->transform.modelViewStack.top->m00 g->transform.modelViewStack.top->m10 g->transform.modelViewStack.top->m20 g->transform.modelViewStack.top->m30 g->transform.modelViewStack.top->m01 g->transform.modelViewStack.top->m11 g->transform.modelViewStack.top->m21 g->transform.modelViewStack.top->m31 g->transform.modelViewStack.top->m02 g->transform.modelViewStack.top->m12 g->transform.modelViewStack.top->m22 g->transform.modelViewStack.top->m32 g->transform.modelViewStack.top->m03 g->transform.modelViewStack.top->m13 g->transform.modelViewStack.top->m23 g->transform.modelViewStack.top->m33 +GLdefault GL_TRANSPOSE_PROJECTION_MATRIX GL_ARB_transpose_matrix g->transform.projectionStack.top->m00 g->transform.projectionStack.top->m10 g->transform.projectionStack.top->m20 g->transform.projectionStack.top->m30 g->transform.projectionStack.top->m01 g->transform.projectionStack.top->m11 g->transform.projectionStack.top->m21 g->transform.projectionStack.top->m31 g->transform.projectionStack.top->m02 g->transform.projectionStack.top->m12 g->transform.projectionStack.top->m22 g->transform.projectionStack.top->m32 g->transform.projectionStack.top->m03 g->transform.projectionStack.top->m13 g->transform.projectionStack.top->m23 g->transform.projectionStack.top->m33 +GLdefault GL_TRANSPOSE_TEXTURE_MATRIX GL_ARB_transpose_matrix g->transform.textureStack[g->texture.curTextureUnit].top->m00 g->transform.textureStack[g->texture.curTextureUnit].top->m10 g->transform.textureStack[g->texture.curTextureUnit].top->m20 g->transform.textureStack[g->texture.curTextureUnit].top->m30 g->transform.textureStack[g->texture.curTextureUnit].top->m01 g->transform.textureStack[g->texture.curTextureUnit].top->m11 g->transform.textureStack[g->texture.curTextureUnit].top->m21 g->transform.textureStack[g->texture.curTextureUnit].top->m31 g->transform.textureStack[g->texture.curTextureUnit].top->m02 g->transform.textureStack[g->texture.curTextureUnit].top->m12 g->transform.textureStack[g->texture.curTextureUnit].top->m22 g->transform.textureStack[g->texture.curTextureUnit].top->m32 g->transform.textureStack[g->texture.curTextureUnit].top->m03 g->transform.textureStack[g->texture.curTextureUnit].top->m13 g->transform.textureStack[g->texture.curTextureUnit].top->m23 g->transform.textureStack[g->texture.curTextureUnit].top->m33 + +# GL_ARB_multisample + +GLboolean GL_MULTISAMPLE_ARB GL_ARB_multisample g->multisample.enabled +GLboolean GL_SAMPLE_ALPHA_TO_COVERAGE_ARB GL_ARB_multisample g->multisample.sampleAlphaToCoverage +GLboolean GL_SAMPLE_ALPHA_TO_ONE_ARB GL_ARB_multisample g->multisample.sampleAlphaToOne +GLboolean GL_SAMPLE_COVERAGE_ARB GL_ARB_multisample g->multisample.sampleCoverage +GLint GL_SAMPLE_BUFFERS_ARB GL_ARB_multisample g->limits.sampleBuffers +GLint GL_SAMPLES_ARB GL_ARB_multisample g->limits.samples +GLint GL_SAMPLE_COVERAGE_VALUE_ARB GL_ARB_multisample g->multisample.sampleCoverageValue +GLboolean GL_SAMPLE_COVERAGE_INVERT_ARB GL_ARB_multisample g->multisample.sampleCoverageInvert + +# GL_ARB_texture_compression + +GLint GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB GL_ARB_texture_compression g->limits.numCompressedFormats +GLint GL_COMPRESSED_TEXTURE_FORMATS_ARB GL_ARB_texture_compression g->limits.compressedFormats[0] +GLint GL_TEXTURE_COMPRESSION_HINT_ARB GL_ARB_texture_compression g->hint.textureCompression + +# GL_EXT_texture_lod_bias +GLfloat GL_MAX_TEXTURE_LOD_BIAS_EXT GL_EXT_texture_lod_bias g->limits.maxTextureLodBias + +# GL_EXT_fog_coordinate +GLfloat GL_CURRENT_FOG_COORDINATE_EXT GL_EXT_fog_coord g->current.vertexAttrib[VERT_ATTRIB_FOG][0] +GLboolean GL_FOG_COORDINATE_ARRAY_EXT GL_EXT_fog_coord g->client.array.f.enabled +GLint GL_FOG_COORDINATE_ARRAY_TYPE_EXT GL_EXT_fog_coord g->client.array.f.type +GLint GL_FOG_COORDINATE_ARRAY_STRIDE_EXT GL_EXT_fog_coord g->client.array.f.stride +GLenum GL_FOG_COORDINATE_SOURCE_EXT GL_EXT_fog_coord g->fog.fogCoordinateSource + +# GL_EXT_secondary_color +GLboolean GL_COLOR_SUM_EXT GL_EXT_secondary_color g->lighting.colorSumEXT +GLfloat GL_CURRENT_SECONDARY_COLOR_EXT GL_EXT_secondary_color g->current.vertexAttrib[VERT_ATTRIB_COLOR1][0] g->current.vertexAttrib[VERT_ATTRIB_COLOR1][1] g->current.vertexAttrib[VERT_ATTRIB_COLOR1][2] +GLboolean GL_SECONDARY_COLOR_ARRAY_EXT GL_EXT_secondary_color g->client.array.s.enabled +GLint GL_SECONDARY_COLOR_ARRAY_TYPE_EXT GL_EXT_secondary_color g->client.array.s.type +GLint GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT GL_EXT_secondary_color g->client.array.s.stride +GLint GL_SECONDARY_COLOR_ARRAY_SIZE_EXT GL_EXT_secondary_color g->client.array.s.size + +# GL_SGIS_generate_mipmap +GLint GL_GENERATE_MIPMAP_HINT GL_SGIS_generate_mipmap g->hint.generateMipmap + +# GL_ARB_point_sprite +GLboolean GL_POINT_SPRITE_ARB GL_ARB_point_sprite g->point.pointSprite + +# GL_ARB_vertex_buffer_object +GLuint GL_ARRAY_BUFFER_BINDING_ARB GL_ARB_vertex_buffer_object g->bufferobject.arrayBuffer->id +GLuint GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB GL_ARB_vertex_buffer_object g->bufferobject.elementsBuffer->id + +# GL_ARB_pixel_buffer_object +GLuint GL_PIXEL_PACK_BUFFER_BINDING_ARB GL_ARB_pixel_buffer_object g->bufferobject.packBuffer->id +GLuint GL_PIXEL_UNPACK_BUFFER_BINDING_ARB GL_ARB_pixel_buffer_object g->bufferobject.unpackBuffer->id diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_extensions_isenabled.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_extensions_isenabled.txt new file mode 100644 index 00000000..d9c1da64 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_extensions_isenabled.txt @@ -0,0 +1,71 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +# GL_OPENGL_VERSION_1_2 + +GLboolean GL_RESCALE_NORMAL OPENGL_VERSION_1_2 g->transform.rescaleNormals +GLboolean GL_TEXTURE_3D OPENGL_VERSION_1_2 g->texture.unit[g->texture.curTextureUnit].enabled3D +GLboolean GL_MULTISAMPLE_ARB ARB_multisample g->multisample.enabled +GLboolean GL_SAMPLE_ALPHA_TO_COVERAGE_ARB ARB_multisample g->multisample.sampleAlphaToCoverage +GLboolean GL_SAMPLE_ALPHA_TO_ONE_ARB ARB_multisample g->multisample.sampleAlphaToOne +GLboolean GL_SAMPLE_COVERAGE_ARB ARB_multisample g->multisample.sampleCoverage +GLboolean GL_VERTEX_PROGRAM_NV NV_vertex_program g->program.vpEnabled +GLboolean GL_VERTEX_PROGRAM_POINT_SIZE_NV NV_vertex_program g->program.vpPointSize +GLboolean GL_VERTEX_PROGRAM_TWO_SIDE_NV NV_vertex_program g->program.vpTwoSide + +GLboolean GL_FRAGMENT_PROGRAM_NV NV_fragment_program g->program.fpEnabled +GLboolean GL_FRAGMENT_PROGRAM_ARB ARB_fragment_program g->program.fpEnabledARB +GLboolean GL_SECONDARY_COLOR_ARRAY_EXT EXT_secondary_color g->client.array.s.enabled +GLboolean GL_FOG_COORDINATE_ARRAY_EXT EXT_fog_coord g->client.array.f.enabled +GLboolean GL_TEXTURE_RECTANGLE_NV NV_texture_rectangle g->texture.unit[g->texture.curTextureUnit].enabledRect +GLboolean GL_VERTEX_ATTRIB_ARRAY0_NV NV_vertex_program g->client.array.a[0].enabled +GLboolean GL_VERTEX_ATTRIB_ARRAY1_NV NV_vertex_program g->client.array.a[1].enabled +GLboolean GL_VERTEX_ATTRIB_ARRAY2_NV NV_vertex_program g->client.array.a[2].enabled +GLboolean GL_VERTEX_ATTRIB_ARRAY3_NV NV_vertex_program g->client.array.a[3].enabled +GLboolean GL_VERTEX_ATTRIB_ARRAY4_NV NV_vertex_program g->client.array.a[4].enabled +GLboolean GL_VERTEX_ATTRIB_ARRAY5_NV NV_vertex_program g->client.array.a[5].enabled +GLboolean GL_VERTEX_ATTRIB_ARRAY6_NV NV_vertex_program g->client.array.a[6].enabled +GLboolean GL_VERTEX_ATTRIB_ARRAY7_NV NV_vertex_program g->client.array.a[7].enabled +GLboolean GL_VERTEX_ATTRIB_ARRAY8_NV NV_vertex_program g->client.array.a[8].enabled +GLboolean GL_VERTEX_ATTRIB_ARRAY9_NV NV_vertex_program g->client.array.a[9].enabled +GLboolean GL_VERTEX_ATTRIB_ARRAY10_NV NV_vertex_program g->client.array.a[10].enabled +GLboolean GL_VERTEX_ATTRIB_ARRAY11_NV NV_vertex_program g->client.array.a[11].enabled +GLboolean GL_VERTEX_ATTRIB_ARRAY12_NV NV_vertex_program g->client.array.a[12].enabled +GLboolean GL_VERTEX_ATTRIB_ARRAY13_NV NV_vertex_program g->client.array.a[13].enabled +GLboolean GL_VERTEX_ATTRIB_ARRAY14_NV NV_vertex_program g->client.array.a[14].enabled +GLboolean GL_VERTEX_ATTRIB_ARRAY15_NV NV_vertex_program g->client.array.a[15].enabled +GLboolean GL_MAP1_VERTEX_ATTRIB0_4_NV NV_vertex_program g->eval.enableAttrib1D[0] +GLboolean GL_MAP1_VERTEX_ATTRIB1_4_NV NV_vertex_program g->eval.enableAttrib1D[1] +GLboolean GL_MAP1_VERTEX_ATTRIB2_4_NV NV_vertex_program g->eval.enableAttrib1D[2] +GLboolean GL_MAP1_VERTEX_ATTRIB3_4_NV NV_vertex_program g->eval.enableAttrib1D[3] +GLboolean GL_MAP1_VERTEX_ATTRIB4_4_NV NV_vertex_program g->eval.enableAttrib1D[4] +GLboolean GL_MAP1_VERTEX_ATTRIB5_4_NV NV_vertex_program g->eval.enableAttrib1D[5] +GLboolean GL_MAP1_VERTEX_ATTRIB6_4_NV NV_vertex_program g->eval.enableAttrib1D[6] +GLboolean GL_MAP1_VERTEX_ATTRIB7_4_NV NV_vertex_program g->eval.enableAttrib1D[7] +GLboolean GL_MAP1_VERTEX_ATTRIB8_4_NV NV_vertex_program g->eval.enableAttrib1D[8] +GLboolean GL_MAP1_VERTEX_ATTRIB9_4_NV NV_vertex_program g->eval.enableAttrib1D[9] +GLboolean GL_MAP1_VERTEX_ATTRIB10_4_NV NV_vertex_program g->eval.enableAttrib1D[10] +GLboolean GL_MAP1_VERTEX_ATTRIB11_4_NV NV_vertex_program g->eval.enableAttrib1D[11] +GLboolean GL_MAP1_VERTEX_ATTRIB12_4_NV NV_vertex_program g->eval.enableAttrib1D[12] +GLboolean GL_MAP1_VERTEX_ATTRIB13_4_NV NV_vertex_program g->eval.enableAttrib1D[13] +GLboolean GL_MAP1_VERTEX_ATTRIB14_4_NV NV_vertex_program g->eval.enableAttrib1D[14] +GLboolean GL_MAP1_VERTEX_ATTRIB15_4_NV NV_vertex_program g->eval.enableAttrib1D[15] +GLboolean GL_MAP2_VERTEX_ATTRIB0_4_NV NV_vertex_program g->eval.enableAttrib2D[0] +GLboolean GL_MAP2_VERTEX_ATTRIB1_4_NV NV_vertex_program g->eval.enableAttrib2D[1] +GLboolean GL_MAP2_VERTEX_ATTRIB2_4_NV NV_vertex_program g->eval.enableAttrib2D[2] +GLboolean GL_MAP2_VERTEX_ATTRIB3_4_NV NV_vertex_program g->eval.enableAttrib2D[3] +GLboolean GL_MAP2_VERTEX_ATTRIB4_4_NV NV_vertex_program g->eval.enableAttrib2D[4] +GLboolean GL_MAP2_VERTEX_ATTRIB5_4_NV NV_vertex_program g->eval.enableAttrib2D[5] +GLboolean GL_MAP2_VERTEX_ATTRIB6_4_NV NV_vertex_program g->eval.enableAttrib2D[6] +GLboolean GL_MAP2_VERTEX_ATTRIB7_4_NV NV_vertex_program g->eval.enableAttrib2D[7] +GLboolean GL_MAP2_VERTEX_ATTRIB8_4_NV NV_vertex_program g->eval.enableAttrib2D[8] +GLboolean GL_MAP2_VERTEX_ATTRIB9_4_NV NV_vertex_program g->eval.enableAttrib2D[9] +GLboolean GL_MAP2_VERTEX_ATTRIB10_4_NV NV_vertex_program g->eval.enableAttrib2D[10] +GLboolean GL_MAP2_VERTEX_ATTRIB11_4_NV NV_vertex_program g->eval.enableAttrib2D[11] +GLboolean GL_MAP2_VERTEX_ATTRIB12_4_NV NV_vertex_program g->eval.enableAttrib2D[12] +GLboolean GL_MAP2_VERTEX_ATTRIB13_4_NV NV_vertex_program g->eval.enableAttrib2D[13] +GLboolean GL_MAP2_VERTEX_ATTRIB14_4_NV NV_vertex_program g->eval.enableAttrib2D[14] +GLboolean GL_MAP2_VERTEX_ATTRIB15_4_NV NV_vertex_program g->eval.enableAttrib2D[15] +GLboolean GL_RASTER_POSITION_UNCLIPPED_IBM IBM_rasterpos_clip g->transform.rasterPositionUnclipped diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_feedback.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_feedback.c new file mode 100644 index 00000000..a8591976 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_feedback.c @@ -0,0 +1,2423 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "state.h" +#include "state_internals.h" +#include "state/cr_statetypes.h" +#include "state/cr_feedback.h" + +/* + * This file is really a complement to the feedbackSPU and as such + * has big dependencies upon it. We have to monitor a whole bunch + * of state in the feedbackSPU to be able to properly implement + * full functionality. + * + * We have to intercept glColor3f(v)/4f(v) to get state updates on + * color properties and also glTexCoord* too, as unlike the tilesortSPU + * we don't have a pincher that pulls these out as they're passing + * through. + * + * - Alan. + */ + + +/* + * Selection and feedback + * + * TODO: + * 1. Implement lighting for vertex colors for feedback + * 2. Implement user clip planes for points and lines + */ + + +/**********************************************************************/ +/***** Vertex Transformation and Clipping *****/ +/**********************************************************************/ + +/* + * Transform a point (column vector) by a matrix: Q = M * P + */ +#define TRANSFORM_POINT( Q, M, P ) \ + Q.x = (M).m00 * P.x + (M).m10 * P.y + (M).m20 * P.z + (M).m30 * P.w; \ + Q.y = (M).m01 * P.x + (M).m11 * P.y + (M).m21 * P.z + (M).m31 * P.w; \ + Q.z = (M).m02 * P.x + (M).m12 * P.y + (M).m22 * P.z + (M).m32 * P.w; \ + Q.w = (M).m03 * P.x + (M).m13 * P.y + (M).m23 * P.z + (M).m33 * P.w; + +#define TRANSFORM_POINTA( Q, M, P ) \ + Q.x = (M).m00 * (P)[0] + (M).m10 * (P)[1] + (M).m20 * (P)[2] + (M).m30 * (P)[3]; \ + Q.y = (M).m01 * (P)[0] + (M).m11 * (P)[1] + (M).m21 * (P)[2] + (M).m31 * (P)[3]; \ + Q.z = (M).m02 * (P)[0] + (M).m12 * (P)[1] + (M).m22 * (P)[2] + (M).m32 * (P)[3]; \ + Q.w = (M).m03 * (P)[0] + (M).m13 * (P)[1] + (M).m23 * (P)[2] + (M).m33 * (P)[3]; + +/* + * clip coord to window coord mapping + */ +#define MAP_POINT( Q, P, VP ) \ + Q.x = (GLfloat) (((P.x / P.w) + 1.0) * VP.viewportW / 2.0 + VP.viewportX); \ + Q.y = (GLfloat) (((P.y / P.w) + 1.0) * VP.viewportH / 2.0 + VP.viewportY); \ + Q.z = (GLfloat) (((P.z / P.w) + 1.0) * (VP.farClip - VP.nearClip) / 2.0 + VP.nearClip);\ + Q.w = (GLfloat) P.w; + + +/* + * Linear interpolation: + */ +#define INTERPOLATE(T, A, B) ((A) + ((B) - (A)) * (T)) + + +/* + * Interpolate vertex position, color, texcoords, etc. + */ +static void +interpolate_vertex(GLfloat t, + const CRVertex *v0, const CRVertex *v1, + CRVertex *vOut) +{ + vOut->eyePos.x = INTERPOLATE(t, v0->eyePos.x, v1->eyePos.x); + vOut->eyePos.y = INTERPOLATE(t, v0->eyePos.y, v1->eyePos.y); + vOut->eyePos.z = INTERPOLATE(t, v0->eyePos.z, v1->eyePos.z); + vOut->eyePos.w = INTERPOLATE(t, v0->eyePos.w, v1->eyePos.w); + + vOut->clipPos.x = INTERPOLATE(t, v0->clipPos.x, v1->clipPos.x); + vOut->clipPos.y = INTERPOLATE(t, v0->clipPos.y, v1->clipPos.y); + vOut->clipPos.z = INTERPOLATE(t, v0->clipPos.z, v1->clipPos.z); + vOut->clipPos.w = INTERPOLATE(t, v0->clipPos.w, v1->clipPos.w); + + vOut->attrib[VERT_ATTRIB_COLOR0][0] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_COLOR0][0], v1->attrib[VERT_ATTRIB_COLOR0][0]); + vOut->attrib[VERT_ATTRIB_COLOR0][1] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_COLOR0][1], v1->attrib[VERT_ATTRIB_COLOR0][1]); + vOut->attrib[VERT_ATTRIB_COLOR0][2] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_COLOR0][2], v1->attrib[VERT_ATTRIB_COLOR0][2]); + vOut->attrib[VERT_ATTRIB_COLOR0][3] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_COLOR0][3], v1->attrib[VERT_ATTRIB_COLOR0][3]); + + vOut->colorIndex = INTERPOLATE(t, v0->colorIndex, v1->colorIndex); + + vOut->attrib[VERT_ATTRIB_TEX0][0] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_TEX0][0], v1->attrib[VERT_ATTRIB_TEX0][0]); + vOut->attrib[VERT_ATTRIB_TEX0][1] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_TEX0][1], v1->attrib[VERT_ATTRIB_TEX0][0]); + vOut->attrib[VERT_ATTRIB_TEX0][2] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_TEX0][2], v1->attrib[VERT_ATTRIB_TEX0][0]); + vOut->attrib[VERT_ATTRIB_TEX0][3] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_TEX0][3], v1->attrib[VERT_ATTRIB_TEX0][0]); +} + + + + +/* clip bit codes */ +#define CLIP_LEFT 1 +#define CLIP_RIGHT 2 +#define CLIP_BOTTOM 4 +#define CLIP_TOP 8 +#define CLIP_NEAR 16 +#define CLIP_FAR 32 +#define CLIP_USER0 64 +#define CLIP_USER1 128 + + +/* + * Apply clip testing to a point. + * Return: 0 - visible + * non-zero - clip code mask (or of above CLIP_ bits) + */ +static GLuint +clip_point(const CRVertex *v) +{ + CRContext *g = GetCurrentContext(); + GLuint mask = 0; + GLuint i; + + /* user-defined clip planes */ + for (i = 0; i < g->limits.maxClipPlanes; i++) + { + if (g->transform.clip[i]) + { + const GLvectord *plane = g->transform.clipPlane + i; + if (plane->x * v->eyePos.x + + plane->y * v->eyePos.y + + plane->z * v->eyePos.z + + plane->w * v->eyePos.w < 0.0) + mask |= (CLIP_USER0 << i); + } + } + + /* view volume clipping */ + if (v->clipPos.x > v->clipPos.w) + mask |= CLIP_RIGHT; + if (v->clipPos.x < -v->clipPos.w) + mask |= CLIP_LEFT; + if (v->clipPos.y > v->clipPos.w) + mask |= CLIP_TOP; + if (v->clipPos.y < -v->clipPos.w) + mask |= CLIP_BOTTOM; + if (v->clipPos.z > v->clipPos.w) + mask |= CLIP_FAR; + if (v->clipPos.z < -v->clipPos.w) + mask |= CLIP_NEAR; + return mask; +} + + +/* + * Apply clipping to a line segment. + * Input: v0, v1 - incoming vertices + * Output: v0out, v1out - result/clipped vertices + * Return: GL_TRUE: visible + * GL_FALSE: totally clipped + */ +static GLboolean +clip_line(const CRVertex *v0in, const CRVertex *v1in, + CRVertex *v0new, CRVertex *v1new) +{ + CRVertex v0, v1, vNew; + GLfloat dx, dy, dz, dw, t; + GLuint code0, code1; + + /* XXX need to do user-clip planes */ + + code0 = clip_point(v0in); + code1 = clip_point(v1in); + if (code0 & code1) + return GL_FALSE; /* totally clipped */ + + *v0new = *v0in; + *v1new = *v1in; + if (code0 == 0 && code1 == 0) + return GL_TRUE; /* no clipping needed */ + + v0 = *v0in; + v1 = *v1in; + + +/* + * We use 6 instances of this code to clip agains the 6 planes. + * For each plane, we define the OUTSIDE and COMPUTE_INTERSECTION + * macros appropriately. + */ +#define GENERAL_CLIP \ + if (OUTSIDE(v0)) { \ + if (OUTSIDE(v1)) { \ + /* both verts are outside ==> return 0 */ \ + return 0; \ + } \ + else { \ + /* v0 is outside, v1 is inside ==> clip */ \ + COMPUTE_INTERSECTION( v1, v0, vNew ) \ + interpolate_vertex(t, &v1, &v0, &vNew); \ + v0 = vNew; \ + } \ + } \ + else { \ + if (OUTSIDE(v1)) { \ + /* v0 is inside, v1 is outside ==> clip */ \ + COMPUTE_INTERSECTION( v0, v1, vNew ) \ + interpolate_vertex(t, &v0, &v1, &vNew); \ + v1 = vNew; \ + } \ + /* else both verts are inside ==> do nothing */ \ + } + + /*** Clip against +X side ***/ +#define OUTSIDE(V) (V.clipPos.x > V.clipPos.w) +#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \ + dx = OUT.clipPos.x - IN.clipPos.x; \ + dw = OUT.clipPos.w - IN.clipPos.w; \ + t = (IN.clipPos.x - IN.clipPos.w) / (dw-dx); + GENERAL_CLIP +#undef OUTSIDE +#undef COMPUTE_INTERSECTION + + /*** Clip against -X side ***/ +#define OUTSIDE(V) (V.clipPos.x < -(V.clipPos.w)) +#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \ + dx = OUT.clipPos.x - IN.clipPos.x; \ + dw = OUT.clipPos.w - IN.clipPos.w; \ + t = -(IN.clipPos.x + IN.clipPos.w) / (dw+dx); + GENERAL_CLIP +#undef OUTSIDE +#undef COMPUTE_INTERSECTION + + /*** Clip against +Y side ***/ +#define OUTSIDE(V) (V.clipPos.y > V.clipPos.w) +#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \ + dy = OUT.clipPos.y - IN.clipPos.y; \ + dw = OUT.clipPos.w - IN.clipPos.w; \ + t = (IN.clipPos.y - IN.clipPos.w) / (dw-dy); + GENERAL_CLIP +#undef OUTSIDE +#undef COMPUTE_INTERSECTION + + /*** Clip against -Y side ***/ +#define OUTSIDE(V) (V.clipPos.y < -(V.clipPos.w)) +#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \ + dy = OUT.clipPos.y - IN.clipPos.y; \ + dw = OUT.clipPos.w - IN.clipPos.w; \ + t = -(IN.clipPos.y + IN.clipPos.w) / (dw+dy); + GENERAL_CLIP +#undef OUTSIDE +#undef COMPUTE_INTERSECTION + + /*** Clip against +Z side ***/ +#define OUTSIDE(V) (V.clipPos.z > V.clipPos.w) +#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \ + dz = OUT.clipPos.z - IN.clipPos.z; \ + dw = OUT.clipPos.w - IN.clipPos.w; \ + t = (IN.clipPos.z - IN.clipPos.w) / (dw-dz); + GENERAL_CLIP +#undef OUTSIDE +#undef COMPUTE_INTERSECTION + + /*** Clip against -Z side ***/ +#define OUTSIDE(V) (V.clipPos.z < -(V.clipPos.w)) +#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \ + dz = OUT.clipPos.z - IN.clipPos.z; \ + dw = OUT.clipPos.w - IN.clipPos.w; \ + t = -(IN.clipPos.z + IN.clipPos.w) / (dw+dz); + GENERAL_CLIP +#undef OUTSIDE +#undef COMPUTE_INTERSECTION + +#undef GENERAL_CLIP + + *v0new = v0; + *v1new = v1; + return GL_TRUE; +} + + + +/* + * Apply clipping to a polygon. + * Input: vIn - array of input vertices + * inCount - number of input vertices + * Output: vOut - new vertices + * Return: number of vertices in vOut + */ +static GLuint +clip_polygon(const CRVertex *vIn, unsigned int inCount, + CRVertex *vOut) +{ + CRVertex inlist[20], outlist[20]; + GLfloat dx, dy, dz, dw, t; + GLuint incount, outcount, previ, curri, result; + const CRVertex *currVert, *prevVert; + CRVertex *newVert; + + /* XXX need to do user-clip planes */ + +#define GENERAL_CLIP(INCOUNT, INLIST, OUTCOUNT, OUTLIST) \ + if (INCOUNT < 3) \ + return GL_FALSE; \ + previ = INCOUNT - 1; /* let previous = last vertex */ \ + prevVert = INLIST + previ; \ + OUTCOUNT = 0; \ + for (curri = 0; curri < INCOUNT; curri++) { \ + currVert = INLIST + curri; \ + if (INSIDE(currVert)) { \ + if (INSIDE(prevVert)) { \ + /* both verts are inside ==> copy current to outlist */ \ + OUTLIST[OUTCOUNT] = *currVert; \ + OUTCOUNT++; \ + } \ + else { \ + newVert = OUTLIST + OUTCOUNT; \ + /* current is inside and previous is outside ==> clip */ \ + COMPUTE_INTERSECTION( currVert, prevVert, newVert ) \ + OUTCOUNT++; \ + /* Output current */ \ + OUTLIST[OUTCOUNT] = *currVert; \ + OUTCOUNT++; \ + } \ + } \ + else { \ + if (INSIDE(prevVert)) { \ + newVert = OUTLIST + OUTCOUNT; \ + /* current is outside and previous is inside ==> clip */ \ + COMPUTE_INTERSECTION( prevVert, currVert, newVert ); \ + OUTLIST[OUTCOUNT] = *newVert; \ + OUTCOUNT++; \ + } \ + /* else both verts are outside ==> do nothing */ \ + } \ + /* let previous = current */ \ + previ = curri; \ + prevVert = currVert; \ + } + +/* + * Clip against +X + */ +#define INSIDE(V) (V->clipPos.x <= V->clipPos.w) +#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \ + dx = OUT->clipPos.x - IN->clipPos.x; \ + dw = OUT->clipPos.w - IN->clipPos.w; \ + t = (IN->clipPos.x - IN->clipPos.w) / (dw - dx); \ + interpolate_vertex(t, IN, OUT, NEW ); + + GENERAL_CLIP(inCount, vIn, outcount, outlist) + +#undef INSIDE +#undef COMPUTE_INTERSECTION + +/* + * Clip against -X + */ +#define INSIDE(V) (V->clipPos.x >= -V->clipPos.w) +#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \ + dx = OUT->clipPos.x - IN->clipPos.x; \ + dw = OUT->clipPos.w - IN->clipPos.w; \ + t = -(IN->clipPos.x + IN->clipPos.w) / (dw + dx); \ + interpolate_vertex(t, IN, OUT, NEW ); + + GENERAL_CLIP(outcount, outlist, incount, inlist) + +#undef INSIDE +#undef COMPUTE_INTERSECTION + +/* + * Clip against +Y + */ +#define INSIDE(V) (V->clipPos.y <= V->clipPos.w) +#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \ + dy = OUT->clipPos.y - IN->clipPos.y; \ + dw = OUT->clipPos.w - IN->clipPos.w; \ + t = (IN->clipPos.y - IN->clipPos.w) / (dw - dy); \ + interpolate_vertex(t, IN, OUT, NEW ); + + GENERAL_CLIP(incount, inlist, outcount, outlist) + +#undef INSIDE +#undef COMPUTE_INTERSECTION + +/* + * Clip against -Y + */ +#define INSIDE(V) (V->clipPos.y >= -V->clipPos.w) +#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \ + dy = OUT->clipPos.y - IN->clipPos.y; \ + dw = OUT->clipPos.w - IN->clipPos.w; \ + t = -(IN->clipPos.y + IN->clipPos.w) / (dw + dy); \ + interpolate_vertex(t, IN, OUT, NEW ); + + GENERAL_CLIP(outcount, outlist, incount, inlist) + +#undef INSIDE +#undef COMPUTE_INTERSECTION + +/* + * Clip against +Z + */ +#define INSIDE(V) (V->clipPos.z <= V->clipPos.w) +#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \ + dz = OUT->clipPos.z - IN->clipPos.z; \ + dw = OUT->clipPos.w - IN->clipPos.w; \ + t = (IN->clipPos.z - IN->clipPos.w) / (dw - dz); \ + interpolate_vertex(t, IN, OUT, NEW ); + + GENERAL_CLIP(incount, inlist, outcount, outlist) + +#undef INSIDE +#undef COMPUTE_INTERSECTION + +/* + * Clip against -Z + */ +#define INSIDE(V) (V->clipPos.z >= -V->clipPos.w) +#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \ + dz = OUT->clipPos.z - IN->clipPos.z; \ + dw = OUT->clipPos.w - IN->clipPos.w; \ + t = -(IN->clipPos.z + IN->clipPos.w) / (dw + dz); \ + interpolate_vertex(t, IN, OUT, NEW ); + + GENERAL_CLIP(outcount, outlist, result, vOut) + +#undef INSIDE +#undef COMPUTE_INTERSECTION + +#undef GENERAL_CLIP + + return result; +} + + +/**********************************************************************/ +/***** Feedback *****/ +/**********************************************************************/ + + +#define FB_3D 0x01 +#define FB_4D 0x02 +#define FB_INDEX 0x04 +#define FB_COLOR 0x08 +#define FB_TEXTURE 0X10 + +#define FEEDBACK_TOKEN( T ) \ + do { \ + if (f->count < f->bufferSize) { \ + f->buffer[f->count] = (GLfloat) (T); \ + } \ + f->count++; \ + } while (0) + +/* + * Put a vertex into the feedback buffer. + */ +static void +feedback_vertex(const CRVertex *v) +{ + CRContext *g = GetCurrentContext(); + CRFeedbackState *f = &(g->feedback); + CRTransformState *t = &(g->transform); + + FEEDBACK_TOKEN(v->winPos.x); + FEEDBACK_TOKEN(v->winPos.y); + + if (f->mask & FB_3D) + { + FEEDBACK_TOKEN(v->winPos.z); + } + + if (f->mask & FB_4D) + { + FEEDBACK_TOKEN(v->winPos.w); + } + + /* We don't deal with color index in Chromium */ + if (f->mask & FB_INDEX) + { + FEEDBACK_TOKEN(v->colorIndex); + } + + if (f->mask & FB_COLOR) + { + FEEDBACK_TOKEN(v->attrib[VERT_ATTRIB_COLOR0][0]); + FEEDBACK_TOKEN(v->attrib[VERT_ATTRIB_COLOR0][1]); + FEEDBACK_TOKEN(v->attrib[VERT_ATTRIB_COLOR0][2]); + FEEDBACK_TOKEN(v->attrib[VERT_ATTRIB_COLOR0][3]); + } + + if (f->mask & FB_TEXTURE) + { + GLvectorf coord, transCoord; + /* Ugh, copy (s,t,r,q) to (x,y,z,w) */ + coord.x = v->attrib[VERT_ATTRIB_TEX0][0]; + coord.y = v->attrib[VERT_ATTRIB_TEX0][1]; + coord.z = v->attrib[VERT_ATTRIB_TEX0][2]; + coord.w = v->attrib[VERT_ATTRIB_TEX0][3]; + TRANSFORM_POINT(transCoord, *(t->textureStack[0].top), coord); + FEEDBACK_TOKEN(transCoord.x); + FEEDBACK_TOKEN(transCoord.y); + FEEDBACK_TOKEN(transCoord.z); + FEEDBACK_TOKEN(transCoord.w); + } +} + + + +static void +feedback_rasterpos(void) +{ + CRContext *g = GetCurrentContext(); + CRVertex *tv = g->vBuffer + g->vCount; + CRVertex v; + + v.winPos.x = g->current.rasterAttrib[VERT_ATTRIB_POS][0]; + v.winPos.y = g->current.rasterAttrib[VERT_ATTRIB_POS][1]; + v.winPos.z = g->current.rasterAttrib[VERT_ATTRIB_POS][2]; + v.winPos.w = g->current.rasterAttrib[VERT_ATTRIB_POS][3]; + COPY_4V(v.attrib[VERT_ATTRIB_COLOR0] , g->current.rasterAttrib[VERT_ATTRIB_COLOR0]); /* XXX need to apply lighting */ + COPY_4V(v.attrib[VERT_ATTRIB_COLOR1] , g->current.rasterAttrib[VERT_ATTRIB_COLOR1]); + v.colorIndex = (GLfloat) g->current.rasterIndex; + + /* Don't do this, we're capturing TexCoord ourselves and + * we'd miss the conversion in RasterPosUpdate */ + /* v.texCoord[0] = g->current.rasterTexture; */ + + /* So we do this instead, and pluck it from the current vertex */ + COPY_4V(v.attrib[VERT_ATTRIB_TEX0] , tv->attrib[VERT_ATTRIB_TEX0]); + + feedback_vertex(&v); +} + + +static void +feedback_point(const CRVertex *v) +{ + CRContext *g = GetCurrentContext(); + CRFeedbackState *f = &(g->feedback); + if (clip_point(v) == 0) + { + CRVertex c = *v; + MAP_POINT(c.winPos, c.clipPos, g->viewport); + FEEDBACK_TOKEN((GLfloat) GL_POINT_TOKEN); + feedback_vertex(&c); + } +} + + +static void +feedback_line(const CRVertex *v0, const CRVertex *v1, GLboolean reset) +{ + CRContext *g = GetCurrentContext(); + CRFeedbackState *f = &(g->feedback); + CRVertex c0, c1; + if (clip_line(v0, v1, &c0, &c1)) + { + MAP_POINT(c0.winPos, c0.clipPos, g->viewport); + MAP_POINT(c1.winPos, c1.clipPos, g->viewport); + if (reset) + FEEDBACK_TOKEN((GLfloat) GL_LINE_RESET_TOKEN); + else + FEEDBACK_TOKEN((GLfloat) GL_LINE_TOKEN); + feedback_vertex(&c0); + feedback_vertex(&c1); + } +} + + +static void +feedback_triangle(const CRVertex *v0, const CRVertex *v1, const CRVertex *v2) +{ + CRContext *g = GetCurrentContext(); + CRFeedbackState *f = &(g->feedback); + CRVertex vlist[3], vclipped[8]; + GLuint i, n; + + vlist[0] = *v0; + vlist[1] = *v1; + vlist[2] = *v2; + n = clip_polygon(vlist, 3, vclipped); + FEEDBACK_TOKEN( (GLfloat) GL_POLYGON_TOKEN ); + FEEDBACK_TOKEN( (GLfloat) n ); + for (i = 0; i < n; i++) { + MAP_POINT(vclipped[i].winPos, vclipped[i].clipPos, g->viewport); + feedback_vertex(vclipped + i); + } +} + + +void STATE_APIENTRY +crStateFeedbackVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &(g->transform); + CRPolygonState *p = &(g->polygon); + CRVertex *v = g->vBuffer + g->vCount; + + /* store the vertex */ + v->attrib[VERT_ATTRIB_POS][0] = x; + v->attrib[VERT_ATTRIB_POS][1] = y; + v->attrib[VERT_ATTRIB_POS][2] = z; + v->attrib[VERT_ATTRIB_POS][3] = w; + COPY_4V(v->attrib[VERT_ATTRIB_COLOR0] , g->current.vertexAttrib[VERT_ATTRIB_COLOR0]); /* XXX need to apply lighting */ + v->colorIndex = g->current.colorIndex; /* XXX need to apply lighting */ + /* Don't do this, we're capturing TexCoord ourselves as + * we don't have a pincher like the tilesortSPU */ + /* v->texCoord[0] = g->current.texCoord[0]; */ + + /* transform to eye space, then clip space */ + TRANSFORM_POINTA(v->eyePos, *(t->modelViewStack.top), v->attrib[VERT_ATTRIB_POS]); + TRANSFORM_POINT(v->clipPos, *(t->projectionStack.top), v->eyePos); + + switch (g->current.mode) { + case GL_POINTS: + CRASSERT(g->vCount == 0); + feedback_point(v); + break; + case GL_LINES: + if (g->vCount == 0) + { + g->vCount = 1; + } + else + { + CRASSERT(g->vCount == 1); + feedback_line(g->vBuffer + 0, g->vBuffer + 1, g->lineReset); + g->vCount = 0; + } + break; + case GL_LINE_STRIP: + if (g->vCount == 0) + { + g->vCount = 1; + } + else + { + CRASSERT(g->vCount == 1); + feedback_line(g->vBuffer + 0, g->vBuffer + 1, g->lineReset); + g->vBuffer[0] = g->vBuffer[1]; + g->lineReset = GL_FALSE; + /* leave g->vCount at 1 */ + } + break; + case GL_LINE_LOOP: + if (g->vCount == 0) + { + g->lineLoop = GL_FALSE; + g->vCount = 1; + } + else if (g->vCount == 1) + { + feedback_line(g->vBuffer + 0, g->vBuffer + 1, g->lineReset); + g->lineReset = GL_FALSE; + g->lineLoop = GL_TRUE; + g->vCount = 2; + } + else + { + CRASSERT(g->vCount == 2); + CRASSERT(g->lineReset == GL_FALSE); + g->lineLoop = GL_FALSE; + feedback_line(g->vBuffer + 1, g->vBuffer + 2, g->lineReset); + g->vBuffer[1] = g->vBuffer[2]; + /* leave g->vCount at 2 */ + } + break; + case GL_TRIANGLES: + if (g->vCount == 0 || g->vCount == 1) + { + g->vCount++; + } + else + { + CRASSERT(g->vCount == 2); + feedback_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2); + g->vCount = 0; + } + break; + case GL_TRIANGLE_STRIP: + if (g->vCount == 0 || g->vCount == 1) + { + g->vCount++; + } + else if (g->vCount == 2) + { + feedback_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2); + g->vCount = 3; + } + else + { + CRASSERT(g->vCount == 3); + feedback_triangle(g->vBuffer + 1, g->vBuffer + 3, g->vBuffer + 2); + g->vBuffer[0] = g->vBuffer[2]; + g->vBuffer[1] = g->vBuffer[3]; + g->vCount = 2; + } + break; + case GL_TRIANGLE_FAN: + if (g->vCount == 0 || g->vCount == 1) + { + g->vCount++; + } + else + { + CRASSERT(g->vCount == 2); + feedback_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2); + g->vBuffer[1] = g->vBuffer[2]; + /* leave g->vCount = 2 */ + } + break; + case GL_QUADS: + if (g->vCount < 3) + { + g->vCount++; + } + else + { + CRASSERT(g->vCount == 3); + feedback_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2); + feedback_triangle(g->vBuffer + 0, g->vBuffer + 2, g->vBuffer + 3); + g->vCount = 0; + } + break; + case GL_QUAD_STRIP: + if (g->vCount < 3) + { + g->vCount++; + } + else + { + CRASSERT(g->vCount == 3); + feedback_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2); + feedback_triangle(g->vBuffer + 1, g->vBuffer + 3, g->vBuffer + 2); + g->vBuffer[0] = g->vBuffer[2]; + g->vBuffer[1] = g->vBuffer[3]; + g->vCount = 2; + } + break; + case GL_POLYGON: + /* XXX need to observe polygon mode for the above TRI/QUAD prims */ + switch (p->frontMode) { + case GL_POINT: + CRASSERT(g->vCount == 0); + feedback_point(v); + break; + case GL_LINE: + if (g->vCount == 0) + { + g->lineLoop = GL_FALSE; + g->vCount = 1; + } + else if (g->vCount == 1) + { + feedback_line(g->vBuffer + 0, g->vBuffer + 1, g->lineReset); + g->lineReset = GL_FALSE; + g->lineLoop = GL_TRUE; + g->vCount = 2; + } + else + { + CRASSERT(g->vCount == 2); + CRASSERT(g->lineReset == GL_FALSE); + g->lineLoop = GL_FALSE; + feedback_line(g->vBuffer + 1, g->vBuffer + 2, g->lineReset); + g->vBuffer[1] = g->vBuffer[2]; + /* leave g->vCount at 2 */ + } + break; + case GL_FILL: + /* draw as a tri-fan */ + if (g->vCount == 0 || g->vCount == 1) + { + g->vCount++; + } + else + { + CRASSERT(g->vCount == 2); + feedback_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2); + g->vBuffer[1] = g->vBuffer[2]; + /* leave g->vCount = 2 */ + } + break; + default: + ; /* impossible */ + } + break; + default: + ; /* impossible */ + } +} + + +void STATE_APIENTRY +crStateFeedbackBegin(GLenum mode) +{ + CRContext *g = GetCurrentContext(); + + crStateBegin(mode); + + g->vCount = 0; + g->lineReset = GL_TRUE; + g->lineLoop = GL_FALSE; +} + + +void STATE_APIENTRY +crStateFeedbackEnd(void) +{ + CRContext *g = GetCurrentContext(); + + if ( (g->current.mode == GL_LINE_LOOP || + (g->current.mode == GL_POLYGON && g->polygon.frontMode == GL_LINE)) + && g->vCount == 2 ) + { + /* draw the last line segment */ + if (g->lineLoop) + feedback_line(g->vBuffer + 1, g->vBuffer + 0, GL_FALSE); + else + feedback_line(g->vBuffer + 2, g->vBuffer + 0, GL_FALSE); + } + + crStateEnd(); +} + + +void STATE_APIENTRY +crStateFeedbackBuffer(GLsizei size, GLenum type, GLfloat * buffer) +{ + CRContext *g = GetCurrentContext(); + CRFeedbackState *f = &(g->feedback); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "FeedbackBuffer called in begin/end"); + return; + } + + if (g->renderMode == GL_FEEDBACK) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "Invalid Operation GL_FEEDBACK"); + return; + } + if (size < 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "Invalid Value size < 0"); + return; + } + if (!buffer) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "Invalid Value buffer = NULL"); + f->bufferSize = 0; + return; + } + + FLUSH(); + + switch (type) + { + case GL_2D: + f->mask = 0; + break; + case GL_3D: + f->mask = FB_3D; + break; + case GL_3D_COLOR: + f->mask = (FB_3D | FB_COLOR); /* FB_INDEX ?? */ + break; + case GL_3D_COLOR_TEXTURE: + f->mask = (FB_3D | FB_COLOR | FB_TEXTURE); /* FB_INDEX ?? */ + break; + case GL_4D_COLOR_TEXTURE: + f->mask = (FB_3D | FB_4D | FB_COLOR | FB_TEXTURE); /* FB_INDEX ?? */ + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "invalid type"); + return; + } + + f->type = type; + f->bufferSize = size; + f->buffer = buffer; + f->count = 0; +} + + +void STATE_APIENTRY +crStatePassThrough(GLfloat token) +{ + CRContext *g = GetCurrentContext(); + CRFeedbackState *f = &(g->feedback); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "PassThrough called in begin/end"); + return; + } + + FLUSH(); + + if (g->renderMode == GL_FEEDBACK) + { + FEEDBACK_TOKEN((GLfloat) (GLint) GL_PASS_THROUGH_TOKEN); + FEEDBACK_TOKEN(token); + } +} + + +/* + * Although these functions are used by the feedbackSPU alone, + * I've left them here as they interface to the other functions..... + */ +void STATE_APIENTRY +crStateFeedbackGetBooleanv(GLenum pname, GLboolean * params) +{ + CRContext *g = GetCurrentContext(); + + switch (pname) + { + + case GL_FEEDBACK_BUFFER_SIZE: + params[0] = (GLboolean) (g->feedback.bufferSize != 0); + break; + case GL_FEEDBACK_BUFFER_TYPE: + params[0] = (GLboolean) (g->feedback.type != 0); + break; + case GL_SELECTION_BUFFER_SIZE: + params[0] = (GLboolean) (g->selection.bufferSize != 0); + break; + default: + break; + } +} + + +void STATE_APIENTRY +crStateFeedbackGetDoublev(GLenum pname, GLdouble * params) +{ + CRContext *g = GetCurrentContext(); + + switch (pname) + { + + case GL_FEEDBACK_BUFFER_SIZE: + params[0] = (GLdouble) g->feedback.bufferSize; + break; + case GL_FEEDBACK_BUFFER_TYPE: + params[0] = (GLdouble) g->feedback.type; + break; + case GL_SELECTION_BUFFER_SIZE: + params[0] = (GLdouble) g->selection.bufferSize; + break; + default: + break; + } +} + + +void STATE_APIENTRY +crStateFeedbackGetFloatv(GLenum pname, GLfloat * params) +{ + CRContext *g = GetCurrentContext(); + + switch (pname) + { + + case GL_FEEDBACK_BUFFER_SIZE: + params[0] = (GLfloat) g->feedback.bufferSize; + break; + case GL_FEEDBACK_BUFFER_TYPE: + params[0] = (GLfloat) g->feedback.type; + break; + case GL_SELECTION_BUFFER_SIZE: + params[0] = (GLfloat) g->selection.bufferSize; + break; + default: + break; + } +} + + +void STATE_APIENTRY +crStateFeedbackGetIntegerv(GLenum pname, GLint * params) +{ + CRContext *g = GetCurrentContext(); + + switch (pname) + { + + case GL_FEEDBACK_BUFFER_SIZE: + params[0] = (GLint) g->feedback.bufferSize; + break; + case GL_FEEDBACK_BUFFER_TYPE: + params[0] = (GLint) g->feedback.type; + break; + case GL_SELECTION_BUFFER_SIZE: + params[0] = (GLint) g->selection.bufferSize; + break; + default: + break; + } +} + + +void STATE_APIENTRY +crStateFeedbackDrawPixels(GLsizei width, GLsizei height, GLenum format, + GLenum type, const GLvoid * pixels) +{ + CRContext *g = GetCurrentContext(); + CRFeedbackState *f = &(g->feedback); + + (void) width; + (void) height; + (void) format; + (void) type; + (void) pixels; + + FEEDBACK_TOKEN((GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN); + + feedback_rasterpos(); +} + +void STATE_APIENTRY +crStateFeedbackCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, + GLenum type) +{ + CRContext *g = GetCurrentContext(); + CRFeedbackState *f = &(g->feedback); + + (void) x; + (void) y; + (void) width; + (void) height; + (void) type; + + FEEDBACK_TOKEN((GLfloat) (GLint) GL_COPY_PIXEL_TOKEN); + feedback_rasterpos(); +} + +void STATE_APIENTRY +crStateFeedbackBitmap(GLsizei width, GLsizei height, GLfloat xorig, + GLfloat yorig, GLfloat xmove, GLfloat ymove, + const GLubyte * bitmap) +{ + CRContext *g = GetCurrentContext(); + CRFeedbackState *f = &(g->feedback); + + (void) width; + (void) height; + (void) bitmap; + (void) xorig; + (void) yorig; + + FEEDBACK_TOKEN((GLfloat) (GLint) GL_BITMAP_TOKEN); + + feedback_rasterpos(); + + if (g->current.rasterValid) + { + g->current.rasterAttrib[VERT_ATTRIB_POS][0] += xmove; + g->current.rasterAttrib[VERT_ATTRIB_POS][1] += ymove; + } +} + + +void STATE_APIENTRY +crStateFeedbackVertex4fv(const GLfloat * v) +{ + crStateFeedbackVertex4f(v[0], v[1], v[2], v[3]); +} + +void STATE_APIENTRY +crStateFeedbackVertex4s(GLshort v0, GLshort v1, GLshort v2, GLshort v3) +{ + crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, (GLfloat) v2, + (GLfloat) v3); +} + +void STATE_APIENTRY +crStateFeedbackVertex4sv(const GLshort * v) +{ + crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], + (GLfloat) v[3]); +} + +void STATE_APIENTRY +crStateFeedbackVertex4i(GLint v0, GLint v1, GLint v2, GLint v3) +{ + crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, (GLfloat) v2, + (GLfloat) v3); +} + +void STATE_APIENTRY +crStateFeedbackVertex4iv(const GLint * v) +{ + crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], + (GLfloat) v[3]); +} + +void STATE_APIENTRY +crStateFeedbackVertex4d(GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3) +{ + crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, (GLfloat) v2, + (GLfloat) v3); +} + +void STATE_APIENTRY +crStateFeedbackVertex4dv(const GLdouble * v) +{ + crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], + (GLfloat) v[3]); +} + +void STATE_APIENTRY +crStateFeedbackVertex2i(GLint v0, GLint v1) +{ + crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, 0.0f, 1.0f); +} + +void STATE_APIENTRY +crStateFeedbackVertex2iv(const GLint * v) +{ + crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], 0.0f, 1.0f); +} + +void STATE_APIENTRY +crStateFeedbackVertex2s(GLshort v0, GLshort v1) +{ + crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, 0.0f, 1.0f); +} + +void STATE_APIENTRY +crStateFeedbackVertex2sv(const GLshort * v) +{ + crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], 0.0f, 1.0f); +} + +void STATE_APIENTRY +crStateFeedbackVertex2f(GLfloat v0, GLfloat v1) +{ + crStateFeedbackVertex4f(v0, v1, 0.0f, 1.0f); +} + +void STATE_APIENTRY +crStateFeedbackVertex2fv(const GLfloat * v) +{ + crStateFeedbackVertex4f(v[0], v[1], 0.0f, 1.0f); +} + +void STATE_APIENTRY +crStateFeedbackVertex2d(GLdouble v0, GLdouble v1) +{ + crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, 0.0f, 1.0f); +} + +void STATE_APIENTRY +crStateFeedbackVertex2dv(const GLdouble * v) +{ + crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], 0.0f, 1.0f); +} + +void STATE_APIENTRY +crStateFeedbackVertex3i(GLint v0, GLint v1, GLint v2) +{ + crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, (GLfloat) v2, 1.0f); +} + +void STATE_APIENTRY +crStateFeedbackVertex3iv(const GLint * v) +{ + crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0f); +} + +void STATE_APIENTRY +crStateFeedbackVertex3s(GLshort v0, GLshort v1, GLshort v2) +{ + crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, (GLfloat) v2, 1.0f); +} + +void STATE_APIENTRY +crStateFeedbackVertex3sv(const GLshort * v) +{ + crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], + 1.0f); +} + +void STATE_APIENTRY +crStateFeedbackVertex3f(GLfloat v0, GLfloat v1, GLfloat v2) +{ + crStateFeedbackVertex4f(v0, v1, v2, 1.0f); +} + +void STATE_APIENTRY +crStateFeedbackVertex3fv(const GLfloat * v) +{ + crStateFeedbackVertex4f(v[0], v[1], v[2], 1.0f); +} + +void STATE_APIENTRY +crStateFeedbackVertex3d(GLdouble v0, GLdouble v1, GLdouble v2) +{ + crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, (GLfloat) v2, 1.0f); +} + +void STATE_APIENTRY +crStateFeedbackVertex3dv(const GLdouble * v) +{ + crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], + 1.0f); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord4f( GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3 ) +{ + CRContext *g = GetCurrentContext(); + CRVertex *v = g->vBuffer + g->vCount; + + /* store the texCoord in the current vertex */ + v->attrib[VERT_ATTRIB_TEX0][0] = v0; + v->attrib[VERT_ATTRIB_TEX0][1] = v1; + v->attrib[VERT_ATTRIB_TEX0][2] = v2; + v->attrib[VERT_ATTRIB_TEX0][3] = v3; +} + +void STATE_APIENTRY +crStateFeedbackTexCoord4fv( const GLfloat *v ) +{ + crStateFeedbackTexCoord4f( v[0], v[1], v[2], v[3] ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord4s( GLshort v0, GLshort v1, GLshort v2, GLshort v3 ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, (GLfloat)v2, (GLfloat)v3 ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord4sv( const GLshort *v ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3] ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord4i( GLint v0, GLint v1, GLint v2, GLint v3 ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, (GLfloat)v2, (GLfloat)v3 ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord4iv( const GLint *v ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3] ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord4d( GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3 ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, (GLfloat)v2, (GLfloat)v3 ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord4dv( const GLdouble *v ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3] ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord1i( GLint v0 ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v0, 0.0f, 0.0f, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord1iv( const GLint *v ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v[0], 0.0f, 0.0f, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord1s( GLshort v0 ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v0, 0.0f, 0.0f, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord1sv( const GLshort *v ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v[0], 0.0f, 0.0f, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord1f( GLfloat v0 ) +{ + crStateFeedbackTexCoord4f( v0, 0.0f, 0.0f, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord1fv( const GLfloat *v ) +{ + crStateFeedbackTexCoord4f( v[0], 0.0f, 0.0f, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord1d( GLdouble v0 ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v0, 0.0f, 0.0f, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord1dv( const GLdouble *v ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v[0], 0.0f, 0.0f, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord2i( GLint v0, GLint v1 ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, 0.0f, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord2iv( const GLint *v ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], 0.0f, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord2s( GLshort v0, GLshort v1 ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, 0.0f, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord2sv( const GLshort *v ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], 0.0f, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord2f( GLfloat v0, GLfloat v1 ) +{ + crStateFeedbackTexCoord4f( v0, v1, 0.0f, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord2fv( const GLfloat *v ) +{ + crStateFeedbackTexCoord4f( v[0], v[1], 0.0f, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord2d( GLdouble v0, GLdouble v1 ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, 0.0f, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord2dv( const GLdouble *v ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], 0.0f, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord3i( GLint v0, GLint v1, GLint v2 ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, (GLfloat)v2, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord3iv( const GLint *v ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], 0.0f, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord3s( GLshort v0, GLshort v1, GLshort v2 ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, (GLfloat)v2, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord3sv( const GLshort *v ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord3f( GLfloat v0, GLfloat v1, GLfloat v2 ) +{ + crStateFeedbackTexCoord4f( v0, v1, v2, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord3fv( const GLfloat *v ) +{ + crStateFeedbackTexCoord4f( v[0], v[1], v[2], 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord3d( GLdouble v0, GLdouble v1, GLdouble v2 ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, (GLfloat)v2, 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackTexCoord3dv( const GLdouble *v ) +{ + crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], 1.0f ); +} + +void STATE_APIENTRY +crStateFeedbackRectf(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1) +{ + crStateFeedbackBegin(GL_QUADS); + crStateFeedbackVertex2f(x0, y0); + crStateFeedbackVertex2f(x0, y1); + crStateFeedbackVertex2f(x1, y1); + crStateFeedbackVertex2f(x1, y0); + crStateFeedbackEnd(); +} + +void STATE_APIENTRY +crStateFeedbackRecti(GLint x0, GLint y0, GLint x1, GLint y1) +{ + crStateFeedbackRectf((GLfloat) x0, (GLfloat) y0, (GLfloat) x1, (GLfloat) y1); +} + +void STATE_APIENTRY +crStateFeedbackRectd(GLdouble x0, GLdouble y0, GLdouble x1, GLdouble y1) +{ + crStateFeedbackRectf((GLfloat) x0, (GLfloat) y0, (GLfloat) x1, (GLfloat) y1); +} + +void STATE_APIENTRY +crStateFeedbackRects(GLshort x0, GLshort y0, GLshort x1, GLshort y1) +{ + crStateFeedbackRectf((GLfloat) x0, (GLfloat) y0, (GLfloat) x1, (GLfloat) y1); +} + +void STATE_APIENTRY +crStateFeedbackRectiv(const GLint *v0, const GLint *v1) +{ + crStateFeedbackRectf((GLfloat) v0[0], (GLfloat) v0[1], (GLfloat) v1[0], (GLfloat) v1[1]); +} + +void STATE_APIENTRY +crStateFeedbackRectfv(const GLfloat *v0, const GLfloat *v1) +{ + crStateFeedbackRectf(v0[0], v0[1], v1[0], v1[1]); +} + +void STATE_APIENTRY +crStateFeedbackRectdv(const GLdouble *v0, const GLdouble *v1) +{ + crStateFeedbackRectf((GLfloat) v0[0], (GLfloat) v0[1], (GLfloat) v1[0], (GLfloat) v1[1]); +} + +void STATE_APIENTRY +crStateFeedbackRectsv(const GLshort *v0, const GLshort *v1) +{ + crStateFeedbackRectf((GLfloat) v0[0], (GLfloat) v0[1], (GLfloat) v1[0], (GLfloat) v1[1]); +} + +/**********************************************************************/ +/***** Selection *****/ +/**********************************************************************/ + + +void STATE_APIENTRY +crStateSelectBuffer(GLsizei size, GLuint * buffer) +{ + CRContext *g = GetCurrentContext(); + CRSelectionState *se = &(g->selection); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "SelectBuffer called in begin/end"); + return; + } + + if (g->renderMode == GL_SELECT) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "SelectBuffer called with RenderMode = GL_SELECT"); + return; + } + + FLUSH(); + + se->buffer = buffer; + se->bufferSize = size; + se->bufferCount = 0; + se->hitFlag = GL_FALSE; + se->hitMinZ = 1.0; + se->hitMaxZ = 0.0; +} + + +#define WRITE_RECORD( V ) \ + if (se->bufferCount < se->bufferSize) { \ + se->buffer[se->bufferCount] = (V); \ + } \ + se->bufferCount++; + + +static void +write_hit_record(CRSelectionState * se) +{ + GLuint i; + GLuint zmin, zmax, zscale = (~0u); + + /* hitMinZ and hitMaxZ are in [0,1]. Multiply these values by */ + /* 2^32-1 and round to nearest unsigned integer. */ + + zmin = (GLuint) ((GLfloat) zscale * se->hitMinZ); + zmax = (GLuint) ((GLfloat) zscale * se->hitMaxZ); + + WRITE_RECORD(se->nameStackDepth); + WRITE_RECORD(zmin); + WRITE_RECORD(zmax); + for (i = 0; i < se->nameStackDepth; i++) + { + WRITE_RECORD(se->nameStack[i]); + } + + se->hits++; + se->hitFlag = GL_FALSE; + se->hitMinZ = 1.0; + se->hitMaxZ = -1.0; +} + + + +void STATE_APIENTRY +crStateInitNames(void) +{ + CRContext *g = GetCurrentContext(); + CRSelectionState *se = &(g->selection); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "InitNames called in begin/end"); + return; + } + + FLUSH(); + + /* Record the hit before the hitFlag is wiped out again. */ + if (g->renderMode == GL_SELECT) + { + if (se->hitFlag) + { + write_hit_record(se); + } + } + + se->nameStackDepth = 0; + se->hitFlag = GL_FALSE; + se->hitMinZ = 1.0; + se->hitMaxZ = 0.0; +} + + +void STATE_APIENTRY +crStateLoadName(GLuint name) +{ + CRContext *g = GetCurrentContext(); + CRSelectionState *se = &(g->selection); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "LoadName called in begin/end"); + return; + } + + + if (g->renderMode != GL_SELECT) + { + return; + } + + if (se->nameStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "nameStackDepth = 0"); + return; + } + + FLUSH(); + + if (se->hitFlag) + { + write_hit_record(se); + } + if (se->nameStackDepth < MAX_NAME_STACK_DEPTH) + { + se->nameStack[se->nameStackDepth - 1] = name; + } + else + { + se->nameStack[MAX_NAME_STACK_DEPTH - 1] = name; + } +} + + +void STATE_APIENTRY +crStatePushName(GLuint name) +{ + CRContext *g = GetCurrentContext(); + CRSelectionState *se = &(g->selection); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "PushName called in begin/end"); + return; + } + + + if (g->renderMode != GL_SELECT) + { + return; + } + + FLUSH(); + + if (se->hitFlag) + { + write_hit_record(se); + } + if (se->nameStackDepth >= MAX_NAME_STACK_DEPTH) + { + crStateError(__LINE__, __FILE__, GL_STACK_OVERFLOW, + "nameStackDepth overflow"); + } + else + se->nameStack[se->nameStackDepth++] = name; +} + +void STATE_APIENTRY +crStatePopName(void) +{ + CRContext *g = GetCurrentContext(); + CRSelectionState *se = &(g->selection); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "PopName called in begin/end"); + return; + } + + if (g->renderMode != GL_SELECT) + { + return; + } + + FLUSH(); + + if (se->hitFlag) + { + write_hit_record(se); + } + + if (se->nameStackDepth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, + "nameStackDepth underflow"); + } + else + se->nameStackDepth--; +} + + +static void +update_hitflag(GLfloat z) +{ + CRContext *g = GetCurrentContext(); + CRSelectionState *se = &(g->selection); + + se->hitFlag = GL_TRUE; + + if (z < se->hitMinZ) + se->hitMinZ = z; + + if (z > se->hitMaxZ) + se->hitMaxZ = z; +} + + +static void +select_rasterpos(void) +{ + CRContext *g = GetCurrentContext(); + + if (g->current.rasterValid) + update_hitflag(g->current.rasterAttrib[VERT_ATTRIB_POS][2]); +} + +static void +select_point(const CRVertex *v) +{ + CRContext *g = GetCurrentContext(); + if (clip_point(v) == 0) + { + CRVertex c = *v; + MAP_POINT(c.winPos, c.clipPos, g->viewport); + update_hitflag(c.winPos.z); + } +} + + +static void +select_line(const CRVertex *v0, const CRVertex *v1) +{ + CRContext *g = GetCurrentContext(); + CRVertex c0, c1; + if (clip_line(v0, v1, &c0, &c1)) + { + MAP_POINT(c0.winPos, c0.clipPos, g->viewport); + MAP_POINT(c1.winPos, c1.clipPos, g->viewport); + update_hitflag(c0.winPos.z); + update_hitflag(c1.winPos.z); + } +} + + +static void +select_triangle(const CRVertex *v0, + const CRVertex *v1, + const CRVertex *v2) +{ + CRContext *g = GetCurrentContext(); + CRVertex vlist[3], vclipped[8]; + GLuint i, n; + + vlist[0] = *v0; + vlist[1] = *v1; + vlist[2] = *v2; + n = clip_polygon(vlist, 3, vclipped); + for (i = 0; i < n; i++) { + MAP_POINT(vclipped[i].winPos, vclipped[i].clipPos, g->viewport); + update_hitflag(vclipped[i].winPos.z); + } +} + + +void STATE_APIENTRY +crStateSelectVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &(g->transform); + CRVertex *v = g->vBuffer + g->vCount; + + /* store the vertex */ + v->attrib[VERT_ATTRIB_POS][0] = x; + v->attrib[VERT_ATTRIB_POS][1] = y; + v->attrib[VERT_ATTRIB_POS][2] = z; + v->attrib[VERT_ATTRIB_POS][3] = w; + COPY_4V(v->attrib[VERT_ATTRIB_COLOR0] , g->current.vertexAttrib[VERT_ATTRIB_COLOR0]); /* XXX need to apply lighting */ + v->colorIndex = g->current.colorIndex; /* XXX need to apply lighting */ + /* Don't do this, we're capturing TexCoord ourselves as + * we don't have a pincher like the tilesortSPU */ + /* v->texCoord[0] = g->current.texCoord[0]; */ + + /* transform to eye space, then clip space */ + TRANSFORM_POINTA(v->eyePos, *(t->modelViewStack.top), v->attrib[VERT_ATTRIB_POS]); + TRANSFORM_POINT(v->clipPos, *(t->projectionStack.top), v->eyePos); + + switch (g->current.mode) { + case GL_POINTS: + CRASSERT(g->vCount == 0); + select_point(v); + break; + case GL_LINES: + if (g->vCount == 0) + { + g->vCount = 1; + } + else + { + CRASSERT(g->vCount == 1); + select_line(g->vBuffer + 0, g->vBuffer + 1); + g->vCount = 0; + } + break; + case GL_LINE_STRIP: + if (g->vCount == 0) + { + g->vCount = 1; + } + else + { + CRASSERT(g->vCount == 1); + select_line(g->vBuffer + 0, g->vBuffer + 1); + g->vBuffer[0] = g->vBuffer[1]; + /* leave g->vCount at 1 */ + } + break; + case GL_LINE_LOOP: + if (g->vCount == 0) + { + g->vCount = 1; + g->lineLoop = GL_FALSE; + } + else if (g->vCount == 1) + { + select_line(g->vBuffer + 0, g->vBuffer + 1); + g->lineLoop = GL_TRUE; + g->vCount = 2; + } + else + { + CRASSERT(g->vCount == 2); + g->lineLoop = GL_FALSE; + select_line(g->vBuffer + 1, g->vBuffer + 2); + g->vBuffer[1] = g->vBuffer[2]; + /* leave g->vCount at 2 */ + } + break; + case GL_TRIANGLES: + if (g->vCount == 0 || g->vCount == 1) + { + g->vCount++; + } + else + { + CRASSERT(g->vCount == 2); + select_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2); + g->vCount = 0; + } + break; + case GL_TRIANGLE_STRIP: + if (g->vCount == 0 || g->vCount == 1) + { + g->vCount++; + } + else if (g->vCount == 2) + { + select_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2); + g->vCount = 3; + } + else + { + CRASSERT(g->vCount == 3); + select_triangle(g->vBuffer + 1, g->vBuffer + 3, g->vBuffer + 2); + g->vBuffer[0] = g->vBuffer[2]; + g->vBuffer[1] = g->vBuffer[3]; + g->vCount = 2; + } + break; + case GL_TRIANGLE_FAN: + if (g->vCount == 0 || g->vCount == 1) + { + g->vCount++; + } + else + { + CRASSERT(g->vCount == 2); + select_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2); + g->vBuffer[1] = g->vBuffer[2]; + /* leave g->vCount = 2 */ + } + break; + case GL_QUADS: + if (g->vCount < 3) + { + g->vCount++; + } + else + { + CRASSERT(g->vCount == 3); + select_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2); + select_triangle(g->vBuffer + 0, g->vBuffer + 2, g->vBuffer + 3); + g->vCount = 0; + } + break; + case GL_QUAD_STRIP: + if (g->vCount < 3) + { + g->vCount++; + } + else + { + CRASSERT(g->vCount == 3); + select_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2); + select_triangle(g->vBuffer + 1, g->vBuffer + 3, g->vBuffer + 2); + g->vBuffer[0] = g->vBuffer[2]; + g->vBuffer[1] = g->vBuffer[3]; + g->vCount = 2; + } + break; + case GL_POLYGON: + /* draw as a tri-fan */ + if (g->vCount == 0 || g->vCount == 1) + { + g->vCount++; + } + else + { + CRASSERT(g->vCount == 2); + select_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2); + g->vBuffer[1] = g->vBuffer[2]; + /* leave g->vCount = 2 */ + } + break; + default: + ; /* impossible */ + } +} + +void STATE_APIENTRY +crStateSelectRasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + crStateRasterPos4f( x, y, z, w ); + + select_rasterpos(); +} + +void STATE_APIENTRY +crStateSelectBegin(GLenum mode) +{ + CRContext *g = GetCurrentContext(); + + crStateBegin(mode); + + g->vCount = 0; + g->lineReset = GL_TRUE; + g->lineLoop = GL_FALSE; +} + + +void STATE_APIENTRY +crStateSelectEnd(void) +{ + CRContext *g = GetCurrentContext(); + + if (g->current.mode == GL_LINE_LOOP && g->vCount == 2) + { + /* draw the last line segment */ + select_line(g->vBuffer + 1, g->vBuffer + 0); + } + + crStateEnd(); +} + +void STATE_APIENTRY +crStateSelectVertex2d(GLdouble x, GLdouble y) +{ + crStateSelectVertex4f((GLfloat) x, (GLfloat) y, 0.0, 1.0); +} + +void STATE_APIENTRY +crStateSelectVertex2dv(const GLdouble * v) +{ + crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], 0.0, 1.0); +} + +void STATE_APIENTRY +crStateSelectVertex2f(GLfloat x, GLfloat y) +{ + crStateSelectVertex4f(x, y, 0.0, 1.0); +} + +void STATE_APIENTRY +crStateSelectVertex2fv(const GLfloat * v) +{ + crStateSelectVertex4f(v[0], v[1], 0.0, 1.0); +} + +void STATE_APIENTRY +crStateSelectVertex2i(GLint x, GLint y) +{ + crStateSelectVertex4f((GLfloat) x, (GLfloat) y, 0.0, 1.0); +} + +void STATE_APIENTRY +crStateSelectVertex2iv(const GLint * v) +{ + crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], 0.0, 1.0); +} + +void STATE_APIENTRY +crStateSelectVertex2s(GLshort x, GLshort y) +{ + crStateSelectVertex4f((GLfloat) x, (GLfloat) y, 0.0, 1.0); +} + +void STATE_APIENTRY +crStateSelectVertex2sv(const GLshort * v) +{ + crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], 0.0, 1.0); +} + +void STATE_APIENTRY +crStateSelectVertex3d(GLdouble x, GLdouble y, GLdouble z) +{ + crStateSelectVertex4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0); +} + +void STATE_APIENTRY +crStateSelectVertex3dv(const GLdouble * v) +{ + crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0); +} + +void STATE_APIENTRY +crStateSelectVertex3f(GLfloat x, GLfloat y, GLfloat z) +{ + crStateSelectVertex4f(x, y, z, 1.0); +} + +void STATE_APIENTRY +crStateSelectVertex3fv(const GLfloat * v) +{ + crStateSelectVertex4f(v[0], v[1], v[2], 1.0); +} + +void STATE_APIENTRY +crStateSelectVertex3i(GLint x, GLint y, GLint z) +{ + crStateSelectVertex4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0); +} + +void STATE_APIENTRY +crStateSelectVertex3iv(const GLint * v) +{ + crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0); +} + +void STATE_APIENTRY +crStateSelectVertex3s(GLshort x, GLshort y, GLshort z) +{ + crStateSelectVertex4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0); +} + +void STATE_APIENTRY +crStateSelectVertex3sv(const GLshort * v) +{ + crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0); +} + +void STATE_APIENTRY +crStateSelectVertex4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + crStateSelectVertex4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +void STATE_APIENTRY +crStateSelectVertex4dv(const GLdouble * v) +{ + crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); +} + +void STATE_APIENTRY +crStateSelectVertex4fv(const GLfloat * v) +{ + crStateSelectVertex4f(v[0], v[1], v[2], v[3]); +} + +void STATE_APIENTRY +crStateSelectVertex4i(GLint x, GLint y, GLint z, GLint w) +{ + crStateSelectVertex4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +void STATE_APIENTRY +crStateSelectVertex4iv(const GLint * v) +{ + crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); +} + +void STATE_APIENTRY +crStateSelectVertex4s(GLshort x, GLshort y, GLshort z, GLshort w) +{ + crStateSelectVertex4f(x, y, z, w); +} + +void STATE_APIENTRY +crStateSelectVertex4sv(const GLshort * v) +{ + crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); +} + +void STATE_APIENTRY +crStateSelectRasterPos2d(GLdouble x, GLdouble y) +{ + crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, 0.0, 1.0); +} + +void STATE_APIENTRY +crStateSelectRasterPos2dv(const GLdouble * v) +{ + crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0, 1.0); +} + +void STATE_APIENTRY +crStateSelectRasterPos2f(GLfloat x, GLfloat y) +{ + crStateSelectRasterPos4f(x, y, 0.0, 1.0); +} + +void STATE_APIENTRY +crStateSelectRasterPos2fv(const GLfloat * v) +{ + crStateSelectRasterPos4f(v[0], v[1], 0.0, 1.0); +} + +void STATE_APIENTRY +crStateSelectRasterPos2i(GLint x, GLint y) +{ + crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, 0.0, 1.0); +} + +void STATE_APIENTRY +crStateSelectRasterPos2iv(const GLint * v) +{ + crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0, 1.0); +} + +void STATE_APIENTRY +crStateSelectRasterPos2s(GLshort x, GLshort y) +{ + crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, 0.0, 1.0); +} + +void STATE_APIENTRY +crStateSelectRasterPos2sv(const GLshort * v) +{ + crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0, 1.0); +} + +void STATE_APIENTRY +crStateSelectRasterPos3d(GLdouble x, GLdouble y, GLdouble z) +{ + crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0); +} + +void STATE_APIENTRY +crStateSelectRasterPos3dv(const GLdouble * v) +{ + crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] , 1.0); +} + +void STATE_APIENTRY +crStateSelectRasterPos3f(GLfloat x, GLfloat y, GLfloat z) +{ + crStateSelectRasterPos4f(x, y, z, 1.0); +} + +void STATE_APIENTRY +crStateSelectRasterPos3fv(const GLfloat * v) +{ + crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] , 1.0); +} + +void STATE_APIENTRY +crStateSelectRasterPos3i(GLint x, GLint y, GLint z) +{ + crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0); +} + +void STATE_APIENTRY +crStateSelectRasterPos3iv(const GLint * v) +{ + crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] , 1.0); +} + +void STATE_APIENTRY +crStateSelectRasterPos3s(GLshort x, GLshort y, GLshort z) +{ + crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0); +} + +void STATE_APIENTRY +crStateSelectRasterPos3sv(const GLshort * v) +{ + crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] , 1.0); +} + +void STATE_APIENTRY +crStateSelectRasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +void STATE_APIENTRY +crStateSelectRasterPos4dv(const GLdouble * v) +{ + crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] , (GLfloat) v[3]); +} + +void STATE_APIENTRY +crStateSelectRasterPos4fv(const GLfloat * v) +{ + crStateSelectRasterPos4f(v[0], v[1], v[2], v[3]); +} + +void STATE_APIENTRY +crStateSelectRasterPos4i(GLint x, GLint y, GLint z, GLint w) +{ + crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +void STATE_APIENTRY +crStateSelectRasterPos4iv(const GLint * v) +{ + crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); +} + +void STATE_APIENTRY +crStateSelectRasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w) +{ + crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +void STATE_APIENTRY +crStateSelectRasterPos4sv(const GLshort * v) +{ + crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] , (GLfloat) v[3]); +} + +void STATE_APIENTRY +crStateSelectRectf(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1) +{ + crStateSelectBegin(GL_QUADS); + crStateSelectVertex2f(x0, y0); + crStateSelectVertex2f(x0, y1); + crStateSelectVertex2f(x1, y1); + crStateSelectVertex2f(x1, y0); + crStateSelectEnd(); +} + +void STATE_APIENTRY +crStateSelectRecti(GLint x0, GLint y0, GLint x1, GLint y1) +{ + crStateSelectRectf((GLfloat) x0, (GLfloat) y0, (GLfloat) x1, (GLfloat) y1); +} + +void STATE_APIENTRY +crStateSelectRectd(GLdouble x0, GLdouble y0, GLdouble x1, GLdouble y1) +{ + crStateSelectRectf((GLfloat) x0, (GLfloat) y0, (GLfloat) x1, (GLfloat) y1); +} + +void STATE_APIENTRY +crStateSelectRects(GLshort x0, GLshort y0, GLshort x1, GLshort y1) +{ + crStateSelectRectf((GLfloat) x0, (GLfloat) y0, (GLfloat) x1, (GLfloat) y1); +} + +void STATE_APIENTRY +crStateSelectRectiv(const GLint *v0, const GLint *v1) +{ + crStateSelectRectf((GLfloat) v0[0], (GLfloat) v0[1], (GLfloat) v1[0], (GLfloat) v1[1]); +} + +void STATE_APIENTRY +crStateSelectRectfv(const GLfloat *v0, const GLfloat *v1) +{ + crStateSelectRectf(v0[0], v0[1], v1[0], v1[1]); +} + +void STATE_APIENTRY +crStateSelectRectdv(const GLdouble *v0, const GLdouble *v1) +{ + crStateSelectRectf((GLfloat) v0[0], (GLfloat) v0[1], (GLfloat) v1[0], (GLfloat) v1[1]); +} + +void STATE_APIENTRY +crStateSelectRectsv(const GLshort *v0, const GLshort *v1) +{ + crStateSelectRectf((GLfloat) v0[0], (GLfloat) v0[1], (GLfloat) v1[0], (GLfloat) v1[1]); +} + + +GLint STATE_APIENTRY +crStateRenderMode(GLenum mode) +{ + CRContext *g = GetCurrentContext(); + CRFeedbackState *f = &(g->feedback); + CRSelectionState *se = &(g->selection); + GLint result; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "RenderMode called in begin/end"); + return 0; + } + + FLUSH(); + + switch (g->renderMode) + { + case GL_RENDER: + result = 0; + break; + case GL_SELECT: + if (se->hitFlag) + { + write_hit_record(se); + } + + if (se->bufferCount > se->bufferSize) + { + /* overflow */ + result = -1; + } + else + { + result = se->hits; + } + se->bufferCount = 0; + se->hits = 0; + se->nameStackDepth = 0; + break; + case GL_FEEDBACK: + if (f->count > f->bufferSize) + { + /* overflow */ + result = -1; + } + else + { + result = f->count; + } + f->count = 0; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "invalid rendermode"); + return 0; + } + + switch (mode) + { + case GL_RENDER: + break; + case GL_SELECT: + if (se->bufferSize == 0) + { + /* haven't called glSelectBuffer yet */ + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "buffersize = 0"); + } + break; + case GL_FEEDBACK: + if (f->bufferSize == 0) + { + /* haven't called glFeedbackBuffer yet */ + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "buffersize = 0"); + } + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "invalid rendermode"); + return 0; + } + + g->renderMode = mode; + + return result; +} + + +void STATE_APIENTRY +crStateSelectDrawPixels(GLsizei width, GLsizei height, GLenum format, + GLenum type, const GLvoid * pixels) +{ + (void) width; + (void) height; + (void) format; + (void) type; + (void) pixels; + select_rasterpos(); +} + +void STATE_APIENTRY +crStateSelectCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, + GLenum type) +{ + (void) x; + (void) y; + (void) width; + (void) height; + (void) type; + select_rasterpos(); +} + +void STATE_APIENTRY +crStateSelectBitmap(GLsizei width, GLsizei height, GLfloat xorig, + GLfloat yorig, GLfloat xmove, GLfloat ymove, + const GLubyte * bitmap) +{ + CRContext *g = GetCurrentContext(); + (void) width; + (void) height; + (void) xorig; + (void) yorig; + (void) bitmap; + + select_rasterpos(); + if (g->current.rasterValid) + { + g->current.rasterAttrib[VERT_ATTRIB_POS][0] += xmove; + g->current.rasterAttrib[VERT_ATTRIB_POS][1] += ymove; + } +} + diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_feedback_special b/src/VBox/GuestHost/OpenGL/state_tracker/state_feedback_special new file mode 100644 index 00000000..e0b16e71 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_feedback_special @@ -0,0 +1,73 @@ +Vertex4f +Begin +End +GetBooleanv +GetDoublev +GetFloatv +GetIntegerv +DrawPixels +CopyPixels +Bitmap +Vertex4fv +Vertex4s +Vertex4sv +Vertex4i +Vertex4iv +Vertex4d +Vertex4dv +Vertex2i +Vertex2iv +Vertex2s +Vertex2sv +Vertex2f +Vertex2fv +Vertex2d +Vertex2dv +Vertex3i +Vertex3iv +Vertex3s +Vertex3sv +Vertex3f +Vertex3fv +Vertex3d +Vertex3dv +Rectf +Recti +Rectd +Rects +Rectiv +Rectfv +Rectdv +Rectsv +TexCoord1d +TexCoord1dv +TexCoord1f +TexCoord1fv +TexCoord1i +TexCoord1iv +TexCoord1s +TexCoord1sv +TexCoord2d +TexCoord2dv +TexCoord2f +TexCoord2fv +TexCoord2i +TexCoord2iv +TexCoord2s +TexCoord2sv +TexCoord3d +TexCoord3dv +TexCoord3f +TexCoord3fv +TexCoord3i +TexCoord3iv +TexCoord3s +TexCoord3sv +TexCoord4d +TexCoord4dv +TexCoord4f +TexCoord4fv +TexCoord4i +TexCoord4iv +TexCoord4s +TexCoord4sv diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_fence.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_fence.c new file mode 100644 index 00000000..054f1c4b --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_fence.c @@ -0,0 +1,50 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "state.h" +#include "state_internals.h" +#include "state/cr_statetypes.h" + + + +void APIENTRY crStateGenFencesNV(GLsizei n, GLuint *fences) +{ + (void)n; (void)fences; +} + + +void APIENTRY crStateDeleteFencesNV(GLsizei n, const GLuint *fences) +{ + (void)n; (void)fences; +} + +void APIENTRY crStateSetFenceNV(GLuint fence, GLenum condition) +{ + (void)fence; (void)condition; +} + +GLboolean APIENTRY crStateTestFenceNV(GLuint fence) +{ + (void)fence; + return GL_FALSE; +} + +void APIENTRY crStateFinishFenceNV(GLuint fence) +{ + (void)fence; +} + +GLboolean APIENTRY crStateIsFenceNV(GLuint fence) +{ + (void)fence; + return GL_FALSE; +} + +void APIENTRY crStateGetFenceivNV(GLuint fence, GLenum pname, GLint *params) +{ + (void)fence; (void)pname; (void)params; +} + diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_flush.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_flush.c new file mode 100644 index 00000000..052080e0 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_flush.c @@ -0,0 +1,34 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "state.h" +#include "cr_spu.h" + +SPUDispatchTable diff_api; + +void crStateFlushFunc( CRStateFlushFunc func ) +{ + CRContext *g = GetCurrentContext(); + + g->flush_func = func; +} + +void crStateFlushArg( void *arg ) +{ + CRContext *g = GetCurrentContext(); + + g->flush_arg = arg; +} + +void crStateDiffAPI( SPUDispatchTable *api ) +{ + if (!diff_api.AlphaFunc) + { + /* Called when starting up Chromium */ + crSPUInitDispatchTable( &(diff_api) ); + } + crSPUCopyDispatchTable( &(diff_api), api ); +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_fog.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_fog.c new file mode 100644 index 00000000..41f1f313 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_fog.c @@ -0,0 +1,199 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include <stdio.h> +#include "state.h" +#include "state/cr_statetypes.h" +#include "state_internals.h" + +void crStateFogInit (CRContext *ctx) +{ + CRFogState *f = &ctx->fog; + CRStateBits *sb = GetCurrentBits(); + CRFogBits *fb = &(sb->fog); + GLcolorf black = {0.0f, 0.0f, 0.0f, 0.0f}; + + f->color = black; + RESET(fb->color, ctx->bitid); + f->density = 1.0f; + RESET(fb->density, ctx->bitid); + f->end = 1.0f; + RESET(fb->end, ctx->bitid); + f->start = 0.0f; + RESET(fb->start, ctx->bitid); + f->mode = GL_EXP; + RESET(fb->mode, ctx->bitid); + f->index = 0; + RESET(fb->index, ctx->bitid); + f->enable = GL_FALSE; + RESET(fb->enable, ctx->bitid); + +#ifdef CR_NV_fog_distance + f->fogDistanceMode = GL_EYE_PLANE_ABSOLUTE_NV; + RESET(fb->fogDistanceMode, ctx->bitid); +#endif +#ifdef CR_EXT_fog_coord + f->fogCoordinateSource = GL_FRAGMENT_DEPTH_EXT; + RESET(fb->fogCoordinateSource, ctx->bitid); +#endif + RESET(fb->dirty, ctx->bitid); +} + +void STATE_APIENTRY crStateFogf(GLenum pname, GLfloat param) +{ + crStateFogfv( pname, ¶m ); +} + +void STATE_APIENTRY crStateFogi(GLenum pname, GLint param) +{ + GLfloat f_param = (GLfloat) param; + crStateFogfv( pname, &f_param ); +} + +void STATE_APIENTRY crStateFogiv(GLenum pname, const GLint *param) +{ + GLcolor f_color; + GLfloat f_param; + switch (pname) + { + case GL_FOG_MODE: + case GL_FOG_DENSITY: + case GL_FOG_START: + case GL_FOG_END: + case GL_FOG_INDEX: + f_param = (GLfloat) (*param); + crStateFogfv( pname, &f_param ); + break; + case GL_FOG_COLOR: + f_color.r = ((GLfloat) param[0]) / ((GLfloat) CR_MAXINT); + f_color.g = ((GLfloat) param[1]) / ((GLfloat) CR_MAXINT); + f_color.b = ((GLfloat) param[2]) / ((GLfloat) CR_MAXINT); + f_color.a = ((GLfloat) param[3]) / ((GLfloat) CR_MAXINT); + crStateFogfv( pname, (GLfloat *) &f_color ); + break; +#ifdef CR_NV_fog_distance + case GL_FOG_DISTANCE_MODE_NV: + f_param = (GLfloat) (*param); + crStateFogfv( pname, &f_param ); + break; +#endif +#ifdef CR_EXT_fog_coord + case GL_FOG_COORDINATE_SOURCE_EXT: + f_param = (GLfloat) (*param); + crStateFogfv( pname, &f_param ); + break; +#endif + default: + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Invalid glFog Param: %d", param); + return; + } +} + +void STATE_APIENTRY crStateFogfv(GLenum pname, const GLfloat *param) +{ + CRContext *g = GetCurrentContext(); + CRFogState *f = &(g->fog); + CRStateBits *sb = GetCurrentBits(); + CRFogBits *fb = &(sb->fog); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glFogfv called in Begin/End"); + return; + } + + FLUSH(); + + switch (pname) + { + case GL_FOG_MODE: + { + GLenum e = (GLenum) *param; + if (e != GL_LINEAR && e != GL_EXP && e != GL_EXP2) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid param for glFog: %d", e); + return; + } + f->mode = e; + DIRTY(fb->mode, g->neg_bitid); + } + break; + case GL_FOG_DENSITY: + f->density = *param; + if (f->density < 0.0f) + { + f->density = 0.0f; + } + DIRTY(fb->density, g->neg_bitid); + break; + case GL_FOG_START: + f->start = *param; + DIRTY(fb->start, g->neg_bitid); + break; + case GL_FOG_END: + f->end = *param; + DIRTY(fb->end, g->neg_bitid); + break; + case GL_FOG_INDEX: + f->index = (GLint) *param; + DIRTY(fb->index, g->neg_bitid); + break; + case GL_FOG_COLOR: + f->color.r = param[0]; + f->color.g = param[1]; + f->color.b = param[2]; + f->color.a = param[3]; + DIRTY(fb->color, g->neg_bitid); + break; +#ifdef CR_NV_fog_distance + case GL_FOG_DISTANCE_MODE_NV: + if (g->extensions.NV_fog_distance) + { + if (param[0] != GL_EYE_RADIAL_NV && + param[0] != GL_EYE_PLANE && + param[0] != GL_EYE_PLANE_ABSOLUTE_NV ) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "Fogfv: GL_FOG_DISTANCE_MODE_NV called with illegal parameter: 0x%x", (GLenum) param[0]); + return; + } + f->fogDistanceMode = (GLenum) param[0]; + DIRTY(fb->fogDistanceMode, g->neg_bitid); + } + else + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Invalid glFog Param: %d", param); + return; + } + break; +#endif +#ifdef CR_EXT_fog_coord + case GL_FOG_COORDINATE_SOURCE_EXT: + if (g->extensions.EXT_fog_coord) + { + if ((GLenum) param[0] != GL_FOG_COORDINATE_EXT && + (GLenum) param[0] != GL_FRAGMENT_DEPTH_EXT) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "Fogfv: GL_FOG_COORDINATE_SOURCE_EXT called with illegal parameter: 0x%x", (GLenum) param[0]); + return; + } + f->fogCoordinateSource = (GLenum) param[0]; + DIRTY(fb->fogCoordinateSource, g->neg_bitid); + } + else + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Invalid glFog Param: 0x%x", (GLint) param[0]); + return; + } + break; +#endif + default: + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Invalid glFog Param: %d", param); + return; + } + DIRTY(fb->dirty, g->neg_bitid); +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_fog.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_fog.txt new file mode 100644 index 00000000..d8e62c0e --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_fog.txt @@ -0,0 +1,13 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +:enable:enable:GL_FOG +:color:color|r,g,b,a:Fogfv,GL_FOG_COLOR +:index:index:Fogi,GL_FOG_INDEX +:density:density:Fogf,GL_FOG_DENSITY +:start:start:Fogf,GL_FOG_START +:end:end:Fogf,GL_FOG_END +:mode:mode:Fogi,GL_FOG_MODE +:fogDistanceMode:fogDistanceMode:Fogi,GL_FOG_DISTANCE_MODE_NV +:fogCoordinateSource:fogCoordinateSource:Fogi,GL_FOG_COORDINATE_SOURCE_EXT diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c new file mode 100644 index 00000000..c82d53a3 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c @@ -0,0 +1,1202 @@ +/* $Id: state_framebuffer.c $ */ + +/** @file + * VBox OpenGL: EXT_framebuffer_object state tracking + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#include "state.h" +#include "state/cr_statetypes.h" +#include "state/cr_statefuncs.h" +#include "state_internals.h" +#include "cr_mem.h" + +DECLEXPORT(void) STATE_APIENTRY +crStateFramebufferObjectInit(CRContext *ctx) +{ + CRFramebufferObjectState *fbo = &ctx->framebufferobject; + + fbo->readFB = NULL; + fbo->drawFB = NULL; + fbo->renderbuffer = NULL; + ctx->shared->bFBOResyncNeeded = GL_FALSE; +} + +void STATE_APIENTRY crStateGenFramebuffersEXT(GLsizei n, GLuint *buffers) +{ + CRContext *g = GetCurrentContext(); + crStateGenNames(g, g->shared->fbTable, n, buffers); +} + +void STATE_APIENTRY crStateGenRenderbuffersEXT(GLsizei n, GLuint *buffers) +{ + CRContext *g = GetCurrentContext(); + crStateGenNames(g, g->shared->rbTable, n, buffers); +} + +void crStateRegFramebuffers(GLsizei n, GLuint *buffers) +{ + CRContext *g = GetCurrentContext(); + crStateRegNames(g, g->shared->fbTable, n, buffers); +} + +void crStateRegRenderbuffers(GLsizei n, GLuint *buffers) +{ + CRContext *g = GetCurrentContext(); + crStateRegNames(g, g->shared->rbTable, n, buffers); +} + +static void crStateInitFrameBuffer(CRFramebufferObject *fbo); + +static CRFramebufferObject * +crStateFramebufferAllocate(CRContext *ctx, GLuint name) +{ + CRFramebufferObject *buffer = (CRFramebufferObject*) crCalloc(sizeof(CRFramebufferObject)); + CRSTATE_CHECKERR_RET(!buffer, GL_OUT_OF_MEMORY, "crStateFramebufferAllocate", NULL); + buffer->id = name; +#ifndef IN_GUEST + diff_api.GenFramebuffersEXT(1, &buffer->hwid); + if (!buffer->hwid) + { + crWarning("GenFramebuffersEXT failed!"); + crFree(buffer); + return NULL; + } +#else + buffer->hwid = name; +#endif + + crStateInitFrameBuffer(buffer); + crHashtableAdd(ctx->shared->fbTable, name, buffer); + CR_STATE_SHAREDOBJ_USAGE_INIT(buffer); + + return buffer; +} + +static CRRenderbufferObject * +crStateRenderbufferAllocate(CRContext *ctx, GLuint name) +{ + CRRenderbufferObject *buffer = (CRRenderbufferObject*) crCalloc(sizeof(CRRenderbufferObject)); + CRSTATE_CHECKERR_RET(!buffer, GL_OUT_OF_MEMORY, "crStateRenderbufferAllocate", NULL); + buffer->id = name; +#ifndef IN_GUEST + diff_api.GenRenderbuffersEXT(1, &buffer->hwid); + if (!buffer->hwid) + { + crWarning("GenRenderbuffersEXT failed!"); + crFree(buffer); + return NULL; + } +#else + buffer->hwid = name; +#endif + + buffer->internalformat = GL_RGBA; + crHashtableAdd(ctx->shared->rbTable, name, buffer); + CR_STATE_SHAREDOBJ_USAGE_INIT(buffer); + + return buffer; +} + +void crStateFreeFBO(void *data) +{ + CRFramebufferObject *pObj = (CRFramebufferObject *)data; + +#ifndef IN_GUEST + if (diff_api.DeleteFramebuffersEXT) + { + diff_api.DeleteFramebuffersEXT(1, &pObj->hwid); + } +#endif + + crFree(pObj); +} + +void crStateFreeRBO(void *data) +{ + CRRenderbufferObject *pObj = (CRRenderbufferObject *)data; + +#ifndef IN_GUEST + if (diff_api.DeleteRenderbuffersEXT) + { + diff_api.DeleteRenderbuffersEXT(1, &pObj->hwid); + } +#endif + + crFree(pObj); +} + +DECLEXPORT(void) STATE_APIENTRY +crStateFramebufferObjectDestroy(CRContext *ctx) +{ + CRFramebufferObjectState *fbo = &ctx->framebufferobject; + + fbo->readFB = NULL; + fbo->drawFB = NULL; + fbo->renderbuffer = NULL; +} + +DECLEXPORT(void) STATE_APIENTRY +crStateBindRenderbufferEXT(GLenum target, GLuint renderbuffer) +{ + CRContext *g = GetCurrentContext(); + CRFramebufferObjectState *fbo = &g->framebufferobject; + + CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end"); + CRSTATE_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target"); + + if (renderbuffer) + { + fbo->renderbuffer = (CRRenderbufferObject*) crHashtableSearch(g->shared->rbTable, renderbuffer); + if (!fbo->renderbuffer) + { + CRSTATE_CHECKERR(!crHashtableIsKeyUsed(g->shared->rbTable, renderbuffer), GL_INVALID_OPERATION, "name is not a renderbuffer"); + fbo->renderbuffer = crStateRenderbufferAllocate(g, renderbuffer); + } + CR_STATE_SHAREDOBJ_USAGE_SET(fbo->renderbuffer, g); + } + else fbo->renderbuffer = NULL; +} + +static void crStateCheckFBOAttachments(CRFramebufferObject *pFBO, GLuint rbo, GLenum target) +{ + CRFBOAttachmentPoint *ap; + int u; + + if (!pFBO) + return; + + for (u=0; u<CR_MAX_COLOR_ATTACHMENTS; ++u) + { + ap = &pFBO->color[u]; + if (ap->type==GL_RENDERBUFFER_EXT && ap->name==rbo) + { + crStateFramebufferRenderbufferEXT(target, u+GL_COLOR_ATTACHMENT0_EXT, 0, 0); +#ifdef IN_GUEST + pFBO->status = GL_FRAMEBUFFER_UNDEFINED; +#endif + } + } + + ap = &pFBO->depth; + if (ap->type==GL_RENDERBUFFER_EXT && ap->name==rbo) + { + crStateFramebufferRenderbufferEXT(target, GL_DEPTH_ATTACHMENT_EXT, 0, 0); +#ifdef IN_GUEST + pFBO->status = GL_FRAMEBUFFER_UNDEFINED; +#endif + } + ap = &pFBO->stencil; + if (ap->type==GL_RENDERBUFFER_EXT && ap->name==rbo) + { + crStateFramebufferRenderbufferEXT(target, GL_STENCIL_ATTACHMENT_EXT, 0, 0); +#ifdef IN_GUEST + pFBO->status = GL_FRAMEBUFFER_UNDEFINED; +#endif + } +} + +static void ctStateRenderbufferRefsCleanup(CRContext *g, GLuint fboId, CRRenderbufferObject *rbo) +{ + CRFramebufferObjectState *fbo = &g->framebufferobject; + + if (fbo->renderbuffer==rbo) + { + fbo->renderbuffer = NULL; + } + + /* check the attachments of current framebuffers */ + crStateCheckFBOAttachments(fbo->readFB, fboId, GL_READ_FRAMEBUFFER); + crStateCheckFBOAttachments(fbo->drawFB, fboId, GL_DRAW_FRAMEBUFFER); + + CR_STATE_SHAREDOBJ_USAGE_CLEAR(rbo, g); +} + +DECLEXPORT(void) STATE_APIENTRY +crStateDeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers) +{ + CRContext *g = GetCurrentContext(); + /*CRFramebufferObjectState *fbo = &g->framebufferobject; - unused */ + int i; + + CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end"); + CRSTATE_CHECKERR(n<0, GL_INVALID_OPERATION, "n<0"); + + for (i = 0; i < n; i++) + { + if (renderbuffers[i]) + { + CRRenderbufferObject *rbo; + rbo = (CRRenderbufferObject*) crHashtableSearch(g->shared->rbTable, renderbuffers[i]); + if (rbo) + { + int j; + + ctStateRenderbufferRefsCleanup(g, renderbuffers[i], rbo); + CR_STATE_SHAREDOBJ_USAGE_FOREACH_USED_IDX(rbo, j) + { + /* saved state version <= SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS does not have usage bits info, + * so on restore, we set mark bits as used. + * This is why g_pAvailableContexts[j] could be NULL + * also g_pAvailableContexts[0] will hold default context, which we should discard */ + CRContext *ctx = g_pAvailableContexts[j]; + if (j && ctx) + { + CRFramebufferObjectState *ctxFbo; + CRASSERT(ctx); + ctxFbo = &ctx->framebufferobject; + if (ctxFbo->renderbuffer==rbo) + crWarning("deleting RBO being used by another context %d", ctx->id); + + ctStateRenderbufferRefsCleanup(ctx, renderbuffers[i], rbo); + } + else + CR_STATE_SHAREDOBJ_USAGE_CLEAR_IDX(rbo, j); + } + crHashtableDelete(g->shared->rbTable, renderbuffers[i], crStateFreeRBO); + } + } + } +} + +DECLEXPORT(void) STATE_APIENTRY +crStateRenderbufferStorageEXT(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +{ + CRContext *g = GetCurrentContext(); + CRFramebufferObjectState *fbo = &g->framebufferobject; + CRRenderbufferObject *rb = fbo->renderbuffer; + + CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end"); + CRSTATE_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target"); + CRSTATE_CHECKERR(!rb, GL_INVALID_OPERATION, "no bound renderbuffer"); + + rb->width = width; + rb->height = height; + rb->internalformat = internalformat; +} + +DECLEXPORT(void) STATE_APIENTRY +crStateGetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params) +{ + CRContext *g = GetCurrentContext(); + CRFramebufferObjectState *fbo = &g->framebufferobject; + CRRenderbufferObject *rb = fbo->renderbuffer; + + CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end"); + CRSTATE_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target"); + CRSTATE_CHECKERR(!rb, GL_INVALID_OPERATION, "no bound renderbuffer"); + + switch (pname) + { + case GL_RENDERBUFFER_WIDTH_EXT: + *params = rb->width; + break; + case GL_RENDERBUFFER_HEIGHT_EXT: + *params = rb->height; + break; + case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT: + *params = rb->internalformat; + break; + case GL_RENDERBUFFER_RED_SIZE_EXT: + case GL_RENDERBUFFER_GREEN_SIZE_EXT: + case GL_RENDERBUFFER_BLUE_SIZE_EXT: + case GL_RENDERBUFFER_ALPHA_SIZE_EXT: + case GL_RENDERBUFFER_DEPTH_SIZE_EXT: + case GL_RENDERBUFFER_STENCIL_SIZE_EXT: + CRSTATE_CHECKERR(GL_TRUE, GL_INVALID_OPERATION, "unimplemented"); + break; + default: + CRSTATE_CHECKERR(GL_TRUE, GL_INVALID_ENUM, "invalid pname"); + } +} + +static void crStateInitFBOAttachmentPoint(CRFBOAttachmentPoint *fboap) +{ + fboap->type = GL_NONE; + fboap->name = 0; + fboap->level = 0; + fboap->face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; + fboap->zoffset = 0; +} + +static void crStateInitFrameBuffer(CRFramebufferObject *fbo) +{ + int i; + + for (i=0; i<CR_MAX_COLOR_ATTACHMENTS; ++i) + crStateInitFBOAttachmentPoint(&fbo->color[i]); + + crStateInitFBOAttachmentPoint(&fbo->depth); + crStateInitFBOAttachmentPoint(&fbo->stencil); + + fbo->readbuffer = GL_COLOR_ATTACHMENT0_EXT; + fbo->drawbuffer[0] = GL_COLOR_ATTACHMENT0_EXT; + +#ifdef IN_GUEST + fbo->status = GL_FRAMEBUFFER_UNDEFINED; +#endif +} + +static GLboolean crStateGetFBOAttachmentPoint(CRFramebufferObject *fb, GLenum attachment, CRFBOAttachmentPoint **ap) +{ + switch (attachment) + { + case GL_DEPTH_ATTACHMENT_EXT: + *ap = &fb->depth; + break; + case GL_STENCIL_ATTACHMENT_EXT: + *ap = &fb->stencil; + break; + default: + if (attachment>=GL_COLOR_ATTACHMENT0_EXT && attachment<=GL_COLOR_ATTACHMENT15_EXT) + { + *ap = &fb->color[attachment-GL_COLOR_ATTACHMENT0_EXT]; + } + else return GL_FALSE; + } + + return GL_TRUE; +} + +DECLEXPORT(void) STATE_APIENTRY +crStateBindFramebufferEXT(GLenum target, GLuint framebuffer) +{ + CRContext *g = GetCurrentContext(); + CRFramebufferObjectState *fbo = &g->framebufferobject; + CRFramebufferObject *pFBO=NULL; + + CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end"); + CRSTATE_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)), + GL_INVALID_ENUM, "invalid target"); + + if (framebuffer) + { + pFBO = (CRFramebufferObject*) crHashtableSearch(g->shared->fbTable, framebuffer); + if (!pFBO) + { + CRSTATE_CHECKERR(!crHashtableIsKeyUsed(g->shared->fbTable, framebuffer), GL_INVALID_OPERATION, "name is not a framebuffer"); + pFBO = crStateFramebufferAllocate(g, framebuffer); + } + + + CR_STATE_SHAREDOBJ_USAGE_SET(pFBO, g); + } + + /** @todo http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt + * FBO status might change when binding a different FBO here...but I doubt it happens. + * So no status reset here until a proper check. + */ + + switch (target) + { + case GL_FRAMEBUFFER_EXT: + fbo->readFB = pFBO; + fbo->drawFB = pFBO; + break; + case GL_READ_FRAMEBUFFER: + fbo->readFB = pFBO; + break; + case GL_DRAW_FRAMEBUFFER: + fbo->drawFB = pFBO; + break; + } +} + +static void ctStateFramebufferRefsCleanup(CRContext *g, CRFramebufferObject *fb) +{ + CRFramebufferObjectState *fbo = &g->framebufferobject; + if (fbo->readFB==fb) + { + fbo->readFB = NULL; + } + if (fbo->drawFB==fb) + { + fbo->drawFB = NULL; + } + + CR_STATE_SHAREDOBJ_USAGE_CLEAR(fb, g); +} + +DECLEXPORT(void) STATE_APIENTRY +crStateDeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) +{ + CRContext *g = GetCurrentContext(); + int i; + + CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end"); + CRSTATE_CHECKERR(n<0, GL_INVALID_OPERATION, "n<0"); + + for (i = 0; i < n; i++) + { + if (framebuffers[i]) + { + CRFramebufferObject *fb; + fb = (CRFramebufferObject*) crHashtableSearch(g->shared->fbTable, framebuffers[i]); + if (fb) + { + int j; + + ctStateFramebufferRefsCleanup(g, fb); + + CR_STATE_SHAREDOBJ_USAGE_FOREACH_USED_IDX(fb, j) + { + /* saved state version <= SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS does not have usage bits info, + * so on restore, we set mark bits as used. + * This is why g_pAvailableContexts[j] could be NULL + * also g_pAvailableContexts[0] will hold default context, which we should discard */ + CRContext *ctx = g_pAvailableContexts[j]; + if (j && ctx) + { + CRFramebufferObjectState *ctxFbo; + CRASSERT(ctx); + ctxFbo = &ctx->framebufferobject; + if (ctxFbo->readFB==fb) + crWarning("deleting FBO being used as read buffer by another context %d", ctx->id); + + if (ctxFbo->drawFB==fb) + crWarning("deleting FBO being used as draw buffer by another context %d", ctx->id); + + ctStateFramebufferRefsCleanup(ctx, fb); + } + else + CR_STATE_SHAREDOBJ_USAGE_CLEAR_IDX(fb, j); + } + crHashtableDelete(g->shared->fbTable, framebuffers[i], crStateFreeFBO); + } + } + } +} + +/** @todo move this function somewhere else*/ +/*return floor of base 2 log of x. log(0)==0*/ +static unsigned int crLog2Floor(unsigned int x) +{ + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + x -= ((x >> 1) & 0x55555555); + x = (((x >> 2) & 0x33333333) + (x & 0x33333333)); + x = (((x >> 4) + x) & 0x0f0f0f0f); + x += (x >> 8); + x += (x >> 16); + return (x & 0x0000003f) - 1; +} + +static GLuint crStateFramebufferGet(CRFramebufferObjectState *fbo, GLenum target, CRFramebufferObject **apFBOs) +{ + /** @todo Since this function returns not more than one FBO, callers can be cleaned up. */ + GLuint cPBOs = 0; + switch (target) + { + case GL_READ_FRAMEBUFFER: + cPBOs = 1; + apFBOs[0] = fbo->readFB; + break; + /* OpenGL glFramebufferTexture, glFramebufferRenderbuffer, glFramebufferRenderbuffer specs: + * "GL_FRAMEBUFFER is equivalent to GL_DRAW_FRAMEBUFFER." + */ + case GL_FRAMEBUFFER: + case GL_DRAW_FRAMEBUFFER: + cPBOs = 1; + apFBOs[0] = fbo->drawFB; + break; + default: + crWarning("unexpected target value: 0x%x", target); + cPBOs = 0; + break; + } + + return cPBOs; +} + +static GLuint crStateFramebufferTextureCheck(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, + CRFBOAttachmentPoint **aap, CRTextureObj **tobj) +{ + CRContext *g = GetCurrentContext(); + CRFramebufferObjectState *fbo = &g->framebufferobject; + CRFramebufferObject *apFBOs[2]; + GLuint cFBOs = 0, i; + GLuint maxtexsizelog2; + + CRSTATE_CHECKERR_RET(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end", 0); + CRSTATE_CHECKERR_RET(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)), + GL_INVALID_ENUM, "invalid target", 0); + + cFBOs = crStateFramebufferGet(fbo, target, apFBOs); + CRSTATE_CHECKERR_RET(!cFBOs, GL_INVALID_ENUM, "unexpected target", 0); + for (i = 0; i < cFBOs; ++i) + { + CRSTATE_CHECKERR_RET(!apFBOs[i], GL_INVALID_OPERATION, "zero fbo bound", 0); + } + + Assert(cFBOs); + Assert(cFBOs <= 2); + + for (i = 0; i < cFBOs; ++i) + { + CRSTATE_CHECKERR_RET(!crStateGetFBOAttachmentPoint(apFBOs[i], attachment, &aap[i]), GL_INVALID_ENUM, "invalid attachment", 0); + } + + if (!texture) + { + return cFBOs; + } + + switch (textarget) + { + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + maxtexsizelog2 = crLog2Floor(g->limits.maxCubeMapTextureSize); + *tobj = crStateTextureGet(GL_TEXTURE_CUBE_MAP_ARB, texture); + break; + case GL_TEXTURE_RECTANGLE_ARB: + maxtexsizelog2 = 0; + *tobj = crStateTextureGet(textarget, texture); + break; + case GL_TEXTURE_3D: + maxtexsizelog2 = crLog2Floor(g->limits.max3DTextureSize); + *tobj = crStateTextureGet(textarget, texture); + break; + case GL_TEXTURE_2D: + case GL_TEXTURE_1D: + maxtexsizelog2 = crLog2Floor(g->limits.maxTextureSize); + *tobj = crStateTextureGet(textarget, texture); + break; + default: + CRSTATE_CHECKERR_RET(GL_TRUE, GL_INVALID_OPERATION, "invalid textarget", 0); + } + + CRSTATE_CHECKERR_RET(!*tobj, GL_INVALID_OPERATION, "invalid textarget/texture combo", 0); + + if (GL_TEXTURE_RECTANGLE_ARB==textarget) + { + CRSTATE_CHECKERR_RET(level!=0, GL_INVALID_VALUE, "non zero mipmap level", 0); + } + + CRSTATE_CHECKERR_RET(level<0, GL_INVALID_VALUE, "level<0", 0); + CRSTATE_CHECKERR_RET((GLuint)level>maxtexsizelog2, GL_INVALID_VALUE, "level too big", 0); + +#ifdef IN_GUEST + for (i = 0; i < cFBOs; ++i) + { + if ((aap[i])->type!=GL_TEXTURE || (aap[i])->name!=texture || (aap[i])->level!=level) + { + apFBOs[i]->status = GL_FRAMEBUFFER_UNDEFINED; + } + } +#endif + + Assert(cFBOs); + Assert(cFBOs <= 2); + + return cFBOs; +} + +DECLEXPORT(void) STATE_APIENTRY +crStateFramebufferTexture1DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ + CRContext *g = GetCurrentContext(); + /*CRFramebufferObjectState *fbo = &g->framebufferobject; - unused */ + CRFBOAttachmentPoint *aap[2]; + GLuint cap, i; + CRTextureObj *tobj; + + cap = crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, aap, &tobj); + if (!cap) return; + + if (!texture) + { + for (i = 0; i < cap; ++i) + { + crStateInitFBOAttachmentPoint(aap[i]); + } + return; + } + + CRSTATE_CHECKERR(textarget!=GL_TEXTURE_1D, GL_INVALID_OPERATION, "textarget"); + + CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g); + + for (i = 0; i < cap; ++i) + { + crStateInitFBOAttachmentPoint(aap[i]); + aap[i]->type = GL_TEXTURE; + aap[i]->name = texture; + aap[i]->level = level; + } +} + +DECLEXPORT(void) STATE_APIENTRY +crStateFramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ + CRContext *g = GetCurrentContext(); + /* CRFramebufferObjectState *fbo = &g->framebufferobject; - unused */ + CRFBOAttachmentPoint *aap[2]; + GLuint cap, i; + CRTextureObj *tobj; + + cap = crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, aap, &tobj); + if (!cap) return; + + if (!texture) + { + for (i = 0; i < cap; ++i) + { + crStateInitFBOAttachmentPoint(aap[i]); + } + return; + } + + CRSTATE_CHECKERR(GL_TEXTURE_1D==textarget || GL_TEXTURE_3D==textarget, GL_INVALID_OPERATION, "textarget"); + + CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g); + + for (i = 0; i < cap; ++i) + { + crStateInitFBOAttachmentPoint(aap[i]); + aap[i]->type = GL_TEXTURE; + aap[i]->name = texture; + aap[i]->level = level; + if (textarget!=GL_TEXTURE_2D && textarget!=GL_TEXTURE_RECTANGLE_ARB) + { + aap[i]->face = textarget; + } + } +} + +DECLEXPORT(void) STATE_APIENTRY +crStateFramebufferTexture3DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) +{ + CRContext *g = GetCurrentContext(); + /* CRFramebufferObjectState *fbo = &g->framebufferobject; - unused */ + CRFBOAttachmentPoint *aap[2]; + GLuint cap, i; + CRTextureObj *tobj; + + cap = crStateFramebufferTextureCheck(target, attachment, textarget, texture, level, aap, &tobj); + if (!cap) return; + + if (!texture) + { + for (i = 0; i < cap; ++i) + { + crStateInitFBOAttachmentPoint(aap[i]); + } + return; + } + + CRSTATE_CHECKERR(zoffset>((GLint)g->limits.max3DTextureSize-1), GL_INVALID_VALUE, "zoffset too big"); + CRSTATE_CHECKERR(textarget!=GL_TEXTURE_3D, GL_INVALID_OPERATION, "textarget"); + + CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g); + + for (i = 0; i < cap; ++i) + { + crStateInitFBOAttachmentPoint(aap[i]); + aap[i]->type = GL_TEXTURE; + aap[i]->name = texture; + aap[i]->level = level; + aap[i]->zoffset = zoffset; + } +} + +DECLEXPORT(void) STATE_APIENTRY +crStateFramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +{ + CRContext *g = GetCurrentContext(); + CRFramebufferObjectState *fbo = &g->framebufferobject; + CRFramebufferObject *apFBOs[2]; + GLuint cFBOs, i; + CRFBOAttachmentPoint *aap[2]; + CRRenderbufferObject *rb; + (void)renderbuffertarget; + + CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end"); + CRSTATE_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)), + GL_INVALID_ENUM, "invalid target"); + cFBOs = crStateFramebufferGet(fbo, target, apFBOs); + CRSTATE_CHECKERR(!cFBOs, GL_INVALID_OPERATION, "no fbo bound"); + for (i = 0; i < cFBOs; ++i) + { + CRSTATE_CHECKERR(!apFBOs[i], GL_INVALID_OPERATION, "zero fbo bound"); + } + + for (i = 0; i < cFBOs; ++i) + { + CRSTATE_CHECKERR(!crStateGetFBOAttachmentPoint(apFBOs[i], attachment, &aap[i]), GL_INVALID_ENUM, "invalid attachment"); + } + + if (!renderbuffer) + { + for (i = 0; i < cFBOs; ++i) + { +#ifdef IN_GUEST + if (&aap[i]->type!=GL_NONE) + { + apFBOs[i]->status = GL_FRAMEBUFFER_UNDEFINED; + } +#endif + crStateInitFBOAttachmentPoint(aap[i]); + } + return; + } + + rb = (CRRenderbufferObject*) crHashtableSearch(g->shared->rbTable, renderbuffer); + if (!rb) + { + CRSTATE_CHECKERR(!crHashtableIsKeyUsed(g->shared->rbTable, renderbuffer), GL_INVALID_OPERATION, "rb doesn't exist"); + rb = crStateRenderbufferAllocate(g, renderbuffer); + } + + CR_STATE_SHAREDOBJ_USAGE_SET(rb, g); + + for (i = 0; i < cFBOs; ++i) + { +#ifdef IN_GUEST + if (aap[i]->type!=GL_RENDERBUFFER_EXT || aap[i]->name!=renderbuffer) + { + apFBOs[i]->status = GL_FRAMEBUFFER_UNDEFINED; + } +#endif + crStateInitFBOAttachmentPoint(aap[i]); + aap[i]->type = GL_RENDERBUFFER_EXT; + aap[i]->name = renderbuffer; + } +} + +DECLEXPORT(void) STATE_APIENTRY +crStateGetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, GLenum pname, GLint *params) +{ + CRContext *g = GetCurrentContext(); + CRFramebufferObjectState *fbo = &g->framebufferobject; + CRFramebufferObject *apFBOs[2]; + GLint cFBOs = 0, i; + CRFBOAttachmentPoint *ap; + + CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end"); + CRSTATE_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)), + GL_INVALID_ENUM, "invalid target"); + + cFBOs = crStateFramebufferGet(fbo, target, apFBOs); + + CRSTATE_CHECKERR(!cFBOs, GL_INVALID_OPERATION, "no fbo bound"); + for (i = 0; i < cFBOs; ++i) + { + CRSTATE_CHECKERR(!apFBOs[i], GL_INVALID_OPERATION, "zero fbo bound"); + } + + if(cFBOs != 1) + { + crWarning("different FBPs attached to draw and read buffers, returning info for the read buffer"); + } + + for (i = 0; i < 1; ++i) + { + CRSTATE_CHECKERR(!crStateGetFBOAttachmentPoint(apFBOs[i], attachment, &ap), GL_INVALID_ENUM, "invalid attachment"); + + switch (pname) + { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT: + *params = ap->type; + break; + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT: + CRSTATE_CHECKERR(ap->type!=GL_RENDERBUFFER_EXT && ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "can't query object name when it's not bound") + *params = ap->name; + break; + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT: + CRSTATE_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture"); + *params = ap->level; + break; + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT: + CRSTATE_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture"); + *params = ap->face; + break; + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT: + CRSTATE_CHECKERR(ap->type!=GL_TEXTURE, GL_INVALID_ENUM, "not a texture"); + *params = ap->zoffset; + break; + default: + CRSTATE_CHECKERR(GL_TRUE, GL_INVALID_ENUM, "invalid pname"); + } + } +} + +DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsFramebufferEXT( GLuint framebuffer ) +{ + CRContext *g = GetCurrentContext(); + + FLUSH(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glIsFramebufferEXT called in begin/end"); + return GL_FALSE; + } + + return framebuffer ? crHashtableIsKeyUsed(g->shared->fbTable, framebuffer) : GL_FALSE; +} + +DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsRenderbufferEXT( GLuint renderbuffer ) +{ + CRContext *g = GetCurrentContext(); + + + FLUSH(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glIsRenderbufferEXT called in begin/end"); + return GL_FALSE; + } + + return renderbuffer ? crHashtableIsKeyUsed(g->shared->rbTable, renderbuffer) : GL_FALSE; +} + +DECLEXPORT(void) STATE_APIENTRY +crStateGenerateMipmapEXT(GLenum target) +{ + (void)target; + /** @todo */ +} + +static void crStateSyncRenderbuffersCB(unsigned long key, void *data1, void *data2) +{ + CRRenderbufferObject *pRBO = (CRRenderbufferObject*) data1; + (void)key; (void)data2; + + diff_api.GenRenderbuffersEXT(1, &pRBO->hwid); + + if (pRBO->width && pRBO->height) + { + diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, pRBO->hwid); + diff_api.RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, pRBO->internalformat, pRBO->width, pRBO->height); + } +} + +static void crStateSyncAP(CRFBOAttachmentPoint *pAP, GLenum ap, CRContext *ctx) +{ + CRRenderbufferObject *pRBO; + CRTextureObj *tobj; + + switch (pAP->type) + { + case GL_TEXTURE: + CRASSERT(pAP->name!=0); + + tobj = (CRTextureObj *) crHashtableSearch(ctx->shared->textureTable, pAP->name); + if (tobj) + { + CRASSERT(!tobj->id || tobj->hwid); + + switch (tobj->target) + { + case GL_TEXTURE_1D: + diff_api.FramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, ap, tobj->target, crStateGetTextureObjHWID(tobj), pAP->level); + break; + case GL_TEXTURE_2D: + case GL_TEXTURE_RECTANGLE_ARB: + diff_api.FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, ap, tobj->target, crStateGetTextureObjHWID(tobj), pAP->level); + break; + case GL_TEXTURE_CUBE_MAP_ARB: + diff_api.FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, ap, pAP->face, crStateGetTextureObjHWID(tobj), pAP->level); + break; + case GL_TEXTURE_3D: + diff_api.FramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, ap, tobj->target, crStateGetTextureObjHWID(tobj), pAP->level, pAP->zoffset); + break; + default: + crWarning("Unexpected textarget %d", tobj->target); + } + } + else + { + crWarning("Unknown texture id %d", pAP->name); + } + break; + case GL_RENDERBUFFER_EXT: + pRBO = (CRRenderbufferObject*) crHashtableSearch(ctx->shared->rbTable, pAP->name); + diff_api.FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, ap, GL_RENDERBUFFER_EXT, pRBO->hwid); + break; + case GL_NONE: + /* Intentionally left blank */ + break; + default: crWarning("Invalid attachment point type %d (ap: %i)", pAP->type, ap); + } +} + +static void crStateSyncFramebuffersCB(unsigned long key, void *data1, void *data2) +{ + CRFramebufferObject *pFBO = (CRFramebufferObject*) data1; + CRContext *ctx = (CRContext*) data2; + GLint i; + (void)key; + + diff_api.GenFramebuffersEXT(1, &pFBO->hwid); + + diff_api.BindFramebufferEXT(GL_FRAMEBUFFER_EXT, pFBO->hwid); + + for (i=0; i<CR_MAX_COLOR_ATTACHMENTS; ++i) + { + crStateSyncAP(&pFBO->color[i], GL_COLOR_ATTACHMENT0_EXT+i, ctx); + } + + crStateSyncAP(&pFBO->depth, GL_DEPTH_ATTACHMENT_EXT, ctx); + crStateSyncAP(&pFBO->stencil, GL_STENCIL_ATTACHMENT_EXT, ctx); +} + +DECLEXPORT(void) STATE_APIENTRY +crStateFramebufferObjectSwitch(CRContext *from, CRContext *to) +{ + if (to->shared->bFBOResyncNeeded) + { + to->shared->bFBOResyncNeeded = GL_FALSE; + + crHashtableWalk(to->shared->rbTable, crStateSyncRenderbuffersCB, NULL); + crHashtableWalk(to->shared->fbTable, crStateSyncFramebuffersCB, to); + + if (to->framebufferobject.drawFB==to->framebufferobject.readFB) + { + diff_api.BindFramebufferEXT(GL_FRAMEBUFFER_EXT, to->framebufferobject.drawFB? + to->framebufferobject.drawFB->hwid:0); + } + else + { + diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, to->framebufferobject.drawFB? + to->framebufferobject.drawFB->hwid:0); + + diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, to->framebufferobject.readFB? + to->framebufferobject.readFB->hwid:0); + } + + diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, to->framebufferobject.renderbuffer? + to->framebufferobject.renderbuffer->hwid:0); + } + else + { + if (to->framebufferobject.drawFB!=from->framebufferobject.drawFB + || to->framebufferobject.readFB!=from->framebufferobject.readFB) + { + if (to->framebufferobject.drawFB==to->framebufferobject.readFB) + { + diff_api.BindFramebufferEXT(GL_FRAMEBUFFER_EXT, to->framebufferobject.drawFB? + to->framebufferobject.drawFB->hwid:0); + } + else + { + diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, to->framebufferobject.drawFB? + to->framebufferobject.drawFB->hwid:0); + + diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, to->framebufferobject.readFB? + to->framebufferobject.readFB->hwid:0); + } + + diff_api.DrawBuffer(to->framebufferobject.drawFB?to->framebufferobject.drawFB->drawbuffer[0]:to->buffer.drawBuffer); + diff_api.ReadBuffer(to->framebufferobject.readFB?to->framebufferobject.readFB->readbuffer:to->buffer.readBuffer); + } + + if (to->framebufferobject.renderbuffer!=from->framebufferobject.renderbuffer) + { + diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, to->framebufferobject.renderbuffer? + to->framebufferobject.renderbuffer->hwid:0); + } + } +} + +DECLEXPORT(void) STATE_APIENTRY +crStateFramebufferObjectDisableHW(CRContext *ctx, GLuint idDrawFBO, GLuint idReadFBO) +{ + GLenum idDrawBuffer = 0, idReadBuffer = 0; + + if (ctx->framebufferobject.drawFB || idDrawFBO) + { + diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0); + idDrawBuffer = ctx->buffer.drawBuffer; + } + + if (ctx->framebufferobject.readFB || idReadFBO) + { + diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0); + idReadBuffer = ctx->buffer.readBuffer; + } + + if (idDrawBuffer) + diff_api.DrawBuffer(idDrawBuffer); + if (idReadBuffer) + diff_api.ReadBuffer(idReadBuffer); + + if (ctx->framebufferobject.renderbuffer) + diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); +} + +DECLEXPORT(void) STATE_APIENTRY +crStateFramebufferObjectReenableHW(CRContext *fromCtx, CRContext *toCtx, GLuint idDrawFBO, GLuint idReadFBO) +{ + GLuint idReadBuffer = 0, idDrawBuffer = 0; + if (!fromCtx) + fromCtx = toCtx; /* <- in case fromCtx is zero, set it to toCtx to ensure framebuffer state gets re-enabled correctly */ + + if ((fromCtx->framebufferobject.drawFB) /* <- the FBO state was reset in crStateFramebufferObjectDisableHW */ + && fromCtx->framebufferobject.drawFB == toCtx->framebufferobject.drawFB) /* .. and it was NOT restored properly in crStateFramebufferObjectSwitch */ + { + diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, toCtx->framebufferobject.drawFB->hwid); + idDrawBuffer = toCtx->framebufferobject.drawFB->drawbuffer[0]; + } + else if (idDrawFBO && !toCtx->framebufferobject.drawFB) + { + diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, idDrawFBO); + idDrawBuffer = GL_COLOR_ATTACHMENT0; + } + + if ((fromCtx->framebufferobject.readFB) /* <- the FBO state was reset in crStateFramebufferObjectDisableHW */ + && fromCtx->framebufferobject.readFB == toCtx->framebufferobject.readFB) /* .. and it was NOT restored properly in crStateFramebufferObjectSwitch */ + { + diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, toCtx->framebufferobject.readFB->hwid); + idReadBuffer = toCtx->framebufferobject.readFB->readbuffer; + } + else if (idReadFBO && !toCtx->framebufferobject.readFB) + { + diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, idReadFBO); + idReadBuffer = GL_COLOR_ATTACHMENT0; + } + + if (idDrawBuffer) + diff_api.DrawBuffer(idDrawBuffer); + if (idReadBuffer) + diff_api.ReadBuffer(idReadBuffer); + + if (fromCtx->framebufferobject.renderbuffer /* <- the FBO state was reset in crStateFramebufferObjectDisableHW */ + && fromCtx->framebufferobject.renderbuffer==toCtx->framebufferobject.renderbuffer) /* .. and it was NOT restored properly in crStateFramebufferObjectSwitch */ + { + diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, toCtx->framebufferobject.renderbuffer->hwid); + } +} + + +DECLEXPORT(GLuint) STATE_APIENTRY crStateGetFramebufferHWID(GLuint id) +{ + CRContext *g = GetCurrentContext(); + CRFramebufferObject *pFBO = (CRFramebufferObject*) crHashtableSearch(g->shared->fbTable, id); +#if 0 /*def DEBUG_misha*/ + crDebug("FB id(%d) hw(%d)", id, pFBO ? pFBO->hwid : 0); +#endif + return pFBO ? pFBO->hwid : 0; +} + +DECLEXPORT(GLuint) STATE_APIENTRY crStateGetRenderbufferHWID(GLuint id) +{ + CRContext *g = GetCurrentContext(); + CRRenderbufferObject *pRBO = (CRRenderbufferObject*) crHashtableSearch(g->shared->rbTable, id); + + return pRBO ? pRBO->hwid : 0; +} + +static void crStateCheckFBOHWIDCB(unsigned long key, void *data1, void *data2) +{ + CRFramebufferObject *pFBO = (CRFramebufferObject *) data1; + crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2; + (void) key; + + if (pFBO->hwid==pParms->hwid) + pParms->id = pFBO->id; +} + +static void crStateCheckRBOHWIDCB(unsigned long key, void *data1, void *data2) +{ + CRRenderbufferObject *pRBO = (CRRenderbufferObject *) data1; + crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2; + (void) key; + + if (pRBO->hwid==pParms->hwid) + pParms->id = pRBO->id; +} + +DECLEXPORT(GLuint) STATE_APIENTRY crStateFBOHWIDtoID(GLuint hwid) +{ + CRContext *g = GetCurrentContext(); + crCheckIDHWID_t parms; + + parms.id = hwid; + parms.hwid = hwid; + + crHashtableWalk(g->shared->fbTable, crStateCheckFBOHWIDCB, &parms); + return parms.id; +} + +DECLEXPORT(GLuint) STATE_APIENTRY crStateRBOHWIDtoID(GLuint hwid) +{ + CRContext *g = GetCurrentContext(); + crCheckIDHWID_t parms; + + parms.id = hwid; + parms.hwid = hwid; + + crHashtableWalk(g->shared->rbTable, crStateCheckRBOHWIDCB, &parms); + return parms.id; +} + +#ifdef IN_GUEST +DECLEXPORT(GLenum) STATE_APIENTRY crStateCheckFramebufferStatusEXT(GLenum target) +{ + GLenum status = GL_FRAMEBUFFER_UNDEFINED; + CRContext *g = GetCurrentContext(); + CRFramebufferObjectState *fbo = &g->framebufferobject; + CRFramebufferObject *pFBO=NULL; + + switch (target) + { + case GL_FRAMEBUFFER_EXT: + pFBO = fbo->drawFB; + break; + case GL_READ_FRAMEBUFFER: + pFBO = fbo->readFB; + break; + case GL_DRAW_FRAMEBUFFER: + pFBO = fbo->drawFB; + break; + } + + if (pFBO) status = pFBO->status; + + return status; +} + +DECLEXPORT(GLenum) STATE_APIENTRY crStateSetFramebufferStatus(GLenum target, GLenum status) +{ + CRContext *g = GetCurrentContext(); + CRFramebufferObjectState *fbo = &g->framebufferobject; + CRFramebufferObject *pFBO=NULL; + + switch (target) + { + case GL_FRAMEBUFFER_EXT: + pFBO = fbo->drawFB; + break; + case GL_READ_FRAMEBUFFER: + pFBO = fbo->readFB; + break; + case GL_DRAW_FRAMEBUFFER: + pFBO = fbo->drawFB; + break; + } + + if (pFBO) pFBO->status = status; + + return status; +} +#endif diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_funcs.py b/src/VBox/GuestHost/OpenGL/state_tracker/state_funcs.py new file mode 100755 index 00000000..ebf1b379 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_funcs.py @@ -0,0 +1,62 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + + +from __future__ import print_function +import sys + +sys.path.append( "../glapi_parser" ) +import apiutil + + +apiutil.CopyrightC() + +print(""" +/* DO NOT EDIT - THIS FILE AUTOMATICALLY GENERATED BY state_funcs.py SCRIPT */ +#ifndef CR_STATE_FUNCS_H +#define CR_STATE_FUNCS_H + +#include "chromium.h" +#include "cr_error.h" + +#include <iprt/cdefs.h> + +#if defined(WINDOWS) +#define STATE_APIENTRY __stdcall +#else +#define STATE_APIENTRY +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define STATE_UNUSED(x) ((void)x)""") + + + +for func_name in apiutil.AllSpecials( "state" ): + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + print('DECLEXPORT(%s) STATE_APIENTRY crState%s(%s);' % (return_type, func_name, apiutil.MakeDeclarationString(params))) + +for func_name in apiutil.AllSpecials( "state_feedback" ): + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + print('DECLEXPORT(%s) STATE_APIENTRY crStateFeedback%s(%s);' % (return_type, func_name, apiutil.MakeDeclarationString(params))) + +for func_name in apiutil.AllSpecials( "state_select" ): + return_type = apiutil.ReturnType(func_name) + params = apiutil.Parameters(func_name) + print('DECLEXPORT(%s) STATE_APIENTRY crStateSelect%s(%s);' % (return_type, func_name, apiutil.MakeDeclarationString(params))) + + +print(""" +#ifdef __cplusplus +} +#endif + +#endif /* CR_STATE_FUNCS_H */ +""") diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py b/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py new file mode 100755 index 00000000..d5238c45 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py @@ -0,0 +1,234 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys, re, string +import apiutil + +line_re = re.compile (r'^(\S+)\s+(GL_\S+)\s+(.*)\s*$') +extensions_line_re = re.compile(r'^(\S+)\s+(GL_\S+)\s+(GL_\S+)\s+(.*)\s*$') + +params = {} +extended_params = {} + +input = open( sys.argv[2]+"/state_get.txt", 'r' ) +for line in input.readlines(): + if line[0] == '#': + continue + match = line_re.match( line ) + if match: + type = match.group(1) + pname = match.group(2) + fields = match.group(3).split() + params[pname] = ( type, fields ) + +input = open( sys.argv[2]+"/state_extensions_get.txt", 'r' ) +for line in input.readlines(): + if line[0] == '#': + continue + match = extensions_line_re.match( line ) + if match: + type = match.group(1) + pname = match.group(2) + ifdef = match.group(3) + fields = match.group(4).split() + extended_params[pname] = ( type, ifdef, fields ) + +convert = { + 'GLenum' : { + 'Boolean' : '(GLboolean) (%s != 0)', + 'Double' : '(GLdouble) %s', + 'Float' : '(GLfloat) %s', + 'Integer' : '(GLint) %s' + }, + 'GLboolean' : { + 'Boolean' : '(GLboolean) (%s != 0)', + 'Double' : '(GLdouble) %s', + 'Float' : '(GLfloat) %s', + 'Integer' : '(GLint) %s' + }, + 'GLint' : { + 'Boolean' : '(GLboolean) (%s != 0)', + 'Double' : '(GLdouble) %s', + 'Float' : '(GLfloat) %s', + 'Integer' : '(GLint) %s' + }, + 'GLuint' : { + 'Boolean' : '(GLboolean) (%s != 0)', + 'Double' : '(GLdouble) %s', + 'Float' : '(GLfloat) %s', + 'Integer' : '(GLint) %s' + }, + 'GLfloat' : { + 'Boolean' : '(GLboolean) (%s != 0.0f)', + 'Double' : '(GLdouble) %s', + 'Float' : '%s', + 'Integer' : '(GLint) %s' + }, + 'GLdouble' : { + 'Boolean' : '(GLboolean) (%s != 0.0)', + 'Double' : '%s', + 'Float' : '(GLfloat) %s', + 'Integer' : '(GLint) %s' + }, + 'GLdefault' : { + 'Boolean' : '(GLboolean) (%s != (GLdefault) 0.0)', + 'Double' : '(GLdouble) %s', + 'Float' : '(GLfloat) %s', + 'Integer' : '(GLint) %s' + }, + 'GLclampd' : { + 'Boolean' : '(GLboolean) (%s != 0.0)', + 'Double' : '%s', + 'Float' : '(GLfloat) %s', + 'Integer' : '__clampd_to_int(%s)' + }, + 'GLclampf' : { + 'Boolean' : '(GLboolean) (%s != 0.0f)', + 'Double' : '(GLdouble) %s', + 'Float' : '%s', + 'Integer' : '__clampf_to_int(%s)' + } + } + +types = [ "Boolean", "Double", "Float", "Integer" ] + +ctypes = { + 'Boolean' : 'GLboolean', + 'Double' : 'GLdouble', + 'Float' : 'GLfloat', + 'Integer' : 'GLint' + } + +apiutil.CopyrightC() + +print(""" +/* DO NOT EDIT - THIS FILE GENERATED BY state_get.txt AND THE state_get.py SCRIPT */ +#include <stdio.h> +#include <math.h> + +#include "state.h" +#include "state/cr_statetypes.h" + +static GLint __clampd_to_int(GLdouble d) +{ + /* -1.0 -> MIN_INT, 1.0 -> MAX_INT */ + if (d > 1.0) + return 0x7fffffff; + if (d < -1.0) + return 0x80000000; + return (GLint) floor(d * 2147483647.5); +} + +static GLint __clampf_to_int(GLfloat f) +{ + /* -1.0f -> MIN_INT, 1.0f -> MAX_INT */ + if (f > 1.0f) + return 0x7fffffff; + if (f < -1.0f) + return 0x80000000; + return (GLint) floor(f * 2147483647.5f); +} + +static GLenum __getDrawBuffer(CRContext *g) +{ + return g->framebufferobject.drawFB ? g->framebufferobject.drawFB->drawbuffer[0] : g->buffer.drawBuffer; +} + +static GLenum __getReadBuffer(CRContext *g) +{ + return g->framebufferobject.readFB ? g->framebufferobject.readFB->readbuffer : g->buffer.readBuffer; +} +""") + +header = """ +{ + CRContext *g = GetCurrentContext(); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGet called in Begin/End"); + return; + } + + if (pname == GL_CURRENT_INDEX || pname == GL_CURRENT_COLOR || + pname == GL_CURRENT_SECONDARY_COLOR_EXT || + pname == GL_CURRENT_FOG_COORDINATE_EXT || + pname == GL_CURRENT_NORMAL || pname == GL_EDGE_FLAG || + pname == GL_CURRENT_TEXTURE_COORDS ) + { +#if 0 + crStateError(__LINE__,__FILE__, GL_INVALID_OPERATION, + "Unimplemented glGet of a 'current' value" ); +#else + crStateCurrentRecover();/* &g->current, &sb->current, g->bitID );*/ + +#endif + } + + switch (pname) { +""" + +for rettype in types: + print('') + print('void STATE_APIENTRY crStateGet%sv( GLenum pname, %s *params )' % ( rettype, ctypes[rettype] )) + print(header) + + for pname in sorted(params.keys()): + print('\t\tcase %s:' % pname) + (srctype,fields) = params[pname] + try: + cvt = convert[srctype][rettype] + i = 0 + for field in fields: + expr = cvt % field + print('\t\t\tparams[%d] = %s;' % (i,expr)) + i += 1 + except: + print('\t\t\tcrStateError(__LINE__,__FILE__,GL_INVALID_OPERATION, "Unimplemented glGet!");') + print("\t\t\tbreak;") + + + for pname in sorted(extended_params.keys()): + (srctype,ifdef,fields) = extended_params[pname] + ext = ifdef[3:] # the extension name with the "GL_" prefix removed + #print '#ifdef %s' % ifdef + print('#ifdef CR_%s' % ext) + print('\t\tcase %s:' % pname) + if ext != 'OPENGL_VERSION_1_2': + print('\t\t\tif (g->extensions.%s) {' % ext) + try: + cvt = convert[srctype][rettype] + i = 0 + for field in fields: + expr = cvt % field + if field[0] == '%': + command = string.split(field, '%') + print('\t\t\t\t%s;' % command[1]) + continue + elif ext != 'OPENGL_VERSION_1_2': + print('\t\t\t\tparams[%d] = %s;' % (i,expr)) + else: + print('\t\t\tparams[%d] = %s;' % (i,expr)) + i += 1 + except: + print('\t\t\tcrStateError(__LINE__,__FILE__,GL_INVALID_OPERATION, "Unimplemented glGet!");') + if ext != 'OPENGL_VERSION_1_2': + print("\t\t\t}") + print("\t\t\telse {") + print('\t\t\t\tcrStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "glGet%sv");' % rettype) + print("\t\t\t}") + print("\t\t\tbreak;") + #print '#endif /* %s */' % ifdef + print('#endif /* CR_%s */' % ext) + + print('\t\tdefault:') + print('\t\t\tcrStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGet: Unknown enum: 0x%x", pname);') + print('\t\t\treturn;') + print('\t}') + print('}') + +from get_components import * diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt new file mode 100644 index 00000000..150d350b --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt @@ -0,0 +1,319 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +GLenum GL_MATRIX_MODE g->transform.matrixMode +GLint GL_MODELVIEW_STACK_DEPTH g->transform.modelViewStack.depth+1 +GLint GL_PROJECTION_STACK_DEPTH g->transform.projectionStack.depth+1 +GLint GL_TEXTURE_STACK_DEPTH g->transform.textureStack[g->texture.curTextureUnit].depth+1 +GLint GL_COLOR_MATRIX_STACK_DEPTH g->transform.colorStack.depth+1 +GLdefault GL_MODELVIEW_MATRIX g->transform.modelViewStack.top->m00 g->transform.modelViewStack.top->m01 g->transform.modelViewStack.top->m02 g->transform.modelViewStack.top->m03 g->transform.modelViewStack.top->m10 g->transform.modelViewStack.top->m11 g->transform.modelViewStack.top->m12 g->transform.modelViewStack.top->m13 g->transform.modelViewStack.top->m20 g->transform.modelViewStack.top->m21 g->transform.modelViewStack.top->m22 g->transform.modelViewStack.top->m23 g->transform.modelViewStack.top->m30 g->transform.modelViewStack.top->m31 g->transform.modelViewStack.top->m32 g->transform.modelViewStack.top->m33 +GLdefault GL_PROJECTION_MATRIX g->transform.projectionStack.top->m00 g->transform.projectionStack.top->m01 g->transform.projectionStack.top->m02 g->transform.projectionStack.top->m03 g->transform.projectionStack.top->m10 g->transform.projectionStack.top->m11 g->transform.projectionStack.top->m12 g->transform.projectionStack.top->m13 g->transform.projectionStack.top->m20 g->transform.projectionStack.top->m21 g->transform.projectionStack.top->m22 g->transform.projectionStack.top->m23 g->transform.projectionStack.top->m30 g->transform.projectionStack.top->m31 g->transform.projectionStack.top->m32 g->transform.projectionStack.top->m33 +GLdefault GL_TEXTURE_MATRIX g->transform.textureStack[g->texture.curTextureUnit].top->m00 g->transform.textureStack[g->texture.curTextureUnit].top->m01 g->transform.textureStack[g->texture.curTextureUnit].top->m02 g->transform.textureStack[g->texture.curTextureUnit].top->m03 g->transform.textureStack[g->texture.curTextureUnit].top->m10 g->transform.textureStack[g->texture.curTextureUnit].top->m11 g->transform.textureStack[g->texture.curTextureUnit].top->m12 g->transform.textureStack[g->texture.curTextureUnit].top->m13 g->transform.textureStack[g->texture.curTextureUnit].top->m20 g->transform.textureStack[g->texture.curTextureUnit].top->m21 g->transform.textureStack[g->texture.curTextureUnit].top->m22 g->transform.textureStack[g->texture.curTextureUnit].top->m23 g->transform.textureStack[g->texture.curTextureUnit].top->m30 g->transform.textureStack[g->texture.curTextureUnit].top->m31 g->transform.textureStack[g->texture.curTextureUnit].top->m32 g->transform.textureStack[g->texture.curTextureUnit].top->m33 +GLdefault GL_COLOR_MATRIX g->transform.colorStack.top->m00 g->transform.colorStack.top->m01 g->transform.colorStack.top->m02 g->transform.colorStack.top->m03 g->transform.colorStack.top->m10 g->transform.colorStack.top->m11 g->transform.colorStack.top->m12 g->transform.colorStack.top->m13 g->transform.colorStack.top->m20 g->transform.colorStack.top->m21 g->transform.colorStack.top->m22 g->transform.colorStack.top->m23 g->transform.colorStack.top->m30 g->transform.colorStack.top->m31 g->transform.colorStack.top->m32 g->transform.colorStack.top->m33 + +GLint GL_ATTRIB_STACK_DEPTH g->attrib.attribStackDepth +GLint GL_ACTIVE_TEXTURE_ARB g->texture.curTextureUnit+GL_TEXTURE0_ARB +GLint GL_CLIENT_ACTIVE_TEXTURE_ARB g->client.curClientTextureUnit+GL_TEXTURE0_ARB + +GLint GL_VIEWPORT g->viewport.viewportX g->viewport.viewportY g->viewport.viewportW g->viewport.viewportH +GLclampd GL_DEPTH_RANGE g->viewport.nearClip g->viewport.farClip +GLint GL_SCISSOR_BOX g->viewport.scissorX g->viewport.scissorY g->viewport.scissorW g->viewport.scissorH +GLboolean GL_SCISSOR_TEST g->viewport.scissorTest + + +GLenum GL_COLOR_MATERIAL_PARAMETER g->lighting.colorMaterialMode +GLenum GL_COLOR_MATERIAL_FACE g->lighting.colorMaterialFace +GLclampf GL_LIGHT_MODEL_AMBIENT g->lighting.lightModelAmbient.r g->lighting.lightModelAmbient.g g->lighting.lightModelAmbient.b g->lighting.lightModelAmbient.a +GLboolean GL_LIGHT_MODEL_LOCAL_VIEWER g->lighting.lightModelLocalViewer +GLboolean GL_LIGHT_MODEL_TWO_SIDE g->lighting.lightModelTwoSide +GLenum GL_SHADE_MODEL g->lighting.shadeModel + +GLfloat GL_FOG_COLOR g->fog.color.r g->fog.color.g g->fog.color.b g->fog.color.a +GLfloat GL_FOG_DENSITY g->fog.density +GLfloat GL_FOG_START g->fog.start +GLfloat GL_FOG_END g->fog.end +GLenum GL_FOG_MODE g->fog.mode +GLint GL_FOG_INDEX g->fog.index + +GLenum GL_FRONT_FACE g->polygon.frontFace +GLenum GL_CULL_FACE_MODE g->polygon.cullFaceMode +GLenum GL_POLYGON_MODE g->polygon.frontMode g->polygon.backMode +GLboolean GL_CULL_FACE g->polygon.cullFace +GLboolean GL_POLYGON_OFFSET_FILL g->polygon.polygonOffsetFill +GLboolean GL_POLYGON_OFFSET_LINE g->polygon.polygonOffsetLine +GLboolean GL_POLYGON_OFFSET_POINT g->polygon.polygonOffsetPoint +GLboolean GL_POLYGON_SMOOTH g->polygon.polygonSmooth +GLboolean GL_POLYGON_STIPPLE g->polygon.polygonStipple +GLfloat GL_POLYGON_OFFSET_FACTOR g->polygon.offsetFactor +GLfloat GL_POLYGON_OFFSET_UNITS g->polygon.offsetUnits + +GLboolean GL_ALPHA_TEST g->buffer.alphaTest +GLboolean GL_BLEND g->buffer.blend +GLboolean GL_COLOR_LOGIC_OP g->buffer.logicOp +GLboolean GL_COLOR_MATERIAL GL_FALSE +GLboolean GL_CLIP_PLANE0 g->transform.clip[0] +GLboolean GL_CLIP_PLANE1 g->transform.clip[1] +GLboolean GL_CLIP_PLANE2 g->transform.clip[2] +GLboolean GL_CLIP_PLANE3 g->transform.clip[3] +GLboolean GL_CLIP_PLANE4 g->transform.clip[4] +GLboolean GL_CLIP_PLANE5 g->transform.clip[5] +GLboolean GL_DEPTH_TEST g->buffer.depthTest +GLboolean GL_DEPTH_WRITEMASK g->buffer.depthMask +GLboolean GL_DITHER g->buffer.dither +GLboolean GL_INDEX_LOGIC_OP g->buffer.indexLogicOp +GLboolean GL_FOG g->fog.enable +GLboolean GL_LIGHT0 g->lighting.light[0].enable +GLboolean GL_LIGHT1 g->lighting.light[1].enable +GLboolean GL_LIGHT2 g->lighting.light[2].enable +GLboolean GL_LIGHT3 g->lighting.light[3].enable +GLboolean GL_LIGHT4 g->lighting.light[4].enable +GLboolean GL_LIGHT5 g->lighting.light[5].enable +GLboolean GL_LIGHT6 g->lighting.light[6].enable +GLboolean GL_LIGHT7 g->lighting.light[7].enable +GLboolean GL_LIGHTING g->lighting.lighting +GLboolean GL_LINE_SMOOTH g->line.lineSmooth +GLboolean GL_LINE_STIPPLE g->line.lineStipple +GLint GL_LOGIC_OP_MODE g->buffer.logicOpMode +GLboolean GL_POINT_SMOOTH g->point.pointSmooth +GLfloat GL_POINT_SIZE g->point.pointSize +GLfloat GL_POINT_SIZE_MIN_ARB g->point.minSize +GLfloat GL_POINT_SIZE_MAX_ARB g->point.maxSize +GLfloat GL_POINT_FADE_THRESHOLD_SIZE_ARB g->point.fadeThresholdSize +GLfloat GL_POINT_SPRITE_COORD_ORIGIN g->point.spriteCoordOrigin +GLfloat GL_POINT_DISTANCE_ATTENUATION_ARB g->point.distanceAttenuation[0] g->point.distanceAttenuation[1] g->point.distanceAttenuation[2] +GLboolean GL_NORMALIZE g->transform.normalize + +GLboolean GL_TEXTURE_GEN_S g->texture.unit[g->texture.curTextureUnit].textureGen.s +GLboolean GL_TEXTURE_GEN_T g->texture.unit[g->texture.curTextureUnit].textureGen.t +GLboolean GL_TEXTURE_GEN_R g->texture.unit[g->texture.curTextureUnit].textureGen.r +GLboolean GL_TEXTURE_GEN_Q g->texture.unit[g->texture.curTextureUnit].textureGen.q +GLboolean GL_TEXTURE_1D g->texture.unit[g->texture.curTextureUnit].enabled1D +GLboolean GL_TEXTURE_2D g->texture.unit[g->texture.curTextureUnit].enabled2D +GLboolean GL_TEXTURE_3D g->texture.unit[g->texture.curTextureUnit].enabled3D + +GLfloat GL_LINE_WIDTH g->line.width +GLint GL_LINE_STIPPLE_PATTERN g->line.pattern +GLint GL_LINE_STIPPLE_REPEAT g->line.repeat + +GLboolean GL_PACK_SWAP_BYTES g->client.pack.swapBytes +GLboolean GL_PACK_LSB_FIRST g->client.pack.psLSBFirst +GLboolean GL_UNPACK_SWAP_BYTES g->client.unpack.swapBytes +GLboolean GL_UNPACK_LSB_FIRST g->client.unpack.psLSBFirst +GLint GL_PACK_ROW_LENGTH g->client.pack.rowLength +GLint GL_PACK_SKIP_ROWS g->client.pack.skipRows +GLint GL_PACK_SKIP_PIXELS g->client.pack.skipPixels +GLint GL_PACK_ALIGNMENT g->client.pack.alignment +GLint GL_PACK_IMAGE_HEIGHT g->client.pack.imageHeight +GLint GL_PACK_SKIP_IMAGES g->client.pack.skipImages +GLint GL_UNPACK_ROW_LENGTH g->client.unpack.rowLength +GLint GL_UNPACK_SKIP_ROWS g->client.unpack.skipRows +GLint GL_UNPACK_SKIP_PIXELS g->client.unpack.skipPixels +GLint GL_UNPACK_ALIGNMENT g->client.unpack.alignment +GLint GL_UNPACK_IMAGE_HEIGHT g->client.unpack.imageHeight +GLint GL_UNPACK_SKIP_IMAGES g->client.unpack.skipImages +GLfloat GL_ZOOM_X g->pixel.xZoom +GLfloat GL_ZOOM_Y g->pixel.yZoom +GLfloat GL_RED_BIAS g->pixel.bias.r +GLfloat GL_GREEN_BIAS g->pixel.bias.g +GLfloat GL_BLUE_BIAS g->pixel.bias.b +GLfloat GL_ALPHA_BIAS g->pixel.bias.a +GLfloat GL_RED_SCALE g->pixel.scale.r +GLfloat GL_GREEN_SCALE g->pixel.scale.g +GLfloat GL_BLUE_SCALE g->pixel.scale.b +GLfloat GL_ALPHA_SCALE g->pixel.scale.a +GLfloat GL_DEPTH_BIAS g->pixel.depthBias +GLfloat GL_DEPTH_SCALE g->pixel.depthScale +GLint GL_INDEX_OFFSET g->pixel.indexOffset +GLint GL_INDEX_SHIFT g->pixel.indexShift +GLboolean GL_MAP_COLOR g->pixel.mapColor +GLboolean GL_MAP_STENCIL g->pixel.mapStencil +GLint GL_PIXEL_MAP_A_TO_A_SIZE g->pixel.mapAtoAsize +GLint GL_PIXEL_MAP_B_TO_B_SIZE g->pixel.mapBtoBsize +GLint GL_PIXEL_MAP_G_TO_G_SIZE g->pixel.mapGtoGsize +GLint GL_PIXEL_MAP_I_TO_A_SIZE g->pixel.mapItoAsize +GLint GL_PIXEL_MAP_I_TO_B_SIZE g->pixel.mapItoBsize +GLint GL_PIXEL_MAP_I_TO_G_SIZE g->pixel.mapItoGsize +GLint GL_PIXEL_MAP_I_TO_I_SIZE g->pixel.mapItoIsize +GLint GL_PIXEL_MAP_I_TO_R_SIZE g->pixel.mapItoRsize +GLint GL_PIXEL_MAP_R_TO_R_SIZE g->pixel.mapRtoRsize +GLint GL_PIXEL_MAP_S_TO_S_SIZE g->pixel.mapStoSsize + +GLboolean GL_AUTO_NORMAL g->eval.autoNormal +GLboolean GL_MAP1_COLOR_4 g->eval.enable1D[pname-GL_MAP1_COLOR_4] +GLboolean GL_MAP1_INDEX g->eval.enable1D[pname-GL_MAP1_COLOR_4] +GLboolean GL_MAP1_NORMAL g->eval.enable1D[pname-GL_MAP1_COLOR_4] +GLboolean GL_MAP1_TEXTURE_COORD_1 g->eval.enable1D[pname-GL_MAP1_COLOR_4] +GLboolean GL_MAP1_TEXTURE_COORD_2 g->eval.enable1D[pname-GL_MAP1_COLOR_4] +GLboolean GL_MAP1_TEXTURE_COORD_3 g->eval.enable1D[pname-GL_MAP1_COLOR_4] +GLboolean GL_MAP1_TEXTURE_COORD_4 g->eval.enable1D[pname-GL_MAP1_COLOR_4] +GLboolean GL_MAP1_VERTEX_3 g->eval.enable1D[pname-GL_MAP1_COLOR_4] +GLboolean GL_MAP1_VERTEX_4 g->eval.enable1D[pname-GL_MAP1_COLOR_4] +GLboolean GL_MAP2_COLOR_4 g->eval.enable2D[pname-GL_MAP2_COLOR_4] +GLboolean GL_MAP2_INDEX g->eval.enable2D[pname-GL_MAP2_COLOR_4] +GLboolean GL_MAP2_NORMAL g->eval.enable2D[pname-GL_MAP2_COLOR_4] +GLboolean GL_MAP2_TEXTURE_COORD_1 g->eval.enable2D[pname-GL_MAP2_COLOR_4] +GLboolean GL_MAP2_TEXTURE_COORD_2 g->eval.enable2D[pname-GL_MAP2_COLOR_4] +GLboolean GL_MAP2_TEXTURE_COORD_3 g->eval.enable2D[pname-GL_MAP2_COLOR_4] +GLboolean GL_MAP2_TEXTURE_COORD_4 g->eval.enable2D[pname-GL_MAP2_COLOR_4] +GLboolean GL_MAP2_VERTEX_3 g->eval.enable2D[pname-GL_MAP2_COLOR_4] +GLboolean GL_MAP2_VERTEX_4 g->eval.enable2D[pname-GL_MAP2_COLOR_4] +GLdouble GL_MAP1_GRID_DOMAIN g->eval.u11D g->eval.u21D +GLint GL_MAP1_GRID_SEGMENTS g->eval.un1D +GLdouble GL_MAP2_GRID_DOMAIN g->eval.u12D g->eval.u22D g->eval.v12D g->eval.v22D +GLint GL_MAP2_GRID_SEGMENTS g->eval.un2D g->eval.vn2D + +GLint GL_NAME_STACK_DEPTH 0 + +GLenum GL_FOG_HINT g->hint.fog +GLenum GL_LINE_SMOOTH_HINT g->hint.lineSmooth +GLenum GL_POINT_SMOOTH_HINT g->hint.pointSmooth +GLenum GL_POLYGON_SMOOTH_HINT g->hint.polygonSmooth +GLenum GL_PERSPECTIVE_CORRECTION_HINT g->hint.perspectiveCorrection + +GLint GL_TEXTURE_BINDING_1D g->texture.unit[g->texture.curTextureUnit].currentTexture1D->id +GLint GL_TEXTURE_BINDING_2D g->texture.unit[g->texture.curTextureUnit].currentTexture2D->id +GLint GL_TEXTURE_BINDING_3D g->texture.unit[g->texture.curTextureUnit].currentTexture3D->id +GLenum GL_TEXTURE_ENV_MODE g->texture.unit[g->texture.curTextureUnit].envMode + +GLboolean GL_VERTEX_ARRAY g->client.array.v.enabled +GLint GL_VERTEX_ARRAY_SIZE g->client.array.v.size +GLint GL_VERTEX_ARRAY_STRIDE g->client.array.v.stride +GLint GL_VERTEX_ARRAY_TYPE g->client.array.v.type +GLboolean GL_NORMAL_ARRAY g->client.array.n.enabled +GLint GL_NORMAL_ARRAY_STRIDE g->client.array.n.stride +GLint GL_NORMAL_ARRAY_TYPE g->client.array.n.type +GLboolean GL_COLOR_ARRAY g->client.array.c.enabled +GLint GL_COLOR_ARRAY_SIZE g->client.array.c.size +GLint GL_COLOR_ARRAY_STRIDE g->client.array.c.stride +GLint GL_COLOR_ARRAY_TYPE g->client.array.c.type +GLboolean GL_INDEX_ARRAY g->client.array.i.enabled +GLint GL_INDEX_ARRAY_STRIDE g->client.array.i.stride +GLint GL_INDEX_ARRAY_TYPE g->client.array.i.type +GLboolean GL_TEXTURE_COORD_ARRAY g->client.array.t[g->client.curClientTextureUnit].enabled +GLint GL_TEXTURE_COORD_ARRAY_SIZE g->client.array.t[g->client.curClientTextureUnit].size +GLint GL_TEXTURE_COORD_ARRAY_STRIDE g->client.array.t[g->client.curClientTextureUnit].stride +GLint GL_TEXTURE_COORD_ARRAY_TYPE g->client.array.t[g->client.curClientTextureUnit].type +GLboolean GL_EDGE_FLAG_ARRAY g->client.array.e.enabled +GLint GL_EDGE_FLAG_ARRAY_STRIDE g->client.array.e.stride + +GLboolean GL_RGBA_MODE g->limits.rgbaMode +GLboolean GL_INDEX_MODE (!g->limits.rgbaMode) +GLint GL_AUX_BUFFERS g->limits.auxBuffers +GLboolean GL_STEREO g->limits.stereo +GLboolean GL_DOUBLEBUFFER g->limits.doubleBuffer +GLint GL_INDEX_BITS g->limits.indexBits +GLint GL_DEPTH_BITS g->limits.depthBits +GLint GL_RED_BITS g->limits.redBits +GLint GL_GREEN_BITS g->limits.greenBits +GLint GL_BLUE_BITS g->limits.blueBits +GLint GL_ALPHA_BITS g->limits.alphaBits +GLint GL_STENCIL_BITS g->limits.stencilBits +GLint GL_ACCUM_RED_BITS g->limits.accumRedBits +GLint GL_ACCUM_GREEN_BITS g->limits.accumGreenBits +GLint GL_ACCUM_BLUE_BITS g->limits.accumBlueBits +GLint GL_ACCUM_ALPHA_BITS g->limits.accumAlphaBits +GLclampf GL_COLOR_CLEAR_VALUE g->buffer.colorClearValue.r g->buffer.colorClearValue.g g->buffer.colorClearValue.b g->buffer.colorClearValue.a +GLclampf GL_INDEX_CLEAR_VALUE g->buffer.indexClearValue +GLclampd GL_DEPTH_CLEAR_VALUE g->buffer.depthClearValue +GLfloat GL_ACCUM_CLEAR_VALUE g->buffer.accumClearValue.r g->buffer.accumClearValue.g g->buffer.accumClearValue.b g->buffer.accumClearValue.a +GLenum GL_BLEND_SRC g->buffer.blendSrcRGB +GLenum GL_BLEND_DST g->buffer.blendDstRGB +#GLenum GL_BLEND_EQUATION g->buffer.blendEquation +#GLclampf GL_BLEND_COLOR g->buffer.blendColor.r g->buffer.blendColor.g g->buffer.blendColor.b g->buffer.blendColor.a +GLenum GL_DEPTH_FUNC g->buffer.depthFunc +GLenum GL_ALPHA_TEST_FUNC g->buffer.alphaTestFunc +GLint GL_ALPHA_TEST_REF g->buffer.alphaTestRef +GLenum GL_DRAW_BUFFER __getDrawBuffer(g) +GLenum GL_READ_BUFFER __getReadBuffer(g) +GLboolean GL_COLOR_WRITEMASK g->buffer.colorWriteMask.r g->buffer.colorWriteMask.g g->buffer.colorWriteMask.b g->buffer.colorWriteMask.a +GLint GL_INDEX_WRITEMASK g->buffer.indexWriteMask + +GLint GL_LIST_BASE g->lists.base +GLint GL_LIST_INDEX g->lists.currentIndex +GLenum GL_LIST_MODE g->lists.mode + +GLint GL_STENCIL_CLEAR_VALUE g->stencil.clearValue +GLint GL_STENCIL_FAIL g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_FRONT:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].fail +GLint GL_STENCIL_BACK_FAIL g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_BACK:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].fail +GLint GL_STENCIL_FUNC g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_FRONT:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].func +GLint GL_STENCIL_BACK_FUNC g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_BACK:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].func +GLint GL_STENCIL_PASS_DEPTH_FAIL g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_FRONT:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthFail +GLint GL_STENCIL_BACK_PASS_DEPTH_FAIL g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_BACK:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthFail +GLint GL_STENCIL_PASS_DEPTH_PASS g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_FRONT:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthPass +GLint GL_STENCIL_BACK_PASS_DEPTH_PASS g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_BACK:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthPass +GLint GL_STENCIL_REF g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_FRONT:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].ref +GLint GL_STENCIL_BACK_REF g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_BACK:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].ref +GLboolean GL_STENCIL_TEST g->stencil.stencilTest +GLint GL_STENCIL_VALUE_MASK g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_FRONT:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].mask +GLint GL_STENCIL_BACK_VALUE_MASK g->stencil.buffers[g->stencil.activeStencilFace==GL_FRONT?CRSTATE_STENCIL_BUFFER_ID_BACK:CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].mask +GLint GL_STENCIL_WRITEMASK g->stencil.writeMask + +GLfloat GL_CURRENT_INDEX g->current.colorIndex +GLclampf GL_CURRENT_COLOR g->current.vertexAttrib[VERT_ATTRIB_COLOR0][0] g->current.vertexAttrib[VERT_ATTRIB_COLOR0][1] g->current.vertexAttrib[VERT_ATTRIB_COLOR0][2] g->current.vertexAttrib[VERT_ATTRIB_COLOR0][3] +GLclampf GL_CURRENT_NORMAL g->current.vertexAttrib[VERT_ATTRIB_NORMAL][0] g->current.vertexAttrib[VERT_ATTRIB_NORMAL][1] g->current.vertexAttrib[VERT_ATTRIB_NORMAL][2] +GLfloat GL_CURRENT_TEXTURE_COORDS g->current.vertexAttrib[VERT_ATTRIB_TEX0+g->texture.curTextureUnit][0] g->current.vertexAttrib[VERT_ATTRIB_TEX0+g->texture.curTextureUnit][1] g->current.vertexAttrib[VERT_ATTRIB_TEX0+g->texture.curTextureUnit][2] g->current.vertexAttrib[VERT_ATTRIB_TEX0+g->texture.curTextureUnit][3] +GLboolean GL_EDGE_FLAG g->current.edgeFlag + +#?b?ub?s?us?i?ui?f?d GL_CURRENT_RASTER_POSITION g->current.rasterpos?.x g->current.rasterpos?.y g->current.rasterpos?.z g->current.rasterpos?.w +GLfloat GL_CURRENT_RASTER_POSITION g->current.rasterAttrib[VERT_ATTRIB_POS][0] g->current.rasterAttrib[VERT_ATTRIB_POS][1] g->current.rasterAttrib[VERT_ATTRIB_POS][2] g->current.rasterAttrib[VERT_ATTRIB_POS][3] +GLboolean GL_CURRENT_RASTER_POSITION_VALID g->current.rasterValid +#?s?i?f?d GL_CURRENT_RASTER_TEXTURE_COORDS g->current.rastertexture?.s g->current.rastertexture?.t g->current.rastertexture?.p g->current.rastertexture?.q +GLfloat GL_CURRENT_RASTER_TEXTURE_COORDS g->current.rasterAttrib[VERT_ATTRIB_TEX0][0] g->current.rasterAttrib[VERT_ATTRIB_TEX0][1] g->current.rasterAttrib[VERT_ATTRIB_TEX0][2] g->current.rasterAttrib[VERT_ATTRIB_TEX0][3] +#GLclampf?b?ub?s?us?i?ui?f?d GL_CURRENT_RASTER_COLOR g->current.rastercolor?.r g->current.rastercolor?.g g->current.rastercolor?.b g->current.rastercolor?.a +GLfloat GL_CURRENT_RASTER_COLOR g->current.rasterAttrib[VERT_ATTRIB_COLOR0][0] g->current.rasterAttrib[VERT_ATTRIB_COLOR0][1] g->current.rasterAttrib[VERT_ATTRIB_COLOR0][2] g->current.rasterAttrib[VERT_ATTRIB_COLOR0][3] +GLfloat GL_CURRENT_RASTER_DISTANCE g->current.rasterAttrib[VERT_ATTRIB_FOG][0] +GLdouble GL_CURRENT_RASTER_INDEX g->current.rasterIndex + +#GLclampf GL_CURRENT_SECONDARY_COLOR_EXT g->lighting.vertexAttrib[VERT_ATTRIB_COLOR1][0] g->lighting.vertexAttrib[VERT_ATTRIB_COLOR1][1] g->lighting.vertexAttrib[VERT_ATTRIB_COLOR1][2] +#GLint GL_SECONDARY_COLOR_ARRAY_SIZE_EXT +#GLint GL_SECONDARY_COLOR_ARRAY_TYPE_EXT +#GLint GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT + +GLint GL_MAX_VERTEX_ATTRIBS_ARB g->limits.maxVertexProgramAttribs + +# Implementation-dependent limits queries + +GLint GL_MAX_TEXTURE_UNITS_ARB g->limits.maxTextureUnits +GLint GL_MAX_TEXTURE_SIZE g->limits.maxTextureSize +GLint GL_MAX_3D_TEXTURE_SIZE g->limits.max3DTextureSize +GLint GL_MAX_LIGHTS g->limits.maxLights +GLint GL_MAX_CLIP_PLANES g->limits.maxClipPlanes +GLint GL_MAX_PROJECTION_STACK_DEPTH g->limits.maxProjectionStackDepth +GLint GL_MAX_MODELVIEW_STACK_DEPTH g->limits.maxModelviewStackDepth +GLint GL_MAX_TEXTURE_STACK_DEPTH g->limits.maxTextureStackDepth +GLint GL_MAX_COLOR_MATRIX_STACK_DEPTH g->limits.maxColorStackDepth +GLint GL_MAX_ATTRIB_STACK_DEPTH g->limits.maxAttribStackDepth +GLint GL_MAX_CLIENT_ATTRIB_STACK_DEPTH g->limits.maxClientAttribStackDepth +GLint GL_MAX_NAME_STACK_DEPTH g->limits.maxNameStackDepth +GLint GL_MAX_ELEMENTS_INDICES g->limits.maxElementsIndices +GLint GL_MAX_ELEMENTS_VERTICES g->limits.maxElementsVertices +GLint GL_MAX_EVAL_ORDER g->limits.maxEvalOrder +GLint GL_MAX_LIST_NESTING g->limits.maxListNesting +GLint GL_MAX_PIXEL_MAP_TABLE g->limits.maxPixelMapTable +GLint GL_MAX_VIEWPORT_DIMS g->limits.maxViewportDims[0] g->limits.maxViewportDims[1] +GLint GL_SUBPIXEL_BITS g->limits.subpixelBits +GLfloat GL_ALIASED_POINT_SIZE_RANGE g->limits.aliasedPointSizeRange[0] g->limits.aliasedPointSizeRange[1] +GLfloat GL_SMOOTH_POINT_SIZE_RANGE g->limits.smoothPointSizeRange[0] g->limits.smoothPointSizeRange[1] +GLfloat GL_SMOOTH_POINT_SIZE_GRANULARITY g->limits.pointSizeGranularity +GLfloat GL_ALIASED_LINE_WIDTH_RANGE g->limits.aliasedLineWidthRange[0] g->limits.aliasedLineWidthRange[1] +GLfloat GL_SMOOTH_LINE_WIDTH_RANGE g->limits.smoothLineWidthRange[0] g->limits.smoothLineWidthRange[1] +GLfloat GL_SMOOTH_LINE_WIDTH_GRANULARITY g->limits.lineWidthGranularity +GLint GL_RENDER_MODE g->renderMode + +# Feedback + +GLint GL_FEEDBACK_BUFFER_SIZE g->feedback.bufferSize +GLint GL_FEEDBACK_BUFFER_TYPE g->feedback.type +GLint GL_SELECTION_BUFFER_SIZE g->selection.bufferSize + +# FBO +GLint GL_FRAMEBUFFER_BINDING_EXT (g->framebufferobject.drawFB?g->framebufferobject.drawFB->id:0) +GLint GL_READ_FRAMEBUFFER_BINDING (g->framebufferobject.readFB?g->framebufferobject.readFB->id:0) +GLint GL_RENDERBUFFER_BINDING_EXT (g->framebufferobject.renderbuffer?g->framebufferobject.renderbuffer->id:0) + +#CVA +GLint GL_ARRAY_ELEMENT_LOCK_FIRST_EXT g->client.array.lockFirst +GLint GL_ARRAY_ELEMENT_LOCK_COUNT_EXT g->client.array.lockCount + +GLint GL_ACTIVE_STENCIL_FACE_EXT g->stencil.activeStencilFace
\ No newline at end of file diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_getstring.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_getstring.c new file mode 100644 index 00000000..3bee1c3f --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_getstring.c @@ -0,0 +1,55 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "cr_error.h" +#include "cr_version.h" +#include "state.h" +#include "state/cr_statetypes.h" +#include "cr_extstring.h" +#include "cr_mem.h" +#include "cr_string.h" + + +const GLubyte * STATE_APIENTRY crStateGetString( GLenum name ) +{ + CRContext *g = GetCurrentContext(); + if (!g) + return NULL; + + switch( name ) + { + case GL_VENDOR: + return (const GLubyte *) CR_VENDOR; + case GL_RENDERER: + return (const GLubyte *) CR_RENDERER; + case GL_VERSION: + return (const GLubyte *) CR_OPENGL_VERSION_STRING " Chromium " CR_VERSION_STRING; + case GL_EXTENSIONS: + /* This shouldn't normally be queried - the relevant SPU should + * catch this query and do all the extension string merging/mucking. + */ + { + static char *extensions = NULL; + if (!extensions) { + extensions = crAlloc(crStrlen(crExtensions) + crStrlen(crChromiumExtensions) + 2); + crStrcpy(extensions, crExtensions); + crStrcpy(extensions, " "); + crStrcat(extensions, crChromiumExtensions); + } + return (const GLubyte *) extensions; + } +#if defined(CR_ARB_vertex_program) || defined(CR_ARB_fragment_program) + case GL_PROGRAM_ERROR_STRING_ARB: + return g->program.errorString; +#endif + default: + crStateError( __LINE__, __FILE__, GL_INVALID_ENUM, + "calling glGetString() with invalid name" ); + return NULL; + } + + (void) crAppOnlyExtensions; /* silence warnings */ +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c new file mode 100644 index 00000000..5767ca91 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_glsl.c @@ -0,0 +1,1527 @@ +/* $Id: state_glsl.c $ */ + +/** @file + * VBox OpenGL: GLSL state tracking + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#include "state.h" +#include "state/cr_statetypes.h" +#include "state/cr_statefuncs.h" +#include "state_internals.h" +#include "cr_mem.h" +#include "cr_string.h" + +static CRGLSLShader* crStateGetShaderObj(GLuint id) +{ + CRContext *g = GetCurrentContext(); + + if (!g) + { + crWarning("crStateGetShaderObj called without current ctx"); + } + + return !g ? NULL : (CRGLSLShader *) crHashtableSearch(g->glsl.shaders, id); +} + +static CRGLSLProgram* crStateGetProgramObj(GLuint id) +{ + CRContext *g = GetCurrentContext(); + + if (!g) + { + crWarning("crStateGetProgramObj called without current ctx"); + } + + return !g ? NULL : (CRGLSLProgram *) crHashtableSearch(g->glsl.programs, id); +} + +static void crStateFreeGLSLShader(void *data) +{ + CRGLSLShader* pShader = (CRGLSLShader *) data; + + if (pShader->source) + crFree(pShader->source); + + crFree(pShader); +} + +#ifdef IN_GUEST +static void crStateFreeProgramAttribsLocationCache(CRGLSLProgram* pProgram) +{ + if (pProgram->pAttribs) crFree(pProgram->pAttribs); + + pProgram->pAttribs = NULL; + pProgram->cAttribs = 0; +} +#endif + +static void crStateFreeProgramAttribs(CRGLSLProgram* pProgram) +{ + GLuint i; + + for (i=0; i<pProgram->activeState.cAttribs; ++i) + { + crFree(pProgram->activeState.pAttribs[i].name); + } + + for (i=0; i<pProgram->currentState.cAttribs; ++i) + { + crFree(pProgram->currentState.pAttribs[i].name); + } + + if (pProgram->activeState.pAttribs) + crFree(pProgram->activeState.pAttribs); + + if (pProgram->currentState.pAttribs) + crFree(pProgram->currentState.pAttribs); + +#ifdef IN_GUEST + crStateFreeProgramAttribsLocationCache(pProgram); + + pProgram->bAttribsSynced = GL_FALSE; +#endif + +} + +static void crStateFreeProgramUniforms(CRGLSLProgram* pProgram) +{ + GLuint i; + + for (i=0; i<pProgram->cUniforms; ++i) + { + if (pProgram->pUniforms[i].name) crFree(pProgram->pUniforms[i].name); + if (pProgram->pUniforms[i].data) crFree(pProgram->pUniforms[i].data); + } + + if (pProgram->pUniforms) crFree(pProgram->pUniforms); + + pProgram->pUniforms = NULL; + pProgram->cUniforms = 0; + +#ifdef IN_GUEST + pProgram->bUniformsSynced = GL_FALSE; +#endif +} + +static void crStateShaderDecRefCount(void *data) +{ + CRGLSLShader *pShader = (CRGLSLShader *) data; + + CRASSERT(pShader->refCount>0); + + pShader->refCount--; + + if (0==pShader->refCount && pShader->deleted) + { + CRContext *g = GetCurrentContext(); + crHashtableDelete(g->glsl.shaders, pShader->id, crStateFreeGLSLShader); + } +} + +static void crStateFakeDecRefCountCB(unsigned long key, void *data1, void *data2) +{ + CRGLSLShader *pShader = (CRGLSLShader *) data1; + CRContext *ctx = (CRContext*) data2; + CRGLSLShader *pRealShader; + (void) key; (void)ctx; + + pRealShader = crStateGetShaderObj(pShader->id); + + if (pRealShader) + { + crStateShaderDecRefCount(pRealShader); + } + else + { + crWarning("crStateFakeDecRefCountCB: NULL pRealShader"); + } +} + +static void crStateFreeGLSLProgram(void *data) +{ + CRGLSLProgram* pProgram = (CRGLSLProgram *) data; + + crFreeHashtable(pProgram->currentState.attachedShaders, crStateShaderDecRefCount); + + if (pProgram->activeState.attachedShaders) + { + CRContext *g = GetCurrentContext(); + crHashtableWalk(pProgram->activeState.attachedShaders, crStateFakeDecRefCountCB, g); + crFreeHashtable(pProgram->activeState.attachedShaders, crStateFreeGLSLShader); + } + + crStateFreeProgramAttribs(pProgram); + + crStateFreeProgramUniforms(pProgram); + + crFree(pProgram); +} + +DECLEXPORT(void) STATE_APIENTRY crStateGLSLInit(CRContext *ctx) +{ + ctx->glsl.shaders = crAllocHashtable(); + ctx->glsl.programs = crAllocHashtable(); + ctx->glsl.activeProgram = NULL; + ctx->glsl.bResyncNeeded = GL_FALSE; + + if (!ctx->glsl.shaders || !ctx->glsl.programs) + { + crWarning("crStateGLSLInit: Out of memory!"); + return; + } +} + +DECLEXPORT(void) STATE_APIENTRY crStateGLSLDestroy(CRContext *ctx) +{ + CRContext *g = GetCurrentContext(); + + /** @todo hack to allow crStateFreeGLSLProgram to work correctly, + as the current context isn't the one being destroyed*/ +#ifdef CHROMIUM_THREADSAFE + CRASSERT(g != ctx); + VBoxTlsRefAddRef(ctx); /* <- this is a hack to avoid subsequent SetCurrentContext(g) do recursive Destroy for ctx */ + if (g) + VBoxTlsRefAddRef(g); /* <- ensure the g is not destroyed by the following SetCurrentContext call */ + SetCurrentContext(ctx); +#else + __currentContext = ctx; +#endif + + crFreeHashtable(ctx->glsl.programs, crStateFreeGLSLProgram); + crFreeHashtable(ctx->glsl.shaders, crStateFreeGLSLShader); + +#ifdef CHROMIUM_THREADSAFE + SetCurrentContext(g); + if (g) + VBoxTlsRefRelease(g); + VBoxTlsRefRelease(ctx); /* <- restore back the cRefs (see above) */ +#else + __currentContext = g; +#endif + +} + +DECLEXPORT(GLuint) STATE_APIENTRY crStateGetShaderHWID(GLuint id) +{ + CRGLSLShader *pShader = crStateGetShaderObj(id); +#ifdef IN_GUEST + CRASSERT(!pShader || pShader->hwid == id); +#endif + return pShader ? pShader->hwid : 0; +} + +DECLEXPORT(GLuint) STATE_APIENTRY crStateGetProgramHWID(GLuint id) +{ + CRGLSLProgram *pProgram = crStateGetProgramObj(id); +#ifdef IN_GUEST + CRASSERT(!pProgram || pProgram->hwid == id); +#endif + return pProgram ? pProgram->hwid : 0; +} + +static void crStateCheckShaderHWIDCB(unsigned long key, void *data1, void *data2) +{ + CRGLSLShader *pShader = (CRGLSLShader *) data1; + crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2; + (void) key; + + if (pShader->hwid==pParms->hwid) + pParms->id = pShader->id; +} + +static void crStateCheckProgramHWIDCB(unsigned long key, void *data1, void *data2) +{ + CRGLSLProgram *pProgram = (CRGLSLProgram *) data1; + crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2; + (void) key; + + if (pProgram->hwid==pParms->hwid) + pParms->id = pProgram->id; +} + +DECLEXPORT(GLuint) STATE_APIENTRY crStateGLSLShaderHWIDtoID(GLuint hwid) +{ + CRContext *g = GetCurrentContext(); + crCheckIDHWID_t parms; + + parms.id = hwid; + parms.hwid = hwid; + + crHashtableWalk(g->glsl.shaders, crStateCheckShaderHWIDCB, &parms); + return parms.id; +} + +DECLEXPORT(GLuint) STATE_APIENTRY crStateGLSLProgramHWIDtoID(GLuint hwid) +{ + CRContext *g = GetCurrentContext(); + crCheckIDHWID_t parms; + + parms.id = hwid; + parms.hwid = hwid; + + crHashtableWalk(g->glsl.programs, crStateCheckProgramHWIDCB, &parms); + return parms.id; +} + +DECLEXPORT(GLuint) STATE_APIENTRY crStateDeleteObjectARB( VBoxGLhandleARB obj ) +{ + GLuint hwId = crStateGetProgramHWID(obj); + if (hwId) + { + crStateDeleteProgram(obj); + } + else + { + hwId = crStateGetShaderHWID(obj); + crStateDeleteShader(obj); + } + return hwId; +} + +DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateShader(GLuint hwid, GLenum type) +{ + CRGLSLShader *pShader; + CRContext *g = GetCurrentContext(); + GLuint stateId = hwid; + +#ifdef IN_GUEST + CRASSERT(!crStateGetShaderObj(stateId)); +#else + /* the proogram and shader names must not intersect because DeleteObjectARB must distinguish between them + * see crStateDeleteObjectARB + * this is why use programs table for shader keys allocation */ + stateId = crHashtableAllocKeys(g->glsl.programs, 1); + if (!stateId) + { + crWarning("failed to allocate program key"); + return 0; + } + + Assert((pShader = crStateGetShaderObj(stateId)) == NULL); +#endif + + pShader = (CRGLSLShader *) crAlloc(sizeof(*pShader)); + if (!pShader) + { + crWarning("crStateCreateShader: Out of memory!"); + return 0; + } + + pShader->id = stateId; + pShader->hwid = hwid; + pShader->type = type; + pShader->source = NULL; + pShader->compiled = GL_FALSE; + pShader->deleted = GL_FALSE; + pShader->refCount = 0; + + crHashtableAdd(g->glsl.shaders, stateId, pShader); + + return stateId; +} + +DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateProgram(GLuint hwid) +{ + CRGLSLProgram *pProgram; + CRContext *g = GetCurrentContext(); + GLuint stateId = hwid; + +#ifdef IN_GUEST + pProgram = crStateGetProgramObj(stateId); + if (pProgram) + { + crWarning("Program object %d already exists!", stateId); + crStateDeleteProgram(stateId); + CRASSERT(!crStateGetProgramObj(stateId)); + } +#else + stateId = crHashtableAllocKeys(g->glsl.programs, 1); + if (!stateId) + { + crWarning("failed to allocate program key"); + return 0; + } +#endif + + pProgram = (CRGLSLProgram *) crAlloc(sizeof(*pProgram)); + if (!pProgram) + { + crWarning("crStateCreateProgram: Out of memory!"); + return 0; + } + + pProgram->id = stateId; + pProgram->hwid = hwid; + pProgram->validated = GL_FALSE; + pProgram->linked = GL_FALSE; + pProgram->deleted = GL_FALSE; + pProgram->activeState.attachedShaders = NULL; + pProgram->currentState.attachedShaders = crAllocHashtable(); + + pProgram->activeState.cAttribs = 0; + pProgram->activeState.pAttribs = NULL; + pProgram->currentState.cAttribs = 0; + pProgram->currentState.pAttribs = NULL; + + pProgram->pUniforms = NULL; + pProgram->cUniforms = 0; + +#ifdef IN_GUEST + pProgram->pAttribs = NULL; + pProgram->cAttribs = 0; + + pProgram->bUniformsSynced = GL_FALSE; + pProgram->bAttribsSynced = GL_FALSE; +#endif + + crHashtableAdd(g->glsl.programs, stateId, pProgram); + + return stateId; +} + +DECLEXPORT(void) STATE_APIENTRY crStateCompileShader(GLuint shader) +{ + CRGLSLShader *pShader = crStateGetShaderObj(shader); + if (!pShader) + { + crWarning("Unknown shader %d", shader); + return; + } + + pShader->compiled = GL_TRUE; +} + +static void crStateDbgCheckNoProgramOfId(void *data) +{ + (void)data; + crError("Unexpected Program id"); +} + +DECLEXPORT(void) STATE_APIENTRY crStateDeleteShader(GLuint shader) +{ + CRGLSLShader *pShader = crStateGetShaderObj(shader); + if (!pShader) + { + crWarning("Unknown shader %d", shader); + return; + } + + pShader->deleted = GL_TRUE; + + if (0==pShader->refCount) + { + CRContext *g = GetCurrentContext(); + crHashtableDelete(g->glsl.shaders, shader, crStateFreeGLSLShader); + /* since we use programs table for key allocation key allocation, we need to + * free the key in the programs table. + * See comment in crStateCreateShader */ + crHashtableDelete(g->glsl.programs, shader, crStateDbgCheckNoProgramOfId); + } +} + +DECLEXPORT(void) STATE_APIENTRY crStateAttachShader(GLuint program, GLuint shader) +{ + CRGLSLProgram *pProgram = crStateGetProgramObj(program); + CRGLSLShader *pShader; + + if (!pProgram) + { + crWarning("Unknown program %d", program); + return; + } + + if (crHashtableSearch(pProgram->currentState.attachedShaders, shader)) + { + /*shader already attached to this program*/ + return; + } + + pShader = crStateGetShaderObj(shader); + + if (!pShader) + { + crWarning("Unknown shader %d", shader); + return; + } + + pShader->refCount++; + + crHashtableAdd(pProgram->currentState.attachedShaders, shader, pShader); +} + +DECLEXPORT(void) STATE_APIENTRY crStateDetachShader(GLuint program, GLuint shader) +{ + CRGLSLProgram *pProgram = crStateGetProgramObj(program); + CRGLSLShader *pShader; + + if (!pProgram) + { + crWarning("Unknown program %d", program); + return; + } + + pShader = (CRGLSLShader *) crHashtableSearch(pProgram->currentState.attachedShaders, shader); + if (!pShader) + { + crWarning("Shader %d isn't attached to program %d", shader, program); + return; + } + + crHashtableDelete(pProgram->currentState.attachedShaders, shader, NULL); + + CRASSERT(pShader->refCount>0); + pShader->refCount--; + + if (0==pShader->refCount) + { + CRContext *g = GetCurrentContext(); + crHashtableDelete(g->glsl.shaders, shader, crStateFreeGLSLShader); + } +} + +DECLEXPORT(void) STATE_APIENTRY crStateUseProgram(GLuint program) +{ + CRContext *g = GetCurrentContext(); + + if (program>0) + { + CRGLSLProgram *pProgram = crStateGetProgramObj(program); + + if (!pProgram) + { + crWarning("Unknown program %d", program); + return; + } + + g->glsl.activeProgram = pProgram; + } + else + { + g->glsl.activeProgram = NULL; + } +} + +DECLEXPORT(void) STATE_APIENTRY crStateDeleteProgram(GLuint program) +{ + CRContext *g = GetCurrentContext(); + CRGLSLProgram *pProgram = crStateGetProgramObj(program); + + if (!pProgram) + { + crWarning("Unknown program %d", program); + return; + } + + if (g->glsl.activeProgram == pProgram) + { + g->glsl.activeProgram = NULL; + } + + crHashtableDelete(g->glsl.programs, program, crStateFreeGLSLProgram); +} + +DECLEXPORT(void) STATE_APIENTRY crStateValidateProgram(GLuint program) +{ + CRGLSLProgram *pProgram = crStateGetProgramObj(program); + + if (!pProgram) + { + crWarning("Unknown program %d", program); + return; + } + + pProgram->validated = GL_TRUE; +} + +static void crStateCopyShaderCB(unsigned long key, void *data1, void *data2) +{ + CRGLSLShader *pRealShader = (CRGLSLShader *) data1; + CRGLSLProgram *pProgram = (CRGLSLProgram *) data2; + CRGLSLShader *pShader; + GLint sLen=0; + + CRASSERT(pRealShader); + pRealShader->refCount++; + + pShader = (CRGLSLShader *) crAlloc(sizeof(*pShader)); + if (!pShader) + { + crWarning("crStateCopyShaderCB: Out of memory!"); + return; + } + + crMemcpy(pShader, pRealShader, sizeof(*pShader)); + + diff_api.GetShaderiv(pShader->hwid, GL_SHADER_SOURCE_LENGTH, &sLen); + if (sLen>0) + { + pShader->source = (GLchar*) crAlloc(sLen); + diff_api.GetShaderSource(pShader->hwid, sLen, NULL, pShader->source); + } + + crHashtableAdd(pProgram->activeState.attachedShaders, key, pShader); +} + +DECLEXPORT(void) STATE_APIENTRY crStateLinkProgram(GLuint program) +{ + CRGLSLProgram *pProgram = crStateGetProgramObj(program); + GLuint i; + + if (!pProgram) + { + crWarning("Unknown program %d", program); + return; + } + + pProgram->linked = GL_TRUE; + + /*Free program's active state*/ + if (pProgram->activeState.attachedShaders) + { + crHashtableWalk(pProgram->activeState.attachedShaders, crStateFakeDecRefCountCB, NULL); + crFreeHashtable(pProgram->activeState.attachedShaders, crStateFreeGLSLShader); + pProgram->activeState.attachedShaders = NULL; + } + for (i=0; i<pProgram->activeState.cAttribs; ++i) + { + crFree(pProgram->activeState.pAttribs[i].name); + } + if (pProgram->activeState.pAttribs) crFree(pProgram->activeState.pAttribs); + + /*copy current state to active state*/ + crMemcpy(&pProgram->activeState, &pProgram->currentState, sizeof(CRGLSLProgramState)); + + pProgram->activeState.attachedShaders = crAllocHashtable(); + if (!pProgram->activeState.attachedShaders) + { + crWarning("crStateLinkProgram: Out of memory!"); + return; + } + crHashtableWalk(pProgram->currentState.attachedShaders, crStateCopyShaderCB, pProgram); + + /*that's not a bug, note the memcpy above*/ + if (pProgram->activeState.pAttribs) + { + pProgram->activeState.pAttribs = (CRGLSLAttrib *) crAlloc(pProgram->activeState.cAttribs * sizeof(CRGLSLAttrib)); + } + + for (i=0; i<pProgram->activeState.cAttribs; ++i) + { + crMemcpy(&pProgram->activeState.pAttribs[i], &pProgram->currentState.pAttribs[i], sizeof(CRGLSLAttrib)); + pProgram->activeState.pAttribs[i].name = crStrdup(pProgram->currentState.pAttribs[i].name); + } + +#ifdef IN_GUEST + crStateFreeProgramAttribsLocationCache(pProgram); +#endif + + crStateFreeProgramUniforms(pProgram); +} + +DECLEXPORT(void) STATE_APIENTRY crStateBindAttribLocation(GLuint program, GLuint index, const char * name) +{ + CRGLSLProgram *pProgram = crStateGetProgramObj(program); + GLuint i; + CRGLSLAttrib *pAttribs; + + if (!pProgram) + { + crWarning("Unknown program %d", program); + return; + } + + if (index>=CR_MAX_VERTEX_ATTRIBS) + { + crWarning("crStateBindAttribLocation: Index too big %d", index); + return; + } + + for (i=0; i<pProgram->currentState.cAttribs; ++i) + { + if (!crStrcmp(pProgram->currentState.pAttribs[i].name, name)) + { + pProgram->currentState.pAttribs[i].index = index; + return; + } + } + + pAttribs = (CRGLSLAttrib*) crAlloc((pProgram->currentState.cAttribs+1)*sizeof(CRGLSLAttrib)); + if (!pAttribs) + { + crWarning("crStateBindAttribLocation: Out of memory!"); + return; + } + + if (pProgram->currentState.cAttribs) + { + crMemcpy(&pAttribs[0], &pProgram->currentState.pAttribs[0], pProgram->currentState.cAttribs*sizeof(CRGLSLAttrib)); + } + pAttribs[pProgram->currentState.cAttribs].index = index; + pAttribs[pProgram->currentState.cAttribs].name = crStrdup(name); + + pProgram->currentState.cAttribs++; + if (pProgram->currentState.pAttribs) crFree(pProgram->currentState.pAttribs); + pProgram->currentState.pAttribs = pAttribs; +} + +DECLEXPORT(GLint) STATE_APIENTRY crStateGetUniformSize(GLenum type) +{ + GLint size; + + switch (type) + { + case GL_FLOAT: + size = 1; + break; + case GL_FLOAT_VEC2: + size = 2; + break; + case GL_FLOAT_VEC3: + size = 3; + break; + case GL_FLOAT_VEC4: + size = 4; + break; + case GL_INT: + size = 1; + break; + case GL_INT_VEC2: + size = 2; + break; + case GL_INT_VEC3: + size = 3; + break; + case GL_INT_VEC4: + size = 4; + break; + case GL_BOOL: + size = 1; + break; + case GL_BOOL_VEC2: + size = 2; + break; + case GL_BOOL_VEC3: + size = 3; + break; + case GL_BOOL_VEC4: + size = 4; + break; + case GL_FLOAT_MAT2: + size = 8; + break; + case GL_FLOAT_MAT3: + size = 12; + break; + case GL_FLOAT_MAT4: + size = 16; + break; + case GL_SAMPLER_1D: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_1D_SHADOW: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_2D_RECT_ARB: + case GL_SAMPLER_2D_RECT_SHADOW_ARB: + size = 1; + break; +#ifdef CR_OPENGL_VERSION_2_1 + case GL_FLOAT_MAT2x3: + size = 8; + break; + case GL_FLOAT_MAT2x4: + size = 8; + break; + case GL_FLOAT_MAT3x2: + size = 12; + break; + case GL_FLOAT_MAT3x4: + size = 12; + break; + case GL_FLOAT_MAT4x2: + size = 16; + break; + case GL_FLOAT_MAT4x3: + size = 16; + break; +#endif + default: + crWarning("crStateGetUniformSize: unknown uniform type 0x%x", (GLint)type); + size = 16; + break; + } + + return size; +} + +DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsIntUniform(GLenum type) +{ + if (GL_INT==type + || GL_INT_VEC2==type + || GL_INT_VEC3==type + || GL_INT_VEC4==type + || GL_BOOL==type + || GL_BOOL_VEC2==type + || GL_BOOL_VEC3==type + || GL_BOOL_VEC4==type + || GL_SAMPLER_1D==type + || GL_SAMPLER_2D==type + || GL_SAMPLER_3D==type + || GL_SAMPLER_CUBE==type + || GL_SAMPLER_1D_SHADOW==type + || GL_SAMPLER_2D_SHADOW==type + || GL_SAMPLER_2D_RECT_ARB==type + || GL_SAMPLER_2D_RECT_SHADOW_ARB==type) + { + return GL_TRUE; + } + else return GL_FALSE; +} + +DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsProgramUniformsCached(GLuint program) +{ + CRGLSLProgram *pProgram = crStateGetProgramObj(program); + + if (!pProgram) + { + WARN(("Unknown program %d", program)); + return GL_FALSE; + } + +#ifdef IN_GUEST + return pProgram->bUniformsSynced; +#else + WARN(("crStateIsProgramUniformsCached called on host side!!")); + return GL_FALSE; +#endif +} + +DECLEXPORT(GLboolean) STATE_APIENTRY crStateIsProgramAttribsCached(GLuint program) +{ + CRGLSLProgram *pProgram = crStateGetProgramObj(program); + + if (!pProgram) + { + WARN(("Unknown program %d", program)); + return GL_FALSE; + } + +#ifdef IN_GUEST + return pProgram->bAttribsSynced; +#else + WARN(("crStateIsProgramAttribsCached called on host side!!")); + return GL_FALSE; +#endif +} + +/** @todo one of those functions should ignore uniforms starting with "gl"*/ + +#ifdef IN_GUEST +DECLEXPORT(void) STATE_APIENTRY +crStateGLSLProgramCacheUniforms(GLuint program, GLsizei cbData, GLvoid *pData) +{ + CRGLSLProgram *pProgram = crStateGetProgramObj(program); + char *pCurrent = pData; + GLsizei cbRead, cbName; + GLuint i; + + if (!pProgram) + { + crWarning("Unknown program %d", program); + return; + } + + if (pProgram->bUniformsSynced) + { + crWarning("crStateGLSLProgramCacheUniforms: this shouldn't happen!"); + crStateFreeProgramUniforms(pProgram); + } + + if (cbData<(GLsizei)sizeof(GLsizei)) + { + crWarning("crStateGLSLProgramCacheUniforms: data too short"); + return; + } + + pProgram->cUniforms = ((GLsizei*)pCurrent)[0]; + pCurrent += sizeof(GLsizei); + cbRead = sizeof(GLsizei); + + /*crDebug("crStateGLSLProgramCacheUniforms: %i active uniforms", pProgram->cUniforms);*/ + + if (pProgram->cUniforms) + { + pProgram->pUniforms = crAlloc(pProgram->cUniforms*sizeof(CRGLSLUniform)); + if (!pProgram->pUniforms) + { + crWarning("crStateGLSLProgramCacheUniforms: no memory"); + pProgram->cUniforms = 0; + return; + } + } + + for (i=0; i<pProgram->cUniforms; ++i) + { + cbRead += sizeof(GLuint)+sizeof(GLsizei); + if (cbRead>cbData) + { + crWarning("crStateGLSLProgramCacheUniforms: out of data reading uniform %i", i); + return; + } + pProgram->pUniforms[i].data = NULL; + pProgram->pUniforms[i].location = ((GLint*)pCurrent)[0]; + pCurrent += sizeof(GLint); + cbName = ((GLsizei*)pCurrent)[0]; + pCurrent += sizeof(GLsizei); + + cbRead += cbName; + if (cbRead>cbData) + { + crWarning("crStateGLSLProgramCacheUniforms: out of data reading uniform's name %i", i); + return; + } + + pProgram->pUniforms[i].name = crStrndup(pCurrent, cbName); + pCurrent += cbName; + + /*crDebug("crStateGLSLProgramCacheUniforms: uniform[%i]=%d, %s", i, pProgram->pUniforms[i].location, pProgram->pUniforms[i].name);*/ + } + + pProgram->bUniformsSynced = GL_TRUE; + + CRASSERT((pCurrent-((char*)pData))==cbRead); + CRASSERT(cbRead==cbData); +} + +DECLEXPORT(void) STATE_APIENTRY +crStateGLSLProgramCacheAttribs(GLuint program, GLsizei cbData, GLvoid *pData) +{ + CRGLSLProgram *pProgram = crStateGetProgramObj(program); + char *pCurrent = pData; + GLsizei cbRead, cbName; + GLuint i; + + if (!pProgram) + { + WARN(("Unknown program %d", program)); + return; + } + + if (pProgram->bAttribsSynced) + { + WARN(("crStateGLSLProgramCacheAttribs: this shouldn't happen!")); + crStateFreeProgramAttribsLocationCache(pProgram); + } + + if (cbData<(GLsizei)sizeof(GLsizei)) + { + WARN(("crStateGLSLProgramCacheAttribs: data too short")); + return; + } + + pProgram->cAttribs = ((GLsizei*)pCurrent)[0]; + pCurrent += sizeof(GLsizei); + cbRead = sizeof(GLsizei); + + crDebug("crStateGLSLProgramCacheAttribs: %i active attribs", pProgram->cAttribs); + + if (pProgram->cAttribs) + { + pProgram->pAttribs = crAlloc(pProgram->cAttribs*sizeof(CRGLSLAttrib)); + if (!pProgram->pAttribs) + { + WARN(("crStateGLSLProgramCacheAttribs: no memory")); + pProgram->cAttribs = 0; + return; + } + } + + for (i=0; i<pProgram->cAttribs; ++i) + { + cbRead += sizeof(GLuint)+sizeof(GLsizei); + if (cbRead>cbData) + { + crWarning("crStateGLSLProgramCacheAttribs: out of data reading attrib %i", i); + return; + } + pProgram->pAttribs[i].index = ((GLint*)pCurrent)[0]; + pCurrent += sizeof(GLint); + cbName = ((GLsizei*)pCurrent)[0]; + pCurrent += sizeof(GLsizei); + + cbRead += cbName; + if (cbRead>cbData) + { + crWarning("crStateGLSLProgramCacheAttribs: out of data reading attrib's name %i", i); + return; + } + + pProgram->pAttribs[i].name = crStrndup(pCurrent, cbName); + pCurrent += cbName; + + crDebug("crStateGLSLProgramCacheAttribs: attribs[%i]=%d, %s", i, pProgram->pAttribs[i].index, pProgram->pAttribs[i].name); + } + + pProgram->bAttribsSynced = GL_TRUE; + + CRASSERT((pCurrent-((char*)pData))==cbRead); + CRASSERT(cbRead==cbData); +} +#else /* IN_GUEST */ +static GLboolean crStateGLSLProgramCacheOneUniform(GLuint location, GLsizei cbName, GLchar *pName, + char **pCurrent, GLsizei *pcbWritten, GLsizei maxcbData) +{ + *pcbWritten += sizeof(GLint)+sizeof(GLsizei)+cbName; + if (*pcbWritten>maxcbData) + { + crWarning("crStateGLSLProgramCacheUniforms: buffer too small"); + crFree(pName); + return GL_FALSE; + } + + /*crDebug("crStateGLSLProgramCacheUniforms: uniform[%i]=%s.", location, pName);*/ + + ((GLint*)*pCurrent)[0] = location; + *pCurrent += sizeof(GLint); + ((GLsizei*)*pCurrent)[0] = cbName; + *pCurrent += sizeof(GLsizei); + crMemcpy(*pCurrent, pName, cbName); + *pCurrent += cbName; + + return GL_TRUE; +} + +DECLEXPORT(void) STATE_APIENTRY +crStateGLSLProgramCacheUniforms(GLuint program, GLsizei maxcbData, GLsizei *cbData, GLvoid *pData) +{ + CRGLSLProgram *pProgram = crStateGetProgramObj(program); + GLint maxUniformLen = 0, activeUniforms=0, fakeUniformsCount, i, j; + char *pCurrent = pData; + GLsizei cbWritten; + + if (!pProgram) + { + crWarning("Unknown program %d", program); + return; + } + + /* + * OpenGL spec says about GL_ACTIVE_UNIFORM_MAX_LENGTH: + * "If no active uniform variable exist, 0 is returned." + */ + diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen); + if (maxUniformLen > 0) + diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORMS, &activeUniforms); + + *cbData = 0; + + cbWritten = sizeof(GLsizei); + if (cbWritten>maxcbData) + { + crWarning("crStateGLSLProgramCacheUniforms: buffer too small"); + return; + } + ((GLsizei*)pCurrent)[0] = activeUniforms; + fakeUniformsCount = activeUniforms; + pCurrent += sizeof(GLsizei); + + crDebug("crStateGLSLProgramCacheUniforms: %i active uniforms", activeUniforms); + + if (activeUniforms>0) + { + /*+8 to make sure our array uniforms with higher indices and [] will fit in as well*/ + GLchar *name = (GLchar *) crAlloc(maxUniformLen+8); + GLenum type; + GLint size; + GLsizei cbName; + GLint location; + + if (!name) + { + crWarning("crStateGLSLProgramCacheUniforms: no memory"); + return; + } + + for (i=0; i<activeUniforms; ++i) + { + diff_api.GetActiveUniform(pProgram->hwid, i, maxUniformLen, &cbName, &size, &type, name); + location = diff_api.GetUniformLocation(pProgram->hwid, name); + + if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData)) + return; + + /* Only one active uniform variable will be reported for a uniform array by glGetActiveUniform, + * so we insert fake elements for other array elements. + */ + if (size!=1) + { + char *pIndexStr = crStrchr(name, '['); + GLint firstIndex=1; + fakeUniformsCount += size; + + crDebug("crStateGLSLProgramCacheUniforms: expanding array uniform, size=%i", size); + + /*For array uniforms it's valid to query location of 1st element as both uniform and uniform[0]. + *The name returned by glGetActiveUniform is driver dependent, + *atleast it's with [0] on win/ati and without [0] on linux/nvidia. + */ + if (!pIndexStr) + { + pIndexStr = name+cbName; + firstIndex=0; + } + else + { + cbName = pIndexStr-name; + if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData)) + return; + } + + for (j=firstIndex; j<size; ++j) + { + sprintf(pIndexStr, "[%i]", j); + cbName = crStrlen(name); + + location = diff_api.GetUniformLocation(pProgram->hwid, name); + + if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData)) + return; + } + } + } + + crFree(name); + } + + if (fakeUniformsCount!=activeUniforms) + { + ((GLsizei*)pData)[0] = fakeUniformsCount; + crDebug("FakeCount %i", fakeUniformsCount); + } + + *cbData = cbWritten; + + CRASSERT((pCurrent-((char*)pData))==cbWritten); +} + +static GLboolean crStateGLSLProgramCacheOneAttrib(GLuint location, GLsizei cbName, GLchar *pName, + char **pCurrent, GLsizei *pcbWritten, GLsizei maxcbData) +{ + *pcbWritten += sizeof(GLint)+sizeof(GLsizei)+cbName; + if (*pcbWritten>maxcbData) + { + WARN(("crStateGLSLProgramCacheOneAttrib: buffer too small")); + crFree(pName); + return GL_FALSE; + } + + crDebug("crStateGLSLProgramCacheOneAttrib: attrib[%i]=%s.", location, pName); + + ((GLint*)*pCurrent)[0] = location; + *pCurrent += sizeof(GLint); + ((GLsizei*)*pCurrent)[0] = cbName; + *pCurrent += sizeof(GLsizei); + crMemcpy(*pCurrent, pName, cbName); + *pCurrent += cbName; + + return GL_TRUE; +} + +DECLEXPORT(void) STATE_APIENTRY +crStateGLSLProgramCacheAttribs(GLuint program, GLsizei maxcbData, GLsizei *cbData, GLvoid *pData) +{ + CRGLSLProgram *pProgram = crStateGetProgramObj(program); + GLint maxAttribLen, activeAttribs=0, fakeAttribsCount, i, j; + char *pCurrent = pData; + GLsizei cbWritten; + + if (!pProgram) + { + crWarning("Unknown program %d", program); + return; + } + + diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttribLen); + diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_ATTRIBUTES, &activeAttribs); + + *cbData = 0; + + cbWritten = sizeof(GLsizei); + if (cbWritten>maxcbData) + { + crWarning("crStateGLSLProgramCacheAttribs: buffer too small"); + return; + } + ((GLsizei*)pCurrent)[0] = activeAttribs; + fakeAttribsCount = activeAttribs; + pCurrent += sizeof(GLsizei); + + crDebug("crStateGLSLProgramCacheAttribs: %i active attribs", activeAttribs); + + if (activeAttribs>0) + { + /*+8 to make sure our array attribs with higher indices and [] will fit in as well*/ + GLchar *name = (GLchar *) crAlloc(maxAttribLen+8); + GLenum type; + GLint size; + GLsizei cbName; + GLint location; + + if (!name) + { + crWarning("crStateGLSLProgramCacheAttribs: no memory"); + return; + } + + for (i=0; i<activeAttribs; ++i) + { + diff_api.GetActiveAttrib(pProgram->hwid, i, maxAttribLen, &cbName, &size, &type, name); + location = diff_api.GetAttribLocation(pProgram->hwid, name); + + if (!crStateGLSLProgramCacheOneAttrib(location, cbName, name, &pCurrent, &cbWritten, maxcbData)) + return; + + /* Only one active attrib variable will be reported for a attrib array by glGetActiveAttrib, + * so we insert fake elements for other array elements. + */ + if (size!=1) + { + char *pIndexStr = crStrchr(name, '['); + GLint firstIndex=1; + fakeAttribsCount += size; + + crDebug("crStateGLSLProgramCacheAttribs: expanding array attrib, size=%i", size); + + /*For array attribs it's valid to query location of 1st element as both attrib and attrib[0]. + *The name returned by glGetActiveAttrib is driver dependent, + *atleast it's with [0] on win/ati and without [0] on linux/nvidia. + */ + if (!pIndexStr) + { + pIndexStr = name+cbName; + firstIndex=0; + } + else + { + cbName = pIndexStr-name; + if (!crStateGLSLProgramCacheOneAttrib(location, cbName, name, &pCurrent, &cbWritten, maxcbData)) + return; + } + + for (j=firstIndex; j<size; ++j) + { + sprintf(pIndexStr, "[%i]", j); + cbName = crStrlen(name); + + location = diff_api.GetAttribLocation(pProgram->hwid, name); + + if (!crStateGLSLProgramCacheOneAttrib(location, cbName, name, &pCurrent, &cbWritten, maxcbData)) + return; + } + } + } + + crFree(name); + } + + if (fakeAttribsCount!=activeAttribs) + { + ((GLsizei*)pData)[0] = fakeAttribsCount; + crDebug("FakeCount %i", fakeAttribsCount); + } + + *cbData = cbWritten; + + CRASSERT((pCurrent-((char*)pData))==cbWritten); +} +#endif + +DECLEXPORT(GLint) STATE_APIENTRY crStateGetUniformLocation(GLuint program, const char * name) +{ +#ifdef IN_GUEST + CRGLSLProgram *pProgram = crStateGetProgramObj(program); + GLint result=-1; + GLuint i; + + if (!pProgram) + { + crWarning("Unknown program %d", program); + return -1; + } + + if (!pProgram->bUniformsSynced) + { + crWarning("crStateGetUniformLocation called for uncached uniforms"); + return -1; + } + + for (i=0; i<pProgram->cUniforms; ++i) + { + if (!crStrcmp(name, pProgram->pUniforms[i].name)) + { + result = pProgram->pUniforms[i].location; + break; + } + } + + return result; +#else + crWarning("crStateGetUniformLocation called on host side!!"); + return -1; +#endif +} + +DECLEXPORT(GLint) STATE_APIENTRY crStateGetAttribLocation(GLuint program, const char * name) +{ +#ifdef IN_GUEST + CRGLSLProgram *pProgram = crStateGetProgramObj(program); + GLint result=-1; + GLuint i; + + if (!pProgram) + { + WARN(("Unknown program %d", program)); + return -1; + } + + if (!pProgram->bAttribsSynced) + { + WARN(("crStateGetAttribLocation called for uncached attribs")); + return -1; + } + + for (i=0; i<pProgram->cAttribs; ++i) + { + if (!crStrcmp(name, pProgram->pAttribs[i].name)) + { + result = pProgram->pAttribs[i].index; + break; + } + } + + return result; +#else + crWarning("crStateGetAttribLocation called on host side!!"); + return -1; +#endif +} + +static void crStateGLSLCreateShadersCB(unsigned long key, void *data1, void *data2) +{ + CRGLSLShader *pShader = (CRGLSLShader*) data1; + CRContext *ctx = (CRContext *) data2; + (void)ctx; (void)key; + + pShader->hwid = diff_api.CreateShader(pShader->type); +} + +static void crStateFixAttachedShaderHWIDsCB(unsigned long key, void *data1, void *data2) +{ + CRGLSLShader *pShader = (CRGLSLShader*) data1; + CRGLSLShader *pRealShader; + CRContext *pCtx = (CRContext *) data2; + + pRealShader = (CRGLSLShader *) crHashtableSearch(pCtx->glsl.shaders, key); + CRASSERT(pRealShader); + + pShader->hwid = pRealShader->hwid; +} + +static void crStateGLSLSyncShadersCB(unsigned long key, void *data1, void *data2) +{ + CRGLSLShader *pShader = (CRGLSLShader*) data1; + (void) key; + (void) data2; + + if (pShader->source) + { + diff_api.ShaderSource(pShader->hwid, 1, (const char**)&pShader->source, NULL); + if (pShader->compiled) + diff_api.CompileShader(pShader->hwid); + crFree(pShader->source); + pShader->source = NULL; + } + + if (pShader->deleted) + diff_api.DeleteShader(pShader->hwid); +} + +static void crStateAttachShaderCB(unsigned long key, void *data1, void *data2) +{ + CRGLSLShader *pShader = (CRGLSLShader*) data1; + CRGLSLProgram *pProgram = (CRGLSLProgram *) data2; + (void) key; + + if (pShader->source) + { + diff_api.ShaderSource(pShader->hwid, 1, (const char**)&pShader->source, NULL); + if (pShader->compiled) + diff_api.CompileShader(pShader->hwid); + } + + diff_api.AttachShader(pProgram->hwid, pShader->hwid); +} + +static void crStateDetachShaderCB(unsigned long key, void *data1, void *data2) +{ + CRGLSLShader *pShader = (CRGLSLShader*) data1; + CRGLSLProgram *pProgram = (CRGLSLProgram *) data2; + (void) key; + + diff_api.DetachShader(pProgram->hwid, pShader->hwid); +} + +static void crStateGLSLCreateProgramCB(unsigned long key, void *data1, void *data2) +{ + CRGLSLProgram *pProgram = (CRGLSLProgram*) data1; + CRContext *ctx = (CRContext *) data2; + GLuint i; + (void)key; + + pProgram->hwid = diff_api.CreateProgram(); + + if (pProgram->linked) + { + CRASSERT(pProgram->activeState.attachedShaders); + + crHashtableWalk(pProgram->activeState.attachedShaders, crStateFixAttachedShaderHWIDsCB, ctx); + crHashtableWalk(pProgram->activeState.attachedShaders, crStateAttachShaderCB, pProgram); + + for (i=0; i<pProgram->activeState.cAttribs; ++i) + { + diff_api.BindAttribLocation(pProgram->hwid, pProgram->activeState.pAttribs[i].index, pProgram->activeState.pAttribs[i].name); + } + + if (pProgram->validated) + diff_api.ValidateProgram(pProgram->hwid); + + diff_api.LinkProgram(pProgram->hwid); + } + + diff_api.UseProgram(pProgram->hwid); + + for (i=0; i<pProgram->cUniforms; ++i) + { + GLint location; + GLfloat *pFdata = (GLfloat*)pProgram->pUniforms[i].data; + GLint *pIdata = (GLint*)pProgram->pUniforms[i].data; + + location = diff_api.GetUniformLocation(pProgram->hwid, pProgram->pUniforms[i].name); + switch (pProgram->pUniforms[i].type) + { + case GL_FLOAT: + diff_api.Uniform1fv(location, 1, pFdata); + break; + case GL_FLOAT_VEC2: + diff_api.Uniform2fv(location, 1, pFdata); + break; + case GL_FLOAT_VEC3: + diff_api.Uniform3fv(location, 1, pFdata); + break; + case GL_FLOAT_VEC4: + diff_api.Uniform4fv(location, 1, pFdata); + break; + case GL_INT: + case GL_BOOL: + diff_api.Uniform1iv(location, 1, pIdata); + break; + case GL_INT_VEC2: + case GL_BOOL_VEC2: + diff_api.Uniform2iv(location, 1, pIdata); + break; + case GL_INT_VEC3: + case GL_BOOL_VEC3: + diff_api.Uniform3iv(location, 1, pIdata); + break; + case GL_INT_VEC4: + case GL_BOOL_VEC4: + diff_api.Uniform4iv(location, 1, pIdata); + break; + case GL_FLOAT_MAT2: + diff_api.UniformMatrix2fv(location, 1, GL_FALSE, pFdata); + break; + case GL_FLOAT_MAT3: + diff_api.UniformMatrix3fv(location, 1, GL_FALSE, pFdata); + break; + case GL_FLOAT_MAT4: + diff_api.UniformMatrix4fv(location, 1, GL_FALSE, pFdata); + break; + case GL_SAMPLER_1D: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_1D_SHADOW: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_2D_RECT_ARB: + case GL_SAMPLER_2D_RECT_SHADOW_ARB: + diff_api.Uniform1iv(location, 1, pIdata); + break; +#ifdef CR_OPENGL_VERSION_2_1 + case GL_FLOAT_MAT2x3: + diff_api.UniformMatrix2x3fv(location, 1, GL_FALSE, pFdata); + break; + case GL_FLOAT_MAT2x4: + diff_api.UniformMatrix2x4fv(location, 1, GL_FALSE, pFdata); + break; + case GL_FLOAT_MAT3x2: + diff_api.UniformMatrix3x2fv(location, 1, GL_FALSE, pFdata); + break; + case GL_FLOAT_MAT3x4: + diff_api.UniformMatrix3x4fv(location, 1, GL_FALSE, pFdata); + break; + case GL_FLOAT_MAT4x2: + diff_api.UniformMatrix4x2fv(location, 1, GL_FALSE, pFdata); + break; + case GL_FLOAT_MAT4x3: + diff_api.UniformMatrix4x3fv(location, 1, GL_FALSE, pFdata); + break; +#endif + default: + crWarning("crStateGLSLCreateProgramCB: unknown uniform type 0x%x", (GLint)pProgram->pUniforms[i].type); + break; + } + crFree(pProgram->pUniforms[i].data); + crFree(pProgram->pUniforms[i].name); + } /*for (i=0; i<pProgram->cUniforms; ++i)*/ + if (pProgram->pUniforms) crFree(pProgram->pUniforms); + pProgram->pUniforms = NULL; + pProgram->cUniforms = 0; + + crHashtableWalk(pProgram->activeState.attachedShaders, crStateDetachShaderCB, pProgram); + crHashtableWalk(pProgram->currentState.attachedShaders, crStateAttachShaderCB, pProgram); +} + +DECLEXPORT(void) STATE_APIENTRY crStateGLSLSwitch(CRContext *from, CRContext *to) +{ + GLboolean fForceUseProgramSet = GL_FALSE; + if (to->glsl.bResyncNeeded) + { + to->glsl.bResyncNeeded = GL_FALSE; + + crHashtableWalk(to->glsl.shaders, crStateGLSLCreateShadersCB, to); + + crHashtableWalk(to->glsl.programs, crStateGLSLCreateProgramCB, to); + + /* crStateGLSLCreateProgramCB changes the current program, ensure we have the proper program re-sored */ + fForceUseProgramSet = GL_TRUE; + + crHashtableWalk(to->glsl.shaders, crStateGLSLSyncShadersCB, NULL); + } + + if (to->glsl.activeProgram != from->glsl.activeProgram || fForceUseProgramSet) + { + diff_api.UseProgram(to->glsl.activeProgram ? to->glsl.activeProgram->hwid : 0); + } +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_hint.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_hint.c new file mode 100644 index 00000000..a3989258 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_hint.c @@ -0,0 +1,132 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include <stdio.h> +#include "state.h" +#include "state/cr_statetypes.h" +#include "state_internals.h" + +void crStateHintInit (CRContext *ctx) +{ + CRHintState *h = &ctx->hint; + CRStateBits *sb = GetCurrentBits(); + CRHintBits *hb = &(sb->hint); + + h->perspectiveCorrection = GL_DONT_CARE; + RESET(hb->perspectiveCorrection, ctx->bitid); + h->pointSmooth = GL_DONT_CARE; + RESET(hb->pointSmooth, ctx->bitid); + h->lineSmooth = GL_DONT_CARE; + RESET(hb->lineSmooth, ctx->bitid); + h->polygonSmooth = GL_DONT_CARE; + RESET(hb->polygonSmooth, ctx->bitid); + h->fog = GL_DONT_CARE; + RESET(hb->fog, ctx->bitid); +#ifdef CR_EXT_clip_volume_hint + h->clipVolumeClipping = GL_DONT_CARE; + RESET(hb->clipVolumeClipping, ctx->bitid); +#endif +#ifdef CR_ARB_texture_compression + h->textureCompression = GL_DONT_CARE; + RESET(hb->textureCompression, ctx->bitid); +#endif +#ifdef CR_SGIS_generate_mipmap + h->generateMipmap = GL_DONT_CARE; + RESET(hb->generateMipmap, ctx->bitid); +#endif + RESET(hb->dirty, ctx->bitid); +} + +void STATE_APIENTRY crStateHint(GLenum target, GLenum mode) +{ + CRContext *g = GetCurrentContext(); + CRHintState *h = &(g->hint); + CRStateBits *sb = GetCurrentBits(); + CRHintBits *hb = &(sb->hint); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glHint called in Begin/End"); + return; + } + + FLUSH(); + + if (mode != GL_FASTEST && mode != GL_NICEST && mode != GL_DONT_CARE) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glHint(mode)"); + return; + } + + switch (target) { + case GL_PERSPECTIVE_CORRECTION_HINT: + h->perspectiveCorrection = mode; + DIRTY(hb->perspectiveCorrection, g->neg_bitid); + break; + case GL_FOG_HINT: + h->fog = mode; + DIRTY(hb->fog, g->neg_bitid); + break; + case GL_LINE_SMOOTH_HINT: + h->lineSmooth = mode; + DIRTY(hb->lineSmooth, g->neg_bitid); + break; + case GL_POINT_SMOOTH_HINT: + h->pointSmooth = mode; + DIRTY(hb->pointSmooth, g->neg_bitid); + break; + case GL_POLYGON_SMOOTH_HINT: + h->polygonSmooth = mode; + DIRTY(hb->polygonSmooth, g->neg_bitid); + break; +#ifdef CR_EXT_clip_volume_hint + case GL_CLIP_VOLUME_CLIPPING_HINT_EXT: + if (g->extensions.EXT_clip_volume_hint) { + h->clipVolumeClipping = mode; + DIRTY(hb->clipVolumeClipping, g->neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glHint(target)"); + return; + } + break; +#endif +#ifdef CR_ARB_texture_compression + case GL_TEXTURE_COMPRESSION_HINT_ARB: + if (g->extensions.ARB_texture_compression) { + h->textureCompression = mode; + DIRTY(hb->textureCompression, g->neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glHint(target)"); + return; + } + break; +#endif +#ifdef CR_SGIS_generate_mipmap + case GL_GENERATE_MIPMAP_HINT_SGIS: + if (g->extensions.SGIS_generate_mipmap) { + h->generateMipmap = mode; + DIRTY(hb->generateMipmap, g->neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glHint(target)"); + return; + } + break; +#endif + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glHint(target)"); + return; + } + + DIRTY(hb->dirty, g->neg_bitid); +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_hint.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_hint.txt new file mode 100644 index 00000000..9f129338 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_hint.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +:lineSmooth:lineSmooth:Hint,GL_LINE_SMOOTH_HINT +:pointSmooth:pointSmooth:Hint,GL_POINT_SMOOTH_HINT +:polygonSmooth:polygonSmooth:Hint,GL_POLYGON_SMOOTH_HINT +:perspectiveCorrection:perspectiveCorrection:Hint,GL_PERSPECTIVE_CORRECTION_HINT +:fog:fog:Hint,GL_FOG_HINT +:clipVolumeClipping:clipVolumeClipping:Hint,GL_CLIP_VOLUME_CLIPPING_HINT_EXT +:generateMipmap:generateMipmap:Hint,GL_GENERATE_MIPMAP_HINT_SGIS +:textureCompression:textureCompression:Hint,GL_TEXTURE_COMPRESSION_HINT_ARB diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c new file mode 100644 index 00000000..61e73a1b --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c @@ -0,0 +1,892 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "state.h" +#include "cr_mem.h" +#include "cr_error.h" +#include "cr_spu.h" + +#include <iprt/asm.h> + +#ifdef CHROMIUM_THREADSAFE +static bool __isContextTLSInited = false; +CRtsd __contextTSD; +#else +CRContext *__currentContext = NULL; +#endif + +CRStateBits *__currentBits = NULL; +CRContext *g_pAvailableContexts[CR_MAX_CONTEXTS]; +uint32_t g_cContexts = 0; + +static CRSharedState *gSharedState=NULL; + +static CRContext *defaultContext = NULL; + +GLboolean g_bVBoxEnableDiffOnMakeCurrent = GL_TRUE; + + +/** + * Allocate a new shared state object. + * Contains texture objects, display lists, etc. + */ +static CRSharedState * +crStateAllocShared(void) +{ + CRSharedState *s = (CRSharedState *) crCalloc(sizeof(CRSharedState)); + if (s) { + s->textureTable = crAllocHashtable(); + s->dlistTable = crAllocHashtable(); + s->buffersTable = crAllocHashtable(); + s->fbTable = crAllocHashtable(); + s->rbTable = crAllocHashtable(); + s->refCount = 1; /* refcount is number of contexts using this state */ + s->saveCount = 0; + } + return s; +} + +/** + * Callback used for crFreeHashtable(). + */ +DECLEXPORT(void) +crStateDeleteTextureCallback(void *texObj) +{ +#ifndef IN_GUEST + diff_api.DeleteTextures(1, &((CRTextureObj *)texObj)->hwid); +#endif + crStateDeleteTextureObject((CRTextureObj *) texObj); +} + +typedef struct CR_STATE_RELEASEOBJ +{ + CRContext *pCtx; + CRSharedState *s; +} CR_STATE_RELEASEOBJ, *PCR_STATE_RELEASEOBJ; + +void crStateOnTextureUsageRelease(CRSharedState *pS, CRTextureObj *pObj) +{ + if (!pObj->pinned) + crHashtableDelete(pS->textureTable, pObj->id, crStateDeleteTextureCallback); + else + Assert(crHashtableSearch(pS->textureTable, pObj->id)); +} + +static void crStateReleaseTextureInternal(CRSharedState *pS, CRContext *pCtx, CRTextureObj *pObj) +{ + Assert(CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj) || pObj->pinned); + CR_STATE_SHAREDOBJ_USAGE_CLEAR(pObj, pCtx); + if (CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj)) + return; + + crStateOnTextureUsageRelease(pS, pObj); +} + +DECLEXPORT(void) crStateReleaseTexture(CRContext *pCtx, CRTextureObj *pObj) +{ + Assert(CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj)); + CR_STATE_SHAREDOBJ_USAGE_CLEAR(pObj, pCtx); + if (CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj)) + return; + + if (!gSharedState) + { + WARN(("no global shared")); + return; + } + + crStateOnTextureUsageRelease(gSharedState, pObj); +} + +static void crStateReleaseBufferObjectInternal(CRSharedState *pS, CRContext *pCtx, CRBufferObject *pObj) +{ + Assert(CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj)); + CR_STATE_SHAREDOBJ_USAGE_CLEAR(pObj, pCtx); + if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj)) + crHashtableDelete(pS->buffersTable, pObj->id, crStateFreeBufferObject); +} + +static void crStateReleaseFBOInternal(CRSharedState *pS, CRContext *pCtx, CRFramebufferObject *pObj) +{ + Assert(CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj)); + CR_STATE_SHAREDOBJ_USAGE_CLEAR(pObj, pCtx); + if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj)) + crHashtableDelete(pS->fbTable, pObj->id, crStateFreeFBO); +} + +static void crStateReleaseRBOInternal(CRSharedState *pS, CRContext *pCtx, CRRenderbufferObject *pObj) +{ + Assert(CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj)); + CR_STATE_SHAREDOBJ_USAGE_CLEAR(pObj, pCtx); + if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj)) + crHashtableDelete(pS->rbTable, pObj->id, crStateFreeRBO); +} + +static void ReleaseTextureCallback(unsigned long key, void *data1, void *data2) +{ + PCR_STATE_RELEASEOBJ pData = (PCR_STATE_RELEASEOBJ)data2; + CRTextureObj *pObj = (CRTextureObj *)data1; + (void)key; + crStateReleaseTextureInternal(pData->s, pData->pCtx, pObj); +} + +static void ReleaseBufferObjectCallback(unsigned long key, void *data1, void *data2) +{ + PCR_STATE_RELEASEOBJ pData = (PCR_STATE_RELEASEOBJ)data2; + CRBufferObject *pObj = (CRBufferObject *)data1; + (void)key; + crStateReleaseBufferObjectInternal(pData->s, pData->pCtx, pObj); +} + +static void ReleaseFBOCallback(unsigned long key, void *data1, void *data2) +{ + PCR_STATE_RELEASEOBJ pData = (PCR_STATE_RELEASEOBJ)data2; + CRFramebufferObject *pObj = (CRFramebufferObject *)data1; + (void)key; + crStateReleaseFBOInternal(pData->s, pData->pCtx, pObj); +} + +static void ReleaseRBOCallback(unsigned long key, void *data1, void *data2) +{ + PCR_STATE_RELEASEOBJ pData = (PCR_STATE_RELEASEOBJ)data2; + CRRenderbufferObject *pObj = (CRRenderbufferObject *)data1; + (void)key; + crStateReleaseRBOInternal(pData->s, pData->pCtx, pObj); +} + + +/** + * Decrement shared state's refcount and delete when it hits zero. + */ +#ifndef IN_GUEST +DECLEXPORT(void) crStateFreeShared(CRContext *pContext, CRSharedState *s) +#else +static void crStateFreeShared(CRContext *pContext, CRSharedState *s) +#endif +{ + int32_t refCount = ASMAtomicDecS32(&s->refCount); + + Assert(refCount >= 0); + if (refCount <= 0) { + if (s==gSharedState) + { + gSharedState = NULL; + } + crFreeHashtable(s->textureTable, crStateDeleteTextureCallback); + crFreeHashtable(s->dlistTable, crFree); /* call crFree for each entry */ + crFreeHashtable(s->buffersTable, crStateFreeBufferObject); + crFreeHashtable(s->fbTable, crStateFreeFBO); + crFreeHashtable(s->rbTable, crStateFreeRBO); + crFree(s); + } + else if (pContext) + { + /* evaluate usage bits*/ + CR_STATE_RELEASEOBJ CbData; + CbData.pCtx = pContext; + CbData.s = s; + crHashtableWalk(s->textureTable, ReleaseTextureCallback, &CbData); + crHashtableWalk(s->buffersTable, ReleaseBufferObjectCallback , &CbData); + crHashtableWalk(s->fbTable, ReleaseFBOCallback, &CbData); + crHashtableWalk(s->rbTable, ReleaseRBOCallback, &CbData); + } +} + +#ifndef IN_GUEST + +DECLEXPORT(CRSharedState *) crStateGlobalSharedAcquire(void) +{ + if (!gSharedState) + { + crWarning("No Global Shared State!"); + return NULL; + } + ASMAtomicIncS32(&gSharedState->refCount); + return gSharedState; +} + +DECLEXPORT(void) crStateGlobalSharedRelease(void) +{ + crStateFreeShared(NULL, gSharedState); +} + +#endif /* IN_GUEST */ + +DECLEXPORT(void) STATE_APIENTRY +crStateShareContext(GLboolean value) +{ + CRContext *pCtx = GetCurrentContext(); + CRASSERT(pCtx && pCtx->shared); + + if (value) + { + if (pCtx->shared == gSharedState) + { + return; + } + + crDebug("Context(%i) shared", pCtx->id); + + if (!gSharedState) + { + gSharedState = pCtx->shared; + } + else + { + crStateFreeShared(pCtx, pCtx->shared); + pCtx->shared = gSharedState; + ASMAtomicIncS32(&gSharedState->refCount); + } + } + else + { + if (pCtx->shared != gSharedState) + { + return; + } + + crDebug("Context(%i) unshared", pCtx->id); + + if (gSharedState->refCount==1) + { + gSharedState = NULL; + } + else + { + pCtx->shared = crStateAllocShared(); + pCtx->shared->id = pCtx->id; + crStateFreeShared(pCtx, gSharedState); + } + } +} + +DECLEXPORT(void) STATE_APIENTRY +crStateShareLists(CRContext *pContext1, CRContext *pContext2) +{ + CRASSERT(pContext1->shared); + CRASSERT(pContext2->shared); + + if (pContext2->shared == pContext1->shared) + { + return; + } + + crStateFreeShared(pContext1, pContext1->shared); + pContext1->shared = pContext2->shared; + ASMAtomicIncS32(&pContext2->shared->refCount); +} + +DECLEXPORT(GLboolean) STATE_APIENTRY +crStateContextIsShared(CRContext *pCtx) +{ + return pCtx->shared==gSharedState; +} + +DECLEXPORT(void) STATE_APIENTRY +crStateSetSharedContext(CRContext *pCtx) +{ + if (gSharedState) + { + crWarning("crStateSetSharedContext: shared is being changed from %p to %p", gSharedState, pCtx->shared); + } + + gSharedState = pCtx->shared; +} + +#ifdef CHROMIUM_THREADSAFE +static void +crStateFreeContext(CRContext *ctx); +static DECLCALLBACK(void) crStateContextDtor(void *pvCtx) +{ + crStateFreeContext((CRContext*)pvCtx); +} +#endif + +/* + * Helper for crStateCreateContext, below. + */ +static CRContext * +crStateCreateContextId(int i, const CRLimitsState *limits, GLint visBits, CRContext *shareCtx) +{ + CRContext *ctx; + int j; + int node32 = i >> 5; + int node = i & 0x1f; + (void)limits; + + if (g_pAvailableContexts[i] != NULL) + { + crWarning("trying to create context with used id"); + return NULL; + } + + ctx = (CRContext *) crCalloc( sizeof( *ctx ) ); + if (!ctx) + { + crWarning("failed to allocate context"); + return NULL; + } + g_pAvailableContexts[i] = ctx; + ++g_cContexts; + CRASSERT(g_cContexts < RT_ELEMENTS(g_pAvailableContexts)); + ctx->id = i; +#ifdef CHROMIUM_THREADSAFE + VBoxTlsRefInit(ctx, crStateContextDtor); +#endif + ctx->flush_func = NULL; + for (j=0;j<CR_MAX_BITARRAY;j++){ + if (j == node32) { + ctx->bitid[j] = (1 << node); + } else { + ctx->bitid[j] = 0; + } + ctx->neg_bitid[j] = ~(ctx->bitid[j]); + } + + if (shareCtx) { + CRASSERT(shareCtx->shared); + ctx->shared = shareCtx->shared; + ASMAtomicIncS32(&ctx->shared->refCount); + } + else { + ctx->shared = crStateAllocShared(); + ctx->shared->id = ctx->id; + } + + /* use Chromium's OpenGL defaults */ + crStateLimitsInit( &(ctx->limits) ); + crStateExtensionsInit( &(ctx->limits), &(ctx->extensions) ); + + crStateBufferObjectInit( ctx ); /* must precede client state init! */ + crStateClientInit( ctx ); + + crStateBufferInit( ctx ); + crStateCurrentInit( ctx ); + crStateEvaluatorInit( ctx ); + crStateFogInit( ctx ); + crStateHintInit( ctx ); + crStateLightingInit( ctx ); + crStateLineInit( ctx ); + crStateListsInit( ctx ); + crStateMultisampleInit( ctx ); + crStateOcclusionInit( ctx ); + crStatePixelInit( ctx ); + crStatePolygonInit( ctx ); + crStatePointInit( ctx ); + crStateProgramInit( ctx ); + crStateRegCombinerInit( ctx ); + crStateStencilInit( ctx ); + crStateTextureInit( ctx ); + crStateTransformInit( ctx ); + crStateViewportInit ( ctx ); + crStateFramebufferObjectInit(ctx); + crStateGLSLInit(ctx); + + /* This has to come last. */ + crStateAttribInit( &(ctx->attrib) ); + + ctx->renderMode = GL_RENDER; + + /* Initialize values that depend on the visual mode */ + if (visBits & CR_DOUBLE_BIT) { + ctx->limits.doubleBuffer = GL_TRUE; + } + if (visBits & CR_RGB_BIT) { + ctx->limits.redBits = 8; + ctx->limits.greenBits = 8; + ctx->limits.blueBits = 8; + if (visBits & CR_ALPHA_BIT) { + ctx->limits.alphaBits = 8; + } + } + else { + ctx->limits.indexBits = 8; + } + if (visBits & CR_DEPTH_BIT) { + ctx->limits.depthBits = 24; + } + if (visBits & CR_STENCIL_BIT) { + ctx->limits.stencilBits = 8; + } + if (visBits & CR_ACCUM_BIT) { + ctx->limits.accumRedBits = 16; + ctx->limits.accumGreenBits = 16; + ctx->limits.accumBlueBits = 16; + if (visBits & CR_ALPHA_BIT) { + ctx->limits.accumAlphaBits = 16; + } + } + if (visBits & CR_STEREO_BIT) { + ctx->limits.stereo = GL_TRUE; + } + if (visBits & CR_MULTISAMPLE_BIT) { + ctx->limits.sampleBuffers = 1; + ctx->limits.samples = 4; + ctx->multisample.enabled = GL_TRUE; + } + + if (visBits & CR_OVERLAY_BIT) { + ctx->limits.level = 1; + } + + return ctx; +} + +/** @todo crStateAttribDestroy*/ +static void +crStateFreeContext(CRContext *ctx) +{ +#ifndef DEBUG_misha + CRASSERT(g_pAvailableContexts[ctx->id] == ctx); +#endif + if (g_pAvailableContexts[ctx->id] == ctx) + { + g_pAvailableContexts[ctx->id] = NULL; + --g_cContexts; + CRASSERT(g_cContexts < RT_ELEMENTS(g_pAvailableContexts)); + } + else + { +#ifndef DEBUG_misha + crWarning("freeing context %p, id(%d) not being in the context list", ctx, ctx->id); +#endif + } + + crStateClientDestroy( ctx ); + crStateLimitsDestroy( &(ctx->limits) ); + crStateBufferObjectDestroy( ctx ); + crStateEvaluatorDestroy( ctx ); + crStateListsDestroy( ctx ); + crStateLightingDestroy( ctx ); + crStateOcclusionDestroy( ctx ); + crStateProgramDestroy( ctx ); + crStateTextureDestroy( ctx ); + crStateTransformDestroy( ctx ); + crStateFreeShared(ctx, ctx->shared); + crStateFramebufferObjectDestroy(ctx); + crStateGLSLDestroy(ctx); + if (ctx->buffer.pFrontImg) crFree(ctx->buffer.pFrontImg); + if (ctx->buffer.pBackImg) crFree(ctx->buffer.pBackImg); + crFree( ctx ); +} + +#ifdef CHROMIUM_THREADSAFE +# ifndef RT_OS_WINDOWS +static void crStateThreadTlsDtor(void *pvValue) +{ + CRContext *pCtx = (CRContext*)pvValue; + VBoxTlsRefRelease(pCtx); +} +# endif +#endif + +/* + * Allocate the state (dirty) bits data structures. + * This should be called before we create any contexts. + * We'll also create the default/NULL context at this time and make + * it the current context by default. This means that if someone + * tries to set GL state before calling MakeCurrent() they'll be + * modifying the default state object, and not segfaulting on a NULL + * pointer somewhere. + */ +void crStateInit(void) +{ + unsigned int i; + + /* Purely initialize the context bits */ + if (!__currentBits) { + __currentBits = (CRStateBits *) crCalloc( sizeof(CRStateBits) ); + crStateClientInitBits( &(__currentBits->client) ); + crStateLightingInitBits( &(__currentBits->lighting) ); + } else + { +#ifndef DEBUG_misha + crWarning("State tracker is being re-initialized..\n"); +#endif + } + + for (i=0;i<CR_MAX_CONTEXTS;i++) + g_pAvailableContexts[i] = NULL; + g_cContexts = 0; + +#ifdef CHROMIUM_THREADSAFE + if (!__isContextTLSInited) + { +# ifndef RT_OS_WINDOWS + /* tls destructor is implemented for all platforms except windows*/ + crInitTSDF(&__contextTSD, crStateThreadTlsDtor); +# else + /* windows should do cleanup via DllMain THREAD_DETACH notification */ + crInitTSD(&__contextTSD); +# endif + __isContextTLSInited = 1; + } +#endif + + if (defaultContext) { + /* Free the default/NULL context. + * Ensures context bits are reset */ +#ifdef CHROMIUM_THREADSAFE + SetCurrentContext(NULL); + VBoxTlsRefRelease(defaultContext); +#else + crStateFreeContext(defaultContext); + __currentContext = NULL; +#endif + } + + /* Reset diff_api */ + crMemZero(&diff_api, sizeof(SPUDispatchTable)); + + Assert(!gSharedState); + gSharedState = NULL; + + /* Allocate the default/NULL context */ + CRASSERT(g_pAvailableContexts[0] == NULL); + defaultContext = crStateCreateContextId(0, NULL, CR_RGB_BIT, NULL); + CRASSERT(g_pAvailableContexts[0] == defaultContext); + CRASSERT(g_cContexts == 1); +#ifdef CHROMIUM_THREADSAFE + SetCurrentContext(defaultContext); +#else + __currentContext = defaultContext; +#endif +} + +void crStateDestroy(void) +{ + int i; + if (__currentBits) + { + crStateClientDestroyBits(&(__currentBits->client)); + crStateLightingDestroyBits(&(__currentBits->lighting)); + crFree(__currentBits); + __currentBits = NULL; + } + + SetCurrentContext(NULL); + + for (i = CR_MAX_CONTEXTS-1; i >= 0; i--) + { + if (g_pAvailableContexts[i]) + { +#ifdef CHROMIUM_THREADSAFE + if (VBoxTlsRefIsFunctional(g_pAvailableContexts[i])) + VBoxTlsRefRelease(g_pAvailableContexts[i]); +#else + crStateFreeContext(g_pAvailableContexts[i]); +#endif + } + } + + /* default context was stored in g_pAvailableContexts[0], so it was destroyed already */ + defaultContext = NULL; + + +#ifdef CHROMIUM_THREADSAFE + crFreeTSD(&__contextTSD); + __isContextTLSInited = 0; +#endif +} + +/* + * Notes on context switching and the "default context". + * + * See the paper "Tracking Graphics State for Networked Rendering" + * by Ian Buck, Greg Humphries and Pat Hanrahan for background + * information about how the state tracker and context switching + * works. + * + * When we make a new context current, we call crStateSwitchContext() + * in order to transform the 'from' context into the 'to' context + * (i.e. the old context to the new context). The transformation + * is accomplished by calling GL functions through the 'diff_api' + * so that the downstream GL machine (represented by the __currentContext + * structure) is updated to reflect the new context state. Finally, + * we point __currentContext to the new context. + * + * A subtle problem we have to deal with is context destruction. + * This issue arose while testing with Glean. We found that when + * the currently bound context was getting destroyed that state + * tracking was incorrect when a subsequent new context was activated. + * In DestroyContext, the __hwcontext was being set to NULL and effectively + * going away. Later in MakeCurrent we had no idea what the state of the + * downstream GL machine was (since __hwcontext was gone). This meant + * we had nothing to 'diff' against and the downstream GL machine was + * in an unknown state. + * + * The solution to this problem is the "default/NULL" context. The + * default context is created the first time CreateContext is called + * and is never freed. Whenever we get a crStateMakeCurrent(NULL) call + * or destroy the currently bound context in crStateDestroyContext() + * we call crStateSwitchContext() to switch to the default context and + * then set the __currentContext pointer to point to the default context. + * This ensures that the dirty bits are updated and the diff_api functions + * are called to keep the downstream GL machine in a known state. + * Finally, the __hwcontext variable is no longer needed now. + * + * Yeah, this is kind of a mind-bender, but it really solves the problem + * pretty cleanly. + * + * -Brian + */ + + +CRContext * +crStateCreateContext(const CRLimitsState *limits, GLint visBits, CRContext *share) +{ + return crStateCreateContextEx(limits, visBits, share, -1); +} + +CRContext * +crStateCreateContextEx(const CRLimitsState *limits, GLint visBits, CRContext *share, GLint presetID) +{ + /* Must have created the default context via crStateInit() first */ + CRASSERT(defaultContext); + + if (presetID>0) + { + if(g_pAvailableContexts[presetID]) + { + crWarning("requesting to create context with already allocated id"); + return NULL; + } + } + else + { + int i; + + for (i = 1 ; i < CR_MAX_CONTEXTS ; i++) + { + if (!g_pAvailableContexts[i]) + { + presetID = i; + break; + } + } + + if (presetID<=0) + { + crError( "Out of available contexts in crStateCreateContexts (max %d)", + CR_MAX_CONTEXTS ); + /* never get here */ + return NULL; + } + } + + return crStateCreateContextId(presetID, limits, visBits, share); +} + +void crStateDestroyContext( CRContext *ctx ) +{ + CRContext *current = GetCurrentContext(); + + if (current == ctx) { + /* destroying the current context - have to be careful here */ + CRASSERT(defaultContext); + /* Check to see if the differencer exists first, + we may not have one, aka the packspu */ + if (diff_api.AlphaFunc) + crStateSwitchContext(current, defaultContext); +#ifdef CHROMIUM_THREADSAFE + SetCurrentContext(defaultContext); +#else + __currentContext = defaultContext; +#endif + /* ensure matrix state is also current */ + crStateMatrixMode(defaultContext->transform.matrixMode); + } + +#ifdef CHROMIUM_THREADSAFE + VBoxTlsRefMarkDestroy(ctx); +# ifdef IN_GUEST + if (VBoxTlsRefCountGet(ctx) > 1 && ctx->shared == gSharedState) + { + /* we always need to free the global shared state to prevent the situation when guest thinks the shared objects are still valid, while host destroys them */ + crStateFreeShared(ctx, ctx->shared); + ctx->shared = crStateAllocShared(); + } +# endif + VBoxTlsRefRelease(ctx); +#else + crStateFreeContext(ctx); +#endif +} + +GLboolean crStateEnableDiffOnMakeCurrent(GLboolean fEnable) +{ + GLboolean bOld = g_bVBoxEnableDiffOnMakeCurrent; + g_bVBoxEnableDiffOnMakeCurrent = fEnable; + return bOld; +} + +void crStateMakeCurrent( CRContext *ctx ) +{ + CRContext *current = GetCurrentContext(); + CRContext *pLocalCtx = ctx; + + if (pLocalCtx == NULL) + pLocalCtx = defaultContext; + + if (current == pLocalCtx) + return; /* no-op */ + + CRASSERT(pLocalCtx); + + if (g_bVBoxEnableDiffOnMakeCurrent && current) { + /* Check to see if the differencer exists first, + we may not have one, aka the packspu */ + if (diff_api.AlphaFunc) + crStateSwitchContext( current, pLocalCtx ); + } + +#ifdef CHROMIUM_THREADSAFE + SetCurrentContext(pLocalCtx); +#else + __currentContext = pLocalCtx; +#endif + + /* ensure matrix state is also current */ + crStateMatrixMode(pLocalCtx->transform.matrixMode); +} + + +/* + * As above, but don't call crStateSwitchContext(). + */ +static void crStateSetCurrentEx( CRContext *ctx, GLboolean fCleanupDefault ) +{ + CRContext *current = GetCurrentContext(); + CRContext *pLocalCtx = ctx; + + if (pLocalCtx == NULL && !fCleanupDefault) + pLocalCtx = defaultContext; + + if (current == pLocalCtx) + return; /* no-op */ + +#ifdef CHROMIUM_THREADSAFE + SetCurrentContext(pLocalCtx); +#else + __currentContext = pLocalCtx; +#endif + + if (pLocalCtx) + { + /* ensure matrix state is also current */ + crStateMatrixMode(pLocalCtx->transform.matrixMode); + } +} + +void crStateSetCurrent( CRContext *ctx ) +{ + crStateSetCurrentEx( ctx, GL_FALSE ); +} + +void crStateCleanupCurrent() +{ + crStateSetCurrentEx( NULL, GL_TRUE ); +} + + +CRContext *crStateGetCurrent(void) +{ + return GetCurrentContext(); +} + + +void crStateUpdateColorBits(void) +{ + /* This is a hack to force updating the 'current' attribs */ + CRStateBits *sb = GetCurrentBits(); + FILLDIRTY(sb->current.dirty); + FILLDIRTY(sb->current.vertexAttrib[VERT_ATTRIB_COLOR0]); +} + + +void STATE_APIENTRY +crStateChromiumParameteriCR( GLenum target, GLint value ) +{ + /* This no-op function helps smooth code-gen */ + (void)target; (void)value; +} + +void STATE_APIENTRY +crStateChromiumParameterfCR( GLenum target, GLfloat value ) +{ + /* This no-op function helps smooth code-gen */ + (void)target; (void)value; +} + +void STATE_APIENTRY +crStateChromiumParametervCR( GLenum target, GLenum type, GLsizei count, const GLvoid *values ) +{ + /* This no-op function helps smooth code-gen */ + (void)target; (void)type; (void)count; (void)values; +} + +void STATE_APIENTRY +crStateGetChromiumParametervCR( GLenum target, GLuint index, GLenum type, GLsizei count, GLvoid *values ) +{ + /* This no-op function helps smooth code-gen */ + (void)target; (void)index; (void)type; (void)count; (void)values; +} + +void STATE_APIENTRY +crStateReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLvoid *pixels ) +{ + /* This no-op function helps smooth code-gen */ + (void)x; (void)y; (void)width; (void)height; (void)format; (void)type; (void)pixels; +} + +void crStateVBoxDetachThread(void) +{ + /* release the context ref so that it can be freed */ + SetCurrentContext(NULL); +} + + +void crStateVBoxAttachThread(void) +{ +} + +#if 0 /* who's refering to these? */ + +GLint crStateVBoxCreateContext( GLint con, const char * dpyName, GLint visual, GLint shareCtx ) +{ + (void)con; (void)dpyName; (void)visual; (void)shareCtx; + return 0; +} + +GLint crStateVBoxWindowCreate( GLint con, const char *dpyName, GLint visBits ) +{ + (void)con; (void)dpyName; (void)visBits; + return 0; +} + +void crStateVBoxWindowDestroy( GLint con, GLint window ) +{ + (void)con; (void)window; +} + +GLint crStateVBoxConCreate(struct VBOXUHGSMI *pHgsmi) +{ + (void)pHgsmi; + return 0; +} + +void crStateVBoxConDestroy(GLint con) +{ + (void)con; +} + +void crStateVBoxConFlush(GLint con) +{ + (void)con; +} + +#endif /* unused? */ diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_internals.h b/src/VBox/GuestHost/OpenGL/state_tracker/state_internals.h new file mode 100644 index 00000000..6610ca8a --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_internals.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved. + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#ifndef STATE_INTERNALS_H +#define STATE_INTERNALS_H + +#include "cr_spu.h" +#include "state/cr_statetypes.h" + +/* Set the flush_func to NULL *before* it's called, so that we can + * call state functions from within flush without infinite recursion. + * Yucky, but "necessary" for color material. */ + +#define FLUSH() \ + if (g->flush_func != NULL) \ + { \ + CRStateFlushFunc cached_ff = g->flush_func; \ + g->flush_func = NULL; \ + cached_ff( g->flush_arg ); \ + } + +typedef void (SPU_APIENTRY *glAble)(GLenum); + +#define GLCLIENT_BIT_ALLOC 1024 + +#endif diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_isenabled.py b/src/VBox/GuestHost/OpenGL/state_tracker/state_isenabled.py new file mode 100755 index 00000000..35a3815a --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_isenabled.py @@ -0,0 +1,75 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. + +from __future__ import print_function +import sys, re, string +import apiutil + + +line_re = re.compile(r'^(\S+)\s+(GL_\S+)\s+(.*)\s*$') +extensions_line_re = re.compile(r'^(\S+)\s+(GL_\S+)\s(\S+)\s+(.*)\s*$') + +params = {} +extended_params = {} + +input = open( sys.argv[2]+"/state_isenabled.txt", 'r' ) +for line in input.readlines(): + match = line_re.match( line ) + if match: + type = match.group(1) + pname = match.group(2) + fields = match.group(3).split() + params[pname] = ( type, fields ) + +input = open( sys.argv[2]+"/state_extensions_isenabled.txt", 'r' ) +for line in input.readlines(): + match = extensions_line_re.match( line ) + if match: + type = match.group(1) + pname = match.group(2) + ifdef = match.group(3) + fields = match.group(4).split() + extended_params[pname] = ( type, ifdef, fields ) + +apiutil.CopyrightC() + +print(""" +/* DO NOT EDIT - THIS FILE GENERATED BY THE state_isenabled.py SCRIPT */ +#include <stdio.h> +#include <math.h> + +#include "state.h" +#include "state/cr_statetypes.h" + +GLboolean STATE_APIENTRY crStateIsEnabled( GLenum pname ) +{ + CRContext *g = GetCurrentContext(); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glGet called in Begin/End"); + return 0; + } + + switch (pname) { +""") + +for pname in sorted(params.keys()): + print("\tcase %s:" % pname) + print("\t\treturn %s;" % params[pname][1][0]) + +for pname in sorted(extended_params.keys()): + (srctype,ifdef,fields) = extended_params[pname] + ext = ifdef[3:] # the extension name with the "GL_" prefix removed + ext = ifdef + print('#ifdef CR_%s' % ext) + print("\tcase %s:" % pname) + print("\t\treturn %s;" % extended_params[pname][2][0]) + print('#endif /* CR_%s */' % ext) +print("\tdefault:") +print("\t\tcrStateError(__LINE__, __FILE__, GL_INVALID_ENUM, \"glIsEnabled: Unknown enum: %d\", pname);") +print("\t\treturn 0;") +print("\t}") +print("}") diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_isenabled.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_isenabled.txt new file mode 100644 index 00000000..4e7435dd --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_isenabled.txt @@ -0,0 +1,76 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +GLboolean GL_ALPHA_TEST g->buffer.alphaTest +GLboolean GL_AUTO_NORMAL g->eval.autoNormal +GLboolean GL_BLEND g->buffer.blend +GLboolean GL_CULL_FACE g->polygon.cullFace +GLboolean GL_COLOR_MATERIAL GL_FALSE +GLboolean GL_CLIP_PLANE0 g->transform.clip[0] +GLboolean GL_CLIP_PLANE1 g->transform.clip[1] +GLboolean GL_CLIP_PLANE2 g->transform.clip[2] +GLboolean GL_CLIP_PLANE3 g->transform.clip[3] +GLboolean GL_CLIP_PLANE4 g->transform.clip[4] +GLboolean GL_CLIP_PLANE5 g->transform.clip[5] +GLboolean GL_COLOR_LOGIC_OP g->buffer.logicOp +GLboolean GL_DEPTH_TEST g->buffer.depthTest +GLboolean GL_DEPTH_WRITEMASK g->buffer.depthMask +GLboolean GL_DITHER g->buffer.dither +GLboolean GL_FOG g->fog.enable +GLboolean GL_INDEX_LOGIC_OP g->buffer.indexLogicOp +GLboolean GL_LIGHT0 g->lighting.light[0].enable +GLboolean GL_LIGHT1 g->lighting.light[1].enable +GLboolean GL_LIGHT2 g->lighting.light[2].enable +GLboolean GL_LIGHT3 g->lighting.light[3].enable +GLboolean GL_LIGHT4 g->lighting.light[4].enable +GLboolean GL_LIGHT5 g->lighting.light[5].enable +GLboolean GL_LIGHT6 g->lighting.light[6].enable +GLboolean GL_LIGHT7 g->lighting.light[7].enable +GLboolean GL_LIGHTING g->lighting.lighting +GLboolean GL_LINE_SMOOTH g->line.lineSmooth +GLboolean GL_LINE_STIPPLE g->line.lineStipple +GLboolean GL_MAP1_COLOR_4 g->eval.enable1D[GL_MAP1_COLOR_4-GL_MAP1_COLOR_4] +GLboolean GL_MAP1_INDEX g->eval.enable1D[GL_MAP1_INDEX-GL_MAP1_COLOR_4] +GLboolean GL_MAP1_NORMAL g->eval.enable1D[GL_MAP1_NORMAL-GL_MAP1_COLOR_4] +GLboolean GL_MAP1_TEXTURE_COORD_1 g->eval.enable1D[GL_MAP1_TEXTURE_COORD_1-GL_MAP1_COLOR_4] +GLboolean GL_MAP1_TEXTURE_COORD_2 g->eval.enable1D[GL_MAP1_TEXTURE_COORD_2-GL_MAP1_COLOR_4] +GLboolean GL_MAP1_TEXTURE_COORD_3 g->eval.enable1D[GL_MAP1_TEXTURE_COORD_3-GL_MAP1_COLOR_4] +GLboolean GL_MAP1_TEXTURE_COORD_4 g->eval.enable1D[GL_MAP1_TEXTURE_COORD_4-GL_MAP1_COLOR_4] +GLboolean GL_MAP1_VERTEX_3 g->eval.enable1D[GL_MAP1_VERTEX_3-GL_MAP1_COLOR_4] +GLboolean GL_MAP1_VERTEX_4 g->eval.enable1D[GL_MAP1_VERTEX_4-GL_MAP1_COLOR_4] +GLboolean GL_MAP2_COLOR_4 g->eval.enable2D[GL_MAP2_COLOR_4-GL_MAP2_COLOR_4] +GLboolean GL_MAP2_INDEX g->eval.enable2D[GL_MAP2_INDEX-GL_MAP2_COLOR_4] +GLboolean GL_MAP2_NORMAL g->eval.enable2D[GL_MAP2_NORMAL-GL_MAP2_COLOR_4] +GLboolean GL_MAP2_TEXTURE_COORD_1 g->eval.enable2D[GL_MAP2_TEXTURE_COORD_1-GL_MAP2_COLOR_4] +GLboolean GL_MAP2_TEXTURE_COORD_2 g->eval.enable2D[GL_MAP2_TEXTURE_COORD_2-GL_MAP2_COLOR_4] +GLboolean GL_MAP2_TEXTURE_COORD_3 g->eval.enable2D[GL_MAP2_TEXTURE_COORD_3-GL_MAP2_COLOR_4] +GLboolean GL_MAP2_TEXTURE_COORD_4 g->eval.enable2D[GL_MAP2_TEXTURE_COORD_4-GL_MAP2_COLOR_4] +GLboolean GL_MAP2_VERTEX_3 g->eval.enable2D[GL_MAP2_VERTEX_3-GL_MAP2_COLOR_4] +GLboolean GL_MAP2_VERTEX_4 g->eval.enable2D[GL_MAP2_VERTEX_4-GL_MAP2_COLOR_4] +GLboolean GL_PACK_SWAP_BYTES g->client.pack.swapBytes +GLboolean GL_PACK_LSB_FIRST g->client.pack.psLSBFirst +GLboolean GL_POINT_SMOOTH g->point.pointSmooth +GLboolean GL_POLYGON_SMOOTH g->polygon.polygonSmooth +GLboolean GL_POLYGON_STIPPLE g->polygon.polygonStipple +GLboolean GL_POLYGON_OFFSET_POINT g->polygon.polygonOffsetPoint +GLboolean GL_POLYGON_OFFSET_LINE g->polygon.polygonOffsetLine +GLboolean GL_POLYGON_OFFSET_FILL g->polygon.polygonOffsetFill +GLboolean GL_NORMALIZE g->transform.normalize +GLboolean GL_RGBA_MODE GL_TRUE +GLboolean GL_SCISSOR_TEST g->viewport.scissorTest +GLboolean GL_STENCIL_TEST g->stencil.stencilTest +GLboolean GL_TEXTURE_GEN_S g->texture.unit[g->texture.curTextureUnit].textureGen.s +GLboolean GL_TEXTURE_GEN_T g->texture.unit[g->texture.curTextureUnit].textureGen.t +GLboolean GL_TEXTURE_GEN_R g->texture.unit[g->texture.curTextureUnit].textureGen.r +GLboolean GL_TEXTURE_GEN_Q g->texture.unit[g->texture.curTextureUnit].textureGen.q +GLboolean GL_TEXTURE_1D g->texture.unit[g->texture.curTextureUnit].enabled1D +GLboolean GL_TEXTURE_2D g->texture.unit[g->texture.curTextureUnit].enabled2D +# GLboolean GL_TEXTURE_3D g->texture.unit[g->texture.curTextureUnit].enabled3D +GLboolean GL_TEXTURE_CUBE_MAP_ARB g->texture.unit[g->texture.curTextureUnit].enabledCubeMap + +GLboolean GL_UNPACK_SWAP_BYTES g->client.unpack.swapBytes +GLboolean GL_UNPACK_LSB_FIRST g->client.unpack.psLSBFirst +GLboolean GL_REGISTER_COMBINERS_NV g->regcombiner.enabledRegCombiners +GLboolean GL_PER_STAGE_CONSTANTS_NV g->regcombiner.enabledPerStageConstants +GLboolean GL_COLOR_SUM_EXT g->lighting.colorSumEXT diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_lighting.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_lighting.c new file mode 100644 index 00000000..bfea8559 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_lighting.c @@ -0,0 +1,1212 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include <stdio.h> +#include "state.h" +#include "cr_mem.h" +#include "state/cr_statetypes.h" +#include "state_internals.h" + +void crStateLightingInitBits (CRLightingBits *l) +{ + l->light = (CRLightBits *) crCalloc (sizeof(*(l->light)) * CR_MAX_LIGHTS); +} + +void crStateLightingDestroyBits (CRLightingBits *l) +{ + crFree(l->light); +} + +void crStateLightingDestroy (CRContext *ctx) +{ + crFree(ctx->lighting.light); +} + +void crStateLightingInit (CRContext *ctx) +{ + CRLightingState *l = &ctx->lighting; + CRStateBits *sb = GetCurrentBits(); + CRLightingBits *lb = &(sb->lighting); + int i; + GLvectorf zero_vector = {0.0f, 0.0f, 0.0f, 1.0f}; + GLcolorf zero_color = {0.0f, 0.0f, 0.0f, 1.0f}; + GLcolorf ambient_color = {0.2f, 0.2f, 0.2f, 1.0f}; + GLcolorf diffuse_color = {0.8f, 0.8f, 0.8f, 1.0f}; + GLvectorf spot_vector = {0.0f, 0.0f, -1.0f, 0.0f}; + GLcolorf one_color = {1.0f, 1.0f, 1.0f, 1.0f}; + + l->lighting = GL_FALSE; + RESET(lb->enable, ctx->bitid); + l->colorMaterial = GL_FALSE; + RESET(lb->colorMaterial, ctx->bitid); + l->shadeModel = GL_SMOOTH; + RESET(lb->shadeModel, ctx->bitid); + l->colorMaterialMode = GL_AMBIENT_AND_DIFFUSE; + l->colorMaterialFace = GL_FRONT_AND_BACK; + l->ambient[0] = ambient_color; + l->diffuse[0] = diffuse_color; + l->specular[0] = zero_color; + l->emission[0] = zero_color; + l->shininess[0] = 0.0f; + l->indexes[0][0] = 0; + l->indexes[0][1] = 1; + l->indexes[0][2] = 1; + l->ambient[1] = ambient_color; + l->diffuse[1] = diffuse_color; + l->specular[1] = zero_color; + l->emission[1] = zero_color; + l->shininess[1] = 0.0f; + l->indexes[1][0] = 0; + l->indexes[1][1] = 1; + l->indexes[1][2] = 1; + RESET(lb->material, ctx->bitid); + l->lightModelAmbient = ambient_color; + l->lightModelLocalViewer = GL_FALSE; + l->lightModelTwoSide = GL_FALSE; +#if defined(CR_EXT_separate_specular_color) + l->lightModelColorControlEXT = GL_SINGLE_COLOR_EXT; +#elif defined(CR_OPENGL_VERSION_1_2) + l->lightModelColorControlEXT = GL_SINGLE_COLOR; +#endif + RESET(lb->lightModel, ctx->bitid); +#if defined(CR_EXT_secondary_color) + l->colorSumEXT = GL_FALSE; +#endif + l->light = (CRLight *) crCalloc (sizeof (*(l->light)) * CR_MAX_LIGHTS); + + for (i=0; i<CR_MAX_LIGHTS; i++) + { + CRLightBits *ltb = lb->light + i; + l->light[i].enable = GL_FALSE; + RESET(ltb->enable, ctx->bitid); + l->light[i].ambient = zero_color; + RESET(ltb->ambient, ctx->bitid); + l->light[i].diffuse = zero_color; + RESET(ltb->diffuse, ctx->bitid); + l->light[i].specular = zero_color; + RESET(ltb->specular, ctx->bitid); + l->light[i].position = zero_vector; + l->light[i].position.z = 1.0f; + l->light[i].position.w = 0.0f; + l->light[i].objPosition = l->light[i].position; + RESET(ltb->position, ctx->bitid); + l->light[i].spotDirection = spot_vector; + l->light[i].spotExponent = 0.0f; + l->light[i].spotCutoff = 180.0f; + RESET(ltb->spot, ctx->bitid); + l->light[i].constantAttenuation= 1.0f; + l->light[i].linearAttenuation= 0.0f; + l->light[i].quadraticAttenuation = 0.0f; + RESET(ltb->attenuation, ctx->bitid); + RESET(ltb->dirty, ctx->bitid); + } + l->light[0].diffuse = one_color; + l->light[0].specular = one_color; + + RESET(lb->dirty, ctx->bitid); +} + +void STATE_APIENTRY crStateShadeModel (GLenum mode) +{ + CRContext *g = GetCurrentContext(); + CRLightingState *l = &(g->lighting); + CRStateBits *sb = GetCurrentBits(); + CRLightingBits *lb = &(sb->lighting); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "ShadeModel called in begin/end"); + return; + } + + FLUSH(); + + if (mode != GL_SMOOTH && + mode != GL_FLAT) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "ShadeModel: Bogus mode 0x%x", mode); + return; + } + + l->shadeModel = mode; + DIRTY(lb->shadeModel, g->neg_bitid); + DIRTY(lb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateColorMaterial (GLenum face, GLenum mode) +{ + CRContext *g = GetCurrentContext(); + CRLightingState *l = &(g->lighting); + CRStateBits *sb = GetCurrentBits(); + CRLightingBits *lb = &(sb->lighting); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "ColorMaterial called in begin/end"); + return; + } + + FLUSH(); + + if (face != GL_FRONT && + face != GL_BACK && + face != GL_FRONT_AND_BACK) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "ColorMaterial: Bogus face &d", face); + return; + } + + if (mode != GL_EMISSION && + mode != GL_AMBIENT && + mode != GL_DIFFUSE && + mode != GL_SPECULAR && + mode != GL_AMBIENT_AND_DIFFUSE) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "ColorMaterial: Bogus mode &d", mode); + return; + } + + l->colorMaterialFace = face; + l->colorMaterialMode = mode; + /* XXX this could conceivably be needed here (BP) */ + /* + crStateColorMaterialRecover(); + */ + DIRTY(lb->colorMaterial, g->neg_bitid); + DIRTY(lb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateLightModelfv (GLenum pname, const GLfloat *param) +{ + CRContext *g = GetCurrentContext(); + CRLightingState *l = &(g->lighting); + CRStateBits *sb = GetCurrentBits(); + CRLightingBits *lb = &(sb->lighting); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "LightModelfv called in begin/end"); + return; + } + + FLUSH(); + + switch (pname) + { + case GL_LIGHT_MODEL_LOCAL_VIEWER: + l->lightModelLocalViewer = (GLboolean) (*param==0.0f?GL_FALSE:GL_TRUE); + break; + case GL_LIGHT_MODEL_TWO_SIDE: + l->lightModelTwoSide = (GLboolean) (*param==0.0f?GL_FALSE:GL_TRUE); + break; + case GL_LIGHT_MODEL_AMBIENT: + l->lightModelAmbient.r = param[0]; + l->lightModelAmbient.g = param[1]; + l->lightModelAmbient.b = param[2]; + l->lightModelAmbient.a = param[3]; + break; +#if defined(CR_OPENGL_VERSION_1_2) + case GL_LIGHT_MODEL_COLOR_CONTROL: + if (param[0] == GL_SEPARATE_SPECULAR_COLOR || param[0] == GL_SINGLE_COLOR) + { + l->lightModelColorControlEXT = (GLenum) param[0]; + } + else + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "LightModel: Invalid param for LIGHT_MODEL_COLOR_CONTROL: 0x%x", param[0]); + return; + } + break; +#else +#if defined(CR_EXT_separate_specular_color) + case GL_LIGHT_MODEL_COLOR_CONTROL_EXT: + if(g->extensions.EXT_separate_specular_color) + { + if (param[0] == GL_SEPARATE_SPECULAR_COLOR_EXT || param[0] == GL_SINGLE_COLOR_EXT) + { + l->lightModelColorControlEXT = (GLenum) param[0]; + } + else + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "LightModel: Invalid param for LIGHT_MODEL_COLOR_CONTROL: 0x%x", param[0]); + return; + } + } + else + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "LightModel( LIGHT_MODEL_COLOR_CONTROL, ...) - EXT_separate_specular_color is unavailable."); + return; + } + break; +#endif +#endif + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "LightModelfv: Invalid pname: 0x%x", pname); + return; + } + DIRTY(lb->lightModel, g->neg_bitid); + DIRTY(lb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateLightModeliv (GLenum pname, const GLint *param) +{ + GLfloat f_param; + GLcolor f_color; +#ifndef CR_OPENGL_VERSION_1_2 + CRContext *g = GetCurrentContext(); +#endif + + switch (pname) + { + case GL_LIGHT_MODEL_LOCAL_VIEWER: + case GL_LIGHT_MODEL_TWO_SIDE: + f_param = (GLfloat) (*param); + crStateLightModelfv(pname, &f_param); + break; + case GL_LIGHT_MODEL_AMBIENT: + f_color.r = ((GLfloat)param[0])/CR_MAXINT; + f_color.g = ((GLfloat)param[1])/CR_MAXINT; + f_color.b = ((GLfloat)param[2])/CR_MAXINT; + f_color.a = ((GLfloat)param[3])/CR_MAXINT; + crStateLightModelfv(pname, (GLfloat *) &f_color); + break; +#if defined(CR_OPENGL_VERSION_1_2) + case GL_LIGHT_MODEL_COLOR_CONTROL: + f_param = (GLfloat) (*param); + crStateLightModelfv(pname, &f_param); + break; +#else +#ifdef CR_EXT_separate_specular_color + case GL_LIGHT_MODEL_COLOR_CONTROL_EXT: + if (g->extensions.EXT_separate_specular_color) { + f_param = (GLfloat) (*param); + crStateLightModelfv(pname, &f_param); + } else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "LightModeliv(GL_LIGHT_MODEL_COLOR_CONTROL_EXT, ...) - EXT_separate_specular_color not enabled!"); + return; + } + break; +#endif +#endif + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "LightModeliv: Invalid pname: 0x%x", pname); + return; + } +} + +void STATE_APIENTRY crStateLightModelf (GLenum pname, GLfloat param) +{ + crStateLightModelfv(pname, ¶m); +} + +void STATE_APIENTRY crStateLightModeli (GLenum pname, GLint param) +{ + GLfloat f_param = (GLfloat) param; + crStateLightModelfv(pname, &f_param); +} + +void STATE_APIENTRY crStateLightfv (GLenum light, GLenum pname, const GLfloat *param) +{ + CRContext *g = GetCurrentContext(); + CRLightingState *l = &(g->lighting); + CRTransformState *t = &(g->transform); + CRLight *lt; + unsigned int i; + GLfloat x, y, z, w; + CRmatrix inv; + CRmatrix *mat; + CRStateBits *sb = GetCurrentBits(); + CRLightingBits *lb = &(sb->lighting); + CRLightBits *ltb; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glLightfv called in begin/end"); + return; + } + + FLUSH(); + + i = light - GL_LIGHT0; + if (i>=g->limits.maxLights) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glLight: invalid light specified: 0x%x", light); + return; + } + + lt = l->light + i; + ltb = lb->light + i; + + switch (pname) + { + case GL_AMBIENT: + lt->ambient.r = param[0]; + lt->ambient.g = param[1]; + lt->ambient.b = param[2]; + lt->ambient.a = param[3]; + DIRTY(ltb->ambient, g->neg_bitid); + break; + case GL_DIFFUSE: + lt->diffuse.r = param[0]; + lt->diffuse.g = param[1]; + lt->diffuse.b = param[2]; + lt->diffuse.a = param[3]; + DIRTY(ltb->diffuse, g->neg_bitid); + break; + case GL_SPECULAR: + lt->specular.r = param[0]; + lt->specular.g = param[1]; + lt->specular.b = param[2]; + lt->specular.a = param[3]; + DIRTY(ltb->specular, g->neg_bitid); + break; + case GL_POSITION: + x = param[0]; + y = param[1]; + z = param[2]; + w = param[3]; + mat = t->modelViewStack.top; + lt->objPosition.x = x; + lt->objPosition.y = y; + lt->objPosition.z = z; + lt->objPosition.w = w; + + lt->position.x = mat->m00*x + mat->m10*y + mat->m20*z + mat->m30*w; + lt->position.y = mat->m01*x + mat->m11*y + mat->m21*z + mat->m31*w; + lt->position.z = mat->m02*x + mat->m12*y + mat->m22*z + mat->m32*w; + lt->position.w = mat->m03*x + mat->m13*y + mat->m23*z + mat->m33*w; + + DIRTY(ltb->position, g->neg_bitid); + break; + case GL_SPOT_DIRECTION: + lt->spotDirection.x = param[0]; + lt->spotDirection.y = param[1]; + lt->spotDirection.z = param[2]; + lt->spotDirection.w = 0.0f; + mat = t->modelViewStack.top; + + if (lt->objPosition.w != 0.0f) + { + lt->spotDirection.w = - ( ( lt->objPosition.x * lt->spotDirection.x + + lt->objPosition.y * lt->spotDirection.y + + lt->objPosition.z * lt->spotDirection.z ) / + lt->objPosition.w ); + } + + crMatrixInvertTranspose(&inv, mat); + crStateTransformXformPointMatrixf (&inv, &(lt->spotDirection)); + + DIRTY(ltb->spot, g->neg_bitid); + break; + case GL_SPOT_EXPONENT: + if (*param < 0.0f || *param > 180.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glLight: spot exponent out of range: %f", *param); + return; + } + lt->spotExponent = *param; + DIRTY(ltb->spot, g->neg_bitid); + break; + case GL_SPOT_CUTOFF: + if ((*param < 0.0f || *param > 90.0f) && *param != 180.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glLight: spot cutoff out of range: %f", *param); + return; + } + lt->spotCutoff = *param; + DIRTY(ltb->spot, g->neg_bitid); + break; + case GL_CONSTANT_ATTENUATION: + if (*param < 0.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glLight: constant Attenuation negative: %f", *param); + return; + } + lt->constantAttenuation = *param; + DIRTY(ltb->attenuation, g->neg_bitid); + break; + case GL_LINEAR_ATTENUATION: + if (*param < 0.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glLight: linear Attenuation negative: %f", *param); + return; + } + lt->linearAttenuation = *param; + DIRTY(ltb->attenuation, g->neg_bitid); + break; + case GL_QUADRATIC_ATTENUATION: + if (*param < 0.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glLight: quadratic Attenuation negative: %f", *param); + return; + } + lt->quadraticAttenuation = *param; + DIRTY(ltb->attenuation, g->neg_bitid); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glLight: invalid pname: 0x%x", pname); + return; + } + DIRTY(ltb->dirty, g->neg_bitid); + DIRTY(lb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateLightiv (GLenum light, GLenum pname, const GLint *param) +{ + GLfloat f_param; + GLcolor f_color; + GLvector f_vector; + + switch (pname) + { + case GL_AMBIENT: + case GL_DIFFUSE: + case GL_SPECULAR: + f_color.r = ((GLfloat)param[0])/CR_MAXINT; + f_color.g = ((GLfloat)param[1])/CR_MAXINT; + f_color.b = ((GLfloat)param[2])/CR_MAXINT; + f_color.a = ((GLfloat)param[3])/CR_MAXINT; + crStateLightfv(light, pname, (GLfloat *) &f_color); + break; + case GL_POSITION: + case GL_SPOT_DIRECTION: + f_vector.x = (GLfloat) param[0]; + f_vector.y = (GLfloat) param[1]; + f_vector.z = (GLfloat) param[2]; + f_vector.w = (GLfloat) param[3]; + crStateLightfv(light, pname, (GLfloat *) &f_vector); + break; + case GL_SPOT_EXPONENT: + case GL_SPOT_CUTOFF: + case GL_CONSTANT_ATTENUATION: + case GL_LINEAR_ATTENUATION: + case GL_QUADRATIC_ATTENUATION: + f_param = (GLfloat) (*param); + crStateLightfv(light, pname, &f_param); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glLight: invalid pname: 0x%x", pname); + return; + } +} + +void STATE_APIENTRY crStateLightf (GLenum light, GLenum pname, GLfloat param) +{ + crStateLightfv(light, pname, ¶m); +} + +void STATE_APIENTRY crStateLighti (GLenum light, GLenum pname, GLint param) +{ + GLfloat f_param = (GLfloat) param; + crStateLightfv(light, pname, &f_param); +} + +void STATE_APIENTRY crStateMaterialfv (GLenum face, GLenum pname, const GLfloat *param) +{ + CRContext *g = GetCurrentContext(); + CRLightingState *l = &(g->lighting); + CRStateBits *sb = GetCurrentBits(); + CRLightingBits *lb = &(sb->lighting); + + if (!g->current.inBeginEnd) + { + FLUSH(); + } + + switch (pname) + { + case GL_AMBIENT : + switch (face) + { + case GL_FRONT: + l->ambient[0].r = param[0]; + l->ambient[0].g = param[1]; + l->ambient[0].b = param[2]; + l->ambient[0].a = param[3]; + break; + case GL_FRONT_AND_BACK: + l->ambient[0].r = param[0]; + l->ambient[0].g = param[1]; + l->ambient[0].b = param[2]; + l->ambient[0].a = param[3]; + RT_FALL_THRU(); + case GL_BACK: + l->ambient[1].r = param[0]; + l->ambient[1].g = param[1]; + l->ambient[1].b = param[2]; + l->ambient[1].a = param[3]; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMaterialfv: bad face: 0x%x", face); + return; + } + break; + case GL_AMBIENT_AND_DIFFUSE : + switch (face) + { + case GL_FRONT: + l->ambient[0].r = param[0]; + l->ambient[0].g = param[1]; + l->ambient[0].b = param[2]; + l->ambient[0].a = param[3]; + break; + case GL_FRONT_AND_BACK: + l->ambient[0].r = param[0]; + l->ambient[0].g = param[1]; + l->ambient[0].b = param[2]; + l->ambient[0].a = param[3]; + RT_FALL_THRU(); + case GL_BACK: + l->ambient[1].r = param[0]; + l->ambient[1].g = param[1]; + l->ambient[1].b = param[2]; + l->ambient[1].a = param[3]; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMaterialfv: bad face: 0x%x", face); + return; + } + RT_FALL_THRU(); + case GL_DIFFUSE : + switch (face) + { + case GL_FRONT: + l->diffuse[0].r = param[0]; + l->diffuse[0].g = param[1]; + l->diffuse[0].b = param[2]; + l->diffuse[0].a = param[3]; + break; + case GL_FRONT_AND_BACK: + l->diffuse[0].r = param[0]; + l->diffuse[0].g = param[1]; + l->diffuse[0].b = param[2]; + l->diffuse[0].a = param[3]; + RT_FALL_THRU(); + case GL_BACK: + l->diffuse[1].r = param[0]; + l->diffuse[1].g = param[1]; + l->diffuse[1].b = param[2]; + l->diffuse[1].a = param[3]; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMaterialfv: bad face: 0x%x", face); + return; + } + break; + case GL_SPECULAR : + switch (face) + { + case GL_FRONT: + l->specular[0].r = param[0]; + l->specular[0].g = param[1]; + l->specular[0].b = param[2]; + l->specular[0].a = param[3]; + break; + case GL_FRONT_AND_BACK: + l->specular[0].r = param[0]; + l->specular[0].g = param[1]; + l->specular[0].b = param[2]; + l->specular[0].a = param[3]; + RT_FALL_THRU(); + case GL_BACK: + l->specular[1].r = param[0]; + l->specular[1].g = param[1]; + l->specular[1].b = param[2]; + l->specular[1].a = param[3]; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMaterialfv: bad face: 0x%x", face); + return; + } + break; + case GL_EMISSION : + switch (face) + { + case GL_FRONT: + l->emission[0].r = param[0]; + l->emission[0].g = param[1]; + l->emission[0].b = param[2]; + l->emission[0].a = param[3]; + break; + case GL_FRONT_AND_BACK: + l->emission[0].r = param[0]; + l->emission[0].g = param[1]; + l->emission[0].b = param[2]; + l->emission[0].a = param[3]; + RT_FALL_THRU(); + case GL_BACK: + l->emission[1].r = param[0]; + l->emission[1].g = param[1]; + l->emission[1].b = param[2]; + l->emission[1].a = param[3]; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMaterialfv: bad face: 0x%x", face); + return; + } + break; + case GL_SHININESS: + if (*param > 180.0f || *param < 0.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glMaterialfv: param out of range: %f", param); + return; + } + + switch (face) + { + case GL_FRONT: + l->shininess[0] = *param; + break; + case GL_FRONT_AND_BACK: + l->shininess[0] = *param; + RT_FALL_THRU(); + case GL_BACK: + l->shininess[1] = *param; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMaterialfv: bad face: 0x%x", face); + return; + } + break; + case GL_COLOR_INDEXES : + switch (face) + { + case GL_FRONT: + l->indexes[0][0] = (GLint) param[0]; + l->indexes[0][1] = (GLint) param[1]; + l->indexes[0][2] = (GLint) param[2]; + break; + case GL_FRONT_AND_BACK: + l->indexes[0][0] = (GLint) param[0]; + l->indexes[0][1] = (GLint) param[1]; + l->indexes[0][2] = (GLint) param[2]; + RT_FALL_THRU(); + case GL_BACK: + l->indexes[1][0] = (GLint) param[0]; + l->indexes[1][1] = (GLint) param[1]; + l->indexes[1][2] = (GLint) param[2]; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMaterialfv: bad face: 0x%x", face); + return; + } + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMaterialfv: bad pname: 0x%x", pname); + return; + } + DIRTY(lb->material, g->neg_bitid); + DIRTY(lb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateMaterialiv (GLenum face, GLenum pname, const GLint *param) +{ + GLfloat f_param; + GLcolor f_color; + + switch (pname) + { + case GL_AMBIENT : + case GL_AMBIENT_AND_DIFFUSE : + case GL_DIFFUSE : + case GL_SPECULAR : + case GL_EMISSION : + f_color.r = ((GLfloat) param[0]) / ((GLfloat) CR_MAXINT); + f_color.g = ((GLfloat) param[1]) / ((GLfloat) CR_MAXINT); + f_color.b = ((GLfloat) param[2]) / ((GLfloat) CR_MAXINT); + f_color.a = ((GLfloat) param[3]) / ((GLfloat) CR_MAXINT); + crStateMaterialfv(face, pname, (GLfloat *) &f_color); + break; + case GL_SHININESS: + f_param = (GLfloat) (*param); + crStateMaterialfv(face, pname, (GLfloat *) &f_param); + break; + case GL_COLOR_INDEXES : + f_param = (GLfloat) (*param); + crStateMaterialfv(face, pname, (GLfloat *) &f_param); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glMaterialiv: bad pname: 0x%x", pname); + return; + } +} + +void STATE_APIENTRY crStateMaterialf (GLenum face, GLenum pname, GLfloat param) +{ + crStateMaterialfv(face, pname, ¶m); +} + +void STATE_APIENTRY crStateMateriali (GLenum face, GLenum pname, GLint param) +{ + GLfloat f_param = (GLfloat) param; + crStateMaterialfv(face, pname, &f_param); +} + +void STATE_APIENTRY crStateGetLightfv (GLenum light, GLenum pname, GLfloat *param) +{ + CRContext *g = GetCurrentContext(); + CRLightingState *l = &(g->lighting); + CRLight *lt; + unsigned int i; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetLightfv called in begin/end"); + return; + } + + i = light - GL_LIGHT0; + if (i>=g->limits.maxLights) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetLight: invalid light specified: 0x%x", light); + return; + } + + lt = l->light + i; + + switch (pname) + { + case GL_AMBIENT: + param[0] = lt->ambient.r; + param[1] = lt->ambient.g; + param[2] = lt->ambient.b; + param[3] = lt->ambient.a; + break; + case GL_DIFFUSE: + param[0] = lt->diffuse.r; + param[1] = lt->diffuse.g; + param[2] = lt->diffuse.b; + param[3] = lt->diffuse.a; + break; + case GL_SPECULAR: + param[0] = lt->specular.r; + param[1] = lt->specular.g; + param[2] = lt->specular.b; + param[3] = lt->specular.a; + break; + case GL_POSITION: + param[0] = lt->position.x; + param[1] = lt->position.y; + param[2] = lt->position.z; + param[3] = lt->position.w; + break; + case GL_SPOT_DIRECTION: + param[0] = lt->spotDirection.x; + param[1] = lt->spotDirection.y; + param[2] = lt->spotDirection.z; +#if 0 + /* the w-component of the direction, although possibly (?) + useful to keep around internally, is not returned as part + of the get. */ + param[3] = lt->spotDirection.w; +#endif + break; + case GL_SPOT_EXPONENT: + *param = lt->spotExponent; + break; + case GL_SPOT_CUTOFF: + *param = lt->spotCutoff; + break; + case GL_CONSTANT_ATTENUATION: + *param = lt->constantAttenuation; + break; + case GL_LINEAR_ATTENUATION: + *param = lt->linearAttenuation; + break; + case GL_QUADRATIC_ATTENUATION: + *param = lt->quadraticAttenuation; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetLight: invalid pname: 0x%x", pname); + return; + } +} + +void STATE_APIENTRY crStateGetLightiv (GLenum light, GLenum pname, GLint *param) +{ + CRContext *g = GetCurrentContext(); + CRLightingState *l = &(g->lighting); + CRLight *lt; + unsigned int i; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetLightiv called in begin/end"); + return; + } + + i = light - GL_LIGHT0; + if (i>=g->limits.maxLights) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetLight: invalid light specified: 0x%x", light); + return; + } + + lt = l->light + i; + + switch (pname) + { + case GL_AMBIENT: + param[0] = (GLint) (lt->ambient.r * CR_MAXINT); + param[1] = (GLint) (lt->ambient.g * CR_MAXINT); + param[2] = (GLint) (lt->ambient.b * CR_MAXINT); + param[3] = (GLint) (lt->ambient.a * CR_MAXINT); + break; + case GL_DIFFUSE: + param[0] = (GLint) (lt->diffuse.r * CR_MAXINT); + param[1] = (GLint) (lt->diffuse.g * CR_MAXINT); + param[2] = (GLint) (lt->diffuse.b * CR_MAXINT); + param[3] = (GLint) (lt->diffuse.a * CR_MAXINT); + break; + case GL_SPECULAR: + param[0] = (GLint) (lt->specular.r * CR_MAXINT); + param[1] = (GLint) (lt->specular.g * CR_MAXINT); + param[2] = (GLint) (lt->specular.b * CR_MAXINT); + param[3] = (GLint) (lt->specular.a * CR_MAXINT); + break; + case GL_POSITION: + param[0] = (GLint) (lt->position.x); + param[1] = (GLint) (lt->position.y); + param[2] = (GLint) (lt->position.z); + param[3] = (GLint) (lt->position.w); + break; + case GL_SPOT_DIRECTION: + param[0] = (GLint) (lt->spotDirection.x); + param[1] = (GLint) (lt->spotDirection.y); + param[2] = (GLint) (lt->spotDirection.z); +#if 0 + /* the w-component of the direction, although possibly (?) + useful to keep around internally, is not returned as part + of the get. */ + param[3] = (GLint) (lt->spotDirection.w); +#endif + break; + case GL_SPOT_EXPONENT: + *param = (GLint) (lt->spotExponent); + break; + case GL_SPOT_CUTOFF: + *param = (GLint) (lt->spotCutoff); + break; + case GL_CONSTANT_ATTENUATION: + *param = (GLint) (lt->constantAttenuation); + break; + case GL_LINEAR_ATTENUATION: + *param = (GLint) (lt->linearAttenuation); + break; + case GL_QUADRATIC_ATTENUATION: + *param = (GLint) (lt->quadraticAttenuation); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetLight: invalid pname: 0x%x", pname); + return; + } +} + +void STATE_APIENTRY crStateGetMaterialfv (GLenum face, GLenum pname, GLfloat *param) +{ + CRContext *g = GetCurrentContext(); + CRLightingState *l = &(g->lighting); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetMaterialfv called in begin/end"); + return; + } + + switch (pname) + { + case GL_AMBIENT: + switch (face) + { + case GL_FRONT: + param[0] = l->ambient[0].r; + param[1] = l->ambient[0].g; + param[2] = l->ambient[0].b; + param[3] = l->ambient[0].a; + break; + case GL_BACK: + param[0] = l->ambient[1].r; + param[1] = l->ambient[1].g; + param[2] = l->ambient[1].b; + param[3] = l->ambient[1].a; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetMaterialfv: bad face: 0x%x", face); + return; + } + break; + case GL_DIFFUSE: + switch (face) + { + case GL_FRONT: + param[0] = l->diffuse[0].r; + param[1] = l->diffuse[0].g; + param[2] = l->diffuse[0].b; + param[3] = l->diffuse[0].a; + break; + case GL_BACK: + param[0] = l->diffuse[1].r; + param[1] = l->diffuse[1].g; + param[2] = l->diffuse[1].b; + param[3] = l->diffuse[1].a; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetMaterialfv: bad face: 0x%x", face); + return; + } + break; + case GL_SPECULAR : + switch (face) + { + case GL_FRONT: + param[0] = l->specular[0].r; + param[1] = l->specular[0].g; + param[2] = l->specular[0].b; + param[3] = l->specular[0].a; + break; + case GL_BACK: + param[0] = l->specular[1].r; + param[1] = l->specular[1].g; + param[2] = l->specular[1].b; + param[3] = l->specular[1].a; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetMaterialfv: bad face: 0x%x", face); + return; + } + break; + case GL_EMISSION: + switch (face) + { + case GL_FRONT: + param[0] = l->emission[0].r; + param[1] = l->emission[0].g; + param[2] = l->emission[0].b; + param[3] = l->emission[0].a; + break; + case GL_BACK: + param[0] = l->emission[1].r; + param[1] = l->emission[1].g; + param[2] = l->emission[1].b; + param[3] = l->emission[1].a; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetMaterialfv: bad face: 0x%x", face); + return; + } + break; + case GL_SHININESS: + switch (face) + { + case GL_FRONT: + *param = l->shininess[0]; + break; + case GL_BACK: + *param = l->shininess[1]; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetMaterialfv: bad face: 0x%x", face); + return; + } + break; + case GL_COLOR_INDEXES : + switch (face) + { + case GL_FRONT: + param[0] = (GLfloat) l->indexes[0][0]; + param[1] = (GLfloat) l->indexes[0][1]; + param[2] = (GLfloat) l->indexes[0][2]; + break; + case GL_BACK: + param[0] = (GLfloat) l->indexes[1][0]; + param[1] = (GLfloat) l->indexes[1][1]; + param[2] = (GLfloat) l->indexes[1][2]; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetMaterialfv: bad face: 0x%x", face); + return; + } + return; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetMaterialfv: bad pname: 0x%x", pname); + return; + } +} + + +void STATE_APIENTRY crStateGetMaterialiv (GLenum face, GLenum pname, GLint *param) +{ + CRContext *g = GetCurrentContext(); + CRLightingState *l = &(g->lighting); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetMaterialiv called in begin/end"); + return; + } + + switch (pname) + { + case GL_AMBIENT: + switch (face) + { + case GL_FRONT: + param[0] = (GLint) (l->ambient[0].r * CR_MAXINT); + param[1] = (GLint) (l->ambient[0].g * CR_MAXINT); + param[2] = (GLint) (l->ambient[0].b * CR_MAXINT); + param[3] = (GLint) (l->ambient[0].a * CR_MAXINT); + break; + case GL_BACK: + param[0] = (GLint) (l->ambient[1].r * CR_MAXINT); + param[1] = (GLint) (l->ambient[1].g * CR_MAXINT); + param[2] = (GLint) (l->ambient[1].b * CR_MAXINT); + param[3] = (GLint) (l->ambient[1].a * CR_MAXINT); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetMaterialiv: bad face: 0x%x", face); + return; + } + break; + case GL_DIFFUSE: + switch (face) + { + case GL_FRONT: + param[0] = (GLint) (l->diffuse[0].r * CR_MAXINT); + param[1] = (GLint) (l->diffuse[0].g * CR_MAXINT); + param[2] = (GLint) (l->diffuse[0].b * CR_MAXINT); + param[3] = (GLint) (l->diffuse[0].a * CR_MAXINT); + break; + case GL_BACK: + param[0] = (GLint) (l->diffuse[1].r * CR_MAXINT); + param[1] = (GLint) (l->diffuse[1].g * CR_MAXINT); + param[2] = (GLint) (l->diffuse[1].b * CR_MAXINT); + param[3] = (GLint) (l->diffuse[1].a * CR_MAXINT); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetMaterialiv: bad face: 0x%x", face); + return; + } + break; + case GL_SPECULAR: + switch (face) + { + case GL_FRONT: + param[0] = (GLint) (l->specular[0].r * CR_MAXINT); + param[1] = (GLint) (l->specular[0].g * CR_MAXINT); + param[2] = (GLint) (l->specular[0].b * CR_MAXINT); + param[3] = (GLint) (l->specular[0].a * CR_MAXINT); + break; + case GL_BACK: + param[0] = (GLint) (l->specular[1].r * CR_MAXINT); + param[1] = (GLint) (l->specular[1].g * CR_MAXINT); + param[2] = (GLint) (l->specular[1].b * CR_MAXINT); + param[3] = (GLint) (l->specular[1].a * CR_MAXINT); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetMaterialiv: bad face: 0x%x", face); + return; + } + break; + case GL_EMISSION: + switch (face) + { + case GL_FRONT: + param[0] = (GLint) (l->emission[0].r * CR_MAXINT); + param[1] = (GLint) (l->emission[0].g * CR_MAXINT); + param[2] = (GLint) (l->emission[0].b * CR_MAXINT); + param[3] = (GLint) (l->emission[0].a * CR_MAXINT); + break; + case GL_BACK: + param[0] = (GLint) (l->emission[1].r * CR_MAXINT); + param[1] = (GLint) (l->emission[1].g * CR_MAXINT); + param[2] = (GLint) (l->emission[1].b * CR_MAXINT); + param[3] = (GLint) (l->emission[1].a * CR_MAXINT); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetMaterialiv: bad face: 0x%x", face); + return; + } + break; + case GL_SHININESS: + switch (face) { + case GL_FRONT: + *param = (GLint) l->shininess[0]; + break; + case GL_BACK: + *param = (GLint) l->shininess[1]; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetMaterialiv: bad face: 0x%x", face); + return; + } + break; + case GL_COLOR_INDEXES : + switch (face) + { + case GL_FRONT: + param[0] = (GLint) l->indexes[0][0]; + param[1] = (GLint) l->indexes[0][1]; + param[2] = (GLint) l->indexes[0][2]; + break; + case GL_BACK: + param[0] = (GLint) l->indexes[1][0]; + param[1] = (GLint) l->indexes[1][1]; + param[2] = (GLint) l->indexes[1][2]; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetMaterialiv: bad face: 0x%x", face); + return; + } + return; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetMaterialiv: bad pname: 0x%x", pname); + return; + } +} + +void crStateColorMaterialRecover(void) +{ + CRContext *g = GetCurrentContext(); + CRLightingState *l = &(g->lighting); + CRCurrentState *c = &(g->current); + + /* Assuming that the "current" values are up to date, + * this function will extract them into the material + * values if COLOR_MATERIAL has been enabled on the + * client. */ + + if (l->colorMaterial) + { + /* prevent recursion here (was in tilesortspu_flush.c's doFlush() for a + * short time. Without this, kirchner_colormaterial fails. + */ + crStateFlushFunc(NULL); + + crStateMaterialfv(l->colorMaterialFace, l->colorMaterialMode, &(c->vertexAttrib[VERT_ATTRIB_COLOR0][0])); + } +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_lighting.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_lighting.txt new file mode 100644 index 00000000..0a072213 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_lighting.txt @@ -0,0 +1,63 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +:colorMaterial:colorMaterialFace,colorMaterialMode:ColorMaterial +:enable:lighting:GL_LIGHTING +:enable:colorMaterial:GL_COLOR_MATERIAL +:enable:colorSumEXT:GL_COLOR_SUM_EXT +:shadeModel:shadeModel:ShadeModel +:lightModel:lightModelAmbient|r,g,b,a:LightModelfv,GL_LIGHT_MODEL_AMBIENT +:lightModel:lightModelLocalViewer:*diff_api.LightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, to->lightModelLocalViewer==GL_TRUE); +:lightModel:lightModelTwoSide:*diff_api.LightModeli(GL_LIGHT_MODEL_TWO_SIDE, to->lightModelTwoSide==GL_TRUE); +:lightModel:lightModelColorControlEXT:*diff_api.LightModeli(GL_LIGHT_MODEL_COLOR_CONTROL_EXT, to->lightModelColorControlEXT); +%flush +:material:ambient[0]|r,g,b,a:Materialfv, GL_FRONT, GL_AMBIENT +:material:ambient[1]|r,g,b,a:Materialfv, GL_BACK, GL_AMBIENT +:material:diffuse[0]|r,g,b,a:Materialfv, GL_FRONT, GL_DIFFUSE +:material:diffuse[1]|r,g,b,a:Materialfv, GL_BACK, GL_DIFFUSE +:material:specular[0]|r,g,b,a:Materialfv, GL_FRONT, GL_SPECULAR +:material:specular[1]|r,g,b,a:Materialfv, GL_BACK, GL_SPECULAR +:material:emission[0]|r,g,b,a:Materialfv, GL_FRONT, GL_EMISSION +:material:emission[1]|r,g,b,a:Materialfv, GL_BACK, GL_EMISSION +:material:shininess[0]:Materialf, GL_FRONT, GL_SHININESS +:material:shininess[1]:Materialf, GL_BACK, GL_SHININESS +%flush +>for (i=0; i<CR_MAX_LIGHTS; i++) { +>CRLightBits *lb = b->light+i; +>CRLight *tl = to->light+i; +>CRLight *cl = from->light+i; +>if (!(CHECKDIRTY(lb->dirty, bitID))) continue; +%target=tl +%current=cl +%bit=lb +%extrabit=b +:enable:enable:GL_LIGHT0+i +%flush +:ambient:ambient|r,g,b,a:Lightfv, GL_LIGHT0+i, GL_AMBIENT +:diffuse:diffuse|r,g,b,a:Lightfv, GL_LIGHT0+i, GL_DIFFUSE +:specular:specular|r,g,b,a:Lightfv, GL_LIGHT0+i, GL_SPECULAR +:attenuation:constantAttenuation:Lightf, GL_LIGHT0+i, GL_CONSTANT_ATTENUATION +:attenuation:linearAttenuation:Lightf, GL_LIGHT0+i, GL_LINEAR_ATTENUATION +:attenuation:quadraticAttenuation:Lightf, GL_LIGHT0+i, GL_QUADRATIC_ATTENUATION +:position:*diff_api.MatrixMode(GL_MODELVIEW); +:position:*diff_api.PushMatrix(); +:position:*diff_api.LoadIdentity(); +:position:position|x,y,z,w:Lightfv, GL_LIGHT0+i, GL_POSITION +:position:*diff_api.PopMatrix(); +:position:*diff_api.MatrixMode(toCtx->transform.matrixMode); +:spot:*diff_api.MatrixMode(GL_MODELVIEW); +:spot:*diff_api.PushMatrix(); +:spot:*diff_api.LoadIdentity(); +:spot:spotDirection|x,y,z:Lightfv, GL_LIGHT0+i, GL_SPOT_DIRECTION +:spot:spotExponent:Lightf, GL_LIGHT0+i, GL_SPOT_EXPONENT +:spot:spotCutoff:Lightf, GL_LIGHT0+i, GL_SPOT_CUTOFF +:spot:*diff_api.PopMatrix(); +:spot:*diff_api.MatrixMode(toCtx->transform.matrixMode); +%flush +>CLEARDIRTY(lb->dirty, nbitID); +>} +%target=to +%current=from +%bit=b +%extrabit= diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_limits.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_limits.c new file mode 100644 index 00000000..91cdd84f --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_limits.c @@ -0,0 +1,475 @@ + +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include <stdio.h> +#include "state.h" +#include "state/cr_statetypes.h" +#include "cr_mem.h" +#include "cr_string.h" +#include "cr_extstring.h" + +#ifdef WINDOWS +#pragma warning( disable : 4127 ) +#endif + + +/* This is a debug helper function. */ +void crStateLimitsPrint (const CRLimitsState *l) +{ + fprintf(stderr, "----------- OpenGL limits ----------------\n"); + fprintf(stderr, "GL_MAX_TEXTURE_UNITS = %d\n", (int) l->maxTextureUnits); + fprintf(stderr, "GL_MAX_TEXTURE_SIZE = %d\n", (int) l->maxTextureSize); + fprintf(stderr, "GL_MAX_3D_TEXTURE_SIZE = %d\n", (int) l->max3DTextureSize); + fprintf(stderr, "GL_MAX_CUBE_MAP_TEXTURE_SIZE = %d\n", (int) l->maxCubeMapTextureSize); + fprintf(stderr, "GL_MAX_TEXTURE_ANISOTROPY = %f\n", l->maxTextureAnisotropy); + fprintf(stderr, "GL_MAX_LIGHTS = %d\n", (int) l->maxLights); + fprintf(stderr, "GL_MAX_CLIP_PLANES = %d\n", (int) l->maxClipPlanes); + fprintf(stderr, "GL_MAX_ATTRIB_STACK_DEPTH = %d\n", (int) l->maxClientAttribStackDepth); + fprintf(stderr, "GL_MAX_PROJECTION_STACK_DEPTH = %d\n", (int) l->maxProjectionStackDepth); + fprintf(stderr, "GL_MAX_MODELVIEW_STACK_DEPTH = %d\n", (int) l->maxModelviewStackDepth); + fprintf(stderr, "GL_MAX_TEXTURE_STACK_DEPTH = %d\n", (int) l->maxTextureStackDepth); + fprintf(stderr, "GL_MAX_COLOR_STACK_DEPTH = %d\n", (int) l->maxColorStackDepth); + fprintf(stderr, "GL_MAX_ATTRIB_STACK_DEPTH = %d\n", (int) l->maxAttribStackDepth); + fprintf(stderr, "GL_MAX_ATTRIB_STACK_DEPTH = %d\n", (int) l->maxClientAttribStackDepth); + fprintf(stderr, "GL_MAX_NAME_STACK_DEPTH = %d\n", (int) l->maxNameStackDepth); + fprintf(stderr, "GL_MAX_ELEMENTS_INDICES = %d\n", (int) l->maxElementsIndices); + fprintf(stderr, "GL_MAX_ELEMENTS_VERTICES = %d\n", (int) l->maxElementsVertices); + fprintf(stderr, "GL_MAX_EVAL_ORDER = %d\n", (int) l->maxEvalOrder); + fprintf(stderr, "GL_MAX_LIST_NESTING = %d\n", (int) l->maxListNesting); + fprintf(stderr, "GL_MAX_PIXEL_MAP_TABLE = %d\n", (int) l->maxPixelMapTable); + fprintf(stderr, "GL_MAX_VIEWPORT_DIMS = %d %d\n", + (int) l->maxViewportDims[0], (int) l->maxViewportDims[1]); + fprintf(stderr, "GL_SUBPIXEL_BITS = %d\n", (int) l->subpixelBits); + fprintf(stderr, "GL_ALIASED_POINT_SIZE_RANGE = %f .. %f\n", + l->aliasedPointSizeRange[0], l->aliasedPointSizeRange[1]); + fprintf(stderr, "GL_SMOOTH_POINT_SIZE_RANGE = %f .. %f\n", + l->aliasedPointSizeRange[0], l->aliasedPointSizeRange[1]); + fprintf(stderr, "GL_POINT_SIZE_GRANULARITY = %f\n", l->pointSizeGranularity); + fprintf(stderr, "GL_ALIASED_LINE_WIDTH_RANGE = %f .. %f\n", + l->aliasedLineWidthRange[0], l->aliasedLineWidthRange[1]); + fprintf(stderr, "GL_SMOOTH_LINE_WIDTH_RANGE = %f .. %f\n", + l->smoothLineWidthRange[0], l->smoothLineWidthRange[1]); + fprintf(stderr, "GL_LINE_WIDTH_GRANULARITY = %f\n", l->lineWidthGranularity); + fprintf(stderr, "GL_MAX_GENERAL_COMBINERS_NV = %d\n", (int) l->maxGeneralCombiners); + fprintf(stderr, "GL_EXTENSIONS = %s\n", (const char *) l->extensions); + fprintf(stderr, "------------------------------------------\n"); +} + + +void crStateLimitsDestroy(CRLimitsState *l) +{ + if (l->extensions) { + crFree((void *) l->extensions); + l->extensions = NULL; + } +} + + +/* + * Initialize the CRLimitsState object to Chromium's defaults. + */ +void crStateLimitsInit (CRLimitsState *l) +{ + l->maxTextureUnits = CR_MAX_TEXTURE_UNITS; + l->maxTextureSize = CR_MAX_TEXTURE_SIZE; + l->max3DTextureSize = CR_MAX_3D_TEXTURE_SIZE; + l->maxCubeMapTextureSize = CR_MAX_CUBE_TEXTURE_SIZE; +#ifdef CR_NV_texture_rectangle + l->maxRectTextureSize = CR_MAX_RECTANGLE_TEXTURE_SIZE; +#endif + l->maxTextureAnisotropy = CR_MAX_TEXTURE_ANISOTROPY; + l->maxGeneralCombiners = CR_MAX_GENERAL_COMBINERS; + l->maxLights = CR_MAX_LIGHTS; + l->maxClipPlanes = CR_MAX_CLIP_PLANES; + l->maxClientAttribStackDepth = CR_MAX_ATTRIB_STACK_DEPTH; + l->maxProjectionStackDepth = CR_MAX_PROJECTION_STACK_DEPTH; + l->maxModelviewStackDepth = CR_MAX_MODELVIEW_STACK_DEPTH; + l->maxTextureStackDepth = CR_MAX_TEXTURE_STACK_DEPTH; + l->maxColorStackDepth = CR_MAX_COLOR_STACK_DEPTH; + l->maxAttribStackDepth = CR_MAX_ATTRIB_STACK_DEPTH; + l->maxClientAttribStackDepth = CR_MAX_ATTRIB_STACK_DEPTH; + l->maxNameStackDepth = CR_MAX_NAME_STACK_DEPTH; + l->maxElementsIndices = CR_MAX_ELEMENTS_INDICES; + l->maxElementsVertices = CR_MAX_ELEMENTS_VERTICES; + l->maxEvalOrder = CR_MAX_EVAL_ORDER; + l->maxListNesting = CR_MAX_LIST_NESTING; + l->maxPixelMapTable = CR_MAX_PIXEL_MAP_TABLE; + l->maxViewportDims[0] = l->maxViewportDims[1] = CR_MAX_VIEWPORT_DIM; + l->subpixelBits = CR_SUBPIXEL_BITS; + l->aliasedPointSizeRange[0] = CR_ALIASED_POINT_SIZE_MIN; + l->aliasedPointSizeRange[1] = CR_ALIASED_POINT_SIZE_MAX; + l->smoothPointSizeRange[0] = CR_SMOOTH_POINT_SIZE_MIN; + l->smoothPointSizeRange[1] = CR_SMOOTH_POINT_SIZE_MAX; + l->pointSizeGranularity = CR_POINT_SIZE_GRANULARITY; + l->aliasedLineWidthRange[0] = CR_ALIASED_LINE_WIDTH_MIN; + l->aliasedLineWidthRange[1] = CR_ALIASED_LINE_WIDTH_MAX; + l->smoothLineWidthRange[0] = CR_SMOOTH_LINE_WIDTH_MIN; + l->smoothLineWidthRange[1] = CR_SMOOTH_LINE_WIDTH_MAX; + l->lineWidthGranularity = CR_LINE_WIDTH_GRANULARITY; +#ifdef CR_EXT_texture_lod_bias + l->maxTextureLodBias = CR_MAX_TEXTURE_LOD_BIAS; +#endif +#ifdef CR_NV_fragment_program + l->maxTextureCoords = CR_MAX_TEXTURE_COORDS; + l->maxTextureImageUnits = CR_MAX_TEXTURE_IMAGE_UNITS; + l->maxFragmentProgramLocalParams = CR_MAX_FRAGMENT_LOCAL_PARAMS; +#endif +#ifdef CR_NV_vertex_program + l->maxProgramMatrixStackDepth = CR_MAX_PROGRAM_MATRIX_STACK_DEPTH; + l->maxProgramMatrices = CR_MAX_PROGRAM_MATRICES; +#endif +#ifdef CR_ARB_fragment_program + l->maxFragmentProgramInstructions = CR_MAX_FRAGMENT_PROGRAM_INSTRUCTIONS; + l->maxFragmentProgramLocalParams = CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS; + l->maxFragmentProgramEnvParams = CR_MAX_FRAGMENT_PROGRAM_ENV_PARAMS; + l->maxFragmentProgramTemps = CR_MAX_FRAGMENT_PROGRAM_TEMPS; + l->maxFragmentProgramAttribs = CR_MAX_FRAGMENT_PROGRAM_ATTRIBS; + l->maxFragmentProgramAddressRegs = CR_MAX_FRAGMENT_PROGRAM_ADDRESS_REGS; + l->maxFragmentProgramAluInstructions = CR_MAX_FRAGMENT_PROGRAM_ALU_INSTRUCTIONS; + l->maxFragmentProgramTexInstructions = CR_MAX_FRAGMENT_PROGRAM_TEX_INSTRUCTIONS; + l->maxFragmentProgramTexIndirections = CR_MAX_FRAGMENT_PROGRAM_TEX_INDIRECTIONS; +#endif +#ifdef CR_ARB_vertex_program + l->maxVertexProgramInstructions = CR_MAX_VERTEX_PROGRAM_INSTRUCTIONS; + l->maxVertexProgramLocalParams = CR_MAX_VERTEX_PROGRAM_LOCAL_PARAMS; + l->maxVertexProgramEnvParams = CR_MAX_VERTEX_PROGRAM_ENV_PARAMS; + l->maxVertexProgramTemps = CR_MAX_VERTEX_PROGRAM_TEMPS; + l->maxVertexProgramAttribs = CR_MAX_VERTEX_PROGRAM_ATTRIBS; + l->maxVertexProgramAddressRegs = CR_MAX_VERTEX_PROGRAM_ADDRESS_REGS; +#endif + + l->extensions = (GLubyte *) crStrdup(crExtensions); + + /* These will get properly set in crStateCreateContext() by examining + * the visBits bitfield parameter. + */ + l->redBits = 0; + l->greenBits = 0; + l->blueBits = 0; + l->alphaBits = 0; + l->depthBits = 0; + l->stencilBits = 0; + l->accumRedBits = 0; + l->accumGreenBits = 0; + l->accumBlueBits = 0; + l->accumAlphaBits = 0; + l->auxBuffers = 0; + l->rgbaMode = GL_TRUE; + l->doubleBuffer = GL_FALSE; + l->stereo = GL_FALSE; + l->sampleBuffers = 0; + l->samples = 0; + l->level = 0; + + (void) crAppOnlyExtensions; /* silence warning */ +} + + +/* + * Given the GL version number returned from a real GL renderer, + * compute the version number supported by Chromium. + */ +GLfloat crStateComputeVersion(float minVersion) +{ + const GLfloat crVersion = crStrToFloat(CR_OPENGL_VERSION_STRING); + if (crVersion < minVersion) + minVersion = crVersion; + return minVersion; +} + + +/* + * <extenions> is an array [n] of GLubyte pointers which contain lists of + * OpenGL extensions. + * Compute the intersection of those strings, then append the Chromium + * extension strings. + */ +GLubyte * crStateMergeExtensions(GLuint n, const GLubyte **extensions) +{ + char *merged, *result; + GLuint i; + + /* find intersection of all extension strings */ + merged = crStrdup(crExtensions); + for (i = 0; i < n; i++) + { + char *m = crStrIntersect(merged, (const char *) extensions[i]); + if (merged) + crFree(merged); + merged = m; + } + + /* append Cr extensions */ + result = crStrjoin(merged, crChromiumExtensions); + crFree(merged); + return (GLubyte *) result; +} + +static GLboolean hasExtension(const char *haystack, const char *needle) +{ + const int needleLen = crStrlen(needle); + const char *s; + + while (1) { + s = crStrstr(haystack, needle); + if (!s) + return GL_FALSE; + if (s && (s[needleLen] == ' ' || s[needleLen] == 0)) + return GL_TRUE; + haystack += needleLen; + } +} + +/* + * Examine the context's extension string and set the boolean extension + * flags accordingly. This is to be called during context initialization. + */ +void crStateExtensionsInit( CRLimitsState *limits, CRExtensionState *extensions ) +{ + /* init all booleans to false */ + crMemZero(extensions, sizeof(CRExtensionState)); + + if (hasExtension((const char*)limits->extensions, "GL_ARB_depth_texture")) + extensions->ARB_depth_texture = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_fragment_program")) + extensions->ARB_fragment_program = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_imaging")) + extensions->ARB_imaging = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_multisample")) + extensions->ARB_multisample = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_multitexture")) + extensions->ARB_multitexture = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_occlusion_query")) + extensions->ARB_occlusion_query = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_point_parameters")) + extensions->ARB_point_parameters = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_point_sprite")) + extensions->ARB_point_sprite = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_shadow")) + extensions->ARB_shadow = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_shadow_ambient")) + extensions->ARB_shadow_ambient = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_texture_border_clamp") || + hasExtension((const char*)limits->extensions, "GL_SGIS_texture_border_clamp")) + extensions->ARB_texture_border_clamp = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_texture_compression")) + extensions->ARB_texture_compression = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_texture_cube_map") || + hasExtension((const char*)limits->extensions, "GL_EXT_texture_cube_map")) + extensions->ARB_texture_cube_map = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_texture_env_add")) + extensions->ARB_texture_env_add = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_texture_env_combine") || + hasExtension((const char*)limits->extensions, "GL_EXT_texture_env_combine")) + extensions->ARB_texture_env_combine = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_texture_env_crossbar")) + extensions->ARB_texture_env_crossbar = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_texture_env_dot3") || + hasExtension((const char*)limits->extensions, "GL_EXT_texture_env_dot3")) + extensions->ARB_texture_env_dot3 = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_texture_mirrored_repeat")) + extensions->ARB_texture_mirrored_repeat = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ATI_texture_mirror_once")) + extensions->ATI_texture_mirror_once = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_texture_non_power_of_two")) + extensions->ARB_texture_non_power_of_two = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_transpose_matrix")) + extensions->ARB_transpose_matrix = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_vertex_buffer_object")) + extensions->ARB_vertex_buffer_object = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_pixel_buffer_object")) + extensions->ARB_pixel_buffer_object = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_vertex_program")) + extensions->ARB_vertex_program = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_ARB_window_pos")) + extensions->ARB_window_pos = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_EXT_blend_color")) + extensions->EXT_blend_color= GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_EXT_blend_minmax")) + extensions->EXT_blend_minmax = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_EXT_blend_func_separate")) + extensions->EXT_blend_func_separate = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_EXT_blend_logic_op")) + extensions->EXT_blend_logic_op = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_EXT_blend_subtract")) + extensions->EXT_blend_subtract = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_EXT_clip_volume_hint")) + extensions->EXT_clip_volume_hint = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_EXT_fog_coord")) + extensions->EXT_fog_coord = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_EXT_multi_draw_arrays")) + extensions->EXT_multi_draw_arrays = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_EXT_secondary_color")) + extensions->EXT_secondary_color = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_EXT_separate_specular_color")) + extensions->EXT_separate_specular_color = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_EXT_shadow_funcs")) + extensions->EXT_shadow_funcs = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_EXT_stencil_wrap")) + extensions->EXT_stencil_wrap = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_EXT_texture_edge_clamp") || + hasExtension((const char*)limits->extensions, "GL_SGIS_texture_edge_clamp")) + extensions->EXT_texture_edge_clamp = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_EXT_texture_filter_anisotropic")) + extensions->EXT_texture_filter_anisotropic = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_EXT_texture_lod_bias")) + extensions->EXT_texture_lod_bias = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_IBM_rasterpos_clip")) + extensions->IBM_rasterpos_clip = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_NV_fog_distance")) + extensions->NV_fog_distance = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_NV_fragment_program")) + extensions->NV_fragment_program = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_NV_register_combiners")) + extensions->NV_register_combiners = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_NV_register_combiners2")) + extensions->NV_register_combiners2 = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_NV_texgen_reflection")) + extensions->NV_texgen_reflection = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_NV_texture_rectangle") + || hasExtension((const char*)limits->extensions, "GL_EXT_texture_rectangle")) + extensions->NV_texture_rectangle = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_NV_vertex_program")) + extensions->NV_vertex_program = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_NV_vertex_program1_1")) + extensions->NV_vertex_program1_1 = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_NV_vertex_program2")) + extensions->NV_vertex_program2 = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_EXT_texture3D")) + extensions->EXT_texture3D = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GL_SGIS_generate_mipmap")) + extensions->SGIS_generate_mipmap = GL_TRUE; + + if (hasExtension((const char*)limits->extensions, "GLX_EXT_texture_from_pixmap")) + extensions->EXT_texture_from_pixmap = GL_TRUE; + + if (extensions->NV_vertex_program2) + limits->maxVertexProgramEnvParams = 256; + else + limits->maxVertexProgramEnvParams = 96; + + if (extensions->NV_vertex_program || extensions->ARB_vertex_program) + extensions->any_vertex_program = GL_TRUE; + if (extensions->NV_fragment_program || extensions->ARB_fragment_program) + extensions->any_fragment_program = GL_TRUE; + if (extensions->any_vertex_program || extensions->any_fragment_program) + extensions->any_program = GL_TRUE; + +#if 0 + /* Now, determine what level of OpenGL we support */ + if (extensions->ARB_multisample && + extensions->ARB_multitexture && + extensions->ARB_texture_border_clamp && + extensions->ARB_texture_compression && + extensions->ARB_texture_cube_map && + extensions->ARB_texture_env_add && + extensions->ARB_texture_env_combine && + extensions->ARB_texture_env_dot3) { + if (extensions->ARB_depth_texture && + extensions->ARB_point_parameters && + extensions->ARB_shadow && + extensions->ARB_texture_env_crossbar && + extensions->ARB_texture_mirrored_repeat && + extensions->ARB_window_pos && + extensions->EXT_blend_color && + extensions->EXT_blend_func_separate && + extensions->EXT_blend_logic_op && + extensions->EXT_blend_minmax && + extensions->EXT_blend_subtract && + extensions->EXT_fog_coord && + extensions->EXT_multi_draw_arrays && + extensions->EXT_secondary_color && + extensions->EXT_shadow_funcs && + extensions->EXT_stencil_wrap && + extensions->SGIS_generate_mipmap) { + if (extensions->ARB_occlusion_query && + extensions->ARB_vertex_buffer_object && + extensions->ARB_texture_non_power_of_two && + extensions->EXT_shadow_funcs) { + extensions->version = (const GLubyte *) "1.5 Chromium " CR_VERSION_STRING; + } + else { + extensions->version = (const GLubyte *) "1.4 Chromium " CR_VERSION_STRING; + } + } + else { + extensions->version = (const GLubyte *) "1.3 Chromium " CR_VERSION_STRING; + } + } + else { + extensions->version = (const GLubyte *) "1.2 Chromium " CR_VERSION_STRING; + } +#endif +} + + +/* + * Set the GL_EXTENSIONS string for the given context. We'll make + * a copy of the given string. + */ +void +crStateSetExtensionString( CRContext *ctx, const GLubyte *extensions ) +{ + if (ctx->limits.extensions) + crFree((void *) ctx->limits.extensions); + + ctx->limits.extensions = (const GLubyte *)crStrdup((const char*)extensions); + + crStateExtensionsInit(&(ctx->limits), &(ctx->extensions)); +} + diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_line.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_line.c new file mode 100644 index 00000000..ef4a3b4a --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_line.c @@ -0,0 +1,87 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include <stdio.h> +#include "state.h" +#include "state/cr_statetypes.h" +#include "state_internals.h" + +void crStateLineInit (CRContext *ctx) +{ + CRLineState *l = &ctx->line; + CRStateBits *sb = GetCurrentBits(); + CRLineBits *lb = &(sb->line); + + l->lineSmooth = GL_FALSE; + l->lineStipple = GL_FALSE; + RESET(lb->enable, ctx->bitid); + l->width = 1.0f; + RESET(lb->width, ctx->bitid); + l->pattern = 0xFFFF; + l->repeat = 1; + RESET(lb->stipple, ctx->bitid); + /* + *l->aliasedlinewidth_min = c->aliasedlinewidth_min; + *l->aliasedlinewidth_max = c->aliasedlinewidth_max; + *l->aliasedlinegranularity = c->aliasedlinegranularity; + *l->smoothlinewidth_min = c->smoothlinewidth_min; + *l->smoothlinewidth_max = c->smoothlinewidth_max; + *l->smoothlinegranularity = c->smoothlinegranularity; */ + + RESET(lb->dirty, ctx->bitid); +} + +void STATE_APIENTRY crStateLineWidth(GLfloat width) +{ + CRContext *g = GetCurrentContext(); + CRLineState *l = &(g->line); + CRStateBits *sb = GetCurrentBits(); + CRLineBits *lb = &(sb->line); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glLineWidth called in begin/end"); + return; + } + + FLUSH(); + + if (width <= 0.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glLineWidth called with size <= 0.0: %f", width); + return; + } + + l->width = width; + DIRTY(lb->width, g->neg_bitid); + DIRTY(lb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateLineStipple(GLint factor, GLushort pattern) +{ + CRContext *g = GetCurrentContext(); + CRLineState *l = &(g->line); + CRStateBits *sb = GetCurrentBits(); + CRLineBits *lb = &(sb->line); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glLineStipple called in begin/end"); + return; + } + + FLUSH(); + + if (factor < 1) factor = 1; + if (factor > 256) factor = 256; + + l->pattern = pattern; + l->repeat = factor; + DIRTY(lb->stipple, g->neg_bitid); + DIRTY(lb->dirty, g->neg_bitid); +} + diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_line.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_line.txt new file mode 100644 index 00000000..35ab8633 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_line.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +:enable:lineSmooth:GL_LINE_SMOOTH +:enable:lineStipple:GL_LINE_STIPPLE +:width:width:LineWidth +lineStipple:stipple:repeat,pattern:LineStipple diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_lists.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_lists.c new file mode 100644 index 00000000..73511399 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_lists.c @@ -0,0 +1,1407 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include <stdio.h> +#include "cr_mem.h" +#include "state.h" +#include "state/cr_statetypes.h" +#include "state_internals.h" + +void crStateListsDestroy(CRContext *ctx) +{ + /* nothing - dlists are in shared state */ + (void)ctx; +} + +void crStateListsInit(CRContext *ctx) +{ + CRListsState *l = &ctx->lists; + CRStateBits *sb = GetCurrentBits(); + CRListsBits *lb = &(sb->lists); + + l->newEnd = GL_FALSE; + l->mode = 0; + l->currentIndex = 0; + l->base = 0; + + RESET(lb->base, ctx->bitid); + RESET(lb->dirty, ctx->bitid); +} + +/*#define CRSTATE_DEBUG_QUERY_HW_STATE*/ + +#ifndef CRSTATE_DEBUG_QUERY_HW_STATE +# define CRSTATE_SET_CAP(state, value, format) g->state=value +# define CR_STATE_SETTEX_MSG(state, st, hw) +# define CR_STATE_SETMAT_MSG(state, st, hw) +#else +# define CRSTATE_SET_CAP(state, value, format) \ + if (g->state!=value) { \ + crDebug("crStateQueryHWState fixed %s from "format" to "format, #state, g->state, value); \ + g->state=value; \ + } +# define CR_STATE_SETTEX_MSG(state, st, hw) crDebug("crStateQueryHWState fixed %s from %i to %i", state, st, hw) +# define CR_STATE_SETMAT_MSG(state, st, hw) \ + { \ + crDebug("crStateQueryHWState fixed %s", state); \ + crDebug("st: [%f, %f, %f, %f] [%f, %f, %f, %f] [%f, %f, %f, %f] [%f, %f, %f, %f]", \ + st[0], st[1], st[2], st[3], st[4], st[5], st[6], st[7], \ + st[8], st[9], st[10], st[11], st[12], st[13], st[14], st[15]); \ + crDebug("hw: [%f, %f, %f, %f] [%f, %f, %f, %f] [%f, %f, %f, %f] [%f, %f, %f, %f]", \ + hw[0], hw[1], hw[2], hw[3], hw[4], hw[5], hw[6], hw[7], \ + hw[8], hw[9], hw[10], hw[11], hw[12], hw[13], hw[14], hw[15]); \ + } +#endif + +#define CRSTATE_SET_ENABLED(state, cap) CRSTATE_SET_CAP(state, diff_api.IsEnabled(cap), "%u") + +#define CRSTATE_SET_ENUM(state, cap) {GLenum _e=g->state; diff_api.GetIntegerv(cap, &_e); CRSTATE_SET_CAP(state, _e, "%#x");} +#define CRSTATE_SET_FLOAT(state, cap) {GLfloat _f=g->state; diff_api.GetFloatv(cap, &_f); CRSTATE_SET_CAP(state, _f, "%f");} +#define CRSTATE_SET_INT(state, cap) {GLint _i=g->state; diff_api.GetIntegerv(cap, &_i); CRSTATE_SET_CAP(state, _i, "%i");} +#define CRSTATE_SET_BOOL(state, cap) {GLboolean _b=g->state; diff_api.GetBooleanv(cap, &_b); CRSTATE_SET_CAP(state, _b, "%u");} + +#define CRSTATE_SET_COLORF(state, cap) \ + { \ + GLfloat value[4]; \ + value[0]=g->state.r; \ + value[1]=g->state.g; \ + value[2]=g->state.b; \ + value[3]=g->state.a; \ + diff_api.GetFloatv(cap, &value[0]); \ + CRSTATE_SET_CAP(state.r, value[0], "%f"); \ + CRSTATE_SET_CAP(state.g, value[1], "%f"); \ + CRSTATE_SET_CAP(state.b, value[2], "%f"); \ + CRSTATE_SET_CAP(state.a, value[3], "%f"); \ + } + +#define CRSTATE_SET_TEXTURE(state, cap, target) \ + { \ + GLint _stex, _hwtex; \ + _stex = _hwtex = crStateGetTextureObjHWID(g->state); \ + diff_api.GetIntegerv(cap, &_hwtex); \ + if (_stex!=_hwtex) \ + { \ + CR_STATE_SETTEX_MSG(#state, _stex, _hwtex); \ + crStateBindTexture(target, crStateTextureHWIDtoID(_hwtex)); \ + } \ + } + +#define _CRSTATE_SET_4F_RGBA(state, p1, p2, func) \ + { \ + GLfloat value[4]; \ + value[0]=g->state.r; \ + value[1]=g->state.g; \ + value[2]=g->state.b; \ + value[3]=g->state.a; \ + diff_api.func(p1, p2, &value[0]); \ + CRSTATE_SET_CAP(state.r, value[0], "%f"); \ + CRSTATE_SET_CAP(state.g, value[1], "%f"); \ + CRSTATE_SET_CAP(state.b, value[2], "%f"); \ + CRSTATE_SET_CAP(state.a, value[3], "%f"); \ + } + +#define _CRSTATE_SET_4F_XYZW(state, p1, p2, func) \ + { \ + GLfloat value[4]; \ + value[0]=g->state.x; \ + value[1]=g->state.y; \ + value[2]=g->state.z; \ + value[3]=g->state.w; \ + diff_api.func(p1, p2, &value[0]); \ + CRSTATE_SET_CAP(state.x, value[0], "%f"); \ + CRSTATE_SET_CAP(state.y, value[1], "%f"); \ + CRSTATE_SET_CAP(state.z, value[2], "%f"); \ + CRSTATE_SET_CAP(state.w, value[3], "%f"); \ + } + +#define CRSTATE_SET_TEXGEN_4F(state, coord, pname) _CRSTATE_SET_4F_XYZW(state, coord, pname, GetTexGenfv) +#define CRSTATE_SET_TEXGEN_I(state, coord, pname) {GLint _i=g->state; diff_api.GetTexGeniv(coord, pname, &_i); CRSTATE_SET_CAP(state, _i, "%i");} + +#define CRSTATE_SET_TEXENV_I(state, target, pname) {GLint _i=g->state; diff_api.GetTexEnviv(target, pname, &_i); CRSTATE_SET_CAP(state, _i, "%i");} +#define CRSTATE_SET_TEXENV_F(state, target, pname) {GLfloat _f=g->state; diff_api.GetTexEnvfv(target, pname, &_f); CRSTATE_SET_CAP(state, _f, "%f");} +#define CRSTATE_SET_TEXENV_COLOR(state, target, pname) _CRSTATE_SET_4F_RGBA(state, target, pname, GetTexEnvfv) + +#define CRSTATE_SET_MATERIAL_COLOR(state, face, pname) _CRSTATE_SET_4F_RGBA(state, face, pname, GetMaterialfv) +#define CRSTATE_SET_MATERIAL_F(state, face, pname) {GLfloat _f=g->state; diff_api.GetMaterialfv(face, pname, &_f); CRSTATE_SET_CAP(state, _f, "%f");} + +#define CRSTATE_SET_LIGHT_COLOR(state, light, pname) _CRSTATE_SET_4F_RGBA(state, light, pname, GetLightfv) +#define CRSTATE_SET_LIGHT_F(state, light, pname) {GLfloat _f=g->state; diff_api.GetLightfv(light, pname, &_f); CRSTATE_SET_CAP(state, _f, "%f");} +#define CRSTATE_SET_LIGHT_4F(state, light, pname) _CRSTATE_SET_4F_XYZW(state, light, pname, GetLightfv) +#define CRSTATE_SET_LIGHT_3F(state, light, pname) \ + { \ + GLfloat value[3]; \ + value[0]=g->state.x; \ + value[1]=g->state.y; \ + value[2]=g->state.z; \ + diff_api.GetLightfv(light, pname, &value[0]); \ + CRSTATE_SET_CAP(state.x, value[0], "%f"); \ + CRSTATE_SET_CAP(state.y, value[1], "%f"); \ + CRSTATE_SET_CAP(state.z, value[2], "%f"); \ + } + +#define CRSTATE_SET_CLIPPLANE_4D(state, plane) \ + { \ + GLdouble value[4]; \ + value[0]=g->state.x; \ + value[1]=g->state.y; \ + value[2]=g->state.z; \ + value[3]=g->state.w; \ + diff_api.GetClipPlane(plane, &value[0]); \ + CRSTATE_SET_CAP(state.x, value[0], "%G"); \ + CRSTATE_SET_CAP(state.y, value[1], "%G"); \ + CRSTATE_SET_CAP(state.z, value[2], "%G"); \ + CRSTATE_SET_CAP(state.w, value[3], "%G"); \ + } + +#define CRSTATE_SET_MATRIX(state, cap) \ + { \ + GLfloat f[16], sm[16]; \ + crMatrixGetFloats(&f[0], g->state); \ + crMemcpy(&sm[0], &f[0], 16*sizeof(GLfloat)); \ + diff_api.GetFloatv(cap, &f[0]); \ + if (crMemcmp(&f[0], &sm[0], 16*sizeof(GLfloat))) \ + { \ + CR_STATE_SETMAT_MSG(#state, sm, f); \ + crMatrixInitFromFloats(g->state, &f[0]); \ + } \ + } + +void STATE_APIENTRY crStateQueryHWState(GLuint fbFbo, GLuint bbFbo) +{ + CRContext *g = GetCurrentContext(); + CRStateBits *sb = GetCurrentBits(); + CRbitvalue /* *bitID=g->bitid, */ *negbitID=g->neg_bitid; + + CRASSERT(g_bVBoxEnableDiffOnMakeCurrent); + + crStateSyncHWErrorState(g); + + if (CHECKDIRTY(sb->buffer.dirty, negbitID)) + { + if (CHECKDIRTY(sb->buffer.enable, negbitID)) + { + CRSTATE_SET_ENABLED(buffer.depthTest, GL_DEPTH_TEST); + CRSTATE_SET_ENABLED(buffer.blend, GL_BLEND); + CRSTATE_SET_ENABLED(buffer.alphaTest, GL_ALPHA_TEST); + CRSTATE_SET_ENABLED(buffer.logicOp, GL_COLOR_LOGIC_OP); + CRSTATE_SET_ENABLED(buffer.indexLogicOp, GL_INDEX_LOGIC_OP); + CRSTATE_SET_ENABLED(buffer.dither, GL_DITHER); + } + + if (CHECKDIRTY(sb->buffer.alphaFunc, negbitID)) + { + CRSTATE_SET_ENUM(buffer.alphaTestFunc, GL_ALPHA_TEST_FUNC); + CRSTATE_SET_FLOAT(buffer.alphaTestRef, GL_ALPHA_TEST_REF); + } + + if (CHECKDIRTY(sb->buffer.depthFunc, negbitID)) + { + CRSTATE_SET_ENUM(buffer.depthFunc, GL_DEPTH_FUNC); + } + + if (CHECKDIRTY(sb->buffer.blendFunc, negbitID)) + { + CRSTATE_SET_ENUM(buffer.blendSrcRGB, GL_BLEND_SRC); + CRSTATE_SET_ENUM(buffer.blendDstRGB, GL_BLEND_DST); + } + + if (CHECKDIRTY(sb->buffer.logicOp, negbitID)) + { + CRSTATE_SET_ENUM(buffer.logicOpMode, GL_LOGIC_OP_MODE); + } + +/* seems to always match previous .logicOp + if (CHECKDIRTY(sb->buffer.indexLogicOp, negbitID)) + { + CRSTATE_SET_ENUM(buffer.logicOpMode, GL_LOGIC_OP_MODE); + } +*/ + + if (CHECKDIRTY(sb->buffer.drawBuffer, negbitID)) + { + GLuint buf = 0; + diff_api.GetIntegerv(GL_DRAW_BUFFER, &buf); + + if (buf == GL_COLOR_ATTACHMENT0_EXT && (bbFbo || fbFbo)) + { + GLuint binding = 0; + diff_api.GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &binding); + if (!binding) + { + crWarning("HW state synch: GL_DRAW_FRAMEBUFFER_BINDING is NULL"); + } + + if (bbFbo && binding == bbFbo) + { + g->buffer.drawBuffer = GL_BACK; + } + else if (fbFbo && binding == fbFbo) + { + g->buffer.drawBuffer = GL_FRONT; + } + else + { + g->buffer.drawBuffer = buf; + } + } + else + { + g->buffer.drawBuffer = buf; + } + } + + if (CHECKDIRTY(sb->buffer.readBuffer, negbitID)) + { + GLuint buf = 0; + diff_api.GetIntegerv(GL_READ_BUFFER, &buf); + + if (buf == GL_COLOR_ATTACHMENT0_EXT && (bbFbo || fbFbo)) + { + GLuint binding = 0; + diff_api.GetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &binding); + if (!binding) + { + crWarning("HW state synch: GL_READ_FRAMEBUFFER_BINDING is NULL"); + } + + if (bbFbo && binding == bbFbo) + { + g->buffer.readBuffer = GL_BACK; + } + else if (fbFbo && binding == fbFbo) + { + g->buffer.readBuffer = GL_FRONT; + } + else + { + g->buffer.readBuffer = buf; + } + } + else + { + g->buffer.readBuffer = buf; + } + } + + if (CHECKDIRTY(sb->buffer.indexMask, negbitID)) + { + CRSTATE_SET_INT(buffer.indexWriteMask, GL_INDEX_WRITEMASK); + } + + if (CHECKDIRTY(sb->buffer.colorWriteMask, negbitID)) + { + GLboolean value[4]; + value[0]=g->buffer.colorWriteMask.r; + value[1]=g->buffer.colorWriteMask.g; + value[2]=g->buffer.colorWriteMask.b; + value[3]=g->buffer.colorWriteMask.a; + diff_api.GetBooleanv(GL_COLOR_WRITEMASK, &value[0]); + + CRSTATE_SET_CAP(buffer.colorWriteMask.r, value[0], "%u"); + CRSTATE_SET_CAP(buffer.colorWriteMask.g, value[1], "%u"); + CRSTATE_SET_CAP(buffer.colorWriteMask.b, value[2], "%u"); + CRSTATE_SET_CAP(buffer.colorWriteMask.a, value[3], "%u"); + } + + if (CHECKDIRTY(sb->buffer.clearColor, negbitID)) + { + CRSTATE_SET_COLORF(buffer.colorClearValue, GL_COLOR_CLEAR_VALUE); + } + + if (CHECKDIRTY(sb->buffer.clearIndex, negbitID)) + { + CRSTATE_SET_FLOAT(buffer.indexClearValue, GL_INDEX_CLEAR_VALUE); + } + + if (CHECKDIRTY(sb->buffer.clearDepth, negbitID)) + { + CRSTATE_SET_FLOAT(buffer.depthClearValue, GL_DEPTH_CLEAR_VALUE); + } + + if (CHECKDIRTY(sb->buffer.clearAccum, negbitID)) + { + CRSTATE_SET_COLORF(buffer.accumClearValue, GL_ACCUM_CLEAR_VALUE); + } + + if (CHECKDIRTY(sb->buffer.depthMask, negbitID)) + { + CRSTATE_SET_BOOL(buffer.depthMask, GL_DEPTH_WRITEMASK); + } + +#ifdef CR_EXT_blend_color + if (CHECKDIRTY(sb->buffer.blendColor, negbitID)) + { + CRSTATE_SET_COLORF(buffer.blendColor, GL_BLEND_COLOR); + } +#endif +#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op) + if (CHECKDIRTY(sb->buffer.blendEquation, negbitID)) + { + CRSTATE_SET_ENUM(buffer.blendEquation, GL_BLEND_EQUATION_EXT); + } +#endif +#if defined(CR_EXT_blend_func_separate) + if (CHECKDIRTY(sb->buffer.blendFuncSeparate, negbitID)) + { + CRSTATE_SET_ENUM(buffer.blendSrcRGB, GL_BLEND_SRC_RGB_EXT); + CRSTATE_SET_ENUM(buffer.blendDstRGB, GL_BLEND_DST_RGB_EXT); + CRSTATE_SET_ENUM(buffer.blendSrcA, GL_BLEND_SRC_ALPHA_EXT); + CRSTATE_SET_ENUM(buffer.blendDstA, GL_BLEND_DST_ALPHA_EXT); + } +#endif + } + + if (CHECKDIRTY(sb->stencil.dirty, negbitID)) + { + GLenum activeFace; + GLboolean backIsSet = GL_FALSE, frontIsSet = GL_FALSE; + + if (CHECKDIRTY(sb->stencil.enable, negbitID)) + { + CRSTATE_SET_ENABLED(stencil.stencilTest, GL_STENCIL_TEST); + } + + if (CHECKDIRTY(sb->stencil.enableTwoSideEXT, negbitID)) + { + CRSTATE_SET_ENABLED(stencil.stencilTwoSideEXT, GL_STENCIL_TEST_TWO_SIDE_EXT); + } + + if (CHECKDIRTY(sb->stencil.activeStencilFace, negbitID)) + { + CRSTATE_SET_ENUM(stencil.activeStencilFace, GL_ACTIVE_STENCIL_FACE_EXT); + } + + activeFace = g->stencil.activeStencilFace; + + +#define CRSTATE_SET_STENCIL_FUNC(_idx, _suff) do { \ + CRSTATE_SET_ENUM(stencil.buffers[(_idx)].func, GL_STENCIL##_suff##FUNC); \ + CRSTATE_SET_INT(stencil.buffers[(_idx)].ref, GL_STENCIL##_suff##REF); \ + CRSTATE_SET_INT(stencil.buffers[(_idx)].mask, GL_STENCIL##_suff##VALUE_MASK); \ + } while (0) + +#define CRSTATE_SET_STENCIL_OP(_idx, _suff) do { \ + CRSTATE_SET_ENUM(stencil.buffers[(_idx)].fail, GL_STENCIL##_suff##FAIL); \ + CRSTATE_SET_ENUM(stencil.buffers[(_idx)].passDepthFail, GL_STENCIL##_suff##PASS_DEPTH_FAIL); \ + CRSTATE_SET_ENUM(stencil.buffers[(_idx)].passDepthPass, GL_STENCIL##_suff##PASS_DEPTH_PASS); \ + } while (0) + + /* func */ + + if (CHECKDIRTY(sb->stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, negbitID)) + { + /* this if branch is not needed here actually, just in case ogl drivers misbehave */ + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_SET_STENCIL_FUNC(CRSTATE_STENCIL_BUFFER_ID_BACK, _BACK_); + backIsSet = GL_TRUE; + } + + if (CHECKDIRTY(sb->stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, negbitID)) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + CRSTATE_SET_STENCIL_FUNC(CRSTATE_STENCIL_BUFFER_ID_FRONT, _); + frontIsSet = GL_TRUE; + } + + if ((!frontIsSet || !backIsSet) && CHECKDIRTY(sb->stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, negbitID)) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + CRSTATE_SET_STENCIL_FUNC(CRSTATE_STENCIL_BUFFER_ID_FRONT, _); + if (!backIsSet) + { + g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func = g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func; + g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref = g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref; + g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask = g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask; + } + } + + /* op */ + backIsSet = GL_FALSE, frontIsSet = GL_FALSE; + + if (CHECKDIRTY(sb->stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, negbitID)) + { + /* this if branch is not needed here actually, just in case ogl drivers misbehave */ + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_SET_STENCIL_OP(CRSTATE_STENCIL_BUFFER_ID_BACK, _BACK_); + backIsSet = GL_TRUE; + } + + if (CHECKDIRTY(sb->stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, negbitID)) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + CRSTATE_SET_STENCIL_OP(CRSTATE_STENCIL_BUFFER_ID_FRONT, _); + frontIsSet = GL_TRUE; + } + + if ((!frontIsSet || !backIsSet) && CHECKDIRTY(sb->stencil.bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, negbitID)) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + CRSTATE_SET_STENCIL_OP(CRSTATE_STENCIL_BUFFER_ID_FRONT, _); + if (!backIsSet) + { + g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail = g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail; + g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail = g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail; + g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass = g->stencil.buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass; + } + } + + if (CHECKDIRTY(sb->stencil.clearValue, negbitID)) + { + CRSTATE_SET_INT(stencil.clearValue, GL_STENCIL_CLEAR_VALUE); + } + + if (CHECKDIRTY(sb->stencil.writeMask, negbitID)) + { + CRSTATE_SET_INT(stencil.writeMask, GL_STENCIL_WRITEMASK); + } + } + + if (CHECKDIRTY(sb->texture.dirty, negbitID)) + { + unsigned int i, activeUnit = g->texture.curTextureUnit; + + for (i=0; i<g->limits.maxTextureUnits; ++i) + { + if (CHECKDIRTY(sb->texture.enable[i], negbitID)) + { + if (i!=activeUnit) + { + diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB); + activeUnit=i; + } + CRSTATE_SET_ENABLED(texture.unit[i].enabled1D, GL_TEXTURE_1D); + CRSTATE_SET_ENABLED(texture.unit[i].enabled2D, GL_TEXTURE_2D); +#ifdef CR_OPENGL_VERSION_1_2 + CRSTATE_SET_ENABLED(texture.unit[i].enabled3D, GL_TEXTURE_3D); +#endif +#ifdef CR_ARB_texture_cube_map + if (g->extensions.ARB_texture_cube_map) + { + CRSTATE_SET_ENABLED(texture.unit[i].enabledCubeMap, GL_TEXTURE_CUBE_MAP_ARB); + } +#endif +#ifdef CR_NV_texture_rectangle + if (g->extensions.NV_texture_rectangle) + { + CRSTATE_SET_ENABLED(texture.unit[i].enabledRect, GL_TEXTURE_RECTANGLE_NV); + } +#endif + + CRSTATE_SET_ENABLED(texture.unit[i].textureGen.s, GL_TEXTURE_GEN_S); + CRSTATE_SET_ENABLED(texture.unit[i].textureGen.t, GL_TEXTURE_GEN_T); + CRSTATE_SET_ENABLED(texture.unit[i].textureGen.r, GL_TEXTURE_GEN_R); + CRSTATE_SET_ENABLED(texture.unit[i].textureGen.q, GL_TEXTURE_GEN_Q); + } + + if (CHECKDIRTY(sb->texture.current[i], negbitID)) + { + if (i!=activeUnit) + { + diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB); + activeUnit=i; + } + + CRSTATE_SET_TEXTURE(texture.unit[i].currentTexture1D, GL_TEXTURE_BINDING_1D, GL_TEXTURE_1D); + CRSTATE_SET_TEXTURE(texture.unit[i].currentTexture2D, GL_TEXTURE_BINDING_2D, GL_TEXTURE_2D); +#ifdef CR_OPENGL_VERSION_1_2 + CRSTATE_SET_TEXTURE(texture.unit[i].currentTexture3D, GL_TEXTURE_BINDING_3D, GL_TEXTURE_3D); +#endif +#ifdef CR_ARB_texture_cube_map + if (g->extensions.ARB_texture_cube_map) + { + CRSTATE_SET_TEXTURE(texture.unit[i].currentTextureCubeMap, GL_TEXTURE_BINDING_CUBE_MAP_ARB, GL_TEXTURE_CUBE_MAP_ARB); + } +#endif +#ifdef CR_NV_texture_rectangle + if (g->extensions.NV_texture_rectangle) + { + CRSTATE_SET_TEXTURE(texture.unit[i].currentTextureRect, GL_TEXTURE_BINDING_RECTANGLE_NV, GL_TEXTURE_RECTANGLE_NV); + } +#endif + } + + if (CHECKDIRTY(sb->texture.objGen[i], negbitID)) + { + if (i!=activeUnit) + { + diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB); + activeUnit=i; + } + + CRSTATE_SET_TEXGEN_4F(texture.unit[i].objSCoeff, GL_S, GL_OBJECT_PLANE); + CRSTATE_SET_TEXGEN_4F(texture.unit[i].objTCoeff, GL_T, GL_OBJECT_PLANE); + CRSTATE_SET_TEXGEN_4F(texture.unit[i].objRCoeff, GL_R, GL_OBJECT_PLANE); + CRSTATE_SET_TEXGEN_4F(texture.unit[i].objQCoeff, GL_Q, GL_OBJECT_PLANE); + } + + if (CHECKDIRTY(sb->texture.eyeGen[i], negbitID)) + { + if (i!=activeUnit) + { + diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB); + activeUnit=i; + } + + CRSTATE_SET_TEXGEN_4F(texture.unit[i].eyeSCoeff, GL_S, GL_EYE_PLANE); + CRSTATE_SET_TEXGEN_4F(texture.unit[i].eyeTCoeff, GL_T, GL_EYE_PLANE); + CRSTATE_SET_TEXGEN_4F(texture.unit[i].eyeRCoeff, GL_R, GL_EYE_PLANE); + CRSTATE_SET_TEXGEN_4F(texture.unit[i].eyeQCoeff, GL_Q, GL_EYE_PLANE); + } + + if (CHECKDIRTY(sb->texture.genMode[i], negbitID)) + { + if (i!=activeUnit) + { + diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB); + activeUnit=i; + } + + CRSTATE_SET_TEXGEN_I(texture.unit[i].gen.s, GL_S, GL_TEXTURE_GEN_MODE); + CRSTATE_SET_TEXGEN_I(texture.unit[i].gen.t, GL_T, GL_TEXTURE_GEN_MODE); + CRSTATE_SET_TEXGEN_I(texture.unit[i].gen.r, GL_R, GL_TEXTURE_GEN_MODE); + CRSTATE_SET_TEXGEN_I(texture.unit[i].gen.q, GL_Q, GL_TEXTURE_GEN_MODE); + } + + if (CHECKDIRTY(sb->texture.envBit[i], negbitID)) + { + if (i!=activeUnit) + { + diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB); + activeUnit=i; + } + + CRSTATE_SET_TEXENV_I(texture.unit[i].envMode, GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE); + CRSTATE_SET_TEXENV_COLOR(texture.unit[i].envColor, GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR); + CRSTATE_SET_TEXENV_I(texture.unit[i].combineModeRGB, GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB); + CRSTATE_SET_TEXENV_I(texture.unit[i].combineModeA, GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB); + CRSTATE_SET_TEXENV_I(texture.unit[i].combineSourceRGB[0], GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB); + CRSTATE_SET_TEXENV_I(texture.unit[i].combineSourceRGB[1], GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB); + CRSTATE_SET_TEXENV_I(texture.unit[i].combineSourceRGB[2], GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB); + CRSTATE_SET_TEXENV_I(texture.unit[i].combineSourceA[0], GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB); + CRSTATE_SET_TEXENV_I(texture.unit[i].combineSourceA[1], GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB); + CRSTATE_SET_TEXENV_I(texture.unit[i].combineSourceA[2], GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB); + CRSTATE_SET_TEXENV_I(texture.unit[i].combineOperandRGB[0], GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB); + CRSTATE_SET_TEXENV_I(texture.unit[i].combineOperandRGB[1], GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB); + CRSTATE_SET_TEXENV_I(texture.unit[i].combineOperandRGB[2], GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB); + CRSTATE_SET_TEXENV_I(texture.unit[i].combineOperandA[0], GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB); + CRSTATE_SET_TEXENV_I(texture.unit[i].combineOperandA[1], GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB); + CRSTATE_SET_TEXENV_I(texture.unit[i].combineOperandA[2], GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB); + CRSTATE_SET_TEXENV_F(texture.unit[i].combineScaleRGB, GL_TEXTURE_ENV, GL_RGB_SCALE_ARB); + CRSTATE_SET_TEXENV_F(texture.unit[i].combineScaleA, GL_TEXTURE_ENV, GL_ALPHA_SCALE); + } + } + if (activeUnit!=g->texture.curTextureUnit) + { + diff_api.ActiveTextureARB(g->texture.curTextureUnit + GL_TEXTURE0_ARB); + } + } + + if (CHECKDIRTY(sb->lighting.dirty, negbitID)) + { + int i; + + if (CHECKDIRTY(sb->lighting.enable, negbitID)) + { + CRSTATE_SET_ENABLED(lighting.lighting, GL_LIGHTING); + CRSTATE_SET_ENABLED(lighting.colorMaterial, GL_COLOR_MATERIAL); + CRSTATE_SET_ENABLED(lighting.colorSumEXT, GL_COLOR_SUM_EXT); + } + + if (CHECKDIRTY(sb->lighting.shadeModel, negbitID)) + { + CRSTATE_SET_ENUM(lighting.shadeModel, GL_SHADE_MODEL); + } + + if (CHECKDIRTY(sb->lighting.colorMaterial, negbitID)) + { + CRSTATE_SET_ENUM(lighting.colorMaterialFace, GL_COLOR_MATERIAL_FACE); + CRSTATE_SET_ENUM(lighting.colorMaterialMode, GL_COLOR_MATERIAL_PARAMETER); + } + + if (CHECKDIRTY(sb->lighting.lightModel, negbitID)) + { + CRSTATE_SET_COLORF(lighting.lightModelAmbient, GL_LIGHT_MODEL_AMBIENT); + CRSTATE_SET_BOOL(lighting.lightModelLocalViewer, GL_LIGHT_MODEL_LOCAL_VIEWER); + CRSTATE_SET_BOOL(lighting.lightModelTwoSide, GL_LIGHT_MODEL_TWO_SIDE); + CRSTATE_SET_ENUM(lighting.lightModelColorControlEXT, GL_LIGHT_MODEL_COLOR_CONTROL); + } + + if (CHECKDIRTY(sb->lighting.material, negbitID)) + { + CRSTATE_SET_MATERIAL_COLOR(lighting.ambient[0], GL_FRONT, GL_AMBIENT); + CRSTATE_SET_MATERIAL_COLOR(lighting.ambient[1], GL_BACK, GL_AMBIENT); + CRSTATE_SET_MATERIAL_COLOR(lighting.diffuse[0], GL_FRONT, GL_DIFFUSE); + CRSTATE_SET_MATERIAL_COLOR(lighting.diffuse[1], GL_BACK, GL_DIFFUSE); + CRSTATE_SET_MATERIAL_COLOR(lighting.specular[0], GL_FRONT, GL_SPECULAR); + CRSTATE_SET_MATERIAL_COLOR(lighting.specular[1], GL_BACK, GL_SPECULAR); + CRSTATE_SET_MATERIAL_COLOR(lighting.emission[0], GL_FRONT, GL_EMISSION); + CRSTATE_SET_MATERIAL_COLOR(lighting.emission[1], GL_BACK, GL_EMISSION); + CRSTATE_SET_MATERIAL_F(lighting.shininess[0], GL_FRONT, GL_SHININESS); + CRSTATE_SET_MATERIAL_F(lighting.shininess[1], GL_BACK, GL_SHININESS); + } + + for (i=0; i<CR_MAX_LIGHTS; ++i) + { + if (CHECKDIRTY(sb->lighting.light[i].dirty, negbitID)) + { + if (CHECKDIRTY(sb->lighting.light[i].enable, negbitID)) + { + CRSTATE_SET_ENABLED(lighting.light[i].enable, GL_LIGHT0+i); + } + + if (CHECKDIRTY(sb->lighting.light[i].ambient, negbitID)) + { + CRSTATE_SET_LIGHT_COLOR(lighting.light[i].ambient, GL_LIGHT0+i, GL_AMBIENT); + } + + if (CHECKDIRTY(sb->lighting.light[i].diffuse, negbitID)) + { + CRSTATE_SET_LIGHT_COLOR(lighting.light[i].diffuse, GL_LIGHT0+i, GL_DIFFUSE); + } + + if (CHECKDIRTY(sb->lighting.light[i].specular, negbitID)) + { + CRSTATE_SET_LIGHT_COLOR(lighting.light[i].specular, GL_LIGHT0+i, GL_SPECULAR); + } + + if (CHECKDIRTY(sb->lighting.light[i].position, negbitID)) + { + CRSTATE_SET_LIGHT_4F(lighting.light[i].position, GL_LIGHT0+i, GL_POSITION); + } + + if (CHECKDIRTY(sb->lighting.light[i].attenuation, negbitID)) + { + CRSTATE_SET_LIGHT_F(lighting.light[i].constantAttenuation, GL_LIGHT0+i, GL_CONSTANT_ATTENUATION); + CRSTATE_SET_LIGHT_F(lighting.light[i].linearAttenuation, GL_LIGHT0+i, GL_LINEAR_ATTENUATION); + CRSTATE_SET_LIGHT_F(lighting.light[i].quadraticAttenuation, GL_LIGHT0+i, GL_QUADRATIC_ATTENUATION); + } + + if (CHECKDIRTY(sb->lighting.light[i].spot, negbitID)) + { + CRSTATE_SET_LIGHT_3F(lighting.light[i].spotDirection, GL_LIGHT0+i, GL_SPOT_DIRECTION); + CRSTATE_SET_LIGHT_F(lighting.light[i].spotExponent, GL_LIGHT0+i, GL_SPOT_EXPONENT); + CRSTATE_SET_LIGHT_F(lighting.light[i].spotCutoff, GL_LIGHT0+i, GL_SPOT_CUTOFF); + } + } + } + } + + + if (CHECKDIRTY(sb->transform.dirty, negbitID)) + { + if (CHECKDIRTY(sb->transform.enable, negbitID)) + { + CRSTATE_SET_ENABLED(transform.normalize, GL_NORMALIZE); +#ifdef CR_OPENGL_VERSION_1_2 + CRSTATE_SET_ENABLED(transform.rescaleNormals, GL_RESCALE_NORMAL); +#endif +#ifdef CR_IBM_rasterpos_clip + CRSTATE_SET_ENABLED(transform.rasterPositionUnclipped, GL_RASTER_POSITION_UNCLIPPED_IBM); +#endif + } + + if (CHECKDIRTY(sb->transform.clipPlane, negbitID)) + { + int i; + for (i=0; i<CR_MAX_CLIP_PLANES; i++) + { + CRSTATE_SET_CLIPPLANE_4D(transform.clipPlane[i], GL_CLIP_PLANE0+i); + } + } + + if (CHECKDIRTY(sb->transform.modelviewMatrix, negbitID)) + { + CRSTATE_SET_MATRIX(transform.modelViewStack.top, GL_MODELVIEW_MATRIX); + } + + if (CHECKDIRTY(sb->transform.projectionMatrix, negbitID)) + { + CRSTATE_SET_MATRIX(transform.projectionStack.top, GL_PROJECTION_MATRIX); + } + + if (CHECKDIRTY(sb->transform.textureMatrix, negbitID)) + { + unsigned int i; + for (i=0; i<g->limits.maxTextureUnits; i++) + { + diff_api.ActiveTextureARB(GL_TEXTURE0_ARB+i); + CRSTATE_SET_MATRIX(transform.textureStack[i].top, GL_TEXTURE_MATRIX); + } + diff_api.ActiveTextureARB(g->texture.curTextureUnit + GL_TEXTURE0_ARB); + } + + if (CHECKDIRTY(sb->transform.colorMatrix, negbitID)) + { + CRSTATE_SET_MATRIX(transform.colorStack.top, GL_COLOR_MATRIX); + } + + if (CHECKDIRTY(sb->transform.matrixMode, negbitID)) + { + CRSTATE_SET_ENUM(transform.matrixMode, GL_MATRIX_MODE); + } + } + + if (CHECKDIRTY(sb->viewport.dirty, negbitID)) + { + if (CHECKDIRTY(sb->viewport.enable, negbitID)) + { + CRSTATE_SET_ENABLED(viewport.scissorTest, GL_SCISSOR_TEST); + } + + if (CHECKDIRTY(sb->viewport.s_dims, negbitID)) + { + GLint value[4]; + value[0] = g->viewport.scissorX; + value[1] = g->viewport.scissorY; + value[2] = g->viewport.scissorW; + value[3] = g->viewport.scissorH; + diff_api.GetIntegerv(GL_SCISSOR_BOX, &value[0]); + CRSTATE_SET_CAP(viewport.scissorX, value[0], "%i"); + CRSTATE_SET_CAP(viewport.scissorY, value[1], "%i"); + CRSTATE_SET_CAP(viewport.scissorW, value[2], "%i"); + CRSTATE_SET_CAP(viewport.scissorH, value[3], "%i"); + } + + if (CHECKDIRTY(sb->viewport.v_dims, negbitID)) + { + GLint value[4]; + value[0] = g->viewport.viewportX; + value[1] = g->viewport.viewportY; + value[2] = g->viewport.viewportW; + value[3] = g->viewport.viewportH; + diff_api.GetIntegerv(GL_VIEWPORT, &value[0]); + CRSTATE_SET_CAP(viewport.viewportX, value[0], "%i"); + CRSTATE_SET_CAP(viewport.viewportY, value[1], "%i"); + CRSTATE_SET_CAP(viewport.viewportW, value[2], "%i"); + CRSTATE_SET_CAP(viewport.viewportH, value[3], "%i"); + } + + if (CHECKDIRTY(sb->viewport.depth, negbitID)) + { + GLfloat value[2]; + value[0] = g->viewport.nearClip; + value[1] = g->viewport.farClip; + diff_api.GetFloatv(GL_DEPTH_RANGE, &value[0]); + CRSTATE_SET_CAP(viewport.nearClip, value[0], "%f"); + CRSTATE_SET_CAP(viewport.farClip, value[1], "%f"); + } + } + + if (CHECKDIRTY(sb->eval.dirty, negbitID)) + { + int i; + const int gleval_sizes_dup[] = {4, 1, 3, 1, 2, 3, 4, 3, 4}; + + if (CHECKDIRTY(sb->eval.enable, negbitID)) + { + CRSTATE_SET_ENABLED(eval.autoNormal, GL_AUTO_NORMAL); + } + + for (i=0; i<GLEVAL_TOT; i++) + { + if (CHECKDIRTY(sb->eval.enable1D[i], negbitID)) + { + CRSTATE_SET_ENABLED(eval.enable1D[i], i + GL_MAP1_COLOR_4); + } + + if (CHECKDIRTY(sb->eval.enable2D[i], negbitID)) + { + CRSTATE_SET_ENABLED(eval.enable2D[i], i + GL_MAP2_COLOR_4); + } + + if (CHECKDIRTY(sb->eval.eval1D[i], negbitID) && g->eval.enable1D[i]) + { + GLfloat *coeffs=NULL; + GLint order; + GLfloat uval[2]; + order = g->eval.eval1D[i].order; + uval[0] = g->eval.eval1D[i].u1; + uval[1] = g->eval.eval1D[i].u2; + diff_api.GetMapiv(i + GL_MAP1_COLOR_4, GL_ORDER, &order); + diff_api.GetMapfv(i + GL_MAP1_COLOR_4, GL_DOMAIN, &uval[0]); + if (order>0) + { + coeffs = crAlloc(order * gleval_sizes_dup[i] * sizeof(GLfloat)); + if (!coeffs) + { + crWarning("crStateQueryHWState: out of memory, at eval1D[%i]", i); + continue; + } + diff_api.GetMapfv(i + GL_MAP1_COLOR_4, GL_COEFF, coeffs); + } + + CRSTATE_SET_CAP(eval.eval1D[i].order, order, "%i"); + CRSTATE_SET_CAP(eval.eval1D[i].u1, uval[0], "%f"); + CRSTATE_SET_CAP(eval.eval1D[i].u2, uval[1], "%f"); + if (g->eval.eval1D[i].coeff) + { + crFree(g->eval.eval1D[i].coeff); + } + g->eval.eval1D[i].coeff = coeffs; + + if (uval[0]!=uval[1]) + { + g->eval.eval1D[i].du = 1.0f / (uval[0] - uval[1]); + } + } + + if (CHECKDIRTY(sb->eval.eval2D[i], negbitID) && g->eval.enable2D[i]) + { + GLfloat *coeffs=NULL; + GLint order[2]; + GLfloat uval[4]; + order[0] = g->eval.eval2D[i].uorder; + order[1] = g->eval.eval2D[i].vorder; + uval[0] = g->eval.eval2D[i].u1; + uval[1] = g->eval.eval2D[i].u2; + uval[2] = g->eval.eval2D[i].v1; + uval[3] = g->eval.eval2D[i].v2; + diff_api.GetMapiv(i + GL_MAP2_COLOR_4, GL_ORDER, &order[0]); + diff_api.GetMapfv(i + GL_MAP2_COLOR_4, GL_DOMAIN, &uval[0]); + if (order[0]>0 && order[1]>0) + { + coeffs = crAlloc(order[0] * order[1] * gleval_sizes_dup[i] * sizeof(GLfloat)); + if (!coeffs) + { + crWarning("crStateQueryHWState: out of memory, at eval2D[%i]", i); + continue; + } + diff_api.GetMapfv(i + GL_MAP1_COLOR_4, GL_COEFF, coeffs); + } + CRSTATE_SET_CAP(eval.eval2D[i].uorder, order[0], "%i"); + CRSTATE_SET_CAP(eval.eval2D[i].vorder, order[1], "%i"); + CRSTATE_SET_CAP(eval.eval2D[i].u1, uval[0], "%f"); + CRSTATE_SET_CAP(eval.eval2D[i].u2, uval[1], "%f"); + CRSTATE_SET_CAP(eval.eval2D[i].v1, uval[2], "%f"); + CRSTATE_SET_CAP(eval.eval2D[i].v2, uval[3], "%f"); + if (g->eval.eval2D[i].coeff) + { + crFree(g->eval.eval2D[i].coeff); + } + g->eval.eval2D[i].coeff = coeffs; + + if (uval[0]!=uval[1]) + { + g->eval.eval2D[i].du = 1.0f / (uval[0] - uval[1]); + } + if (uval[2]!=uval[3]) + { + g->eval.eval2D[i].dv = 1.0f / (uval[2] - uval[3]); + } + } + } + + if (CHECKDIRTY(sb->eval.grid1D, negbitID)) + { + GLfloat value[2]; + CRSTATE_SET_INT(eval.un1D, GL_MAP1_GRID_SEGMENTS); + value[0] = g->eval.u11D; + value[1] = g->eval.u21D; + diff_api.GetFloatv(GL_MAP1_GRID_DOMAIN, &value[0]); + CRSTATE_SET_CAP(eval.u11D, value[0], "%f"); + CRSTATE_SET_CAP(eval.u21D, value[1], "%f"); + } + + if (CHECKDIRTY(sb->eval.grid2D, negbitID)) + { + GLint iv[2]; + GLfloat value[4]; + iv[0] = g->eval.un2D; + iv[1] = g->eval.vn2D; + diff_api.GetIntegerv(GL_MAP1_GRID_SEGMENTS, &iv[0]); + CRSTATE_SET_CAP(eval.un2D, iv[0], "%i"); + CRSTATE_SET_CAP(eval.vn2D, iv[1], "%i"); + value[0] = g->eval.u12D; + value[1] = g->eval.u22D; + value[2] = g->eval.v12D; + value[3] = g->eval.v22D; + diff_api.GetFloatv(GL_MAP2_GRID_DOMAIN, &value[0]); + CRSTATE_SET_CAP(eval.u12D, value[0], "%f"); + CRSTATE_SET_CAP(eval.u22D, value[1], "%f"); + CRSTATE_SET_CAP(eval.v12D, value[2], "%f"); + CRSTATE_SET_CAP(eval.v22D, value[3], "%f"); + } + } + + if (CHECKDIRTY(sb->fog.dirty, negbitID)) + { + if (CHECKDIRTY(sb->fog.enable, negbitID)) + { + CRSTATE_SET_ENABLED(fog.enable, GL_FOG); + } + + if (CHECKDIRTY(sb->fog.color, negbitID)) + { + CRSTATE_SET_COLORF(fog.color, GL_FOG_COLOR); + } + + if (CHECKDIRTY(sb->fog.index, negbitID)) + { + CRSTATE_SET_INT(fog.index, GL_FOG_INDEX); + } + + if (CHECKDIRTY(sb->fog.density, negbitID)) + { + CRSTATE_SET_FLOAT(fog.density, GL_FOG_DENSITY); + } + + if (CHECKDIRTY(sb->fog.start, negbitID)) + { + CRSTATE_SET_FLOAT(fog.start, GL_FOG_START); + } + + if (CHECKDIRTY(sb->fog.end, negbitID)) + { + CRSTATE_SET_FLOAT(fog.end, GL_FOG_END); + } + + if (CHECKDIRTY(sb->fog.mode, negbitID)) + { + CRSTATE_SET_INT(fog.mode, GL_FOG_MODE); + } + +#ifdef CR_NV_fog_distance + if (CHECKDIRTY(sb->fog.fogDistanceMode, negbitID)) + { + CRSTATE_SET_ENUM(fog.fogDistanceMode, GL_FOG_DISTANCE_MODE_NV); + } +#endif +#ifdef CR_EXT_fog_coord + if (CHECKDIRTY(sb->fog.fogCoordinateSource, negbitID)) + { + CRSTATE_SET_ENUM(fog.fogCoordinateSource, GL_FOG_COORDINATE_SOURCE_EXT); + } +#endif + } + + if (CHECKDIRTY(sb->hint.dirty, negbitID)) + { + if (CHECKDIRTY(sb->hint.perspectiveCorrection, negbitID)) + { + CRSTATE_SET_ENUM(hint.perspectiveCorrection, GL_PERSPECTIVE_CORRECTION_HINT); + } + + if (CHECKDIRTY(sb->hint.pointSmooth, negbitID)) + { + CRSTATE_SET_ENUM(hint.pointSmooth, GL_POINT_SMOOTH_HINT); + } + + if (CHECKDIRTY(sb->hint.lineSmooth, negbitID)) + { + CRSTATE_SET_ENUM(hint.lineSmooth, GL_LINE_SMOOTH_HINT); + } + + if (CHECKDIRTY(sb->hint.polygonSmooth, negbitID)) + { + CRSTATE_SET_ENUM(hint.polygonSmooth, GL_POINT_SMOOTH_HINT); + } + + if (CHECKDIRTY(sb->hint.fog, negbitID)) + { + CRSTATE_SET_ENUM(hint.fog, GL_FOG_HINT); + } + +#ifdef CR_EXT_clip_volume_hint + if (CHECKDIRTY(sb->hint.clipVolumeClipping, negbitID)) + { + CRSTATE_SET_ENUM(hint.clipVolumeClipping, GL_CLIP_VOLUME_CLIPPING_HINT_EXT); + } +#endif +#ifdef CR_ARB_texture_compression + if (CHECKDIRTY(sb->hint.textureCompression, negbitID)) + { + CRSTATE_SET_ENUM(hint.textureCompression, GL_TEXTURE_COMPRESSION_HINT_ARB); + } +#endif +#ifdef CR_SGIS_generate_mipmap + if (CHECKDIRTY(sb->hint.generateMipmap, negbitID)) + { + CRSTATE_SET_ENUM(hint.generateMipmap, GL_GENERATE_MIPMAP_HINT_SGIS); + } +#endif + } + + if (CHECKDIRTY(sb->line.dirty, negbitID)) + { + if (CHECKDIRTY(sb->line.enable, negbitID)) + { + CRSTATE_SET_ENABLED(line.lineSmooth, GL_LINE_SMOOTH); + CRSTATE_SET_ENABLED(line.lineStipple, GL_LINE_STIPPLE); + } + + if (CHECKDIRTY(sb->line.width, negbitID)) + { + CRSTATE_SET_FLOAT(line.width, GL_LINE_WIDTH); + } + + if (CHECKDIRTY(sb->line.stipple, negbitID)) + { + CRSTATE_SET_INT(line.repeat, GL_LINE_STIPPLE_REPEAT); + CRSTATE_SET_INT(line.pattern, GL_LINE_STIPPLE_PATTERN); + } + } + + if (CHECKDIRTY(sb->multisample.dirty, negbitID)) + { + if (CHECKDIRTY(sb->multisample.enable, negbitID)) + { + CRSTATE_SET_ENABLED(multisample.enabled, GL_MULTISAMPLE_ARB); + CRSTATE_SET_ENABLED(multisample.sampleAlphaToCoverage, GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); + CRSTATE_SET_ENABLED(multisample.sampleAlphaToOne, GL_SAMPLE_ALPHA_TO_ONE_ARB); + CRSTATE_SET_ENABLED(multisample.sampleCoverage, GL_SAMPLE_COVERAGE_ARB); + } + + if (CHECKDIRTY(sb->multisample.sampleCoverageValue, negbitID)) + { + CRSTATE_SET_FLOAT(multisample.sampleCoverageValue, GL_SAMPLE_COVERAGE_VALUE_ARB) + CRSTATE_SET_BOOL(multisample.sampleCoverageInvert, GL_SAMPLE_COVERAGE_INVERT_ARB) + } + } + + if (CHECKDIRTY(sb->point.dirty, negbitID)) + { + if (CHECKDIRTY(sb->point.enableSmooth, negbitID)) + { + CRSTATE_SET_ENABLED(point.pointSmooth, GL_POINT_SMOOTH); + } + + if (CHECKDIRTY(sb->point.size, negbitID)) + { + CRSTATE_SET_FLOAT(point.pointSize, GL_POINT_SIZE); + } + +#ifdef CR_ARB_point_parameters + if (CHECKDIRTY(sb->point.minSize, negbitID)) + { + CRSTATE_SET_FLOAT(point.minSize, GL_POINT_SIZE_MIN_ARB); + } + + if (CHECKDIRTY(sb->point.maxSize, negbitID)) + { + CRSTATE_SET_FLOAT(point.maxSize, GL_POINT_SIZE_MAX_ARB); + } + + if (CHECKDIRTY(sb->point.fadeThresholdSize, negbitID)) + { + CRSTATE_SET_FLOAT(point.fadeThresholdSize, GL_POINT_FADE_THRESHOLD_SIZE_ARB); + } + + if (CHECKDIRTY(sb->point.distanceAttenuation, negbitID)) + { + GLfloat value[3]; + value[0] = g->point.distanceAttenuation[0]; + value[1] = g->point.distanceAttenuation[1]; + value[2] = g->point.distanceAttenuation[2]; + diff_api.GetFloatv(GL_POINT_DISTANCE_ATTENUATION, &value[0]); + CRSTATE_SET_CAP(point.distanceAttenuation[0], value[0], "%f"); + CRSTATE_SET_CAP(point.distanceAttenuation[1], value[1], "%f"); + CRSTATE_SET_CAP(point.distanceAttenuation[2], value[2], "%f"); + } +#endif +#ifdef CR_ARB_point_sprite + if (CHECKDIRTY(sb->point.enableSprite, negbitID)) + { + CRSTATE_SET_ENABLED(point.pointSprite, GL_POINT_SPRITE_ARB); + } + + { + unsigned int i, activeUnit = g->texture.curTextureUnit; + for (i=0; i<g->limits.maxTextureUnits; ++i) + { + if (CHECKDIRTY(sb->point.coordReplacement[i], negbitID)) + { + GLint val=g->point.coordReplacement[i]; + if (activeUnit!=i) + { + diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB); + activeUnit=i; + } + diff_api.GetTexEnviv(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, &val); + CRSTATE_SET_CAP(point.coordReplacement[i], val, "%i"); + } + } + + if (activeUnit!=g->texture.curTextureUnit) + { + diff_api.ActiveTextureARB(g->texture.curTextureUnit + GL_TEXTURE0_ARB); + } + } +#endif + } + + if (CHECKDIRTY(sb->polygon.dirty, negbitID)) + { + if (CHECKDIRTY(sb->polygon.enable, negbitID)) + { + CRSTATE_SET_ENABLED(polygon.polygonSmooth, GL_POLYGON_SMOOTH); + CRSTATE_SET_ENABLED(polygon.polygonOffsetFill, GL_POLYGON_OFFSET_FILL); + CRSTATE_SET_ENABLED(polygon.polygonOffsetLine, GL_POLYGON_OFFSET_LINE); + CRSTATE_SET_ENABLED(polygon.polygonOffsetPoint, GL_POLYGON_OFFSET_POINT); + CRSTATE_SET_ENABLED(polygon.polygonStipple, GL_POLYGON_STIPPLE); + CRSTATE_SET_ENABLED(polygon.cullFace, GL_CULL_FACE); + } + + if (CHECKDIRTY(sb->polygon.offset, negbitID)) + { + CRSTATE_SET_FLOAT(polygon.offsetFactor, GL_POLYGON_OFFSET_FACTOR); + CRSTATE_SET_FLOAT(polygon.offsetUnits, GL_POLYGON_OFFSET_UNITS); + } + + if (CHECKDIRTY(sb->polygon.mode, negbitID)) + { + GLint val[2]; + CRSTATE_SET_ENUM(polygon.frontFace, GL_FRONT_FACE); + CRSTATE_SET_ENUM(polygon.cullFaceMode, GL_CULL_FACE_MODE); + val[0] = g->polygon.frontMode; + val[1] = g->polygon.backMode; + diff_api.GetIntegerv(GL_POLYGON_MODE, &val[0]); + CRSTATE_SET_CAP(polygon.frontMode, val[0], "%#x"); + CRSTATE_SET_CAP(polygon.backMode, val[1], "%#x"); + + + } + + if (CHECKDIRTY(sb->polygon.stipple, negbitID)) + { + GLint stipple[32]; + crMemcpy(&stipple[0], &g->polygon.stipple[0], sizeof(stipple)); + diff_api.GetPolygonStipple((GLubyte*) &stipple[0]); + if (crMemcmp(&stipple[0], &g->polygon.stipple[0], sizeof(stipple))) + { +#ifdef CRSTATE_DEBUG_QUERY_HW_STATE + { + crDebug("crStateQueryHWState fixed polygon.stipple"); + } +#endif + crMemcpy(&g->polygon.stipple[0], &stipple[0], sizeof(stipple)); + } + } + } + + CR_STATE_CLEAN_HW_ERR_WARN("error on hw sync"); +} + +void STATE_APIENTRY crStateNewList (GLuint list, GLenum mode) +{ + CRContext *g = GetCurrentContext(); + CRListsState *l = &(g->lists); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glNewList called in Begin/End"); + return; + } + + if (list == 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glNewList(list=0)"); + return; + } + + if (l->currentIndex) + { + /* already building a list */ + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glNewList called inside display list"); + return; + } + + if (mode != GL_COMPILE && mode != GL_COMPILE_AND_EXECUTE) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glNewList invalid mode"); + return; + } + + FLUSH(); + + /* Must log that this key is used */ + if (!crHashtableIsKeyUsed(g->shared->dlistTable, list)) { + crHashtableAdd(g->shared->dlistTable, list, NULL); + } + + /* Need this??? + crStateCurrentRecover(); + */ + + l->currentIndex = list; + l->mode = mode; +} + +void STATE_APIENTRY crStateEndList (void) +{ + CRContext *g = GetCurrentContext(); + CRListsState *l = &(g->lists); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glEndList called in Begin/End"); + return; + } + + if (!l->currentIndex) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glEndList called outside display list"); + return; + } + + l->currentIndex = 0; + l->mode = 0; +} + +GLuint STATE_APIENTRY crStateGenLists(GLsizei range) +{ + CRContext *g = GetCurrentContext(); + GLuint start; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glGenLists called in Begin/End"); + return 0; + } + + if (range < 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative range passed to glGenLists: %d", range); + return 0; + } + + start = crHashtableAllocKeys(g->shared->dlistTable, range); + + CRASSERT(start > 0); + return start; +} + +void STATE_APIENTRY crStateDeleteLists (GLuint list, GLsizei range) +{ + CRContext *g = GetCurrentContext(); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glDeleteLists called in Begin/End"); + return; + } + + if (range < 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative range passed to glDeleteLists: %d", range); + return; + } + + crHashtableDeleteBlock(g->shared->dlistTable, list, range, crFree); /* call crFree to delete list data */ +} + +GLboolean STATE_APIENTRY crStateIsList(GLuint list) +{ + CRContext *g = GetCurrentContext(); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "GenLists called in Begin/End"); + return GL_FALSE; + } + + if (list == 0) + return GL_FALSE; + + return crHashtableIsKeyUsed(g->shared->dlistTable, list); +} + +void STATE_APIENTRY crStateListBase (GLuint base) +{ + CRContext *g = GetCurrentContext(); + CRListsState *l = &(g->lists); + CRStateBits *sb = GetCurrentBits(); + CRListsBits *lb = &(sb->lists); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "ListBase called in Begin/End"); + return; + } + + l->base = base; + + DIRTY(lb->base, g->neg_bitid); + DIRTY(lb->dirty, g->neg_bitid); +} + + +void +crStateListsDiff( CRListsBits *b, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx ) +{ + CRListsState *from = &(fromCtx->lists); + CRListsState *to = &(toCtx->lists); + unsigned int j; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + + for (j=0;j<CR_MAX_BITARRAY;j++) + nbitID[j] = ~bitID[j]; + + if (CHECKDIRTY(b->base, bitID)) + { + if (from->base != to->base) { + diff_api.ListBase(to->base); + from->base = to->base; + } + CLEARDIRTY(b->base, nbitID); + } + + CLEARDIRTY(b->dirty, nbitID); +} + + +void +crStateListsSwitch( CRListsBits *b, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx ) +{ + CRListsState *from = &(fromCtx->lists); + CRListsState *to = &(toCtx->lists); + unsigned int j; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + + for (j=0;j<CR_MAX_BITARRAY;j++) + nbitID[j] = ~bitID[j]; + + if (CHECKDIRTY(b->base, bitID)) + { + if (from->base != to->base) { + diff_api.ListBase(to->base); + FILLDIRTY(b->base); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->base, nbitID); + } + + CLEARDIRTY(b->dirty, nbitID); +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_multisample.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_multisample.c new file mode 100644 index 00000000..3b7dba5b --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_multisample.c @@ -0,0 +1,51 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include <stdio.h> +#include "state.h" +#include "state/cr_statetypes.h" +#include "state_internals.h" + +void crStateMultisampleInit (CRContext *ctx) +{ + CRMultisampleState *m = &ctx->multisample; + CRStateBits *sb = GetCurrentBits(); + CRMultisampleBits *mb = &(sb->multisample); + + m->enabled = GL_FALSE; /* TRUE if the visual supports it */ + m->sampleAlphaToCoverage = GL_FALSE; + m->sampleAlphaToOne = GL_FALSE; + m->sampleCoverage = GL_FALSE; + RESET(mb->enable, ctx->bitid); + + m->sampleCoverageValue = 1.0F; + m->sampleCoverageInvert = GL_FALSE; + RESET(mb->sampleCoverageValue, ctx->bitid); + + RESET(mb->dirty, ctx->bitid); +} + +void STATE_APIENTRY crStateSampleCoverageARB(GLclampf value, GLboolean invert) +{ + CRContext *g = GetCurrentContext(); + CRMultisampleState *m = &(g->multisample); + CRStateBits *sb = GetCurrentBits(); + CRMultisampleBits *mb = &(sb->multisample); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glStateSampleCoverageARB called in begin/end"); + return; + } + + FLUSH(); + + m->sampleCoverageValue = value; + m->sampleCoverageInvert = invert; + DIRTY(mb->dirty, g->neg_bitid); + DIRTY(mb->sampleCoverageValue, g->neg_bitid); +} + diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_multisample.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_multisample.txt new file mode 100644 index 00000000..a0ed8bcf --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_multisample.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +:enable:enabled:GL_MULTISAMPLE_ARB +:enable:sampleAlphaToCoverage:GL_SAMPLE_ALPHA_TO_COVERAGE_ARB +:enable:sampleAlphaToOne:GL_SAMPLE_ALPHA_TO_ONE_ARB +:enable:sampleCoverage:GL_SAMPLE_COVERAGE_ARB +enabled:sampleCoverageValue:sampleCoverageValue,sampleCoverageInvert:SampleCoverageARB diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_occlude.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_occlude.c new file mode 100644 index 00000000..7249e908 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_occlude.c @@ -0,0 +1,354 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "state.h" +#include "state/cr_statetypes.h" +#include "state/cr_statefuncs.h" +#include "state_internals.h" +#include "cr_mem.h" + +#if !defined(IN_GUEST) +#include "cr_unpack.h" +#endif + +void +crStateOcclusionInit(CRContext *ctx) +{ + CROcclusionState *o = &ctx->occlusion; + + o->objects = crAllocHashtable(); + o->currentQueryObject = 0; +} + + +void +crStateOcclusionDestroy(CRContext *ctx) +{ + CROcclusionState *o = &(ctx->occlusion); + crFreeHashtable(o->objects, crFree); +} + + +static CROcclusionObject * +NewQueryObject(GLenum target, GLuint id) +{ + CROcclusionObject *q = (CROcclusionObject *) crAlloc(sizeof(CROcclusionObject)); + if (q) { + q->target = target; + q->name = id; + q->passedCounter = 0; + q->active = GL_FALSE; + } + return q; +} + + +void STATE_APIENTRY +crStateDeleteQueriesARB(GLsizei n, const GLuint *ids) +{ + CRContext *g = GetCurrentContext(); + CROcclusionState *o = &(g->occlusion); + /*CRStateBits *sb = GetCurrentBits();*/ + /*CROcclusionBits *bb = &(sb->occlusion);*/ + int i; + + FLUSH(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glDeleteQueriesARB called in Begin/End"); + return; + } + + if (n <= 0 || n >= (GLsizei)(INT32_MAX / sizeof(GLuint))) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glDeleteQueriesARB: parameter 'n' is out of range"); + return; + } + +#if !defined(IN_GUEST) + if (!DATA_POINTER_CHECK(n * sizeof(GLuint))) + { + crError("glDeleteQueriesARB: parameter 'n' is out of range"); + return; + } +#endif + + for (i = 0; i < n; i++) { + if (ids[i]) { + CROcclusionObject *q = (CROcclusionObject *) + crHashtableSearch(o->objects, ids[i]); + if (q) { + crHashtableDelete(o->objects, ids[i], crFree); + } + } + } +} + + +void STATE_APIENTRY +crStateGenQueriesARB(GLsizei n, GLuint * queries) +{ + CRContext *g = GetCurrentContext(); + CROcclusionState *o = &(g->occlusion); + GLint start; + + FLUSH(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGenQueriesARB called in Begin/End"); + return; + } + + if (n < 0) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glGenQueriesARB(n < 0)"); + return; + } + + start = crHashtableAllocKeys(o->objects, n); + if (start) { + GLint i; + for (i = 0; i < n; i++) + queries[i] = (GLuint) (start + i); + } + else { + crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glGenQueriesARB"); + } +} + + +GLboolean STATE_APIENTRY +crStateIsQueryARB(GLuint id) +{ + CRContext *g = GetCurrentContext(); + CROcclusionState *o = &(g->occlusion); + + FLUSH(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glIsQueryARB called in begin/end"); + return GL_FALSE; + } + + if (id && crHashtableIsKeyUsed(o->objects, id)) + return GL_TRUE; + else + return GL_FALSE; +} + + +void STATE_APIENTRY +crStateGetQueryivARB(GLenum target, GLenum pname, GLint *params) +{ + CRContext *g = GetCurrentContext(); + CROcclusionState *o = &(g->occlusion); + (void)target; + + FLUSH(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetGetQueryivARB called in begin/end"); + return; + } + + switch (pname) { + case GL_QUERY_COUNTER_BITS_ARB: + *params = 8 * sizeof(GLuint); + break; + case GL_CURRENT_QUERY_ARB: + *params = o->currentQueryObject; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetGetQueryivARB(pname)"); + return; + } +} + + +void STATE_APIENTRY +crStateGetQueryObjectivARB(GLuint id, GLenum pname, GLint *params) +{ + CRContext *g = GetCurrentContext(); + CROcclusionState *o = &(g->occlusion); + CROcclusionObject *q; + + FLUSH(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetGetQueryObjectivARB called in begin/end"); + return; + } + + q = (CROcclusionObject *) crHashtableSearch(o->objects, id); + if (!q || q->active) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetQueryObjectivARB"); + return; + } + + switch (pname) { + case GL_QUERY_RESULT_ARB: + *params = q->passedCounter; + break; + case GL_QUERY_RESULT_AVAILABLE_ARB: + *params = GL_TRUE; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetQueryObjectivARB(pname)"); + return; + } +} + + +void STATE_APIENTRY +crStateGetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params) +{ + CRContext *g = GetCurrentContext(); + CROcclusionState *o = &(g->occlusion); + CROcclusionObject *q; + + FLUSH(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetGetQueryObjectuivARB called in begin/end"); + return; + } + + q = (CROcclusionObject *) crHashtableSearch(o->objects, id); + if (!q || q->active) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetQueryObjectuivARB"); + return; + } + + switch (pname) { + case GL_QUERY_RESULT_ARB: + *params = q->passedCounter; + break; + case GL_QUERY_RESULT_AVAILABLE_ARB: + /* XXX revisit when we have a hardware implementation! */ + *params = GL_TRUE; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetQueryObjectuivARB(pname)"); + return; + } +} + + +void STATE_APIENTRY +crStateBeginQueryARB(GLenum target, GLuint id) +{ + CRContext *g = GetCurrentContext(); + CROcclusionState *o = &(g->occlusion); + CROcclusionObject *q; + + FLUSH(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetGetQueryObjectuivARB called in begin/end"); + return; + } + + if (target != GL_SAMPLES_PASSED_ARB) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glBeginQueryARB(target)"); + return; + } + + if (o->currentQueryObject) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glBeginQueryARB(target)"); + return; + } + + q = (CROcclusionObject *) crHashtableSearch(o->objects, id); + if (q && q->active) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glBeginQueryARB"); + return; + } + else if (!q) { + q = NewQueryObject(target, id); + if (!q) { + crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glBeginQueryARB"); + return; + } + crHashtableAdd(o->objects, id, q); + } + + q->active = GL_TRUE; + q->passedCounter = 0; + q->active = GL_TRUE; + q->passedCounter = 0; + o->currentQueryObject = id; +} + + +void STATE_APIENTRY +crStateEndQueryARB(GLenum target) +{ + CRContext *g = GetCurrentContext(); + CROcclusionState *o = &(g->occlusion); + CROcclusionObject *q; + + FLUSH(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetGetQueryObjectuivARB called in begin/end"); + return; + } + + if (target != GL_SAMPLES_PASSED_ARB) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glEndQueryARB(target)"); + return; + } + + q = (CROcclusionObject *) crHashtableSearch(o->objects, o->currentQueryObject); + if (!q || !q->active) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glEndQueryARB with glBeginQueryARB"); + return; + } + + q->passedCounter = 0; + q->active = GL_FALSE; + o->currentQueryObject = 0; +} + + +void crStateOcclusionDiff(CROcclusionBits *bb, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + /* Apparently, no occlusion state differencing needed */ + (void)bb; (void)bitID; (void)fromCtx; (void)toCtx; +} + + +/* + * XXX this function might need some testing/fixing. + */ +void crStateOcclusionSwitch(CROcclusionBits *bb, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + /* Apparently, no occlusion state switching needed */ + /* Note: we better not do a switch while we're inside a glBeginQuery/ + * glEndQuery sequence. + */ + (void)bb; (void)bitID; (void)fromCtx; (void)toCtx; + CRASSERT(!fromCtx->occlusion.currentQueryObject); +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_pixel.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_pixel.c new file mode 100644 index 00000000..58e08aec --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_pixel.c @@ -0,0 +1,857 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include <stdio.h> +#include "cr_mem.h" +#include "state.h" +#include "state/cr_statetypes.h" +#include "state_internals.h" + +void crStatePixelInit(CRContext *ctx) +{ + CRPixelState *p = &ctx->pixel; + CRStateBits *sb = GetCurrentBits(); + CRPixelBits *pb = &(sb->pixel); + GLcolorf zero_color = {0.0f, 0.0f, 0.0f, 0.0f}; + GLcolorf one_color = {1.0f, 1.0f, 1.0f, 1.0f}; + + p->mapColor = GL_FALSE; + p->mapStencil = GL_FALSE; + p->indexShift = 0; + p->indexOffset = 0; + p->scale = one_color; + p->depthScale = 1.0f; + p->bias = zero_color; + p->depthBias = 0.0f; + p->xZoom = 1.0f; + p->yZoom = 1.0f; + RESET(pb->transfer, ctx->bitid); + RESET(pb->zoom, ctx->bitid); + + p->mapStoS[0] = 0; + p->mapItoI[0] = 0; + p->mapItoR[0] = 0.0; + p->mapItoG[0] = 0.0; + p->mapItoB[0] = 0.0; + p->mapItoA[0] = 0.0; + p->mapRtoR[0] = 0.0; + p->mapGtoG[0] = 0.0; + p->mapBtoB[0] = 0.0; + p->mapAtoA[0] = 0.0; + + p->mapItoIsize = 1; + p->mapStoSsize = 1; + p->mapItoRsize = 1; + p->mapItoGsize = 1; + p->mapItoBsize = 1; + p->mapItoAsize = 1; + p->mapRtoRsize = 1; + p->mapGtoGsize = 1; + p->mapBtoBsize = 1; + p->mapAtoAsize = 1; + RESET(pb->maps, ctx->bitid); + + RESET(pb->dirty, ctx->bitid); +} + +void STATE_APIENTRY crStatePixelTransferi (GLenum pname, GLint param) +{ + crStatePixelTransferf( pname, (GLfloat) param ); +} + +void STATE_APIENTRY crStatePixelTransferf (GLenum pname, GLfloat param) +{ + CRContext *g = GetCurrentContext(); + CRPixelState *p = &(g->pixel); + CRStateBits *sb = GetCurrentBits(); + CRPixelBits *pb = &(sb->pixel); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "PixelTransfer{if} called in Begin/End"); + return; + } + + FLUSH(); + + switch( pname ) + { + case GL_MAP_COLOR: + p->mapColor = (GLboolean) ((param == 0.0f) ? GL_FALSE : GL_TRUE); + break; + case GL_MAP_STENCIL: + p->mapStencil = (GLboolean) ((param == 0.0f) ? GL_FALSE : GL_TRUE); + break; + case GL_INDEX_SHIFT: + p->indexShift = (GLint) param; + break; + case GL_INDEX_OFFSET: + p->indexOffset = (GLint) param; + break; + case GL_RED_SCALE: + p->scale.r = param; + break; + case GL_GREEN_SCALE: + p->scale.g = param; + break; + case GL_BLUE_SCALE: + p->scale.b = param; + break; + case GL_ALPHA_SCALE: + p->scale.a = param; + break; + case GL_DEPTH_SCALE: + p->depthScale = param; + break; + case GL_RED_BIAS: + p->bias.r = param; + break; + case GL_GREEN_BIAS: + p->bias.g = param; + break; + case GL_BLUE_BIAS: + p->bias.b = param; + break; + case GL_ALPHA_BIAS: + p->bias.a = param; + break; + case GL_DEPTH_BIAS: + p->depthBias = param; + break; + default: + crStateError( __LINE__, __FILE__, GL_INVALID_VALUE, "Unknown glPixelTransfer pname: %d", pname ); + return; + } + DIRTY(pb->transfer, g->neg_bitid); + DIRTY(pb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStatePixelZoom (GLfloat xfactor, GLfloat yfactor) +{ + CRContext *g = GetCurrentContext(); + CRPixelState *p = &(g->pixel); + CRStateBits *sb = GetCurrentBits(); + CRPixelBits *pb = &(sb->pixel); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "PixelZoom called in Begin/End"); + return; + } + + FLUSH(); + + p->xZoom = xfactor; + p->yZoom = yfactor; + DIRTY(pb->zoom, g->neg_bitid); + DIRTY(pb->dirty, g->neg_bitid); +} + + +void STATE_APIENTRY crStateBitmap( GLsizei width, GLsizei height, + GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, + const GLubyte *bitmap) +{ + CRContext *g = GetCurrentContext(); + CRCurrentState *c = &(g->current); + CRStateBits *sb = GetCurrentBits(); + CRCurrentBits *cb = &(sb->current); + + (void) xorig; + (void) yorig; + (void) bitmap; + + if (g->lists.mode == GL_COMPILE) + return; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "Bitmap called in begin/end"); + return; + } + + if (width < 0 || height < 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "Bitmap called with neg dims: %dx%d", width, height); + return; + } + + if (!c->rasterValid) + { + return; + } + + c->rasterAttrib[VERT_ATTRIB_POS][0] += xmove; + c->rasterAttrib[VERT_ATTRIB_POS][1] += ymove; + DIRTY(cb->rasterPos, g->neg_bitid); + DIRTY(cb->dirty, g->neg_bitid); + + c->rasterAttribPre[VERT_ATTRIB_POS][0] += xmove; + c->rasterAttribPre[VERT_ATTRIB_POS][1] += ymove; +} + + +#define UNUSED(x) ((void)(x)) + +#define CLAMP(x, min, max) ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x))) + +void STATE_APIENTRY crStatePixelMapfv (GLenum map, GLint mapsize, const GLfloat * values) +{ + CRContext *g = GetCurrentContext(); + CRPixelState *p = &(g->pixel); + CRStateBits *sb = GetCurrentBits(); + CRPixelBits *pb = &(sb->pixel); + GLint i; + GLboolean unpackbuffer = crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "PixelMap called in Begin/End"); + return; + } + + FLUSH(); + + if (mapsize < 0 || mapsize > CR_MAX_PIXEL_MAP_TABLE) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "PixelMap(mapsize)"); + return; + } + + if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) { + /* XXX check that mapsize is a power of two */ + } + + switch (map) { + case GL_PIXEL_MAP_S_TO_S: + p->mapStoSsize = mapsize; + if (!unpackbuffer) + for (i=0;i<mapsize;i++) { + p->mapStoS[i] = (GLint) values[i]; + } + break; + case GL_PIXEL_MAP_I_TO_I: + p->mapItoIsize = mapsize; + if (!unpackbuffer) + for (i=0;i<mapsize;i++) { + p->mapItoI[i] = (GLint) values[i]; + } + break; + case GL_PIXEL_MAP_I_TO_R: + p->mapItoRsize = mapsize; + if (!unpackbuffer) + for (i=0;i<mapsize;i++) { + GLfloat val = CLAMP( values[i], 0.0F, 1.0F ); + p->mapItoR[i] = val; + } + break; + case GL_PIXEL_MAP_I_TO_G: + p->mapItoGsize = mapsize; + if (!unpackbuffer) + for (i=0;i<mapsize;i++) { + GLfloat val = CLAMP( values[i], 0.0F, 1.0F ); + p->mapItoG[i] = val; + } + break; + case GL_PIXEL_MAP_I_TO_B: + p->mapItoBsize = mapsize; + if (!unpackbuffer) + for (i=0;i<mapsize;i++) { + GLfloat val = CLAMP( values[i], 0.0F, 1.0F ); + p->mapItoB[i] = val; + } + break; + case GL_PIXEL_MAP_I_TO_A: + p->mapItoAsize = mapsize; + if (!unpackbuffer) + for (i=0;i<mapsize;i++) { + GLfloat val = CLAMP( values[i], 0.0F, 1.0F ); + p->mapItoA[i] = val; + } + break; + case GL_PIXEL_MAP_R_TO_R: + p->mapRtoRsize = mapsize; + if (!unpackbuffer) + for (i=0;i<mapsize;i++) { + p->mapRtoR[i] = CLAMP( values[i], 0.0F, 1.0F ); + } + break; + case GL_PIXEL_MAP_G_TO_G: + p->mapGtoGsize = mapsize; + if (!unpackbuffer) + for (i=0;i<mapsize;i++) { + p->mapGtoG[i] = CLAMP( values[i], 0.0F, 1.0F ); + } + break; + case GL_PIXEL_MAP_B_TO_B: + p->mapBtoBsize = mapsize; + if (!unpackbuffer) + for (i=0;i<mapsize;i++) { + p->mapBtoB[i] = CLAMP( values[i], 0.0F, 1.0F ); + } + break; + case GL_PIXEL_MAP_A_TO_A: + p->mapAtoAsize = mapsize; + if (!unpackbuffer) + for (i=0;i<mapsize;i++) { + p->mapAtoA[i] = CLAMP( values[i], 0.0F, 1.0F ); + } + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "PixelMap(map)"); + return; + } + + DIRTY(pb->maps, g->neg_bitid); + DIRTY(pb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStatePixelMapuiv (GLenum map, GLint mapsize, const GLuint * values) +{ + if (mapsize < 0 || mapsize > CR_MAX_PIXEL_MAP_TABLE) + { + crError("crStatePixelMapuiv: parameter 'mapsize' is out of range"); + return; + } + + if (!crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + GLfloat fvalues[CR_MAX_PIXEL_MAP_TABLE]; + GLint i; + + if (map==GL_PIXEL_MAP_I_TO_I || map==GL_PIXEL_MAP_S_TO_S) { + for (i=0;i<mapsize;i++) { + fvalues[i] = (GLfloat) values[i]; + } + } + else { + for (i=0;i<mapsize;i++) { + fvalues[i] = values[i] / 4294967295.0F; + } + } + crStatePixelMapfv(map, mapsize, fvalues); + } + else + { + crStatePixelMapfv(map, mapsize, (const GLfloat*) values); + } +} + +void STATE_APIENTRY crStatePixelMapusv (GLenum map, GLint mapsize, const GLushort * values) +{ + if (mapsize < 0 || mapsize > CR_MAX_PIXEL_MAP_TABLE) + { + crError("crStatePixelMapusv: parameter 'mapsize' is out of range"); + return; + } + + if (!crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + GLfloat fvalues[CR_MAX_PIXEL_MAP_TABLE]; + GLint i; + + if (map==GL_PIXEL_MAP_I_TO_I || map==GL_PIXEL_MAP_S_TO_S) { + for (i=0;i<mapsize;i++) { + fvalues[i] = (GLfloat) values[i]; + } + } + else { + for (i=0;i<mapsize;i++) { + fvalues[i] = values[i] / 65535.0F; + } + } + crStatePixelMapfv(map, mapsize, fvalues); + } + else + { + crStatePixelMapfv(map, mapsize, (const GLfloat*) values); + } +} + + +void STATE_APIENTRY crStateGetPixelMapfv (GLenum map, GLfloat * values) +{ + CRContext *g = GetCurrentContext(); + CRPixelState *p = &(g->pixel); + GLint i; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "GetPixelMapfv called in Begin/End"); + return; + } + + switch (map) { + case GL_PIXEL_MAP_S_TO_S: + for (i = 0; i < p->mapStoSsize; i++) { + values[i] = (GLfloat) p->mapStoS[i]; + } + break; + case GL_PIXEL_MAP_I_TO_I: + for (i = 0; i < p->mapItoIsize; i++) { + values[i] = (GLfloat) p->mapItoI[i]; + } + break; + case GL_PIXEL_MAP_I_TO_R: + crMemcpy(values, p->mapItoR, p->mapItoRsize * sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_I_TO_G: + crMemcpy(values, p->mapItoG, p->mapItoGsize * sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_I_TO_B: + crMemcpy(values, p->mapItoB, p->mapItoBsize * sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_I_TO_A: + crMemcpy(values, p->mapItoA, p->mapItoAsize * sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_R_TO_R: + crMemcpy(values, p->mapRtoR, p->mapRtoRsize * sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_G_TO_G: + crMemcpy(values, p->mapGtoG, p->mapGtoGsize * sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_B_TO_B: + crMemcpy(values, p->mapBtoB, p->mapBtoBsize * sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_A_TO_A: + crMemcpy(values, p->mapAtoA, p->mapAtoAsize * sizeof(GLfloat)); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "GetPixelMap(map)"); + return; + } +} + +void STATE_APIENTRY crStateGetPixelMapuiv (GLenum map, GLuint * values) +{ + CRContext *g = GetCurrentContext(); + const GLfloat maxUint = 4294967295.0F; + CRPixelState *p = &(g->pixel); + GLint i; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "GetPixelMapuiv called in Begin/End"); + return; + } + + switch (map) { + case GL_PIXEL_MAP_S_TO_S: + for (i = 0; i < p->mapStoSsize; i++) { + values[i] = p->mapStoS[i]; + } + break; + case GL_PIXEL_MAP_I_TO_I: + for (i = 0; i < p->mapItoIsize; i++) { + values[i] = p->mapItoI[i]; + } + break; + case GL_PIXEL_MAP_I_TO_R: + for (i = 0; i < p->mapItoRsize; i++) { + values[i] = (GLuint) (p->mapItoR[i] * maxUint); + } + break; + case GL_PIXEL_MAP_I_TO_G: + for (i = 0; i < p->mapItoGsize; i++) { + values[i] = (GLuint) (p->mapItoG[i] * maxUint); + } + break; + case GL_PIXEL_MAP_I_TO_B: + for (i = 0; i < p->mapItoBsize; i++) { + values[i] = (GLuint) (p->mapItoB[i] * maxUint); + } + break; + case GL_PIXEL_MAP_I_TO_A: + for (i = 0; i < p->mapItoAsize; i++) { + values[i] = (GLuint) (p->mapItoA[i] * maxUint); + } + break; + case GL_PIXEL_MAP_R_TO_R: + for (i = 0; i < p->mapRtoRsize; i++) { + values[i] = (GLuint) (p->mapRtoR[i] * maxUint); + } + break; + case GL_PIXEL_MAP_G_TO_G: + for (i = 0; i < p->mapGtoGsize; i++) { + values[i] = (GLuint) (p->mapGtoG[i] * maxUint); + } + break; + case GL_PIXEL_MAP_B_TO_B: + for (i = 0; i < p->mapBtoBsize; i++) { + values[i] = (GLuint) (p->mapBtoB[i] * maxUint); + } + break; + case GL_PIXEL_MAP_A_TO_A: + for (i = 0; i < p->mapAtoAsize; i++) { + values[i] = (GLuint) (p->mapAtoA[i] * maxUint); + } + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "GetPixelMapuiv(map)"); + return; + } +} + +void STATE_APIENTRY crStateGetPixelMapusv (GLenum map, GLushort * values) +{ + CRContext *g = GetCurrentContext(); + const GLfloat maxUshort = 65535.0F; + CRPixelState *p = &(g->pixel); + GLint i; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "GetPixelMapusv called in Begin/End"); + return; + } + + switch (map) { + case GL_PIXEL_MAP_S_TO_S: + for (i = 0; i < p->mapStoSsize; i++) { + values[i] = p->mapStoS[i]; + } + break; + case GL_PIXEL_MAP_I_TO_I: + for (i = 0; i < p->mapItoIsize; i++) { + values[i] = p->mapItoI[i]; + } + break; + case GL_PIXEL_MAP_I_TO_R: + for (i = 0; i < p->mapItoRsize; i++) { + values[i] = (GLushort) (p->mapItoR[i] * maxUshort); + } + break; + case GL_PIXEL_MAP_I_TO_G: + for (i = 0; i < p->mapItoGsize; i++) { + values[i] = (GLushort) (p->mapItoG[i] * maxUshort); + } + break; + case GL_PIXEL_MAP_I_TO_B: + for (i = 0; i < p->mapItoBsize; i++) { + values[i] = (GLushort) (p->mapItoB[i] * maxUshort); + } + break; + case GL_PIXEL_MAP_I_TO_A: + for (i = 0; i < p->mapItoAsize; i++) { + values[i] = (GLushort) (p->mapItoA[i] * maxUshort); + } + break; + case GL_PIXEL_MAP_R_TO_R: + for (i = 0; i < p->mapRtoRsize; i++) { + values[i] = (GLushort) (p->mapRtoR[i] * maxUshort); + } + break; + case GL_PIXEL_MAP_G_TO_G: + for (i = 0; i < p->mapGtoGsize; i++) { + values[i] = (GLushort) (p->mapGtoG[i] * maxUshort); + } + break; + case GL_PIXEL_MAP_B_TO_B: + for (i = 0; i < p->mapBtoBsize; i++) { + values[i] = (GLushort) (p->mapBtoB[i] * maxUshort); + } + break; + case GL_PIXEL_MAP_A_TO_A: + for (i = 0; i < p->mapAtoAsize; i++) { + values[i] = (GLushort) (p->mapAtoA[i] * maxUshort); + } + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "GetPixelMapusv(map)"); + return; + } +} + +void crStatePixelDiff(CRPixelBits *b, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + CRPixelState *from = &(fromCtx->pixel); + CRPixelState *to = &(toCtx->pixel); + int j, i; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + for (j=0;j<CR_MAX_BITARRAY;j++) + nbitID[j] = ~bitID[j]; + i = 0; /* silence compiler */ + if (CHECKDIRTY(b->transfer, bitID)) + { + if (from->mapColor != to->mapColor) + { + diff_api.PixelTransferi (GL_MAP_COLOR, to->mapColor); + from->mapColor = to->mapColor; + } + if (from->mapStencil != to->mapStencil) + { + diff_api.PixelTransferi (GL_MAP_STENCIL, to->mapStencil); + from->mapStencil = to->mapStencil; + } + if (from->indexOffset != to->indexOffset) + { + diff_api.PixelTransferi (GL_INDEX_OFFSET, to->indexOffset); + from->indexOffset = to->indexOffset; + } + if (from->indexShift != to->indexShift) + { + diff_api.PixelTransferi (GL_INDEX_SHIFT, to->indexShift); + from->indexShift = to->indexShift; + } + if (from->scale.r != to->scale.r) + { + diff_api.PixelTransferf (GL_RED_SCALE, to->scale.r); + from->scale.r = to->scale.r; + } + if (from->scale.g != to->scale.g) + { + diff_api.PixelTransferf (GL_GREEN_SCALE, to->scale.g); + from->scale.g = to->scale.g; + } + if (from->scale.b != to->scale.b) + { + diff_api.PixelTransferf (GL_BLUE_SCALE, to->scale.b); + from->scale.b = to->scale.b; + } + if (from->scale.a != to->scale.a) + { + diff_api.PixelTransferf (GL_ALPHA_SCALE, to->scale.a); + from->scale.a = to->scale.a; + } + if (from->bias.r != to->bias.r) + { + diff_api.PixelTransferf (GL_RED_BIAS, to->bias.r); + from->bias.r = to->bias.r; + } + if (from->bias.g != to->bias.g) + { + diff_api.PixelTransferf (GL_GREEN_BIAS, to->bias.g); + from->bias.g = to->bias.g; + } + if (from->bias.b != to->bias.b) + { + diff_api.PixelTransferf (GL_BLUE_BIAS, to->bias.b); + from->bias.b = to->bias.b; + } + if (from->bias.a != to->bias.a) + { + diff_api.PixelTransferf (GL_ALPHA_BIAS, to->bias.a); + from->bias.a = to->bias.a; + } + if (from->depthScale != to->depthScale) + { + diff_api.PixelTransferf (GL_DEPTH_SCALE, to->depthScale); + from->depthScale = to->depthScale; + } + if (from->depthBias != to->depthBias) + { + diff_api.PixelTransferf (GL_DEPTH_BIAS, to->depthBias); + from->depthBias = to->depthBias; + } + CLEARDIRTY(b->transfer, nbitID); + } + if (CHECKDIRTY(b->zoom, bitID)) + { + if (from->xZoom != to->xZoom || + from->yZoom != to->yZoom) + { + diff_api.PixelZoom (to->xZoom, + to->yZoom); + from->xZoom = to->xZoom; + from->yZoom = to->yZoom; + } + CLEARDIRTY(b->zoom, nbitID); + } + if (CHECKDIRTY(b->maps, bitID)) + { + if (crMemcmp(to->mapStoS, from->mapStoS, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat))) + diff_api.PixelMapfv(GL_PIXEL_MAP_S_TO_S,to->mapStoSsize,(GLfloat*)to->mapStoS); + if (crMemcmp(to->mapItoI, from->mapItoI, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat))) + diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_I,to->mapItoIsize,(GLfloat*)to->mapItoI); + if (crMemcmp(to->mapItoR, from->mapItoR, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat))) + diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_R,to->mapItoRsize,(GLfloat*)to->mapItoR); + if (crMemcmp(to->mapItoG, from->mapItoG, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat))) + diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_G,to->mapItoGsize,(GLfloat*)to->mapItoG); + if (crMemcmp(to->mapItoB, from->mapItoB, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat))) + diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_B,to->mapItoBsize,(GLfloat*)to->mapItoB); + if (crMemcmp(to->mapItoA, from->mapItoA, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat))) + diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_A,to->mapItoAsize,(GLfloat*)to->mapItoA); + if (crMemcmp(to->mapRtoR, from->mapRtoR, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat))) + diff_api.PixelMapfv(GL_PIXEL_MAP_R_TO_R,to->mapRtoRsize,(GLfloat*)to->mapRtoR); + if (crMemcmp(to->mapGtoG, from->mapGtoG, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat))) + diff_api.PixelMapfv(GL_PIXEL_MAP_G_TO_G,to->mapGtoGsize,(GLfloat*)to->mapGtoG); + if (crMemcmp(to->mapBtoB, from->mapBtoB, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat))) + diff_api.PixelMapfv(GL_PIXEL_MAP_B_TO_B,to->mapBtoBsize,(GLfloat*)to->mapBtoB); + if (crMemcmp(to->mapAtoA, from->mapAtoA, CR_MAX_PIXEL_MAP_TABLE*sizeof(GLfloat))) + diff_api.PixelMapfv(GL_PIXEL_MAP_A_TO_A,to->mapAtoAsize,(GLfloat*)to->mapAtoA); + CLEARDIRTY(b->maps, nbitID); + } + CLEARDIRTY(b->dirty, nbitID); +} + +void crStatePixelSwitch(CRPixelBits *b, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + CRPixelState *from = &(fromCtx->pixel); + CRPixelState *to = &(toCtx->pixel); + int j, i; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + for (j=0;j<CR_MAX_BITARRAY;j++) + nbitID[j] = ~bitID[j]; + i = 0; /* silence compiler */ + if (CHECKDIRTY(b->transfer, bitID)) + { + if (from->mapColor != to->mapColor) + { + diff_api.PixelTransferi (GL_MAP_COLOR, to->mapColor); + FILLDIRTY(b->transfer); + FILLDIRTY(b->dirty); + } + if (from->mapStencil != to->mapStencil) + { + diff_api.PixelTransferi (GL_MAP_STENCIL, to->mapStencil); + FILLDIRTY(b->transfer); + FILLDIRTY(b->dirty); + } + if (from->indexOffset != to->indexOffset) + { + diff_api.PixelTransferi (GL_INDEX_OFFSET, to->indexOffset); + FILLDIRTY(b->transfer); + FILLDIRTY(b->dirty); + } + if (from->indexShift != to->indexShift) + { + diff_api.PixelTransferi (GL_INDEX_SHIFT, to->indexShift); + FILLDIRTY(b->transfer); + FILLDIRTY(b->dirty); + } + if (from->scale.r != to->scale.r) + { + diff_api.PixelTransferf (GL_RED_SCALE, to->scale.r); + FILLDIRTY(b->transfer); + FILLDIRTY(b->dirty); + } + if (from->scale.g != to->scale.g) + { + diff_api.PixelTransferf (GL_GREEN_SCALE, to->scale.g); + FILLDIRTY(b->transfer); + FILLDIRTY(b->dirty); + } + if (from->scale.b != to->scale.b) + { + diff_api.PixelTransferf (GL_BLUE_SCALE, to->scale.b); + FILLDIRTY(b->transfer); + FILLDIRTY(b->dirty); + } + if (from->scale.a != to->scale.a) + { + diff_api.PixelTransferf (GL_ALPHA_SCALE, to->scale.a); + FILLDIRTY(b->transfer); + FILLDIRTY(b->dirty); + } + if (from->bias.r != to->bias.r) + { + diff_api.PixelTransferf (GL_RED_BIAS, to->bias.r); + FILLDIRTY(b->transfer); + FILLDIRTY(b->dirty); + } + if (from->bias.g != to->bias.g) + { + diff_api.PixelTransferf (GL_GREEN_BIAS, to->bias.g); + FILLDIRTY(b->transfer); + FILLDIRTY(b->dirty); + } + if (from->bias.b != to->bias.b) + { + diff_api.PixelTransferf (GL_BLUE_BIAS, to->bias.b); + FILLDIRTY(b->transfer); + FILLDIRTY(b->dirty); + } + if (from->bias.a != to->bias.a) + { + diff_api.PixelTransferf (GL_ALPHA_BIAS, to->bias.a); + FILLDIRTY(b->transfer); + FILLDIRTY(b->dirty); + } + if (from->depthScale != to->depthScale) + { + diff_api.PixelTransferf (GL_DEPTH_SCALE, to->depthScale); + FILLDIRTY(b->transfer); + FILLDIRTY(b->dirty); + } + if (from->depthBias != to->depthBias) + { + diff_api.PixelTransferf (GL_DEPTH_BIAS, to->depthBias); + FILLDIRTY(b->transfer); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->transfer, nbitID); + } + if (CHECKDIRTY(b->zoom, bitID)) + { + if (from->xZoom != to->xZoom || + from->yZoom != to->yZoom) + { + diff_api.PixelZoom (to->xZoom, + to->yZoom); + FILLDIRTY(b->zoom); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->zoom, nbitID); + } + if (CHECKDIRTY(b->maps, bitID)) + { + if (crMemcmp(to->mapStoS, from->mapStoS, CR_MAX_PIXEL_MAP_TABLE)) { + diff_api.PixelMapfv(GL_PIXEL_MAP_S_TO_S,to->mapStoSsize,(GLfloat*)to->mapStoS); + FILLDIRTY(b->maps); + FILLDIRTY(b->dirty); + } + if (crMemcmp(to->mapItoI, from->mapItoI, CR_MAX_PIXEL_MAP_TABLE)) { + diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_I,to->mapItoIsize,(GLfloat*)to->mapItoI); + FILLDIRTY(b->maps); + FILLDIRTY(b->dirty); + } + if (crMemcmp(to->mapItoR, from->mapItoR, CR_MAX_PIXEL_MAP_TABLE)) { + diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_R,to->mapItoRsize,(GLfloat*)to->mapItoR); + FILLDIRTY(b->maps); + FILLDIRTY(b->dirty); + } + if (crMemcmp(to->mapItoG, from->mapItoG, CR_MAX_PIXEL_MAP_TABLE)) { + diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_G,to->mapItoGsize,(GLfloat*)to->mapItoG); + FILLDIRTY(b->maps); + FILLDIRTY(b->dirty); + } + if (crMemcmp(to->mapItoB, from->mapItoB, CR_MAX_PIXEL_MAP_TABLE)) { + diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_B,to->mapItoBsize,(GLfloat*)to->mapItoB); + FILLDIRTY(b->maps); + FILLDIRTY(b->dirty); + } + if (crMemcmp(to->mapItoA, from->mapItoA, CR_MAX_PIXEL_MAP_TABLE)) { + diff_api.PixelMapfv(GL_PIXEL_MAP_I_TO_A,to->mapItoAsize,(GLfloat*)to->mapItoA); + FILLDIRTY(b->maps); + FILLDIRTY(b->dirty); + } + if (crMemcmp(to->mapRtoR, from->mapRtoR, CR_MAX_PIXEL_MAP_TABLE)) { + diff_api.PixelMapfv(GL_PIXEL_MAP_R_TO_R,to->mapRtoRsize,(GLfloat*)to->mapRtoR); + FILLDIRTY(b->maps); + FILLDIRTY(b->dirty); + } + if (crMemcmp(to->mapGtoG, from->mapGtoG, CR_MAX_PIXEL_MAP_TABLE)) { + diff_api.PixelMapfv(GL_PIXEL_MAP_G_TO_G,to->mapGtoGsize,(GLfloat*)to->mapGtoG); + FILLDIRTY(b->maps); + FILLDIRTY(b->dirty); + } + if (crMemcmp(to->mapBtoB, from->mapBtoB, CR_MAX_PIXEL_MAP_TABLE)) { + diff_api.PixelMapfv(GL_PIXEL_MAP_B_TO_B,to->mapBtoBsize,(GLfloat*)to->mapBtoB); + FILLDIRTY(b->maps); + FILLDIRTY(b->dirty); + } + if (crMemcmp(to->mapAtoA, from->mapAtoA, CR_MAX_PIXEL_MAP_TABLE)) { + diff_api.PixelMapfv(GL_PIXEL_MAP_A_TO_A,to->mapAtoAsize,(GLfloat*)to->mapAtoA); + FILLDIRTY(b->maps); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->maps, nbitID); + } + CLEARDIRTY(b->dirty, nbitID); +} + diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_point.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_point.c new file mode 100644 index 00000000..de40c089 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_point.c @@ -0,0 +1,447 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "state.h" +#include "state/cr_statetypes.h" +#include "state_internals.h" + +void crStatePointInit (CRContext *ctx) +{ + CRPointState *p = &ctx->point; + CRStateBits *sb = GetCurrentBits(); + CRPointBits *pb = &(sb->point); + int i; + + p->pointSmooth = GL_FALSE; + RESET(pb->enableSmooth, ctx->bitid); + p->pointSize = 1.0f; + RESET(pb->size, ctx->bitid); +#ifdef CR_ARB_point_parameters + p->minSize = 0.0f; + RESET(pb->minSize, ctx->bitid); + p->maxSize = CR_ALIASED_POINT_SIZE_MAX; + RESET(pb->maxSize, ctx->bitid); + p->fadeThresholdSize = 1.0f; + RESET(pb->fadeThresholdSize, ctx->bitid); + p->distanceAttenuation[0] = 1.0f; + p->distanceAttenuation[1] = 0.0f; + p->distanceAttenuation[2] = 0.0f; + RESET(pb->distanceAttenuation, ctx->bitid); +#endif +#ifdef CR_ARB_point_sprite + p->pointSprite = GL_FALSE; + RESET(pb->enableSprite, ctx->bitid); + for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) { + p->coordReplacement[i] = GL_FALSE; + RESET(pb->coordReplacement[i], ctx->bitid); + } +#endif + + p->spriteCoordOrigin = (GLfloat)GL_UPPER_LEFT; + RESET(pb->spriteCoordOrigin, ctx->bitid); + + RESET(pb->dirty, ctx->bitid); + + /* + *p->aliasedpointsizerange_min = c->aliasedpointsizerange_min; + *p->aliasedpointsizerange_max = c->aliasedpointsizerange_max; + *p->aliasedpointsizegranularity = c->aliasedpointsizegranularity; + *p->smoothpointsizerange_min = c->smoothpointsizerange_min; + *p->smoothpointsizerange_max = c->smoothpointsizerange_max; + *p->smoothpointgranularity = c->smoothpointgranularity; + */ +} + +void STATE_APIENTRY crStatePointSize(GLfloat size) +{ + CRContext *g = GetCurrentContext(); + CRPointState *p = &(g->point); + CRStateBits *sb = GetCurrentBits(); + CRPointBits *pb = &(sb->point); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glPointSize called in begin/end"); + return; + } + + FLUSH(); + + if (size <= 0.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glPointSize called with size <= 0.0: %f", size); + return; + } + + p->pointSize = size; + DIRTY(pb->size, g->neg_bitid); + DIRTY(pb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStatePointParameterfARB(GLenum pname, GLfloat param) +{ + CRContext *g = GetCurrentContext(); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glPointParameterfARB called in begin/end"); + return; + } + + FLUSH(); + + crStatePointParameterfvARB(pname, ¶m); +} + +void STATE_APIENTRY crStatePointParameterfvARB(GLenum pname, const GLfloat *params) +{ + CRContext *g = GetCurrentContext(); + CRPointState *p = &(g->point); + CRStateBits *sb = GetCurrentBits(); + CRPointBits *pb = &(sb->point); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glPointParameterfvARB called in begin/end"); + return; + } + + FLUSH(); + + switch (pname) { + case GL_DISTANCE_ATTENUATION_EXT: + if (g->extensions.ARB_point_parameters) { + p->distanceAttenuation[0] = params[0]; + p->distanceAttenuation[1] = params[1]; + p->distanceAttenuation[2] = params[2]; + DIRTY(pb->distanceAttenuation, g->neg_bitid); + } + else + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glPointParameterfvARB invalid enum: %f", pname); + return; + } + break; + case GL_POINT_SIZE_MIN_EXT: + if (g->extensions.ARB_point_parameters) { + if (params[0] < 0.0F) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glPointParameterfvARB invalid value: %f", params[0]); + return; + } + p->minSize = params[0]; + DIRTY(pb->minSize, g->neg_bitid); + } + else + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glPointParameterfvARB invalid enum: %f", pname); + return; + } + break; + case GL_POINT_SIZE_MAX_EXT: + if (g->extensions.ARB_point_parameters) { + if (params[0] < 0.0F) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glPointParameterfvARB invalid value: %f", params[0]); + return; + } + p->maxSize = params[0]; + DIRTY(pb->maxSize, g->neg_bitid); + } + else + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glPointParameterfvARB invalid enum: %f", pname); + return; + } + break; + case GL_POINT_FADE_THRESHOLD_SIZE_EXT: + if (g->extensions.ARB_point_parameters) { + if (params[0] < 0.0F) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glPointParameterfvARB invalid value: %f", params[0]); + return; + } + p->fadeThresholdSize = params[0]; + DIRTY(pb->fadeThresholdSize, g->neg_bitid); + } + else + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glPointParameterfvARB invalid enum: %f", pname); + return; + } + break; + case GL_POINT_SPRITE_COORD_ORIGIN: + { + GLenum enmVal = (GLenum)params[0]; + if (enmVal != GL_LOWER_LEFT && enmVal != GL_UPPER_LEFT) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glPointParameterfvARB invalid GL_POINT_SPRITE_COORD_ORIGIN value: %f", params[0]); + return; + } + p->spriteCoordOrigin = params[0]; + DIRTY(pb->spriteCoordOrigin, g->neg_bitid); + break; + } + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glPointParameterfvARB invalid enum: %f", pname); + return; + } + + DIRTY(pb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStatePointParameteri(GLenum pname, GLint param) +{ + GLfloat f_param = (GLfloat) param; + crStatePointParameterfvARB( pname, &f_param ); +} + +void STATE_APIENTRY crStatePointParameteriv(GLenum pname, const GLint *params) +{ + GLfloat f_param = (GLfloat) (*params); + crStatePointParameterfvARB( pname, &f_param ); +} + +void crStatePointDiff(CRPointBits *b, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + CRPointState *from = &(fromCtx->point); + CRPointState *to = &(toCtx->point); + unsigned int j, i; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + Assert(0); + for (j=0;j<CR_MAX_BITARRAY;j++) + nbitID[j] = ~bitID[j]; + i = 0; /* silence compiler */ + if (CHECKDIRTY(b->enableSmooth, bitID)) + { + glAble able[2]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + if (from->pointSmooth != to->pointSmooth) + { + able[to->pointSmooth](GL_POINT_SMOOTH); + from->pointSmooth = to->pointSmooth; + } + CLEARDIRTY(b->enableSmooth, nbitID); + } + if (CHECKDIRTY(b->size, bitID)) + { + if (from->pointSize != to->pointSize) + { + diff_api.PointSize (to->pointSize); + from->pointSize = to->pointSize; + } + CLEARDIRTY(b->size, nbitID); + } + if (CHECKDIRTY(b->minSize, bitID)) + { + if (from->minSize != to->minSize) + { + diff_api.PointParameterfARB (GL_POINT_SIZE_MIN_ARB, to->minSize); + from->minSize = to->minSize; + } + CLEARDIRTY(b->minSize, nbitID); + } + if (CHECKDIRTY(b->maxSize, bitID)) + { + if (from->maxSize != to->maxSize) + { + diff_api.PointParameterfARB (GL_POINT_SIZE_MAX_ARB, to->maxSize); + from->maxSize = to->maxSize; + } + CLEARDIRTY(b->maxSize, nbitID); + } + if (CHECKDIRTY(b->fadeThresholdSize, bitID)) + { + if (from->fadeThresholdSize != to->fadeThresholdSize) + { + diff_api.PointParameterfARB (GL_POINT_FADE_THRESHOLD_SIZE_ARB, to->fadeThresholdSize); + from->fadeThresholdSize = to->fadeThresholdSize; + } + CLEARDIRTY(b->fadeThresholdSize, nbitID); + } + if (CHECKDIRTY(b->spriteCoordOrigin, bitID)) + { + if (from->spriteCoordOrigin != to->spriteCoordOrigin) + { + diff_api.PointParameterfARB (GL_POINT_SPRITE_COORD_ORIGIN, to->spriteCoordOrigin); + from->spriteCoordOrigin = to->spriteCoordOrigin; + } + CLEARDIRTY(b->spriteCoordOrigin, nbitID); + } + if (CHECKDIRTY(b->distanceAttenuation, bitID)) + { + if (from->distanceAttenuation[0] != to->distanceAttenuation[0] || from->distanceAttenuation[1] != to->distanceAttenuation[1] || from->distanceAttenuation[2] != to->distanceAttenuation[2]) { + diff_api.PointParameterfvARB (GL_POINT_DISTANCE_ATTENUATION_ARB, to->distanceAttenuation); + from->distanceAttenuation[0] = to->distanceAttenuation[0]; + from->distanceAttenuation[1] = to->distanceAttenuation[1]; + from->distanceAttenuation[2] = to->distanceAttenuation[2]; + } + CLEARDIRTY(b->distanceAttenuation, nbitID); + } + if (CHECKDIRTY(b->enableSprite, bitID)) + { + glAble able[2]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + if (from->pointSprite != to->pointSprite) + { + able[to->pointSprite](GL_POINT_SPRITE_ARB); + from->pointSprite = to->pointSprite; + } + CLEARDIRTY(b->enableSprite, nbitID); + } + { + unsigned int activeUnit = (unsigned int) -1; + for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) { + if (CHECKDIRTY(b->coordReplacement[i], bitID)) + { + GLint replacement = to->coordReplacement[i]; + if (activeUnit != i) { + diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB ); + activeUnit = i; + } + diff_api.TexEnviv(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, &replacement); + from->coordReplacement[i] = to->coordReplacement[i]; + CLEARDIRTY(b->coordReplacement[i], nbitID); + } + } + if (activeUnit != toCtx->texture.curTextureUnit) + diff_api.ActiveTextureARB(GL_TEXTURE0 + toCtx->texture.curTextureUnit); + } + CLEARDIRTY(b->dirty, nbitID); +} + +void crStatePointSwitch(CRPointBits *b, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + CRPointState *from = &(fromCtx->point); + CRPointState *to = &(toCtx->point); + unsigned int j, i; + GLboolean fEnabled; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + for (j=0;j<CR_MAX_BITARRAY;j++) + nbitID[j] = ~bitID[j]; + i = 0; /* silence compiler */ + if (CHECKDIRTY(b->enableSmooth, bitID)) + { + glAble able[2]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + if (from->pointSmooth != to->pointSmooth) + { + able[to->pointSmooth](GL_POINT_SMOOTH); + FILLDIRTY(b->enableSmooth); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->enableSmooth, nbitID); + } + if (CHECKDIRTY(b->size, bitID)) + { + if (from->pointSize != to->pointSize) + { + diff_api.PointSize (to->pointSize); + FILLDIRTY(b->size); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->size, nbitID); + } + if (CHECKDIRTY(b->minSize, bitID)) + { + if (from->minSize != to->minSize) + { + diff_api.PointParameterfARB (GL_POINT_SIZE_MIN_ARB, to->minSize); + FILLDIRTY(b->minSize); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->minSize, nbitID); + } + if (CHECKDIRTY(b->maxSize, bitID)) + { + if (from->maxSize != to->maxSize) + { + diff_api.PointParameterfARB (GL_POINT_SIZE_MAX_ARB, to->maxSize); + FILLDIRTY(b->maxSize); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->maxSize, nbitID); + } + if (CHECKDIRTY(b->fadeThresholdSize, bitID)) + { + if (from->fadeThresholdSize != to->fadeThresholdSize) + { + diff_api.PointParameterfARB (GL_POINT_FADE_THRESHOLD_SIZE_ARB, to->fadeThresholdSize); + FILLDIRTY(b->fadeThresholdSize); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->fadeThresholdSize, nbitID); + } + if (CHECKDIRTY(b->spriteCoordOrigin, bitID)) + { + if (from->spriteCoordOrigin != to->spriteCoordOrigin) + { + diff_api.PointParameterfARB (GL_POINT_SPRITE_COORD_ORIGIN, to->spriteCoordOrigin); + FILLDIRTY(b->spriteCoordOrigin); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->spriteCoordOrigin, nbitID); + } + if (CHECKDIRTY(b->distanceAttenuation, bitID)) + { + if (from->distanceAttenuation[0] != to->distanceAttenuation[0] || from->distanceAttenuation[1] != to->distanceAttenuation[1] || from->distanceAttenuation[2] != to->distanceAttenuation[2]) { + diff_api.PointParameterfvARB (GL_POINT_DISTANCE_ATTENUATION_ARB, to->distanceAttenuation); + FILLDIRTY(b->distanceAttenuation); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->distanceAttenuation, nbitID); + } + fEnabled = from->pointSprite; + { + unsigned int activeUnit = (unsigned int) -1; + for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) { + if (CHECKDIRTY(b->coordReplacement[i], bitID)) + { + if (!fEnabled) + { + diff_api.Enable(GL_POINT_SPRITE_ARB); + fEnabled = GL_TRUE; + } +#if 0 + /*don't set coord replacement, it will be set just before drawing points when necessary, + * to work around gpu driver bugs + * See crServerDispatch[Begin|End|Draw*] */ + GLint replacement = to->coordReplacement[i]; + if (activeUnit != i) { + diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB ); + activeUnit = i; + } + diff_api.TexEnviv(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, &replacement); +#endif + CLEARDIRTY(b->coordReplacement[i], nbitID); + } + } + if (activeUnit != toCtx->texture.curTextureUnit) + diff_api.ActiveTextureARB(GL_TEXTURE0 + toCtx->texture.curTextureUnit); + } + if (CHECKDIRTY(b->enableSprite, bitID)) + { + glAble able[2]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + if (fEnabled != to->pointSprite) + { + able[to->pointSprite](GL_POINT_SPRITE_ARB); + FILLDIRTY(b->enableSprite); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->enableSprite, nbitID); + } + else if (fEnabled != to->pointSprite) + { + glAble able[2]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + able[to->pointSprite](GL_POINT_SPRITE_ARB); + } + CLEARDIRTY(b->dirty, nbitID); +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_point.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_point.txt new file mode 100644 index 00000000..ba92c153 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_point.txt @@ -0,0 +1,39 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +:enableSmooth:pointSmooth:GL_POINT_SMOOTH +:size:pointSize:PointSize +:minSize:minSize:PointParameterfARB,GL_POINT_SIZE_MIN_ARB +:maxSize:maxSize:PointParameterfARB,GL_POINT_SIZE_MAX_ARB +:fadeThresholdSize:fadeThresholdSize:PointParameterfARB,GL_POINT_FADE_THRESHOLD_SIZE_ARB +:spriteCoordOrigin:spriteCoordOrigin:PointParameterfARB,GL_POINT_SPRITE_COORD_ORIGIN +#:distanceAttenuation:distanceAttenuation:PointParameterfvARB,GL_POINT_DISTANCE_ATTENUATION_ARB +-:distanceAttenuation:*if (from->distanceAttenuation[0] != to->distanceAttenuation[0] || from->distanceAttenuation[1] != to->distanceAttenuation[1] || from->distanceAttenuation[2] != to->distanceAttenuation[2]) { +-:distanceAttenuation:* diff_api.PointParameterfvARB (GL_POINT_DISTANCE_ATTENUATION_ARB, to->distanceAttenuation); +-:distanceAttenuation:* FILLDIRTY(b->distanceAttenuation); +-:distanceAttenuation:* FILLDIRTY(b->dirty); +-:distanceAttenuation:*} ++:distanceAttenuation:*if (from->distanceAttenuation[0] != to->distanceAttenuation[0] || from->distanceAttenuation[1] != to->distanceAttenuation[1] || from->distanceAttenuation[2] != to->distanceAttenuation[2]) { ++:distanceAttenuation:* diff_api.PointParameterfvARB (GL_POINT_DISTANCE_ATTENUATION_ARB, to->distanceAttenuation); ++:distanceAttenuation:* from->distanceAttenuation[0] = to->distanceAttenuation[0]; ++:distanceAttenuation:* from->distanceAttenuation[1] = to->distanceAttenuation[1]; ++:distanceAttenuation:* from->distanceAttenuation[2] = to->distanceAttenuation[2]; ++:distanceAttenuation:*} +:enableSprite:pointSprite:GL_POINT_SPRITE_ARB +%flush +>{ +>unsigned int activeUnit = (unsigned int) -1; +>for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) { +:coordReplacement[i]:*GLint replacement = to->coordReplacement[i]; +:coordReplacement[i]:*if (activeUnit != i) { +:coordReplacement[i]:* diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB ); +:coordReplacement[i]:* activeUnit = i; +:coordReplacement[i]:*} +:coordReplacement[i]:*diff_api.TexEnviv(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, &replacement); ++:coordReplacement[i]:*from->coordReplacement[i] = to->coordReplacement[i]; +%flush +>} +>if (activeUnit != toCtx->texture.curTextureUnit) +> diff_api.ActiveTextureARB(GL_TEXTURE0 + toCtx->texture.curTextureUnit); +>} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c new file mode 100644 index 00000000..b00e8e80 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.c @@ -0,0 +1,211 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "cr_mem.h" +#include "state.h" +#include "state/cr_statetypes.h" +#include "state_internals.h" +#include "cr_pixeldata.h" + +void crStatePolygonInit(CRContext *ctx) +{ + CRPolygonState *p = &ctx->polygon; + CRStateBits *sb = GetCurrentBits(); + CRPolygonBits *pb = &(sb->polygon); + int i; + + p->polygonSmooth = GL_FALSE; + p->polygonOffsetFill = GL_FALSE; + p->polygonOffsetLine = GL_FALSE; + p->polygonOffsetPoint = GL_FALSE; + p->polygonStipple = GL_FALSE; + p->cullFace = GL_FALSE; + RESET(pb->enable, ctx->bitid); + + p->offsetFactor = 0; + p->offsetUnits = 0; + RESET(pb->offset, ctx->bitid); + + p->cullFaceMode = GL_BACK; + p->frontFace = GL_CCW; + p->frontMode = GL_FILL; + p->backMode = GL_FILL; + RESET(pb->mode, ctx->bitid); + + for (i=0; i<32; i++) + p->stipple[i] = 0xFFFFFFFF; + RESET(pb->stipple, ctx->bitid); + + RESET(pb->dirty, ctx->bitid); +} + +void STATE_APIENTRY crStateCullFace(GLenum mode) +{ + CRContext *g = GetCurrentContext(); + CRPolygonState *p = &(g->polygon); + CRStateBits *sb = GetCurrentBits(); + CRPolygonBits *pb = &(sb->polygon); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glCullFace called in begin/end"); + return; + } + + FLUSH(); + + if (mode != GL_FRONT && mode != GL_BACK && mode != GL_FRONT_AND_BACK) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glCullFace called with bogus mode: 0x%x", mode); + return; + } + + p->cullFaceMode = mode; + DIRTY(pb->mode, g->neg_bitid); + DIRTY(pb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateFrontFace (GLenum mode) +{ + CRContext *g = GetCurrentContext(); + CRPolygonState *p = &(g->polygon); + CRStateBits *sb = GetCurrentBits(); + CRPolygonBits *pb = &(sb->polygon); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glFrontFace called in begin/end"); + return; + } + + FLUSH(); + + if (mode != GL_CW && mode != GL_CCW) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glFrontFace called with bogus mode: 0x%x", mode); + return; + } + + p->frontFace = mode; + DIRTY(pb->mode, g->neg_bitid); + DIRTY(pb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStatePolygonMode (GLenum face, GLenum mode) +{ + CRContext *g = GetCurrentContext(); + CRPolygonState *p = &(g->polygon); + CRStateBits *sb = GetCurrentBits(); + CRPolygonBits *pb = &(sb->polygon); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glPolygonMode called in begin/end"); + return; + } + + FLUSH(); + + if (mode != GL_POINT && mode != GL_LINE && mode != GL_FILL) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glPolygonMode called with bogus mode: 0x%x", mode); + return; + } + + switch (face) { + case GL_FRONT: + p->frontMode = mode; + break; + case GL_FRONT_AND_BACK: + p->frontMode = mode; + RT_FALL_THRU(); + case GL_BACK: + p->backMode = mode; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glPolygonMode called with bogus face: 0x%x", face); + return; + } + DIRTY(pb->mode, g->neg_bitid); + DIRTY(pb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStatePolygonOffset (GLfloat factor, GLfloat units) +{ + CRContext *g = GetCurrentContext(); + CRPolygonState *p = &(g->polygon); + CRStateBits *sb = GetCurrentBits(); + CRPolygonBits *pb = &(sb->polygon); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glPolygonOffset called in begin/end"); + return; + } + + FLUSH(); + + p->offsetFactor = factor; + p->offsetUnits = units; + + DIRTY(pb->offset, g->neg_bitid); + DIRTY(pb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStatePolygonStipple (const GLubyte *p) +{ + CRContext *g = GetCurrentContext(); + CRPolygonState *poly = &(g->polygon); + CRStateBits *sb = GetCurrentBits(); + CRPolygonBits *pb = &(sb->polygon); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glPolygonStipple called in begin/end"); + return; + } + + FLUSH(); + + if (!p && !crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + crDebug("Void pointer passed to PolygonStipple"); + return; + } + + /** @todo track mask if buffer is bound?*/ + if (!crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) + { + crMemcpy((char*)poly->stipple, (char*)p, 128); + } + + DIRTY(pb->dirty, g->neg_bitid); + DIRTY(pb->stipple, g->neg_bitid); +} + +void STATE_APIENTRY crStateGetPolygonStipple( GLubyte *b ) +{ + CRContext *g = GetCurrentContext(); + CRPolygonState *poly = &(g->polygon); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetPolygonStipple called in begin/end"); + return; + } + + crMemcpy((char*)b, (char*)poly->stipple, 128); +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.txt new file mode 100644 index 00000000..8867dfbc --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_polygon.txt @@ -0,0 +1,22 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +:enable:polygonSmooth:GL_POLYGON_SMOOTH +:enable:polygonOffsetFill:GL_POLYGON_OFFSET_FILL +:enable:polygonOffsetLine:GL_POLYGON_OFFSET_LINE +:enable:polygonOffsetPoint:GL_POLYGON_OFFSET_POINT +:enable:polygonStipple:GL_POLYGON_STIPPLE +:enable:cullFace:GL_CULL_FACE +:offset:offsetFactor,offsetUnits:PolygonOffset +:mode:frontFace:FrontFace +:mode:cullFaceMode:CullFace +:mode:backMode:PolygonMode,GL_BACK +:mode:frontMode:PolygonMode,GL_FRONT +-:stipple:stipple:*diff_api.PolygonStipple ((GLubyte *) to->stipple); ++:stipple:*int iStripple; ++:stipple:*diff_api.PolygonStipple ((GLubyte *) to->stipple); ++:stipple:*for (iStripple=0; iStripple<32; iStripple++) ++:stipple:*{ ++:stipple:* from->stipple[iStripple] = to->stipple[iStripple]; ++:stipple:*} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_program.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_program.c new file mode 100644 index 00000000..b7ed0fba --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_program.c @@ -0,0 +1,2392 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "state.h" +#include "state_internals.h" +#include "cr_mem.h" +#include "cr_string.h" + + +/* + * General notes: + * + * Vertex programs can change vertices so bounding boxes may not be + * practical for tilesort. Tilesort may have to broadcast geometry + * when vertex programs are in effect. We could semi-parse vertex + * programs to determine if they write to the o[HPOS] register. + */ + + +/* + * Lookup the named program and return a pointer to it. + * If the program doesn't exist, create it and reserve its Id and put + * it into the hash table. + */ +static CRProgram * +GetProgram(CRProgramState *p, GLenum target, GLuint id) +{ + CRProgram *prog; + + prog = crHashtableSearch(p->programHash, id); + if (!prog) { + prog = (CRProgram *) crCalloc(sizeof(CRProgram)); + if (!prog) + return NULL; + prog->target = target; + prog->id = id; + prog->format = GL_PROGRAM_FORMAT_ASCII_ARB; + prog->resident = GL_TRUE; + prog->symbolTable = NULL; + + if (id > 0) + crHashtableAdd(p->programHash, id, (void *) prog); + } + return prog; +} + + +/* + * Delete a CRProgram object and all attached data. + */ +static void +DeleteProgram(CRProgram *prog) +{ + CRProgramSymbol *symbol, *next; + + if (prog->string) + crFree((void *) prog->string); + + for (symbol = prog->symbolTable; symbol; symbol = next) { + next = symbol->next; + crFree((void *) symbol->name); + crFree(symbol); + } + crFree(prog); +} + + +/* + * Set the named symbol to the value (x, y, z, w). + * NOTE: Symbols should only really be added during parsing of the program. + * However, the state tracker does not parse the programs (yet). So, when + * someone calls glProgramNamedParameter4fNV() we always enter the symbol + * since we don't know if it's really valid or not. + */ +static void +SetProgramSymbol(CRProgram *prog, const char *name, GLsizei len, + GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + CRProgramSymbol *symbol; + + for (symbol = prog->symbolTable; symbol; symbol = symbol->next) { + /* NOTE: <name> may not be null-terminated! */ + if (crStrncmp(symbol->name, name, len) == 0 && symbol->name[len] == 0) { + /* found it */ + symbol->value[0] = x; + symbol->value[1] = y; + symbol->value[2] = z; + symbol->value[3] = w; + FILLDIRTY(symbol->dirty); + return; + } + } + /* add new symbol table entry */ + symbol = (CRProgramSymbol *) crAlloc(sizeof(CRProgramSymbol)); + if (symbol) { + symbol->name = crStrndup(name, len); + symbol->cbName = len; + symbol->value[0] = x; + symbol->value[1] = y; + symbol->value[2] = z; + symbol->value[3] = w; + symbol->next = prog->symbolTable; + prog->symbolTable = symbol; + FILLDIRTY(symbol->dirty); + } +} + + +/* + * Return a pointer to the values for the given symbol. Return NULL if + * the name doesn't exist in the symbol table. + */ +static const GLfloat * +GetProgramSymbol(const CRProgram *prog, const char *name, GLsizei len) +{ + CRProgramSymbol *symbol = prog->symbolTable; + for (symbol = prog->symbolTable; symbol; symbol = symbol->next) { + /* NOTE: <name> may not be null-terminated! */ + if (crStrncmp(symbol->name, name, len) == 0 && symbol->name[len] == 0) { + return symbol->value; + } + } + return NULL; +} + + +/* + * Used by both glBindProgramNV and glBindProgramARB + */ +static CRProgram * +BindProgram(GLenum target, GLuint id, + GLenum vertexTarget, GLenum fragmentTarget) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + CRStateBits *sb = GetCurrentBits(); + CRProgramBits *pb = &(sb->program); + CRProgram *prog; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glBindProgram called in Begin/End"); + return NULL; + } + + if (id == 0) { + if (target == vertexTarget) { + prog = p->defaultVertexProgram; + } + else if (target == fragmentTarget) { + prog = p->defaultFragmentProgram; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glBindProgram(bad target)"); + return NULL; + } + } + else { + prog = GetProgram(p, target, id ); + } + + if (!prog) { + crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glBindProgram"); + return NULL; + } + else if (prog->target != target) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glBindProgram target mismatch"); + return NULL; + } + + if (target == vertexTarget) { + p->currentVertexProgram = prog; + p->vpProgramBinding = id; + DIRTY(pb->dirty, g->neg_bitid); + DIRTY(pb->vpBinding, g->neg_bitid); + } + else if (target == fragmentTarget) { + p->currentFragmentProgram = prog; + p->fpProgramBinding = id; + DIRTY(pb->dirty, g->neg_bitid); + DIRTY(pb->fpBinding, g->neg_bitid); + } + return prog; +} + + +void STATE_APIENTRY crStateBindProgramNV(GLenum target, GLuint id) +{ + CRProgram *prog = BindProgram(target, id, GL_VERTEX_PROGRAM_NV, + GL_FRAGMENT_PROGRAM_NV); + if (prog) { + prog->isARBprogram = GL_FALSE; + } +} + + +void STATE_APIENTRY crStateBindProgramARB(GLenum target, GLuint id) +{ + CRProgram *prog = BindProgram(target, id, GL_VERTEX_PROGRAM_ARB, + GL_FRAGMENT_PROGRAM_ARB); + if (prog) { + prog->isARBprogram = GL_TRUE; + } +} + + +void STATE_APIENTRY crStateDeleteProgramsARB(GLsizei n, const GLuint *ids) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + CRStateBits *sb = GetCurrentBits(); + CRProgramBits *pb = &(sb->program); + GLint i; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glDeleteProgramsNV called in Begin/End"); + return; + } + + if (n < 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glDeleteProgramsNV(n)"); + return; + } + + for (i = 0; i < n; i++) { + CRProgram *prog; + if (ids[i] > 0) { + prog = (CRProgram *) crHashtableSearch(p->programHash, ids[i]); + if (prog == p->currentVertexProgram) { + p->currentVertexProgram = p->defaultVertexProgram; + DIRTY(pb->dirty, g->neg_bitid); + DIRTY(pb->vpBinding, g->neg_bitid); + } + else if (prog == p->currentFragmentProgram) { + p->currentFragmentProgram = p->defaultFragmentProgram; + DIRTY(pb->dirty, g->neg_bitid); + DIRTY(pb->fpBinding, g->neg_bitid); + } + if (prog) { + DeleteProgram(prog); + } + crHashtableDelete(p->programHash, ids[i], GL_FALSE); + } + } +} + + +void STATE_APIENTRY crStateExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params) +{ + /* Hmmm, this is really hard to do if we don't actually execute + * the program in a software simulation. + */ + (void)params; + (void)target; + (void)id; +} + + +void STATE_APIENTRY crStateGenProgramsNV(GLsizei n, GLuint *ids) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + + crStateGenNames(g, p->programHash, n, ids); +} + +void STATE_APIENTRY crStateGenProgramsARB(GLsizei n, GLuint *ids) +{ + crStateGenProgramsNV(n, ids); +} + + +GLboolean STATE_APIENTRY crStateIsProgramARB(GLuint id) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + CRProgram *prog; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glIsProgram called in Begin/End"); + return GL_FALSE; + } + + if (id == 0) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glIsProgram(id==0)"); + return GL_FALSE; + } + + prog = (CRProgram *) crHashtableSearch(p->programHash, id); + if (prog) + return GL_TRUE; + else + return GL_FALSE; +} + + +GLboolean STATE_APIENTRY crStateAreProgramsResidentNV(GLsizei n, const GLuint *ids, GLboolean *residences) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + int i; + GLboolean retVal = GL_TRUE; + + if (n < 0) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glAreProgramsResidentNV(n)"); + return GL_FALSE; + } + + for (i = 0; i < n; i++) { + CRProgram *prog; + + if (ids[i] == 0) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glAreProgramsResidentNV(id)"); + return GL_FALSE; + } + + prog = (CRProgram *) crHashtableSearch(p->programHash, ids[i]); + if (!prog) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glAreProgramsResidentNV(id)"); + return GL_FALSE; + } + + if (!prog->resident) { + retVal = GL_FALSE; + break; + } + } + + if (retVal == GL_FALSE) { + for (i = 0; i < n; i++) { + CRProgram *prog = (CRProgram *) + crHashtableSearch(p->programHash, ids[i]); + residences[i] = prog->resident; + } + } + + return retVal; +} + + +void STATE_APIENTRY crStateRequestResidentProgramsNV(GLsizei n, const GLuint *ids) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + GLint i; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glRequestResidentProgramsNV called in Begin/End"); + return; + } + + if (n < 0) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glRequestResidentProgramsNV(n<0)"); + return; + } + + for (i = 0; i < n ; i++) { + CRProgram *prog = (CRProgram *) crHashtableSearch(p->programHash, ids[i]); + if (prog) + prog->resident = GL_TRUE; + } +} + + +void STATE_APIENTRY crStateLoadProgramNV(GLenum target, GLuint id, GLsizei len, + const GLubyte *program) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + CRStateBits *sb = GetCurrentBits(); + CRProgramBits *pb = &(sb->program); + CRProgram *prog; + GLubyte *progCopy; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glLoadProgramNV called in Begin/End"); + return; + } + + if (id == 0) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glLoadProgramNV(id==0)"); + return; + } + + prog = GetProgram(p, target, id); + + if (!prog) { + crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glLoadProgramNV"); + return; + } + else if (prog && prog->target != target) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glLoadProgramNV(target)"); + return; + } + + progCopy = crAlloc(len); + if (!progCopy) { + crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glLoadProgramNV"); + return; + } + if (crStrncmp((const char *) program,"!!FP1.0", 7) != 0 + && crStrncmp((const char *) program,"!!FCP1.0", 8) != 0 + && crStrncmp((const char *) program,"!!VP1.0", 7) != 0 + && crStrncmp((const char *) program,"!!VP1.1", 7) != 0 + && crStrncmp((const char *) program,"!!VP2.0", 7) != 0 + && crStrncmp((const char *) program,"!!VSP1.0", 8) != 0) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glLoadProgramNV"); + crDebug("program = (%s)\n",program); + return; + } + crMemcpy(progCopy, program, len); + if (prog->string) + crFree((void *) prog->string); + + prog->string = progCopy; + prog->length = len; + prog->isARBprogram = GL_FALSE; + + DIRTY(prog->dirtyProgram, g->neg_bitid); + DIRTY(pb->dirty, g->neg_bitid); +} + + +void STATE_APIENTRY crStateProgramStringARB(GLenum target, GLenum format, + GLsizei len, const GLvoid *string) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + CRStateBits *sb = GetCurrentBits(); + CRProgramBits *pb = &(sb->program); + CRProgram *prog; + GLubyte *progCopy; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glProgramStringARB called in Begin/End"); + return; + } + + if (format != GL_PROGRAM_FORMAT_ASCII_ARB) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glProgramStringARB(format)"); + return; + } + + if (target == GL_FRAGMENT_PROGRAM_ARB + && g->extensions.ARB_fragment_program) { + prog = p->currentFragmentProgram; + } + else if (target == GL_VERTEX_PROGRAM_ARB + && g->extensions.ARB_vertex_program) { + prog = p->currentVertexProgram; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glProgramStringARB(target)"); + return; + } + + CRASSERT(prog); + + + progCopy = crAlloc(len); + if (!progCopy) { + crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glProgramStringARB"); + return; + } + if (crStrncmp(string,"!!ARBvp1.0", 10) != 0 + && crStrncmp(string,"!!ARBfp1.0", 10) != 0) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glProgramStringARB"); + return; + } + crMemcpy(progCopy, string, len); + if (prog->string) + crFree((void *) prog->string); + + prog->string = progCopy; + prog->length = len; + prog->format = format; + prog->isARBprogram = GL_TRUE; + + DIRTY(prog->dirtyProgram, g->neg_bitid); + DIRTY(pb->dirty, g->neg_bitid); +} + + +void STATE_APIENTRY crStateGetProgramivNV(GLuint id, GLenum pname, GLint *params) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + CRProgram *prog; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetProgramivNV called in Begin/End"); + return; + } + + if (id == 0) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetProgramivNV(bad id)"); + return; + } + + prog = (CRProgram *) crHashtableSearch(p->programHash, id); + if (!prog) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetProgramivNV(bad id)"); + return; + } + + switch (pname) { + case GL_PROGRAM_TARGET_NV: + *params = prog->target; + return; + case GL_PROGRAM_LENGTH_NV: + *params = prog->length; + return; + case GL_PROGRAM_RESIDENT_NV: + *params = prog->resident; + return; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetProgramivNV(pname)"); + return; + } +} + + +void STATE_APIENTRY crStateGetProgramStringNV(GLuint id, GLenum pname, GLubyte *program) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + CRProgram *prog; + + if (pname != GL_PROGRAM_STRING_NV) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetProgramStringNV(pname)"); + return; + } + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetProgramStringNV called in Begin/End"); + return; + } + + if (id == 0) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetProgramStringNV(bad id)"); + return; + } + + prog = (CRProgram *) crHashtableSearch(p->programHash, id); + if (!prog) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetProgramStringNV(bad id)"); + return; + } + + crMemcpy(program, prog->string, prog->length); +} + + +void STATE_APIENTRY crStateGetProgramStringARB(GLenum target, GLenum pname, GLvoid *string) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + CRProgram *prog; + + if (target == GL_VERTEX_PROGRAM_ARB) { + prog = p->currentVertexProgram; + } + else if (target == GL_FRAGMENT_PROGRAM_ARB) { + prog = p->currentFragmentProgram; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetProgramStringNV(target)"); + return; + } + + if (pname != GL_PROGRAM_STRING_NV) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetProgramStringNV(pname)"); + return; + } + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetProgramStringNV called in Begin/End"); + return; + } + + crMemcpy(string, prog->string, prog->length); +} + + +void STATE_APIENTRY crStateProgramParameter4dNV(GLenum target, GLuint index, + GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + crStateProgramParameter4fNV(target, index, (GLfloat) x, (GLfloat) y, + (GLfloat) z, (GLfloat) w); +} + + +void STATE_APIENTRY crStateProgramParameter4dvNV(GLenum target, GLuint index, + const GLdouble *params) +{ + crStateProgramParameter4fNV(target, index, + (GLfloat) params[0], (GLfloat) params[1], + (GLfloat) params[2], (GLfloat) params[3]); +} + + +void STATE_APIENTRY crStateProgramParameter4fNV(GLenum target, GLuint index, + GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + CRStateBits *sb = GetCurrentBits(); + CRProgramBits *pb = &(sb->program); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glProgramParameterNV called in Begin/End"); + return; + } + + if (target == GL_VERTEX_PROGRAM_NV) { + if (index < g->limits.maxVertexProgramEnvParams) { + p->vertexParameters[index][0] = x; + p->vertexParameters[index][1] = y; + p->vertexParameters[index][2] = z; + p->vertexParameters[index][3] = w; + DIRTY(pb->dirty, g->neg_bitid); + DIRTY(pb->vertexEnvParameter[index], g->neg_bitid); + DIRTY(pb->vertexEnvParameters, g->neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glProgramParameterNV(index=%d)", index); + return; + } + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glProgramParameterNV(target)"); + return; + } +} + + +void STATE_APIENTRY crStateProgramParameter4fvNV(GLenum target, GLuint index, + const GLfloat *params) +{ + crStateProgramParameter4fNV(target, index, + params[0], params[1], params[2], params[3]); +} + + +void STATE_APIENTRY crStateProgramParameters4dvNV(GLenum target, GLuint index, + GLuint num, const GLdouble *params) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + CRStateBits *sb = GetCurrentBits(); + CRProgramBits *pb = &(sb->program); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glProgramParameters4dvNV called in Begin/End"); + return; + } + + if (target == GL_VERTEX_PROGRAM_NV) { + if (index >= UINT32_MAX - num) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glProgramParameters4dvNV(index+num) integer overflow"); + return; + } + + if (index + num < g->limits.maxVertexProgramEnvParams) { + GLuint i; + for (i = 0; i < num; i++) { + p->vertexParameters[index+i][0] = (GLfloat) params[i*4+0]; + p->vertexParameters[index+i][1] = (GLfloat) params[i*4+1]; + p->vertexParameters[index+i][2] = (GLfloat) params[i*4+2]; + p->vertexParameters[index+i][3] = (GLfloat) params[i*4+3]; + } + DIRTY(pb->dirty, g->neg_bitid); + DIRTY(pb->vertexEnvParameters, g->neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glProgramParameters4dvNV(index+num)"); + return; + } + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glProgramParameterNV(target)"); + return; + } +} + + +void STATE_APIENTRY crStateProgramParameters4fvNV(GLenum target, GLuint index, + GLuint num, const GLfloat *params) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + CRStateBits *sb = GetCurrentBits(); + CRProgramBits *pb = &(sb->program); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glProgramParameters4dvNV called in Begin/End"); + return; + } + + if (target == GL_VERTEX_PROGRAM_NV) { + if (index >= UINT32_MAX - num) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glProgramParameters4dvNV(index+num) integer overflow"); + return; + } + + if (index + num < g->limits.maxVertexProgramEnvParams) { + GLuint i; + for (i = 0; i < num; i++) { + p->vertexParameters[index+i][0] = params[i*4+0]; + p->vertexParameters[index+i][1] = params[i*4+1]; + p->vertexParameters[index+i][2] = params[i*4+2]; + p->vertexParameters[index+i][3] = params[i*4+3]; + } + DIRTY(pb->dirty, g->neg_bitid); + DIRTY(pb->vertexEnvParameters, g->neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glProgramParameters4dvNV(index+num)"); + return; + } + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glProgramParameterNV(target)"); + return; + } +} + + +void STATE_APIENTRY crStateGetProgramParameterfvNV(GLenum target, GLuint index, + GLenum pname, GLfloat *params) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetProgramParameterfvNV called in Begin/End"); + return; + } + + if (target == GL_VERTEX_PROGRAM_NV) { + if (pname == GL_PROGRAM_PARAMETER_NV) { + if (index < g->limits.maxVertexProgramEnvParams) { + params[0] = p->vertexParameters[index][0]; + params[1] = p->vertexParameters[index][1]; + params[2] = p->vertexParameters[index][2]; + params[3] = p->vertexParameters[index][3]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glGetProgramParameterfvNV(index)"); + return; + } + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetProgramParameterfvNV(pname)"); + return; + } + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetProgramParameterfvNV(target)"); + return; + } +} + + +void STATE_APIENTRY crStateGetProgramParameterdvNV(GLenum target, GLuint index, + GLenum pname, GLdouble *params) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetProgramParameterdvNV called in Begin/End"); + return; + } + + if (target == GL_VERTEX_PROGRAM_NV) { + if (pname == GL_PROGRAM_PARAMETER_NV) { + if (index < g->limits.maxVertexProgramEnvParams) { + params[0] = p->vertexParameters[index][0]; + params[1] = p->vertexParameters[index][1]; + params[2] = p->vertexParameters[index][2]; + params[3] = p->vertexParameters[index][3]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glGetProgramParameterdvNV(index)"); + return; + } + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetProgramParameterdvNV(pname)"); + return; + } + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetProgramParameterdvNV(target)"); + return; + } +} + + +void STATE_APIENTRY crStateTrackMatrixNV(GLenum target, GLuint address, + GLenum matrix, GLenum transform) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + CRStateBits *sb = GetCurrentBits(); + CRProgramBits *pb = &(sb->program); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetTrackMatrixivNV called in Begin/End"); + return; + } + + if (target == GL_VERTEX_PROGRAM_NV) { + if (address & 0x3 || address >= g->limits.maxVertexProgramEnvParams) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glTrackMatrixNV(address)"); + return; + } + + switch (matrix) { + case GL_NONE: + case GL_MODELVIEW: + case GL_PROJECTION: + case GL_TEXTURE: + case GL_COLOR: + case GL_MODELVIEW_PROJECTION_NV: + case GL_MATRIX0_NV: + case GL_MATRIX1_NV: + case GL_MATRIX2_NV: + case GL_MATRIX3_NV: + case GL_MATRIX4_NV: + case GL_MATRIX5_NV: + case GL_MATRIX6_NV: + case GL_MATRIX7_NV: + case GL_TEXTURE0_ARB: + case GL_TEXTURE1_ARB: + case GL_TEXTURE2_ARB: + case GL_TEXTURE3_ARB: + case GL_TEXTURE4_ARB: + case GL_TEXTURE5_ARB: + case GL_TEXTURE6_ARB: + case GL_TEXTURE7_ARB: + /* OK, fallthrough */ + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTrackMatrixNV(matrix = %x)",matrix); + return; + } + + switch (transform) { + case GL_IDENTITY_NV: + case GL_INVERSE_NV: + case GL_TRANSPOSE_NV: + case GL_INVERSE_TRANSPOSE_NV: + /* OK, fallthrough */ + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTrackMatrixNV(transform = %x)",transform); + return; + } + + p->TrackMatrix[address / 4] = matrix; + p->TrackMatrixTransform[address / 4] = transform; + DIRTY(pb->trackMatrix[address/4], g->neg_bitid); + DIRTY(pb->dirty, g->neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTrackMatrixNV(target = %x)",target); + } +} + + +void STATE_APIENTRY crStateGetTrackMatrixivNV(GLenum target, GLuint address, + GLenum pname, GLint *params) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetTrackMatrixivNV called in Begin/End"); + return; + } + + if (target == GL_VERTEX_PROGRAM_NV) { + if ((address & 0x3) || address >= g->limits.maxVertexProgramEnvParams) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glGetTrackMatrixivNV(address)"); + return; + } + if (pname == GL_TRACK_MATRIX_NV) { + params[0] = (GLint) p->TrackMatrix[address / 4]; + } + else if (pname == GL_TRACK_MATRIX_TRANSFORM_NV) { + params[0] = (GLint) p->TrackMatrixTransform[address / 4]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTrackMatrixivNV(pname)"); + return; + } + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTrackMatrixivNV(target)"); + return; + } +} + + +void STATE_APIENTRY crStateGetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params) +{ + /* init vars to prevent compiler warnings/errors */ + GLfloat floatParams[4] = { 0.0, 0.0, 0.0, 0.0 }; + crStateGetVertexAttribfvNV(index, pname, floatParams); + params[0] = floatParams[0]; + if (pname == GL_CURRENT_ATTRIB_NV) { + params[1] = floatParams[1]; + params[2] = floatParams[2]; + params[3] = floatParams[3]; + } +} + + +void STATE_APIENTRY crStateGetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params) +{ + CRContext *g = GetCurrentContext(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetVertexAttribfvNV called in Begin/End"); + return; + } + + if (index >= CR_MAX_VERTEX_ATTRIBS) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glGetVertexAttribfvNV(index)"); + return; + } + + switch (pname) { + case GL_ATTRIB_ARRAY_SIZE_NV: + params[0] = (GLfloat) g->client.array.a[index].size; + break; + case GL_ATTRIB_ARRAY_STRIDE_NV: + params[0] = (GLfloat) g->client.array.a[index].stride; + break; + case GL_ATTRIB_ARRAY_TYPE_NV: + params[0] = (GLfloat) g->client.array.a[index].type; + break; + case GL_CURRENT_ATTRIB_NV: + crStateCurrentRecover(); + COPY_4V(params , g->current.vertexAttrib[index]); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetVertexAttribfvNV"); + return; + } +} + + +void STATE_APIENTRY crStateGetVertexAttribivNV(GLuint index, GLenum pname, GLint *params) +{ + /* init vars to prevent compiler warnings/errors */ + GLfloat floatParams[4] = { 0.0, 0.0, 0.0, 0.0 }; + crStateGetVertexAttribfvNV(index, pname, floatParams); + params[0] = (GLint) floatParams[0]; + if (pname == GL_CURRENT_ATTRIB_NV) { + params[1] = (GLint) floatParams[1]; + params[2] = (GLint) floatParams[2]; + params[3] = (GLint) floatParams[3]; + } +} + + + +void STATE_APIENTRY crStateGetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params) +{ + CRContext *g = GetCurrentContext(); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetVertexAttribfvARB called in Begin/End"); + return; + } + + if (index >= CR_MAX_VERTEX_ATTRIBS) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glGetVertexAttribfvARB(index)"); + return; + } + + switch (pname) { + case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB: + params[0] = (GLfloat) g->client.array.a[index].enabled; + break; + case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB: + params[0] = (GLfloat) g->client.array.a[index].size; + break; + case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB: + params[0] = (GLfloat) g->client.array.a[index].stride; + break; + case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB: + params[0] = (GLfloat) g->client.array.a[index].type; + break; + case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB: + params[0] = (GLfloat) g->client.array.a[index].normalized; + break; + case GL_CURRENT_VERTEX_ATTRIB_ARB: + crStateCurrentRecover(); + COPY_4V(params , g->current.vertexAttrib[index]); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetVertexAttribfvARB"); + return; + } +} + + +void STATE_APIENTRY crStateGetVertexAttribivARB(GLuint index, GLenum pname, GLint *params) +{ + /* init vars to prevent compiler warnings/errors */ + GLfloat floatParams[4] = { 0.0, 0.0, 0.0, 0.0 }; + crStateGetVertexAttribfvARB(index, pname, floatParams); + params[0] = (GLint) floatParams[0]; + if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { + params[1] = (GLint) floatParams[1]; + params[2] = (GLint) floatParams[2]; + params[3] = (GLint) floatParams[3]; + } +} + + +void STATE_APIENTRY crStateGetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params) +{ + /* init vars to prevent compiler warnings/errors */ + GLfloat floatParams[4] = { 0.0, 0.0, 0.0, 0.0 }; + crStateGetVertexAttribfvARB(index, pname, floatParams); + params[0] = floatParams[0]; + if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { + params[1] = floatParams[1]; + params[2] = floatParams[2]; + params[3] = floatParams[3]; + } +} + + +/**********************************************************************/ + +/* + * Added by GL_NV_fragment_program + */ + +void STATE_APIENTRY crStateProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + CRProgram *prog; + CRStateBits *sb = GetCurrentBits(); + CRProgramBits *pb = &(sb->program); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glProgramNamedParameterfNV called in Begin/End"); + return; + } + + prog = (CRProgram *) crHashtableSearch(p->programHash, id); + if (!prog) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glProgramNamedParameterNV(bad id %d)", id); + return; + } + + if (prog->target != GL_FRAGMENT_PROGRAM_NV) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glProgramNamedParameterNV(target)"); + return; + } + + SetProgramSymbol(prog, (const char *)name, len, x, y, z, w); + DIRTY(prog->dirtyNamedParams, g->neg_bitid); + DIRTY(pb->dirty, g->neg_bitid); +} + + +void STATE_APIENTRY crStateProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + crStateProgramNamedParameter4fNV(id, len, name, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + + +void STATE_APIENTRY crStateProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name, const GLfloat v[]) +{ + crStateProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]); +} + + +void STATE_APIENTRY crStateProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name, const GLdouble v[]) +{ + crStateProgramNamedParameter4fNV(id, len, name, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); +} + + +void STATE_APIENTRY crStateGetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name, GLfloat *params) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + const CRProgram *prog; + const GLfloat *value; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetProgramNamedParameterfNV called in Begin/End"); + return; + } + + prog = (const CRProgram *) crHashtableSearch(p->programHash, id); + if (!prog) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetProgramNamedParameterNV(bad id)"); + return; + } + + if (prog->target != GL_FRAGMENT_PROGRAM_NV) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetProgramNamedParameterNV(target)"); + return; + } + + value = GetProgramSymbol(prog, (const char *)name, len); + if (!value) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glGetProgramNamedParameterNV(name)"); + return; + } + + params[0] = value[0]; + params[1] = value[1]; + params[2] = value[2]; + params[3] = value[3]; +} + + +void STATE_APIENTRY crStateGetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name, GLdouble *params) +{ + GLfloat floatParams[4]; + crStateGetProgramNamedParameterfvNV(id, len, name, floatParams); + params[0] = floatParams[0]; + params[1] = floatParams[1]; + params[2] = floatParams[2]; + params[3] = floatParams[3]; +} + + +void STATE_APIENTRY crStateProgramLocalParameter4dARB(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + crStateProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + + +void STATE_APIENTRY crStateProgramLocalParameter4dvARB(GLenum target, GLuint index, const GLdouble *params) +{ + crStateProgramLocalParameter4fARB(target, index, (GLfloat) params[0], (GLfloat) params[1], + (GLfloat) params[2], (GLfloat) params[3]); +} + + +void STATE_APIENTRY crStateProgramLocalParameter4fARB(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + CRProgram *prog; + CRStateBits *sb = GetCurrentBits(); + CRProgramBits *pb = &(sb->program); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glProgramLocalParameterARB called in Begin/End"); + return; + } + + if (target == GL_FRAGMENT_PROGRAM_ARB || target == GL_FRAGMENT_PROGRAM_NV) { + if (index >= CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glProgramLocalParameterARB(index)"); + return; + } + prog = p->currentFragmentProgram; + } + else if (target == GL_VERTEX_PROGRAM_ARB) { + if (index >= CR_MAX_VERTEX_PROGRAM_LOCAL_PARAMS) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glProgramLocalParameterARB(index)"); + return; + } + prog = p->currentVertexProgram; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glProgramLocalParameterARB(target)"); + return; + } + + CRASSERT(prog); + + prog->parameters[index][0] = x; + prog->parameters[index][1] = y; + prog->parameters[index][2] = z; + prog->parameters[index][3] = w; + DIRTY(prog->dirtyParam[index], g->neg_bitid); + DIRTY(prog->dirtyParams, g->neg_bitid); + DIRTY(pb->dirty, g->neg_bitid); +} + + +void STATE_APIENTRY crStateProgramLocalParameter4fvARB(GLenum target, GLuint index, const GLfloat *params) +{ + crStateProgramLocalParameter4fARB(target, index, params[0], params[1], params[2], params[3]); +} + + +void STATE_APIENTRY crStateGetProgramLocalParameterfvARB(GLenum target, GLuint index, GLfloat *params) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + const CRProgram *prog = NULL; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetProgramLocalParameterARB called in Begin/End"); + return; + } + + if (target == GL_FRAGMENT_PROGRAM_ARB || target == GL_FRAGMENT_PROGRAM_NV) { + prog = p->currentFragmentProgram; + if (index >= g->limits.maxFragmentProgramLocalParams) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glGetProgramLocalParameterARB(index)"); + return; + } + } + else if ( target == GL_VERTEX_PROGRAM_ARB +#if GL_VERTEX_PROGRAM_ARB != GL_VERTEX_PROGRAM_NV + || target == GL_VERTEX_PROGRAM_NV +#endif + ) { + prog = p->currentVertexProgram; + if (index >= g->limits.maxVertexProgramLocalParams) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glGetProgramLocalParameterARB(index)"); + return; + } + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetProgramLocalParameterARB(target)"); + return; + } + if (!prog) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetProgramLocalParameterARB(no program)"); + return; + } + + if (!prog) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetProgramLocalParameterARB(no program)"); + return; + } + + CRASSERT(prog); + CRASSERT(index < CR_MAX_PROGRAM_LOCAL_PARAMS); + params[0] = prog->parameters[index][0]; + params[1] = prog->parameters[index][1]; + params[2] = prog->parameters[index][2]; + params[3] = prog->parameters[index][3]; +} + + +void STATE_APIENTRY crStateGetProgramLocalParameterdvARB(GLenum target, GLuint index, GLdouble *params) +{ + GLfloat floatParams[4]; + crStateGetProgramLocalParameterfvARB(target, index, floatParams); + params[0] = floatParams[0]; + params[1] = floatParams[1]; + params[2] = floatParams[2]; + params[3] = floatParams[3]; +} + + + +void STATE_APIENTRY crStateGetProgramivARB(GLenum target, GLenum pname, GLint *params) +{ + CRProgram *prog; + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetProgramivARB called in Begin/End"); + return; + } + + if (target == GL_VERTEX_PROGRAM_ARB) { + prog = p->currentVertexProgram; + } + else if (target == GL_FRAGMENT_PROGRAM_ARB) { + prog = p->currentFragmentProgram; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetProgramivARB(target)"); + return; + } + + CRASSERT(prog); + + switch (pname) { + case GL_PROGRAM_LENGTH_ARB: + *params = prog->length; + break; + case GL_PROGRAM_FORMAT_ARB: + *params = prog->format; + break; + case GL_PROGRAM_BINDING_ARB: + *params = prog->id; + break; + case GL_PROGRAM_INSTRUCTIONS_ARB: + *params = prog->numInstructions; + break; + case GL_MAX_PROGRAM_INSTRUCTIONS_ARB: + if (target == GL_VERTEX_PROGRAM_ARB) + *params = g->limits.maxVertexProgramInstructions; + else + *params = g->limits.maxFragmentProgramInstructions; + break; + case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB: + *params = prog->numInstructions; + break; + case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB: + if (target == GL_VERTEX_PROGRAM_ARB) + *params = g->limits.maxVertexProgramInstructions; + else + *params = g->limits.maxFragmentProgramInstructions; + break; + case GL_PROGRAM_TEMPORARIES_ARB: + *params = prog->numTemporaries; + break; + case GL_MAX_PROGRAM_TEMPORARIES_ARB: + if (target == GL_VERTEX_PROGRAM_ARB) + *params = g->limits.maxVertexProgramTemps; + else + *params = g->limits.maxFragmentProgramTemps; + break; + case GL_PROGRAM_NATIVE_TEMPORARIES_ARB: + /* XXX same as GL_PROGRAM_TEMPORARIES_ARB? */ + *params = prog->numTemporaries; + break; + case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB: + /* XXX same as GL_MAX_PROGRAM_TEMPORARIES_ARB? */ + if (target == GL_VERTEX_PROGRAM_ARB) + *params = g->limits.maxVertexProgramTemps; + else + *params = g->limits.maxFragmentProgramTemps; + break; + case GL_PROGRAM_PARAMETERS_ARB: + *params = prog->numParameters; + break; + case GL_MAX_PROGRAM_PARAMETERS_ARB: + if (target == GL_VERTEX_PROGRAM_ARB) + *params = g->limits.maxVertexProgramLocalParams; + else + *params = g->limits.maxFragmentProgramLocalParams; + break; + case GL_PROGRAM_NATIVE_PARAMETERS_ARB: + /* XXX same as GL_MAX_PROGRAM_PARAMETERS_ARB? */ + *params = prog->numParameters; + break; + case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB: + /* XXX same as GL_MAX_PROGRAM_PARAMETERS_ARB? */ + if (target == GL_VERTEX_PROGRAM_ARB) + *params = g->limits.maxVertexProgramLocalParams; + else + *params = g->limits.maxFragmentProgramLocalParams; + break; + case GL_PROGRAM_ATTRIBS_ARB: + *params = prog->numAttributes; + break; + case GL_MAX_PROGRAM_ATTRIBS_ARB: + if (target == GL_VERTEX_PROGRAM_ARB) + *params = g->limits.maxVertexProgramAttribs; + else + *params = g->limits.maxFragmentProgramAttribs; + break; + case GL_PROGRAM_NATIVE_ATTRIBS_ARB: + /* XXX same as GL_PROGRAM_ATTRIBS_ARB? */ + *params = prog->numAttributes; + break; + case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB: + /* XXX same as GL_MAX_PROGRAM_ATTRIBS_ARB? */ + if (target == GL_VERTEX_PROGRAM_ARB) + *params = g->limits.maxVertexProgramAttribs; + else + *params = g->limits.maxFragmentProgramAttribs; + break; + case GL_PROGRAM_ADDRESS_REGISTERS_ARB: + *params = prog->numAddressRegs; + break; + case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB: + if (target == GL_VERTEX_PROGRAM_ARB) + *params = g->limits.maxVertexProgramAddressRegs; + else + *params = g->limits.maxFragmentProgramAddressRegs; + break; + case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB: + /* XXX same as GL_PROGRAM_ADDRESS_REGISTERS_ARB? */ + *params = prog->numAddressRegs; + break; + case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB: + /* XXX same as GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB? */ + if (target == GL_VERTEX_PROGRAM_ARB) + *params = g->limits.maxVertexProgramAddressRegs; + else + *params = g->limits.maxFragmentProgramAddressRegs; + break; + case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB: + if (target == GL_VERTEX_PROGRAM_ARB) + *params = g->limits.maxVertexProgramLocalParams; + else + *params = g->limits.maxFragmentProgramLocalParams; + break; + case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB: + if (target == GL_VERTEX_PROGRAM_ARB) + *params = g->limits.maxVertexProgramEnvParams; + else + *params = g->limits.maxFragmentProgramEnvParams; + break; + case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB: + /* XXX ok? */ + *params = GL_TRUE; + break; + + /* + * These are for fragment programs only + */ + case GL_PROGRAM_ALU_INSTRUCTIONS_ARB: + if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "crStateGetProgramivARB(target or pname)"); + return; + } + *params = prog->numAluInstructions; + break; + case GL_PROGRAM_TEX_INSTRUCTIONS_ARB: + if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "crStateGetProgramivARB(target or pname)"); + return; + } + *params = prog->numTexInstructions; + break; + case GL_PROGRAM_TEX_INDIRECTIONS_ARB: + if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "crStateGetProgramivARB(target or pname)"); + return; + } + *params = prog->numTexIndirections; + break; + case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB: + /* XXX same as GL_PROGRAM_ALU_INSTRUCTIONS_ARB? */ + if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "crStateGetProgramivARB(target or pname)"); + return; + } + *params = prog->numAluInstructions; + break; + case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB: + /* XXX same as GL_PROGRAM_ALU_INSTRUCTIONS_ARB? */ + if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "crStateGetProgramivARB(target or pname)"); + return; + } + *params = prog->numTexInstructions; + break; + case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB: + if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "crStateGetProgramivARB(target or pname)"); + return; + } + *params = prog->numTexIndirections; + break; + case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB: + case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB: + if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "crStateGetProgramivARB(target or pname)"); + return; + } + *params = g->limits.maxFragmentProgramAluInstructions; + break; + case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB: + case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB: + if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "crStateGetProgramivARB(target or pname)"); + return; + } + *params = g->limits.maxFragmentProgramTexInstructions; + break; + case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB: + case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB: + if (target != GL_FRAGMENT_PROGRAM_ARB || !g->extensions.ARB_fragment_program) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "crStateGetProgramivARB(target or pname)"); + return; + } + *params = g->limits.maxFragmentProgramTexIndirections; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "crStateGetProgramivARB(pname)"); + return; + } +} + + +/* XXX maybe move these two functions into state_client.c? */ +void STATE_APIENTRY crStateDisableVertexAttribArrayARB(GLuint index) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + CRStateBits *sb = GetCurrentBits(); + CRClientBits *cb = &(sb->client); + + if (index >= g->limits.maxVertexProgramAttribs) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glDisableVertexAttribArrayARB(index)"); + return; + } + c->array.a[index].enabled = GL_FALSE; + DIRTY(cb->dirty, g->neg_bitid); + DIRTY(cb->enableClientState, g->neg_bitid); +} + + +void STATE_APIENTRY crStateEnableVertexAttribArrayARB(GLuint index) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + CRStateBits *sb = GetCurrentBits(); + CRClientBits *cb = &(sb->client); + + if (index >= g->limits.maxVertexProgramAttribs) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glEnableVertexAttribArrayARB(index)"); + return; + } + c->array.a[index].enabled = GL_TRUE; + DIRTY(cb->dirty, g->neg_bitid); + DIRTY(cb->enableClientState, g->neg_bitid); +} + + +void STATE_APIENTRY crStateGetProgramEnvParameterdvARB(GLenum target, GLuint index, GLdouble *params) +{ + GLfloat fparams[4]; + crStateGetProgramEnvParameterfvARB(target, index, fparams); + params[0] = fparams[0]; + params[1] = fparams[1]; + params[2] = fparams[2]; + params[3] = fparams[3]; +} + +void STATE_APIENTRY crStateGetProgramEnvParameterfvARB(GLenum target, GLuint index, GLfloat *params) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetProgramEnvParameterARB called in Begin/End"); + return; + } + + if (target == GL_FRAGMENT_PROGRAM_ARB || target == GL_FRAGMENT_PROGRAM_NV) { + if (index >= g->limits.maxFragmentProgramEnvParams) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glGetProgramEnvParameterARB(index)"); + return; + } + params[0] = p->fragmentParameters[index][0]; + params[1] = p->fragmentParameters[index][1]; + params[2] = p->fragmentParameters[index][2]; + params[3] = p->fragmentParameters[index][3]; + } + else if ( target == GL_VERTEX_PROGRAM_ARB +#if GL_VERTEX_PROGRAM_ARB != GL_VERTEX_PROGRAM_NV + || target == GL_VERTEX_PROGRAM_NV +#endif + ) { + if (index >= g->limits.maxVertexProgramEnvParams) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glGetProgramEnvParameterARB(index)"); + return; + } + params[0] = p->vertexParameters[index][0]; + params[1] = p->vertexParameters[index][1]; + params[2] = p->vertexParameters[index][2]; + params[3] = p->vertexParameters[index][3]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetProgramEnvParameterARB(target)"); + return; + } +} + + +void STATE_APIENTRY crStateProgramEnvParameter4dARB(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + crStateProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +void STATE_APIENTRY crStateProgramEnvParameter4dvARB(GLenum target, GLuint index, const GLdouble *params) +{ + crStateProgramEnvParameter4fARB(target, index, (GLfloat) params[0], (GLfloat) params[1], (GLfloat) params[2], (GLfloat) params[3]); +} + +void STATE_APIENTRY crStateProgramEnvParameter4fARB(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + CRContext *g = GetCurrentContext(); + CRProgramState *p = &(g->program); + CRStateBits *sb = GetCurrentBits(); + CRProgramBits *pb = &(sb->program); + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glProgramEnvParameterARB called in Begin/End"); + return; + } + + if (target == GL_FRAGMENT_PROGRAM_ARB || target == GL_FRAGMENT_PROGRAM_NV) { + if (index >= g->limits.maxFragmentProgramEnvParams) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glProgramEnvParameterARB(index)"); + return; + } + p->fragmentParameters[index][0] = x; + p->fragmentParameters[index][1] = y; + p->fragmentParameters[index][2] = z; + p->fragmentParameters[index][3] = w; + DIRTY(pb->fragmentEnvParameter[index], g->neg_bitid); + DIRTY(pb->fragmentEnvParameters, g->neg_bitid); + } + else if ( target == GL_VERTEX_PROGRAM_ARB +#if GL_VERTEX_PROGRAM_ARB != GL_VERTEX_PROGRAM_NV + || target == GL_VERTEX_PROGRAM_NV +#endif + ) { + if (index >= g->limits.maxVertexProgramEnvParams) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glProgramEnvParameterARB(index)"); + return; + } + p->vertexParameters[index][0] = x; + p->vertexParameters[index][1] = y; + p->vertexParameters[index][2] = z; + p->vertexParameters[index][3] = w; + DIRTY(pb->vertexEnvParameter[index], g->neg_bitid); + DIRTY(pb->vertexEnvParameters, g->neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glProgramEnvParameterARB(target)"); + return; + } + + DIRTY(pb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateProgramEnvParameter4fvARB(GLenum target, GLuint index, const GLfloat *params) +{ + crStateProgramEnvParameter4fARB(target, index, params[0], params[1], params[2], params[3]); +} + + +/**********************************************************************/ + + +void crStateProgramInit( CRContext *ctx ) +{ + CRProgramState *p = &(ctx->program); + CRStateBits *sb = GetCurrentBits(); + CRProgramBits *pb = &(sb->program); + GLuint i; + + CRASSERT(CR_MAX_PROGRAM_ENV_PARAMS >= CR_MAX_VERTEX_PROGRAM_ENV_PARAMS); + CRASSERT(CR_MAX_PROGRAM_ENV_PARAMS >= CR_MAX_FRAGMENT_PROGRAM_ENV_PARAMS); + + CRASSERT(CR_MAX_PROGRAM_LOCAL_PARAMS >= CR_MAX_VERTEX_PROGRAM_LOCAL_PARAMS); + CRASSERT(CR_MAX_PROGRAM_LOCAL_PARAMS >= CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS); + + p->programHash = crAllocHashtable(); + + /* ARB_vertex/fragment_program define default program objects */ + p->defaultVertexProgram = GetProgram(p, GL_VERTEX_PROGRAM_ARB, 0); + p->defaultFragmentProgram = GetProgram(p, GL_FRAGMENT_PROGRAM_ARB, 0); + + p->currentVertexProgram = p->defaultVertexProgram; + p->currentFragmentProgram = p->defaultFragmentProgram; + p->errorPos = -1; + p->errorString = NULL; + + for (i = 0; i < ctx->limits.maxVertexProgramEnvParams / 4; i++) { + p->TrackMatrix[i] = GL_NONE; + p->TrackMatrixTransform[i] = GL_IDENTITY_NV; + } + for (i = 0; i < ctx->limits.maxVertexProgramEnvParams; i++) { + p->vertexParameters[i][0] = 0.0; + p->vertexParameters[i][1] = 0.0; + p->vertexParameters[i][2] = 0.0; + p->vertexParameters[i][3] = 0.0; + } + for (i = 0; i < CR_MAX_FRAGMENT_PROGRAM_ENV_PARAMS; i++) { + p->fragmentParameters[i][0] = 0.0; + p->fragmentParameters[i][1] = 0.0; + p->fragmentParameters[i][2] = 0.0; + p->fragmentParameters[i][3] = 0.0; + } + + p->vpEnabled = GL_FALSE; + p->fpEnabled = GL_FALSE; + p->fpEnabledARB = GL_FALSE; + p->vpPointSize = GL_FALSE; + p->vpTwoSide = GL_FALSE; + RESET(pb->dirty, ctx->bitid); +} + + +static void DeleteProgramCallback( void *data ) +{ + CRProgram *prog = (CRProgram *) data; + DeleteProgram(prog); +} + +void crStateProgramDestroy(CRContext *ctx) +{ + CRProgramState *p = &(ctx->program); + crFreeHashtable(p->programHash, DeleteProgramCallback); + DeleteProgram(p->defaultVertexProgram); + DeleteProgram(p->defaultFragmentProgram); +} + + +/* XXX it would be nice to autogenerate this, but we can't for now. + */ +void +crStateProgramDiff(CRProgramBits *b, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + CRProgramState *from = &(fromCtx->program); + CRProgramState *to = &(toCtx->program); + unsigned int i, j; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + + CRASSERT(from->currentVertexProgram); + CRASSERT(to->currentVertexProgram); + CRASSERT(from->currentFragmentProgram); + CRASSERT(to->currentFragmentProgram); + + for (j=0;j<CR_MAX_BITARRAY;j++) + nbitID[j] = ~bitID[j]; + + /* vertex program enable */ + if (CHECKDIRTY(b->vpEnable, bitID)) { + glAble able[2]; + CRProgram *toProg = to->currentVertexProgram; + + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + if (from->vpEnabled != to->vpEnabled) { + if (toProg->isARBprogram) + able[to->vpEnabled](GL_VERTEX_PROGRAM_ARB); + else + able[to->vpEnabled](GL_VERTEX_PROGRAM_NV); + from->vpEnabled = to->vpEnabled; + } + if (from->vpTwoSide != to->vpTwoSide) { + able[to->vpTwoSide](GL_VERTEX_PROGRAM_TWO_SIDE_NV); + from->vpTwoSide = to->vpTwoSide; + } + if (from->vpPointSize != to->vpPointSize) { + able[to->vpPointSize](GL_VERTEX_PROGRAM_POINT_SIZE_NV); + from->vpPointSize = to->vpPointSize; + } + CLEARDIRTY(b->vpEnable, nbitID); + } + + /* fragment program enable */ + if (CHECKDIRTY(b->fpEnable, bitID)) { + glAble able[2]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + if (from->fpEnabled != to->fpEnabled) { + able[to->fpEnabled](GL_FRAGMENT_PROGRAM_NV); + from->fpEnabled = to->fpEnabled; + } + if (from->fpEnabledARB != to->fpEnabledARB) { + able[to->fpEnabledARB](GL_FRAGMENT_PROGRAM_ARB); + from->fpEnabledARB = to->fpEnabledARB; + } + CLEARDIRTY(b->fpEnable, nbitID); + } + + /* program/track matrices */ + if (to->vpEnabled) { + for (i = 0; i < toCtx->limits.maxVertexProgramEnvParams / 4; i++) { + if (CHECKDIRTY(b->trackMatrix[i], bitID)) { + if (from->TrackMatrix[i] != to->TrackMatrix[i] || + from->TrackMatrixTransform[i] != to->TrackMatrixTransform[i]) { + diff_api.TrackMatrixNV(GL_VERTEX_PROGRAM_NV, i * 4, + to->TrackMatrix[i], + to->TrackMatrixTransform[i]); + from->TrackMatrix[i] = to->TrackMatrix[i]; + from->TrackMatrixTransform[i] = to->TrackMatrixTransform[i]; + } + CLEARDIRTY(b->trackMatrix[i], nbitID); + } + } + } + + if (to->vpEnabled) { + /* vertex program binding */ + CRProgram *fromProg = from->currentVertexProgram; + CRProgram *toProg = to->currentVertexProgram; + + if (CHECKDIRTY(b->vpBinding, bitID)) { + if (fromProg->id != toProg->id) { + if (toProg->isARBprogram) + diff_api.BindProgramARB(GL_VERTEX_PROGRAM_ARB, toProg->id); + else + diff_api.BindProgramNV(GL_VERTEX_PROGRAM_NV, toProg->id); + from->currentVertexProgram = toProg; + } + CLEARDIRTY(b->vpBinding, nbitID); + } + + if (toProg) { + /* vertex program text */ + if (CHECKDIRTY(toProg->dirtyProgram, bitID)) { + if (toProg->isARBprogram) { + diff_api.ProgramStringARB( GL_VERTEX_PROGRAM_ARB, toProg->format, toProg->length, toProg->string ); + } + else { + diff_api.LoadProgramNV( GL_VERTEX_PROGRAM_NV, toProg->id, toProg->length, toProg->string ); + } + CLEARDIRTY(toProg->dirtyProgram, nbitID); + } + + /* vertex program global/env parameters */ + if (CHECKDIRTY(b->vertexEnvParameters, bitID)) { + for (i = 0; i < toCtx->limits.maxVertexProgramEnvParams; i++) { + if (CHECKDIRTY(b->vertexEnvParameter[i], bitID)) { + if (toProg->isARBprogram) + diff_api.ProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, + to->vertexParameters[i]); + else + diff_api.ProgramParameter4fvNV(GL_VERTEX_PROGRAM_NV, i, + to->vertexParameters[i]); + if (fromProg) { + COPY_4V(from->vertexParameters[i], + to->vertexParameters[i]); + } + CLEARDIRTY(b->vertexEnvParameter[i], nbitID); + } + } + CLEARDIRTY(b->vertexEnvParameters, nbitID); + } + + /* vertex program local parameters */ + if (CHECKDIRTY(toProg->dirtyParams, bitID)) { + for (i = 0; i < toCtx->limits.maxVertexProgramLocalParams; i++) { + if (CHECKDIRTY(toProg->dirtyParam[i], bitID)) { + if (toProg->isARBprogram) + diff_api.ProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, toProg->parameters[i]); + else + diff_api.ProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_NV, i, toProg->parameters[i]); + CLEARDIRTY(toProg->dirtyParam[i], nbitID); + } + } + CLEARDIRTY(toProg->dirtyParams, nbitID); + } + } + } + + /* + * Separate paths for NV vs ARB fragment program + */ + if (to->fpEnabled) { + /* NV fragment program binding */ + CRProgram *fromProg = from->currentFragmentProgram; + CRProgram *toProg = to->currentFragmentProgram; + if (CHECKDIRTY(b->fpBinding, bitID)) { + if (fromProg->id != toProg->id) { + diff_api.BindProgramNV(GL_FRAGMENT_PROGRAM_NV, toProg->id); + from->currentFragmentProgram = toProg; + } + CLEARDIRTY(b->fpBinding, nbitID); + } + + if (toProg) { + /* fragment program text */ + if (CHECKDIRTY(toProg->dirtyProgram, bitID)) { + diff_api.LoadProgramNV( GL_FRAGMENT_PROGRAM_NV, toProg->id, + toProg->length, toProg->string ); + CLEARDIRTY(toProg->dirtyProgram, nbitID); + } + + /* fragment program global/env parameters */ + if (CHECKDIRTY(b->fragmentEnvParameters, bitID)) { + for (i = 0; i < toCtx->limits.maxFragmentProgramEnvParams; i++) { + if (CHECKDIRTY(b->fragmentEnvParameter[i], bitID)) { + diff_api.ProgramParameter4fvNV(GL_FRAGMENT_PROGRAM_NV, i, + to->fragmentParameters[i]); + if (fromProg) { + COPY_4V(from->fragmentParameters[i], + to->fragmentParameters[i]); + } + CLEARDIRTY(b->fragmentEnvParameter[i], nbitID); + } + } + CLEARDIRTY(b->fragmentEnvParameters, nbitID); + } + + /* named local parameters */ + if (CHECKDIRTY(toProg->dirtyNamedParams, bitID)) { + CRProgramSymbol *symbol; + for (symbol = toProg->symbolTable; symbol; symbol = symbol->next) { + if (CHECKDIRTY(symbol->dirty, bitID)) { + GLint len = crStrlen(symbol->name); + diff_api.ProgramNamedParameter4fvNV(toProg->id, len, + (const GLubyte *) symbol->name, + symbol->value); + if (fromProg) { + SetProgramSymbol(fromProg, symbol->name, len, + symbol->value[0], symbol->value[1], + symbol->value[2], symbol->value[3]); + } + CLEARDIRTY(symbol->dirty, nbitID); + } + } + CLEARDIRTY(toProg->dirtyNamedParams, nbitID); + } + + /* numbered local parameters */ + if (CHECKDIRTY(toProg->dirtyParams, bitID)) { + for (i = 0; i < CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS; i++) { + if (CHECKDIRTY(toProg->dirtyParam[i], bitID)) { + diff_api.ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_NV, i, + toProg->parameters[i]); + if (fromProg) { + COPY_4V(fromProg->parameters[i], toProg->parameters[i]); + } + CLEARDIRTY(toProg->dirtyParam[i], nbitID); + } + } + CLEARDIRTY(toProg->dirtyParams, nbitID); + } + } + } + else if (to->fpEnabledARB) { + /* ARB fragment program binding */ + CRProgram *fromProg = from->currentFragmentProgram; + CRProgram *toProg = to->currentFragmentProgram; + if (CHECKDIRTY(b->fpBinding, bitID)) { + if (fromProg->id != toProg->id) { + diff_api.BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, toProg->id); + from->currentFragmentProgram = toProg; + } + CLEARDIRTY(b->fpBinding, nbitID); + } + + if (toProg) { + /* fragment program text */ + if (CHECKDIRTY(toProg->dirtyProgram, bitID)) { + diff_api.ProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, toProg->format, + toProg->length, toProg->string ); + CLEARDIRTY(toProg->dirtyProgram, nbitID); + } + + /* fragment program global/env parameters */ + if (CHECKDIRTY(b->fragmentEnvParameters, bitID)) { + for (i = 0; i < toCtx->limits.maxFragmentProgramEnvParams; i++) { + if (CHECKDIRTY(b->fragmentEnvParameter[i], bitID)) { + diff_api.ProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, + to->fragmentParameters[i]); + if (fromProg) { + COPY_4V(from->fragmentParameters[i], + to->fragmentParameters[i]); + } + CLEARDIRTY(b->fragmentEnvParameter[i], nbitID); + } + } + CLEARDIRTY(b->fragmentEnvParameters, nbitID); + } + + /* numbered local parameters */ + if (CHECKDIRTY(toProg->dirtyParams, bitID)) { + for (i = 0; i < CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS; i++) { + if (CHECKDIRTY(toProg->dirtyParam[i], bitID)) { + diff_api.ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, + toProg->parameters[i]); + if (fromProg) { + COPY_4V(fromProg->parameters[i], toProg->parameters[i]); + } + CLEARDIRTY(toProg->dirtyParam[i], nbitID); + } + } + CLEARDIRTY(toProg->dirtyParams, nbitID); + } + } + } + + CLEARDIRTY(b->dirty, nbitID); +} + + +void +crStateProgramSwitch(CRProgramBits *b, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + CRProgramState *from = &(fromCtx->program); + CRProgramState *to = &(toCtx->program); + unsigned int i, j; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + GLenum whichVert = fromCtx->extensions.ARB_vertex_program && toCtx->extensions.ARB_vertex_program ? GL_VERTEX_PROGRAM_ARB : GL_VERTEX_PROGRAM_NV; + + + for (j=0;j<CR_MAX_BITARRAY;j++) + nbitID[j] = ~bitID[j]; + + /* vertex program enable */ + if (CHECKDIRTY(b->vpEnable, bitID)) { + glAble able[2]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + if (from->vpEnabled != to->vpEnabled) { + able[to->vpEnabled](whichVert); + } + if (from->vpTwoSide != to->vpTwoSide) { + able[to->vpTwoSide](GL_VERTEX_PROGRAM_TWO_SIDE_NV); + } + if (from->vpPointSize != to->vpPointSize) { + able[to->vpPointSize](GL_VERTEX_PROGRAM_POINT_SIZE_NV); + } + DIRTY(b->vpEnable, nbitID); + } + + /* fragment program enable */ + if (CHECKDIRTY(b->fpEnable, bitID)) { + glAble able[2]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + if (from->fpEnabled != to->fpEnabled) { + able[to->fpEnabled](GL_FRAGMENT_PROGRAM_NV); + } + if (from->fpEnabledARB != to->fpEnabledARB) { + able[to->fpEnabledARB](GL_FRAGMENT_PROGRAM_ARB); + } + DIRTY(b->fpEnable, nbitID); + } + + /* program/track matrices */ + if (to->vpEnabled) { + for (i = 0; i < toCtx->limits.maxVertexProgramEnvParams / 4; i++) { + if (CHECKDIRTY(b->trackMatrix[i], bitID)) { + if (from->TrackMatrix[i] != to->TrackMatrix[i]) { + diff_api.TrackMatrixNV(GL_VERTEX_PROGRAM_NV, i * 4, + to->TrackMatrix[i], + to->TrackMatrixTransform[i]); + } + DIRTY(b->trackMatrix[i], nbitID); + } + } + } + + if (to->vpEnabled) { + /* vertex program binding */ + CRProgram *fromProg = from->currentVertexProgram; + CRProgram *toProg = to->currentVertexProgram; + if (CHECKDIRTY(b->vpBinding, bitID)) { + if (fromProg->id != toProg->id) { + if (toProg->isARBprogram) + diff_api.BindProgramARB(GL_VERTEX_PROGRAM_ARB, toProg->id); + else + diff_api.BindProgramNV(GL_VERTEX_PROGRAM_NV, toProg->id); + } + DIRTY(b->vpBinding, nbitID); + } + + if (toProg) { + /* vertex program text */ + if (CHECKDIRTY(toProg->dirtyProgram, bitID)) { + if (toProg->isARBprogram) + diff_api.ProgramStringARB(GL_VERTEX_PROGRAM_ARB, toProg->format, toProg->length, toProg->string); + else + diff_api.LoadProgramNV(GL_VERTEX_PROGRAM_NV, toProg->id, toProg->length, toProg->string); + + DIRTY(toProg->dirtyProgram, nbitID); + } + + /* vertex program global/env parameters */ + if (CHECKDIRTY(b->vertexEnvParameters, bitID)) { + for (i = 0; i < toCtx->limits.maxVertexProgramEnvParams; i++) { + if (CHECKDIRTY(b->vertexEnvParameter[i], bitID)) { + if (toProg->isARBprogram) + diff_api.ProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, to->vertexParameters[i]); + else + diff_api.ProgramParameter4fvNV(GL_VERTEX_PROGRAM_NV, i, to->vertexParameters[i]); + + DIRTY(b->vertexEnvParameter[i], nbitID); + } + } + DIRTY(b->vertexEnvParameters, nbitID); + } + + /* vertex program local parameters */ + if (CHECKDIRTY(toProg->dirtyParams, bitID)) { + for (i = 0; i < toCtx->limits.maxVertexProgramLocalParams; i++) { + if (CHECKDIRTY(toProg->dirtyParam[i], bitID)) { + + + if (toProg->isARBprogram) + diff_api.ProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, toProg->parameters[i]); + else + diff_api.ProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_NV, i, toProg->parameters[i]); + } + } + DIRTY(toProg->dirtyParams, nbitID); + } + } + } + + /* + * Separate paths for NV vs ARB fragment program + */ + if (to->fpEnabled) { + /* NV fragment program binding */ + CRProgram *fromProg = from->currentFragmentProgram; + CRProgram *toProg = to->currentFragmentProgram; + if (CHECKDIRTY(b->fpBinding, bitID)) { + if (fromProg->id != toProg->id) { + diff_api.BindProgramNV(GL_FRAGMENT_PROGRAM_NV, toProg->id); + } + DIRTY(b->fpBinding, nbitID); + } + + if (toProg) { + /* fragment program text */ + if (CHECKDIRTY(toProg->dirtyProgram, bitID)) { + diff_api.LoadProgramNV(GL_FRAGMENT_PROGRAM_NV, toProg->id, toProg->length, toProg->string); + DIRTY(toProg->dirtyProgram, nbitID); + } + + /* fragment program global/env parameters */ + if (CHECKDIRTY(b->fragmentEnvParameters, bitID)) { + for (i = 0; i < toCtx->limits.maxFragmentProgramEnvParams; i++) { + if (CHECKDIRTY(b->fragmentEnvParameter[i], bitID)) { + diff_api.ProgramParameter4fvNV(GL_FRAGMENT_PROGRAM_NV, i, + to->fragmentParameters[i]); + DIRTY(b->fragmentEnvParameter[i], nbitID); + } + } + DIRTY(b->fragmentEnvParameters, nbitID); + } + + /* named local parameters */ + if (CHECKDIRTY(toProg->dirtyNamedParams, bitID)) { + CRProgramSymbol *symbol; + for (symbol = toProg->symbolTable; symbol; symbol = symbol->next) { + if (CHECKDIRTY(symbol->dirty, bitID)) { + GLint len = crStrlen(symbol->name); + diff_api.ProgramNamedParameter4fvNV(toProg->id, len, + (const GLubyte *) symbol->name, + symbol->value); + DIRTY(symbol->dirty, nbitID); + } + } + DIRTY(toProg->dirtyNamedParams, nbitID); + } + + /* numbered local parameters */ + if (CHECKDIRTY(toProg->dirtyParams, bitID)) { + for (i = 0; i < CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS; i++) { + if (CHECKDIRTY(toProg->dirtyParam[i], bitID)) { + if (toProg->isARBprogram) + diff_api.ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, toProg->parameters[i]); + else + diff_api.ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_NV, i, toProg->parameters[i]); + } + } + DIRTY(toProg->dirtyParams, nbitID); + } + } + } + else if (to->fpEnabledARB) { + /* ARB fragment program binding */ + CRProgram *fromProg = from->currentFragmentProgram; + CRProgram *toProg = to->currentFragmentProgram; + if (CHECKDIRTY(b->fpBinding, bitID)) { + if (fromProg->id != toProg->id) { + diff_api.BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, toProg->id); + } + DIRTY(b->fpBinding, nbitID); + } + + if (toProg) { + /* fragment program text */ + if (CHECKDIRTY(toProg->dirtyProgram, bitID)) { + diff_api.ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, toProg->format, toProg->length, toProg->string); + DIRTY(toProg->dirtyProgram, nbitID); + } + + /* fragment program global/env parameters */ + if (CHECKDIRTY(b->fragmentEnvParameters, bitID)) { + for (i = 0; i < toCtx->limits.maxFragmentProgramEnvParams; i++) { + if (CHECKDIRTY(b->fragmentEnvParameter[i], bitID)) { + diff_api.ProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, to->fragmentParameters[i]); + DIRTY(b->fragmentEnvParameter[i], nbitID); + } + } + DIRTY(b->fragmentEnvParameters, nbitID); + } + + /* numbered local parameters */ + if (CHECKDIRTY(toProg->dirtyParams, bitID)) { + for (i = 0; i < CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS; i++) { + if (CHECKDIRTY(toProg->dirtyParam[i], bitID)) { + diff_api.ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, toProg->parameters[i]); + DIRTY(toProg->dirtyParam[i], nbitID); + } + } + DIRTY(toProg->dirtyParams, nbitID); + } + } + } + + DIRTY(b->dirty, nbitID); + + /* Resend program data */ + if (toCtx->program.bResyncNeeded) + { + toCtx->program.bResyncNeeded = GL_FALSE; + + crStateDiffAllPrograms(toCtx, bitID, GL_TRUE); + } +} + +/** @todo support NVprograms and add some data validity checks*/ +static void +DiffProgramCallback(unsigned long key, void *pProg, void *pCtx) +{ + CRContext *pContext = (CRContext *) pCtx; + CRProgram *pProgram = (CRProgram *) pProg; + uint32_t i; + (void)key; + + if (pProgram->isARBprogram) + { + diff_api.BindProgramARB(pProgram->target, pProgram->id); + diff_api.ProgramStringARB(pProgram->target, pProgram->format, pProgram->length, pProgram->string); + + if (GL_VERTEX_PROGRAM_ARB == pProgram->target) + { + /* vertex program global/env parameters */ + for (i = 0; i < pContext->limits.maxVertexProgramEnvParams; i++) + { + diff_api.ProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, pContext->program.vertexParameters[i]); + } + /* vertex program local parameters */ + for (i = 0; i < pContext->limits.maxVertexProgramLocalParams; i++) + { + diff_api.ProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, pProgram->parameters[i]); + } + } + else if (GL_FRAGMENT_PROGRAM_ARB == pProgram->target) + { + /* vertex program global/env parameters */ + for (i = 0; i < pContext->limits.maxFragmentProgramEnvParams; i++) + { + diff_api.ProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, pContext->program.fragmentParameters[i]); + } + /* vertex program local parameters */ + for (i = 0; i < CR_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMS; i++) + { + diff_api.ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, pProgram->parameters[i]); + } + } + else + { + crError("Unexpected program target"); + } + } + else + { + diff_api.BindProgramNV(pProgram->target, pProgram->id); + } +} + +void crStateDiffAllPrograms(CRContext *g, CRbitvalue *bitID, GLboolean bForceUpdate) +{ + CRProgram *pOrigVP, *pOrigFP; + + (void) bForceUpdate; (void)bitID; + + /* save original bindings */ + pOrigVP = g->program.currentVertexProgram; + pOrigFP = g->program.currentFragmentProgram; + + crHashtableWalk(g->program.programHash, DiffProgramCallback, g); + + /* restore original bindings */ + if (pOrigVP->isARBprogram) + diff_api.BindProgramARB(pOrigVP->target, pOrigVP->id); + else + diff_api.BindProgramNV(pOrigVP->target, pOrigVP->id); + + if (pOrigFP->isARBprogram) + diff_api.BindProgramARB(pOrigFP->target, pOrigFP->id); + else + diff_api.BindProgramNV(pOrigFP->target, pOrigFP->id); +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_program.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_program.txt new file mode 100644 index 00000000..fdb5c75e --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_program.txt @@ -0,0 +1,14 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +#:enable:lineSmooth:GL_LINE_SMOOTH +#:enable:lineStipple:GL_LINE_STIPPLE +#:width:width:LineWidth +#lineStipple:stipple:repeat,pattern:LineStipple +:vpEnable:vpEnabled:Enable:GL_VERTEX_PROGRAM_NV +:fpEnable:fpEnabled:Enable:GL_FRAGMENT_PROGRAM_NV +%flush +:vpBinding:currentVertexProgram->id:BindProgramNV,GL_VERTEX_PROGRAM_NV +:fpBinding:currentFragmentProgram->id:BindProgramNV,GL_FRAGMENT_PROGRAM_NV +#:errorPos:errorPos:ErrorPos diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_rasterpos.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_rasterpos.c new file mode 100644 index 00000000..29b23970 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_rasterpos.c @@ -0,0 +1,327 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include <stdio.h> +#include "state.h" +#include "state/cr_statetypes.h" +#include "state_internals.h" + + +/* + * Apply modelview, projection, viewport transformations to (x,y,z,w) + * and update the current raster position attributes. + * Do NOT set dirty state. + */ +void +crStateRasterPosUpdate(GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + CRContext *g = GetCurrentContext(); + CRCurrentState *c = &(g->current); + CRTransformState *t = &(g->transform); + CRViewportState *v = &(g->viewport); + GLvectorf p; + int i; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "RasterPos called in Begin/End"); + return; + } + + FLUSH(); + + /* update current color, texcoord, etc from the CurrentStatePointers */ + crStateCurrentRecover(); + + p.x = x; + p.y = y; + p.z = z; + p.w = w; + + /* Apply modelview and projection matrix */ + crStateTransformXformPoint(t, &p); + + /* clip test */ + if (p.x > p.w || p.y > p.w || p.z > p.w || + p.x < -p.w || p.y < -p.w || p.z < -p.w) + { + c->rasterValid = GL_FALSE; + return; + } + + /* divide by W (perspective projection) */ + p.x /= p.w; + p.y /= p.w; + p.z /= p.w; + p.w = 1.0f; + + /* map from NDC to window coords */ + crStateViewportApply(v, &p); + + c->rasterValid = GL_TRUE; + ASSIGN_4V(c->rasterAttrib[VERT_ATTRIB_POS], p.x, p.y, p.z, p.w); + ASSIGN_4V(c->rasterAttribPre[VERT_ATTRIB_POS], p.x, p.y, p.z, p.w); + for (i = 1; i < CR_MAX_VERTEX_ATTRIBS; i++) { + COPY_4V(c->rasterAttrib[i] , c->vertexAttrib[i]); + } + + /* XXX need to update raster distance... */ + /* from Mesa... */ +#ifdef CR_EXT_fog_coord + if (g->fog.fogCoordinateSource == GL_FOG_COORDINATE_EXT) + c->rasterAttrib[VERT_ATTRIB_FOG][0] = c->vertexAttrib[VERT_ATTRIB_FOG][0]; + else +#endif + c->rasterAttrib[VERT_ATTRIB_FOG][0] = 0.0; /*(GLfloat) + sqrt( eye[0]*eye[0] + eye[1]*eye[1] + eye[2]*eye[2] );*/ +} + + +/* As above, but set dirty flags */ +static void RasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + CRContext *g = GetCurrentContext(); + CRStateBits *sb = GetCurrentBits(); + CRCurrentBits *cb = &(sb->current); + + crStateRasterPosUpdate(x, y, z, w); + + DIRTY(cb->dirty, g->neg_bitid); + DIRTY(cb->rasterPos, g->neg_bitid); +} + +void STATE_APIENTRY crStateRasterPos2d(GLdouble x, GLdouble y) +{ + RasterPos4f((GLfloat) x, (GLfloat) y, 0.0f, 1.0f); +} + +void STATE_APIENTRY crStateRasterPos2f(GLfloat x, GLfloat y) +{ + RasterPos4f(x, y, 0.0f, 1.0f); +} + +void STATE_APIENTRY crStateRasterPos2i(GLint x, GLint y) +{ + RasterPos4f((GLfloat) x, (GLfloat) y, 0.0f, 1.0f); +} + +void STATE_APIENTRY crStateRasterPos2s(GLshort x, GLshort y) +{ + RasterPos4f((GLfloat) x, (GLfloat) y, 0.0f, 1.0f); +} + +void STATE_APIENTRY crStateRasterPos3d(GLdouble x, GLdouble y, GLdouble z) +{ + RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0f); +} + +void STATE_APIENTRY crStateRasterPos3f(GLfloat x, GLfloat y, GLfloat z) +{ + RasterPos4f(x, y, z, 1.0f); +} + +void STATE_APIENTRY crStateRasterPos3i(GLint x, GLint y, GLint z) +{ + RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0f); +} + +void STATE_APIENTRY crStateRasterPos3s(GLshort x, GLshort y, GLshort z) +{ + RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0f); +} + +void STATE_APIENTRY crStateRasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +void STATE_APIENTRY crStateRasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + RasterPos4f(x, y, z, w); +} + +void STATE_APIENTRY crStateRasterPos4i(GLint x, GLint y, GLint z, GLint w) +{ + RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +void STATE_APIENTRY crStateRasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w) +{ + RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +void STATE_APIENTRY crStateRasterPos2dv(const GLdouble *v) +{ + RasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0f, 1.0f); +} + +void STATE_APIENTRY crStateRasterPos2fv(const GLfloat *v) +{ + RasterPos4f(v[0], v[1], 0.0f, 1.0f); +} + +void STATE_APIENTRY crStateRasterPos2iv(const GLint *v) +{ + RasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0f, 1.0f); +} + +void STATE_APIENTRY crStateRasterPos2sv(const GLshort *v) +{ + RasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0f, 1.0f); +} + +void STATE_APIENTRY crStateRasterPos3dv(const GLdouble *v) +{ + RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0f); +} + +void STATE_APIENTRY crStateRasterPos3fv(const GLfloat *v) +{ + RasterPos4f(v[0], v[1], v[2], 1.0f); +} + +void STATE_APIENTRY crStateRasterPos3iv(const GLint *v) +{ + RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0f); +} + +void STATE_APIENTRY crStateRasterPos3sv(const GLshort *v) +{ + RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0f); +} + +void STATE_APIENTRY crStateRasterPos4dv(const GLdouble *v) +{ + RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); +} + +void STATE_APIENTRY crStateRasterPos4fv(const GLfloat *v) +{ + RasterPos4f(v[0], v[1], v[2], v[3]); +} + +void STATE_APIENTRY crStateRasterPos4iv(const GLint *v) +{ + RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); +} + +void STATE_APIENTRY crStateRasterPos4sv(const GLshort *v) +{ + RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); +} + + +/**********************************************************************/ + + +static void +crStateWindowPosUpdate(GLfloat x, GLfloat y, GLfloat z) +{ + CRContext *g = GetCurrentContext(); + CRCurrentState *c = &(g->current); + CRStateBits *sb = GetCurrentBits(); + CRCurrentBits *cb = &(sb->current); + int i; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "WindowPos called in Begin/End"); + return; + } + + FLUSH(); + DIRTY(cb->dirty, g->neg_bitid); + DIRTY(cb->rasterPos, g->neg_bitid); + + c->rasterValid = GL_TRUE; + ASSIGN_4V(c->rasterAttrib[VERT_ATTRIB_POS], x, y , z, 1.0); + ASSIGN_4V(c->rasterAttribPre[VERT_ATTRIB_POS], x, y, z, 1.0); + for (i = 1; i < CR_MAX_VERTEX_ATTRIBS; i++) { + COPY_4V(c->rasterAttrib[i] , c->vertexAttrib[i]); + } +} + + +void STATE_APIENTRY crStateWindowPos2dARB (GLdouble x, GLdouble y) +{ + crStateWindowPosUpdate((GLfloat) x, (GLfloat) y, 0.0); +} + +void STATE_APIENTRY crStateWindowPos2dvARB (const GLdouble *v) +{ + crStateWindowPosUpdate((GLfloat) v[0], (GLfloat) v[1], 0.0); +} + +void STATE_APIENTRY crStateWindowPos2fARB (GLfloat x, GLfloat y) +{ + crStateWindowPosUpdate(x, y, 0.0); +} + +void STATE_APIENTRY crStateWindowPos2fvARB (const GLfloat *v) +{ + crStateWindowPosUpdate(v[0], v[1], 0.0); +} + +void STATE_APIENTRY crStateWindowPos2iARB (GLint x, GLint y) +{ + crStateWindowPosUpdate((GLfloat) x, (GLfloat) y, 0.0); +} + +void STATE_APIENTRY crStateWindowPos2ivARB (const GLint *v) +{ + crStateWindowPosUpdate((GLfloat) v[0], (GLfloat) v[1], 0.0); +} + +void STATE_APIENTRY crStateWindowPos2sARB (GLshort x, GLshort y) +{ + crStateWindowPosUpdate((GLfloat) x, (GLfloat) y, 0.0); +} + +void STATE_APIENTRY crStateWindowPos2svARB (const GLshort *v) +{ + crStateWindowPosUpdate((GLfloat) v[0], (GLfloat) v[1], 0.0); +} + +void STATE_APIENTRY crStateWindowPos3dARB (GLdouble x, GLdouble y, GLdouble z) +{ + crStateWindowPosUpdate((GLfloat) x, (GLfloat) y, (GLfloat) z); +} + +void STATE_APIENTRY crStateWindowPos3dvARB (const GLdouble *v) +{ + crStateWindowPosUpdate((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]); +} + +void STATE_APIENTRY crStateWindowPos3fARB (GLfloat x, GLfloat y, GLfloat z) +{ + crStateWindowPosUpdate(x, y, z); +} + +void STATE_APIENTRY crStateWindowPos3fvARB (const GLfloat *v) +{ + crStateWindowPosUpdate(v[0], v[1], v[2]); +} + +void STATE_APIENTRY crStateWindowPos3iARB (GLint x, GLint y, GLint z) +{ + crStateWindowPosUpdate((GLfloat) x, (GLfloat) y, (GLfloat) z); +} + +void STATE_APIENTRY crStateWindowPos3ivARB (const GLint *v) +{ + crStateWindowPosUpdate((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]); +} + +void STATE_APIENTRY crStateWindowPos3sARB (GLshort x, GLshort y, GLshort z) +{ + crStateWindowPosUpdate((GLfloat) x, (GLfloat) y, (GLfloat) z); +} + +void STATE_APIENTRY crStateWindowPos3svARB (const GLshort *v) +{ + crStateWindowPosUpdate((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]); +} + diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_regcombiner.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_regcombiner.c new file mode 100644 index 00000000..069c6fa5 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_regcombiner.c @@ -0,0 +1,705 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "state.h" +#include "state/cr_statetypes.h" + + +#define UNUSED(x) ((void) (x)) + + +void crStateRegCombinerInit( CRContext *ctx ) +{ + CRRegCombinerState *reg = &ctx->regcombiner; + CRStateBits *sb = GetCurrentBits(); + CRRegCombinerBits *rb = &(sb->regcombiner); +#ifndef CR_NV_register_combiners + UNUSED(reg) +#else + GLcolorf zero_color = {0.0f, 0.0f, 0.0f, 0.0f}; + int i; + + reg->enabledRegCombiners = GL_FALSE; + RESET(rb->enable, ctx->bitid); + reg->constantColor0 = zero_color; + RESET(rb->regCombinerColor0, ctx->bitid); + reg->constantColor1 = zero_color; + RESET(rb->regCombinerColor1, ctx->bitid); + for( i=0; i<CR_MAX_GENERAL_COMBINERS; i++ ) + { + /* RGB Portion */ + reg->rgb[i].a = GL_PRIMARY_COLOR_NV; + reg->rgb[i].b = GL_ZERO; + reg->rgb[i].c = GL_ZERO; + reg->rgb[i].d = GL_ZERO; + reg->rgb[i].aMapping = GL_UNSIGNED_IDENTITY_NV; + reg->rgb[i].bMapping = GL_UNSIGNED_INVERT_NV; + reg->rgb[i].cMapping = GL_UNSIGNED_IDENTITY_NV; + reg->rgb[i].dMapping = GL_UNSIGNED_IDENTITY_NV; + reg->rgb[i].aPortion = GL_RGB; + reg->rgb[i].bPortion = GL_RGB; + reg->rgb[i].cPortion = GL_RGB; + reg->rgb[i].dPortion = GL_RGB; + reg->rgb[i].scale = GL_NONE; + reg->rgb[i].bias = GL_NONE; + reg->rgb[i].abOutput = GL_DISCARD_NV; + reg->rgb[i].cdOutput = GL_DISCARD_NV; + reg->rgb[i].sumOutput = GL_SPARE0_NV; + reg->rgb[i].abDotProduct = GL_FALSE; + reg->rgb[i].cdDotProduct = GL_FALSE; + reg->rgb[i].muxSum = GL_FALSE; + + /* Alpha Portion */ + reg->alpha[i].a = GL_PRIMARY_COLOR_NV; + reg->alpha[i].b = GL_ZERO; + reg->alpha[i].c = GL_ZERO; + reg->alpha[i].d = GL_ZERO; + reg->alpha[i].aMapping = GL_UNSIGNED_IDENTITY_NV; + reg->alpha[i].bMapping = GL_UNSIGNED_INVERT_NV; + reg->alpha[i].cMapping = GL_UNSIGNED_IDENTITY_NV; + reg->alpha[i].dMapping = GL_UNSIGNED_IDENTITY_NV; + reg->alpha[i].aPortion = GL_ALPHA; + reg->alpha[i].bPortion = GL_ALPHA; + reg->alpha[i].cPortion = GL_ALPHA; + reg->alpha[i].dPortion = GL_ALPHA; + reg->alpha[i].scale = GL_NONE; + reg->alpha[i].bias = GL_NONE; + reg->alpha[i].abOutput = GL_DISCARD_NV; + reg->alpha[i].cdOutput = GL_DISCARD_NV; + reg->alpha[i].sumOutput = GL_SPARE0_NV; + reg->alpha[i].abDotProduct = GL_FALSE; + reg->alpha[i].cdDotProduct = GL_FALSE; + reg->alpha[i].muxSum = GL_FALSE; + RESET(rb->regCombinerInput[i], ctx->bitid); + RESET(rb->regCombinerOutput[i], ctx->bitid); + } + RESET(rb->regCombinerVars, ctx->bitid); + reg->numGeneralCombiners = 1; + reg->colorSumClamp = GL_TRUE; + reg->a = GL_FOG; + reg->b = GL_SPARE0_PLUS_SECONDARY_COLOR_NV; + reg->c = GL_FOG; + reg->d = GL_ZERO; + reg->e = GL_ZERO; + reg->f = GL_ZERO; + reg->g = GL_SPARE0_NV; + reg->aMapping = GL_UNSIGNED_IDENTITY_NV; + reg->bMapping = GL_UNSIGNED_IDENTITY_NV; + reg->cMapping = GL_UNSIGNED_IDENTITY_NV; + reg->dMapping = GL_UNSIGNED_IDENTITY_NV; + reg->eMapping = GL_UNSIGNED_IDENTITY_NV; + reg->fMapping = GL_UNSIGNED_IDENTITY_NV; + reg->gMapping = GL_UNSIGNED_IDENTITY_NV; + reg->aPortion = GL_ALPHA; + reg->bPortion = GL_RGB; + reg->cPortion = GL_RGB; + reg->dPortion = GL_RGB; + reg->ePortion = GL_RGB; + reg->fPortion = GL_RGB; + reg->gPortion = GL_ALPHA; + RESET(rb->regCombinerFinalInput, ctx->bitid); +#ifdef CR_NV_register_combiners2 + reg->enabledPerStageConstants = GL_FALSE; + for( i=0; i<CR_MAX_GENERAL_COMBINERS; i++ ) + { + reg->stageConstantColor0[i] = zero_color; + reg->stageConstantColor1[i] = zero_color; + RESET(rb->regCombinerStageColor0[i], ctx->bitid); + RESET(rb->regCombinerStageColor1[i], ctx->bitid); + } +#endif /* CR_NV_register_combiners2 */ +#endif /* CR_NV_register_combiners */ + + RESET(rb->dirty, ctx->bitid); +} + +void STATE_APIENTRY crStateCombinerParameterfvNV( GLenum pname, const GLfloat *params ) +{ + CRContext *g = GetCurrentContext(); + CRRegCombinerState *r = &(g->regcombiner); + CRStateBits *sb = GetCurrentBits(); + CRRegCombinerBits *rb = &(sb->regcombiner); + + switch( pname ) + { + case GL_CONSTANT_COLOR0_NV: + r->constantColor0.r = params[0]; + r->constantColor0.g = params[1]; + r->constantColor0.b = params[2]; + r->constantColor0.a = params[3]; + DIRTY(rb->regCombinerColor0, g->neg_bitid); + break; + case GL_CONSTANT_COLOR1_NV: + r->constantColor1.r = params[0]; + r->constantColor1.g = params[1]; + r->constantColor1.b = params[2]; + r->constantColor1.a = params[3]; + DIRTY(rb->regCombinerColor1, g->neg_bitid); + break; + case GL_NUM_GENERAL_COMBINERS_NV: + if( *params < 1 || *params > g->limits.maxGeneralCombiners ) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "CombinerParameter passed invalid NUM_GENERAL_COMBINERS param: %d", (GLint)*params ); + return; + } + r->numGeneralCombiners = (GLint)*params; + DIRTY(rb->regCombinerVars, g->neg_bitid); + break; + case GL_COLOR_SUM_CLAMP_NV: + r->colorSumClamp = (GLboolean)*params; + DIRTY(rb->regCombinerVars, g->neg_bitid); + break; + default: + crStateError( __LINE__, __FILE__, GL_INVALID_ENUM, "CombinerParameter passed bogus pname: 0x%x", pname ); + return; + } + + DIRTY(rb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateCombinerParameterivNV( GLenum pname, const GLint *params ) +{ + GLfloat fparams[4]; + int i; + + if( pname == GL_CONSTANT_COLOR0_NV || pname == GL_CONSTANT_COLOR1_NV ) + { + for( i=0; i<4; i++ ) + { + fparams[i] = (GLfloat)params[i] * (GLfloat)(1.0/255.0); + } + } + else + { + /* Only one parameter: */ + *fparams = (GLfloat) *params; + } + crStateCombinerParameterfvNV( pname, fparams ); +} + +void STATE_APIENTRY crStateCombinerParameterfNV( GLenum pname, GLfloat param ) +{ + GLfloat fparam[1]; + *fparam = (GLfloat) param; + if( pname == GL_CONSTANT_COLOR0_NV || pname == GL_CONSTANT_COLOR1_NV ) + { + crStateError( __LINE__, __FILE__, GL_INVALID_ENUM, "Invalid pname (CONSTANT_COLOR%d) passed to CombinerParameterfNV: 0x%x", (GLint)param-GL_CONSTANT_COLOR0_NV, pname ); + return; + } + crStateCombinerParameterfvNV( pname, fparam ); +} + +void STATE_APIENTRY crStateCombinerParameteriNV( GLenum pname, GLint param ) +{ + GLfloat fparam[1]; + *fparam = (GLfloat) param; + if( pname == GL_CONSTANT_COLOR0_NV || pname == GL_CONSTANT_COLOR1_NV ) + { + crStateError( __LINE__, __FILE__, GL_INVALID_ENUM, "Invalid pname (CONSTANT_COLOR%d) passed to CombinerParameteriNV: 0x%x", param-GL_CONSTANT_COLOR0_NV, pname ); + return; + } + crStateCombinerParameterfvNV( pname, fparam ); +} + +void STATE_APIENTRY crStateCombinerInputNV( GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage ) +{ + CRContext *g = GetCurrentContext(); + CRRegCombinerState *r = &(g->regcombiner); + CRStateBits *sb = GetCurrentBits(); + CRRegCombinerBits *rb = &(sb->regcombiner); + + if( stage < GL_COMBINER0_NV || stage >= GL_COMBINER0_NV + g->limits.maxGeneralCombiners ) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerInputNV passed bogus stage: 0x%x", stage ); + return; + } + if( input != GL_ZERO && input != GL_CONSTANT_COLOR0_NV && input != GL_CONSTANT_COLOR1_NV && input != GL_FOG && input != GL_PRIMARY_COLOR_NV && input != GL_SECONDARY_COLOR_NV && input != GL_SPARE0_NV && input != GL_SPARE1_NV && ( input < GL_TEXTURE0_ARB || input >= GL_TEXTURE0_ARB + g->limits.maxTextureUnits )) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerInputNV passed bogus input: 0x%x", input ); + return; + } + if( mapping != GL_UNSIGNED_IDENTITY_NV && mapping != GL_UNSIGNED_INVERT_NV && mapping != GL_EXPAND_NORMAL_NV && mapping != GL_EXPAND_NEGATE_NV && mapping != GL_HALF_BIAS_NORMAL_NV && mapping != GL_HALF_BIAS_NEGATE_NV && mapping != GL_SIGNED_IDENTITY_NV && mapping != GL_SIGNED_NEGATE_NV ) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerInputNV passed bogus mapping: 0x%x", mapping ); + return; + } + if( componentUsage != GL_RGB && componentUsage != GL_ALPHA && componentUsage != GL_BLUE ) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerInputNV passed bogus componentUsage: 0x%x", componentUsage ); + return; + } + + if(( componentUsage == GL_RGB && portion == GL_ALPHA )||( componentUsage == GL_BLUE && portion == GL_RGB )) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "Incompatible portion and componentUsage passed to CombinerInputNV: portion = 0x%x, componentUsage = 0x%x", portion, componentUsage ); + return; + } + if( componentUsage == GL_ALPHA && input == GL_FOG ) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "CombinerInputNV can not have input of GL_FOG if componentUsage is GL_ALPHA" ); + return; + } + + stage -= GL_COMBINER0_NV; + if( portion == GL_RGB ) + { + switch( variable ) + { + case GL_VARIABLE_A_NV: + r->rgb[stage].a = input; + r->rgb[stage].aMapping = mapping; + r->rgb[stage].aPortion = componentUsage; + break; + case GL_VARIABLE_B_NV: + r->rgb[stage].b = input; + r->rgb[stage].bMapping = mapping; + r->rgb[stage].bPortion = componentUsage; + break; + case GL_VARIABLE_C_NV: + r->rgb[stage].c = input; + r->rgb[stage].cMapping = mapping; + r->rgb[stage].cPortion = componentUsage; + break; + case GL_VARIABLE_D_NV: + r->rgb[stage].d = input; + r->rgb[stage].dMapping = mapping; + r->rgb[stage].dPortion = componentUsage; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerInputNV passed bogus variable: 0x%x", variable ); + return; + } + } + else if( portion == GL_ALPHA ) + { + switch( variable ) + { + case GL_VARIABLE_A_NV: + r->alpha[stage].a = input; + r->alpha[stage].aMapping = mapping; + r->alpha[stage].aPortion = componentUsage; + break; + case GL_VARIABLE_B_NV: + r->alpha[stage].b = input; + r->alpha[stage].bMapping = mapping; + r->alpha[stage].bPortion = componentUsage; + break; + case GL_VARIABLE_C_NV: + r->alpha[stage].c = input; + r->alpha[stage].cMapping = mapping; + r->alpha[stage].cPortion = componentUsage; + break; + case GL_VARIABLE_D_NV: + r->alpha[stage].d = input; + r->alpha[stage].dMapping = mapping; + r->alpha[stage].dPortion = componentUsage; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerInputNV passed bogus variable: 0x%x", variable ); + return; + } + } + else + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerInputNV passed bogus portion: 0x%x", portion ); + return; + } + + DIRTY(rb->regCombinerInput[stage], g->neg_bitid); + DIRTY(rb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateCombinerOutputNV( GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum ) +{ + CRContext *g = GetCurrentContext(); + CRRegCombinerState *r = &(g->regcombiner); + CRStateBits *sb = GetCurrentBits(); + CRRegCombinerBits *rb = &(sb->regcombiner); + + /* + crDebug("%s(stage=0x%x portion=0x%x abOutput=0x%x cdOutput=0x%x " + "sumOutput=0x%x scale=0x%x bias=0x%x abDotProduct=0x%x " + "cdDotProduct=%d muxSum=%d)\n", + __FUNCTION__, + stage, portion, abOutput, cdOutput, sumOutput, scale, bias, + abDotProduct, cdDotProduct, muxSum); + */ + if( stage < GL_COMBINER0_NV || stage >= GL_COMBINER0_NV + g->limits.maxGeneralCombiners ) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerOutputNV passed bogus stage: 0x%x", stage ); + return; + } + if( abOutput != GL_DISCARD_NV && abOutput != GL_PRIMARY_COLOR_NV && abOutput != GL_SECONDARY_COLOR_NV && abOutput != GL_SPARE0_NV && abOutput != GL_SPARE1_NV && ( abOutput < GL_TEXTURE0_ARB || abOutput >= g->limits.maxTextureUnits + GL_TEXTURE0_ARB )) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerOutputNV passed bogus abOutput: 0x%x", abOutput ); + return; + } + if( cdOutput != GL_DISCARD_NV && cdOutput != GL_PRIMARY_COLOR_NV && cdOutput != GL_SECONDARY_COLOR_NV && cdOutput != GL_SPARE0_NV && cdOutput != GL_SPARE1_NV && ( cdOutput < GL_TEXTURE0_ARB || cdOutput >= g->limits.maxTextureUnits + GL_TEXTURE0_ARB )) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerOutputNV passed bogus cdOutput: 0x%x", cdOutput ); + return; + } + if( sumOutput != GL_DISCARD_NV && sumOutput != GL_PRIMARY_COLOR_NV && sumOutput != GL_SECONDARY_COLOR_NV && sumOutput != GL_SPARE0_NV && sumOutput != GL_SPARE1_NV && sumOutput != GL_TEXTURE0_ARB && sumOutput != GL_TEXTURE1_ARB ) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerOutputNV passed bogus sumOutput: 0x%x", sumOutput ); + return; + } + if( scale != GL_NONE && scale != GL_SCALE_BY_TWO_NV && scale != GL_SCALE_BY_FOUR_NV && scale != GL_SCALE_BY_ONE_HALF_NV ) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "CombinerOutputNV passed bogus scale: 0x%x", scale ); + return; + } + if( bias != GL_NONE && bias != GL_BIAS_BY_NEGATIVE_ONE_HALF_NV ) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "CombinerOutputNV passed bogus bias: 0x%x", bias ); + return; + } + + if( bias == GL_BIAS_BY_NEGATIVE_ONE_HALF_NV && ( scale == GL_SCALE_BY_ONE_HALF_NV || scale == GL_SCALE_BY_FOUR_NV )) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "CombinerOutputNV can't accept bias of -1/2 if scale is by 1/2 or 4" ); + return; + } + if(( abOutput == cdOutput && abOutput != GL_DISCARD_NV )||( abOutput == sumOutput && abOutput != GL_DISCARD_NV )||( cdOutput == sumOutput && cdOutput != GL_DISCARD_NV )) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "CombinerOutputNV register output names must be unique unless discarded: abOutput = 0x%x, cdOutput = 0x%x, sumOutput = 0x%x", abOutput, cdOutput, sumOutput ); + return; + } + if( abDotProduct || cdDotProduct ) + { + if( portion == GL_ALPHA ) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "CombinerOutputNV can not do Dot Products when portion = GL_ALPHA" ); + return; + } + if( sumOutput != GL_DISCARD_NV ) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "CombinerOutputNV can not do Dot Products when sumOutput is not discarded" ); + return; + } + } + + stage -= GL_COMBINER0_NV; + if( portion == GL_RGB ) + { + r->rgb[stage].abOutput = abOutput; + r->rgb[stage].cdOutput = cdOutput; + r->rgb[stage].sumOutput = sumOutput; + r->rgb[stage].scale = scale; + r->rgb[stage].bias = bias; + r->rgb[stage].abDotProduct = abDotProduct; + r->rgb[stage].cdDotProduct = cdDotProduct; + r->rgb[stage].muxSum = muxSum; + } + else if( portion == GL_ALPHA ) + { + r->alpha[stage].abOutput = abOutput; + r->alpha[stage].cdOutput = cdOutput; + r->alpha[stage].sumOutput = sumOutput; + r->alpha[stage].scale = scale; + r->alpha[stage].bias = bias; + r->alpha[stage].abDotProduct = abDotProduct; + r->alpha[stage].cdDotProduct = cdDotProduct; + r->alpha[stage].muxSum = muxSum; + } + else + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerOutputNV passed bogus portion: 0x%x", portion ); + return; + } + + DIRTY(rb->regCombinerOutput[stage], g->neg_bitid); + DIRTY(rb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateFinalCombinerInputNV( GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage ) +{ + CRContext *g = GetCurrentContext(); + CRRegCombinerState *r = &(g->regcombiner); + CRStateBits *sb = GetCurrentBits(); + CRRegCombinerBits *rb = &(sb->regcombiner); + + if( input != GL_ZERO && input != GL_CONSTANT_COLOR0_NV && input != GL_CONSTANT_COLOR1_NV && input != GL_FOG && input != GL_PRIMARY_COLOR_NV && input != GL_SECONDARY_COLOR_NV && input != GL_SPARE0_NV && input != GL_SPARE1_NV && ( input < GL_TEXTURE0_ARB || input >= GL_TEXTURE0_ARB + g->limits.maxTextureUnits ) && input != GL_E_TIMES_F_NV && input != GL_SPARE0_PLUS_SECONDARY_COLOR_NV ) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "FinalCombinerInputNV passed bogus input: 0x%x", input ); + return; + } + if( mapping != GL_UNSIGNED_IDENTITY_NV && mapping != GL_UNSIGNED_INVERT_NV && mapping != GL_EXPAND_NORMAL_NV && mapping != GL_EXPAND_NEGATE_NV && mapping != GL_HALF_BIAS_NORMAL_NV && mapping != GL_HALF_BIAS_NEGATE_NV && mapping != GL_SIGNED_IDENTITY_NV && mapping != GL_SIGNED_NEGATE_NV ) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "FinalCombinerInputNV passed bogus mapping: 0x%x", mapping ); + return; + } + if( componentUsage != GL_RGB && componentUsage != GL_ALPHA && componentUsage != GL_BLUE ) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "FinalCombinerInputNV passed bogus componentUsage: 0x%x", componentUsage ); + return; + } + + if( componentUsage == GL_ALPHA && ( input == GL_E_TIMES_F_NV || input == GL_SPARE0_PLUS_SECONDARY_COLOR_NV )) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "FinalCombinerInputNV does not allow componentUsage of ALPHA when input is E_TIMES_F or SPARE0_PLUS_SECONDARY_COLOR" ); + return; + } + + switch( variable ) + { + case GL_VARIABLE_A_NV: + r->a = input; + r->aMapping = mapping; + r->aPortion = componentUsage; + break; + case GL_VARIABLE_B_NV: + r->b = input; + r->bMapping = mapping; + r->bPortion = componentUsage; + break; + case GL_VARIABLE_C_NV: + r->c = input; + r->cMapping = mapping; + r->cPortion = componentUsage; + break; + case GL_VARIABLE_D_NV: + r->d = input; + r->dMapping = mapping; + r->dPortion = componentUsage; + break; + case GL_VARIABLE_E_NV: + r->e = input; + r->eMapping = mapping; + r->ePortion = componentUsage; + break; + case GL_VARIABLE_F_NV: + r->f = input; + r->fMapping = mapping; + r->fPortion = componentUsage; + break; + case GL_VARIABLE_G_NV: + if( componentUsage != GL_ALPHA ) + { + crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "FinalCombinerInputNV can not have variable G when componentUsage is RGB or BLUE" ); + return; + } + r->g = input; + r->gMapping = mapping; + r->gPortion = componentUsage; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerOutputNV passed bogus variable: 0x%x", variable ); + return; + } + + DIRTY(rb->regCombinerFinalInput, g->neg_bitid); + DIRTY(rb->dirty, g->neg_bitid); +} + + +/* XXX Unfinished RegCombiner State functions */ +void STATE_APIENTRY crStateGetCombinerOutputParameterfvNV( GLenum stage, GLenum portion, GLenum pname, GLfloat *params ) +{ + (void) stage; + (void) portion; + (void) pname; + (void) params; +} + +void STATE_APIENTRY crStateGetCombinerOutputParameterivNV( GLenum stage, GLenum portion, GLenum pname, GLint *params ) +{ + (void) stage; + (void) portion; + (void) pname; + (void) params; +} + +void STATE_APIENTRY crStateGetFinalCombinerInputParameterfvNV( GLenum variable, GLenum pname, GLfloat *params ) +{ + (void) variable; + (void) pname; + (void) params; +} + +void STATE_APIENTRY crStateGetFinalCombinerInputParameterivNV( GLenum variable, GLenum pname, GLint *params ) +{ + (void) variable; + (void) pname; + (void) params; +} + + +void STATE_APIENTRY crStateGetCombinerInputParameterivNV( GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params ) +{ + CRContext *g = GetCurrentContext(); + CRRegCombinerState *r = &(g->regcombiner); + int i = stage - GL_COMBINER0_NV; + GLenum input = 0, mapping = 0, usage = 0; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetCombinerParameterivNV called in begin/end"); + return; + } + + if (i < 0 || i >= CR_MAX_GENERAL_COMBINERS) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "GetCombinerInputParameterivNV(stage=0x%x)", stage); + return; + } + + if (portion == GL_RGB) { + switch (variable) { + case GL_VARIABLE_A_NV: + input = r->rgb[i].a; + mapping = r->rgb[i].aMapping; + usage = r->rgb[i].aPortion; + break; + case GL_VARIABLE_B_NV: + input = r->rgb[i].b; + mapping = r->rgb[i].bMapping; + usage = r->rgb[i].bPortion; + break; + case GL_VARIABLE_C_NV: + input = r->rgb[i].c; + mapping = r->rgb[i].cMapping; + usage = r->rgb[i].cPortion; + break; + case GL_VARIABLE_D_NV: + input = r->rgb[i].d; + mapping = r->rgb[i].dMapping; + usage = r->rgb[i].dPortion; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetCombinerInputParameterivNV(variable=0x%x)", variable); + return; + } + } + else if (portion == GL_ALPHA) { + switch (variable) { + case GL_VARIABLE_A_NV: + input = r->alpha[i].a; + mapping = r->alpha[i].aMapping; + usage = r->alpha[i].aPortion; + break; + case GL_VARIABLE_B_NV: + input = r->alpha[i].b; + mapping = r->alpha[i].bMapping; + usage = r->alpha[i].bPortion; + break; + case GL_VARIABLE_C_NV: + input = r->alpha[i].c; + mapping = r->alpha[i].cMapping; + usage = r->alpha[i].cPortion; + break; + case GL_VARIABLE_D_NV: + input = r->alpha[i].d; + mapping = r->alpha[i].dMapping; + usage = r->alpha[i].dPortion; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetCombinerInputParameterivNV(variable=0x%x)", variable); + return; + } + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetCombinerInputParameterivNV(portion=0x%x)", portion); + } + switch (pname) { + case GL_COMBINER_INPUT_NV: + *params = input; + return; + case GL_COMBINER_MAPPING_NV: + *params = mapping; + return; + case GL_COMBINER_COMPONENT_USAGE_NV: + *params = usage; + return; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetCombinerInputParameterivNV(pname=0x%x)", pname); + return; + } +} + + +void STATE_APIENTRY crStateGetCombinerInputParameterfvNV( GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params ) +{ + GLint iparams; + crStateGetCombinerInputParameterivNV(stage, portion, variable, pname, &iparams); + *params = (GLfloat) iparams; +} + + +void STATE_APIENTRY crStateCombinerStageParameterfvNV( GLenum stage, GLenum pname, const GLfloat *params ) +{ + CRContext *g = GetCurrentContext(); + CRRegCombinerState *r = &(g->regcombiner); + CRStateBits *sb = GetCurrentBits(); + CRRegCombinerBits *rb = &(sb->regcombiner); + + stage -= GL_COMBINER0_NV; + if( stage >= g->limits.maxGeneralCombiners ) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "CombinerStageParameterfvNV passed bogus stage: 0x%x", stage+GL_COMBINER0_NV ); + return; + } + + switch( pname ) + { + case GL_CONSTANT_COLOR0_NV: + r->stageConstantColor0[stage].r = params[0]; + r->stageConstantColor0[stage].g = params[1]; + r->stageConstantColor0[stage].b = params[2]; + r->stageConstantColor0[stage].a = params[3]; + DIRTY(rb->regCombinerStageColor0[stage], g->neg_bitid); + break; + case GL_CONSTANT_COLOR1_NV: + r->stageConstantColor1[stage].r = params[0]; + r->stageConstantColor1[stage].g = params[1]; + r->stageConstantColor1[stage].b = params[2]; + r->stageConstantColor1[stage].a = params[3]; + DIRTY(rb->regCombinerStageColor1[stage], g->neg_bitid); + break; + default: + crStateError( __LINE__, __FILE__, GL_INVALID_ENUM, "CombinerStageParameter passed bogus pname: 0x%x", pname ); + return; + } + + DIRTY(rb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateGetCombinerStageParameterfvNV( GLenum stage, GLenum pname, GLfloat *params ) +{ + CRContext *g = GetCurrentContext(); + CRRegCombinerState *r = &(g->regcombiner); + + stage -= GL_COMBINER0_NV; + if( stage >= g->limits.maxGeneralCombiners ) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "GetCombinerStageParameterfvNV passed bogus stage: 0x%x", stage+GL_COMBINER0_NV ); + return; + } + switch( pname ) + { + case GL_CONSTANT_COLOR0_NV: + params[0] = r->stageConstantColor0[stage].r; + params[1] = r->stageConstantColor0[stage].g; + params[2] = r->stageConstantColor0[stage].b; + params[3] = r->stageConstantColor0[stage].a; + break; + case GL_CONSTANT_COLOR1_NV: + params[0] = r->stageConstantColor1[stage].r; + params[1] = r->stageConstantColor1[stage].g; + params[2] = r->stageConstantColor1[stage].b; + params[3] = r->stageConstantColor1[stage].a; + break; + default: + crStateError( __LINE__, __FILE__, GL_INVALID_ENUM, "GetCombinerStageParameter passed bogus pname: 0x%x", pname ); + return; + } + return; +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_regcombiner.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_regcombiner.txt new file mode 100644 index 00000000..4b867ee5 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_regcombiner.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +:enable:enabledRegCombiners:GL_REGISTER_COMBINERS_NV +:enable:enabledPerStageConstants:GL_PER_STAGE_CONSTANTS_NV +%flush +:regCombinerVars:numGeneralCombiners:CombinerParameteriNV, GL_NUM_GENERAL_COMBINERS_NV +:regCombinerVars:colorSumClamp:CombinerParameteriNV, GL_COLOR_SUM_CLAMP_NV +:regCombinerColor0:constantColor0|r,g,b,a:CombinerParameterfvNV, GL_CONSTANT_COLOR0_NV +:regCombinerColor1:constantColor1|r,g,b,a:CombinerParameterfvNV, GL_CONSTANT_COLOR1_NV +%flush +>for( i=0; i<CR_MAX_GENERAL_COMBINERS; i++ ) { +:regCombinerStageColor0[i]:stageConstantColor0[i]|r,g,b,a:CombinerStageParameterfvNV, GL_COMBINER0_NV+i, GL_CONSTANT_COLOR0_NV +:regCombinerStageColor1[i]:stageConstantColor1[i]|r,g,b,a:CombinerStageParameterfvNV, GL_COMBINER0_NV+i, GL_CONSTANT_COLOR1_NV +:regCombinerInput[i]:rgb[i].a,rgb[i].aMapping,rgb[i].aPortion:*diff_api.CombinerInputNV( GL_COMBINER0_NV+i, GL_RGB, GL_VARIABLE_A_NV, to->rgb[i].a, to->rgb[i].aMapping, to->rgb[i].aPortion ); +:regCombinerInput[i]:rgb[i].b,rgb[i].bMapping,rgb[i].bPortion:*diff_api.CombinerInputNV( GL_COMBINER0_NV+i, GL_RGB, GL_VARIABLE_B_NV, to->rgb[i].b, to->rgb[i].bMapping, to->rgb[i].bPortion ); +:regCombinerInput[i]:rgb[i].c,rgb[i].cMapping,rgb[i].cPortion:*diff_api.CombinerInputNV( GL_COMBINER0_NV+i, GL_RGB, GL_VARIABLE_C_NV, to->rgb[i].c, to->rgb[i].cMapping, to->rgb[i].cPortion ); +:regCombinerInput[i]:rgb[i].d,rgb[i].dMapping,rgb[i].dPortion:*diff_api.CombinerInputNV( GL_COMBINER0_NV+i, GL_RGB, GL_VARIABLE_D_NV, to->rgb[i].d, to->rgb[i].dMapping, to->rgb[i].dPortion ); +:regCombinerInput[i]:alpha[i].a,alpha[i].aMapping,alpha[i].aPortion:*diff_api.CombinerInputNV( GL_COMBINER0_NV+i, GL_ALPHA, GL_VARIABLE_A_NV, to->alpha[i].a, to->alpha[i].aMapping, to->alpha[i].aPortion ); +:regCombinerInput[i]:alpha[i].b,alpha[i].bMapping,alpha[i].bPortion:*diff_api.CombinerInputNV( GL_COMBINER0_NV+i, GL_ALPHA, GL_VARIABLE_B_NV, to->alpha[i].b, to->alpha[i].bMapping, to->alpha[i].bPortion ); +:regCombinerInput[i]:alpha[i].c,alpha[i].cMapping,alpha[i].cPortion:*diff_api.CombinerInputNV( GL_COMBINER0_NV+i, GL_ALPHA, GL_VARIABLE_C_NV, to->alpha[i].c, to->alpha[i].cMapping, to->alpha[i].cPortion ); +:regCombinerInput[i]:alpha[i].d,alpha[i].dMapping,alpha[i].dPortion:*diff_api.CombinerInputNV( GL_COMBINER0_NV+i, GL_ALPHA, GL_VARIABLE_D_NV, to->alpha[i].d, to->alpha[i].dMapping, to->alpha[i].dPortion ); +:regCombinerOutput[i]:rgb[i]|abOutput,cdOutput,sumOutput,scale,bias,abDotProduct,cdDotProduct,muxSum:*diff_api.CombinerOutputNV( GL_COMBINER0_NV+i, GL_RGB, to->rgb[i].abOutput, to->rgb[i].cdOutput, to->rgb[i].sumOutput, to->rgb[i].scale, to->rgb[i].bias, to->rgb[i].abDotProduct, to->rgb[i].cdDotProduct, to->rgb[i].muxSum ); +:regCombinerOutput[i]:alpha[i]|abOutput,cdOutput,sumOutput,scale,bias,abDotProduct,cdDotProduct,muxSum:*diff_api.CombinerOutputNV( GL_COMBINER0_NV+i, GL_ALPHA, to->alpha[i].abOutput, to->alpha[i].cdOutput, to->alpha[i].sumOutput, to->alpha[i].scale, to->alpha[i].bias, to->alpha[i].abDotProduct, to->alpha[i].cdDotProduct, to->alpha[i].muxSum ); +%flush +>} +:regCombinerFinalInput:a,aMapping,aPortion:*diff_api.FinalCombinerInputNV( GL_VARIABLE_A_NV, to->a, to->aMapping, to->aPortion ); +:regCombinerFinalInput:b,bMapping,bPortion:*diff_api.FinalCombinerInputNV( GL_VARIABLE_B_NV, to->b, to->bMapping, to->bPortion ); +:regCombinerFinalInput:c,cMapping,cPortion:*diff_api.FinalCombinerInputNV( GL_VARIABLE_C_NV, to->c, to->cMapping, to->cPortion ); +:regCombinerFinalInput:d,dMapping,dPortion:*diff_api.FinalCombinerInputNV( GL_VARIABLE_D_NV, to->d, to->dMapping, to->dPortion ); +:regCombinerFinalInput:e,eMapping,ePortion:*diff_api.FinalCombinerInputNV( GL_VARIABLE_E_NV, to->e, to->eMapping, to->ePortion ); +:regCombinerFinalInput:f,fMapping,fPortion:*diff_api.FinalCombinerInputNV( GL_VARIABLE_F_NV, to->f, to->fMapping, to->fPortion ); +:regCombinerFinalInput:g,gMapping,gPortion:*diff_api.FinalCombinerInputNV( GL_VARIABLE_G_NV, to->g, to->gMapping, to->gPortion ); +%flush +%target=to +%current=from +%bit=b diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_select_special b/src/VBox/GuestHost/OpenGL/state_tracker/state_select_special new file mode 100644 index 00000000..e7b41e36 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_select_special @@ -0,0 +1,61 @@ +Vertex4f +Begin +End +Vertex2d +Vertex2dv +Vertex2f +Vertex2fv +Vertex2i +Vertex2iv +Vertex2s +Vertex2sv +Vertex3d +Vertex3dv +Vertex3f +Vertex3fv +Vertex3i +Vertex3iv +Vertex3s +Vertex3sv +Vertex4d +Vertex4dv +Vertex4fv +Vertex4i +Vertex4iv +Vertex4s +Vertex4sv +Rectf +Recti +Rectd +Rects +Rectiv +Rectfv +Rectdv +Rectsv +DrawPixels +CopyPixels +Bitmap +RasterPos2d +RasterPos2dv +RasterPos2f +RasterPos2fv +RasterPos2i +RasterPos2iv +RasterPos2s +RasterPos2sv +RasterPos3d +RasterPos3dv +RasterPos3f +RasterPos3fv +RasterPos3i +RasterPos3iv +RasterPos3s +RasterPos3sv +RasterPos4d +RasterPos4dv +RasterPos4f +RasterPos4fv +RasterPos4i +RasterPos4iv +RasterPos4s +RasterPos4sv diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c new file mode 100644 index 00000000..ee17cd37 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c @@ -0,0 +1,2678 @@ +/* $Id: state_snapshot.c $ */ +/** @file + * VBox Context state saving/loading used by VM snapshot + */ + +/* + * Copyright (C) 2008-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#include "state.h" +#include "state_internals.h" +#include "state/cr_statetypes.h" +#include "state/cr_texture.h" +#include "cr_mem.h" +#include "cr_string.h" +#include "cr_pixeldata.h" +#include <stdio.h> + +#include <iprt/assert.h> +#include <iprt/types.h> +#include <iprt/err.h> +#include <VBox/err.h> +#include <VBox/log.h> + +/** @todo + * We have two ways of saving/loading states. + * + * First which is being used atm, just pure saving/loading of structures. + * The drawback is we have to deal with all the pointers around those structures, + * we'd have to update this code if we'd change state tracking. + * On the bright side it's fast, though it's not really needed as it's not that often operation. + * It could also worth to split those functions into appropriate parts, + * similar to the way context creation is being done. + * + * Second way would be to implement full dispatch api table and substitute diff_api during saving/loading. + * Then if we implement that api in a similar way to packer/unpacker with a change to store/load + * via provided pSSM handle instead of pack buffer, + * saving state could be done by simple diffing against empty "dummy" context. + * Restoring state in such case would look like unpacking commands from pSSM instead of network buffer. + * This would be slower (who cares) but most likely will not require any code changes to support in future. + * We will reduce amount of saved data as we'd save only changed state parts, but I doubt it'd be that much. + * It could be done for the first way as well, but requires tons of bit checks. + */ + +static int32_t crStateAllocAndSSMR3GetMem(PSSMHANDLE pSSM, void **pBuffer, size_t cbBuffer) +{ + CRASSERT(pSSM && pBuffer && cbBuffer>0); + + *pBuffer = crAlloc((unsigned int /* this case is just so stupid */)cbBuffer); + if (!*pBuffer) + return VERR_NO_MEMORY; + + return SSMR3GetMem(pSSM, *pBuffer, cbBuffer); +} + +#define SHCROGL_GET_STRUCT_PART(_pPtr, _type, _from, _to) do { \ + rc = SSMR3GetMem(pSSM, &(_pPtr)->_from, RT_UOFFSETOF(_type, _to) - RT_UOFFSETOF(_type, _from)); \ + AssertRCReturn(rc, rc); \ + } while (0) + +#define SHCROGL_GET_STRUCT_TAIL(_pPtr, _type, _from) do { \ + rc = SSMR3GetMem(pSSM, &(_pPtr)->_from, sizeof (_type) - RT_UOFFSETOF(_type, _from)); \ + AssertRCReturn(rc, rc); \ + } while (0) + +#define SHCROGL_GET_STRUCT_HEAD(_pPtr, _type, _to) do { \ + rc = SSMR3GetMem(pSSM, (_pPtr), RT_UOFFSETOF(_type, _to)); \ + AssertRCReturn(rc, rc); \ + } while (0) + +#define SHCROGL_CUT_FIELD_ALIGNMENT_SIZE(_type, _prevField, _field) (RT_UOFFSETOF(_type, _field) - RT_UOFFSETOF(_type, _prevField) - RT_SIZEOFMEMB(_type, _prevField)) +#define SHCROGL_CUT_FIELD_ALIGNMENT(_type, _prevField, _field) do { \ + const int32_t cbAlignment = SHCROGL_CUT_FIELD_ALIGNMENT_SIZE(_type, _prevField, _field) ; \ + /*AssertCompile(SHCROGL_CUT_FIELD_ALIGNMENT_SIZE(_type, _prevField, _field) >= 0 && SHCROGL_CUT_FIELD_ALIGNMENT_SIZE(_type, _prevField, _field) < sizeof (void*));*/ \ + if (cbAlignment) { \ + rc = SSMR3Skip(pSSM, cbAlignment); \ + } \ + } while (0) + +#define SHCROGL_ROUNDBOUND(_v, _b) (((_v) + ((_b) - 1)) & ~((_b) - 1)) +#define SHCROGL_ALIGNTAILSIZE(_v, _b) (SHCROGL_ROUNDBOUND((_v),(_b)) - (_v)) +#define SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT_SIZE(_type, _field, _oldFieldType, _nextFieldAllignment) (SHCROGL_ALIGNTAILSIZE(((RT_UOFFSETOF(_type, _field) + sizeof (_oldFieldType))), (_nextFieldAllignment))) +#define SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT(_type, _field, _oldFieldType, _nextFieldAllignment) do { \ + const int32_t cbAlignment = SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT_SIZE(_type, _field, _oldFieldType, _nextFieldAllignment); \ + /*AssertCompile(SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField) >= 0 && SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField) < sizeof (void*));*/ \ + if (cbAlignment) { \ + rc = SSMR3Skip(pSSM, cbAlignment); \ + } \ + } while (0) + + +#define SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField) (sizeof (_type) - RT_UOFFSETOF(_type, _lastField) - RT_SIZEOFMEMB(_type, _lastField)) +#define SHCROGL_CUT_TAIL_ALIGNMENT(_type, _lastField) do { \ + const int32_t cbAlignment = SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField); \ + /*AssertCompile(SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField) >= 0 && SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField) < sizeof (void*));*/ \ + if (cbAlignment) { \ + rc = SSMR3Skip(pSSM, cbAlignment); \ + } \ + } while (0) + +static int32_t crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(CRTextureObj *pTexture, PSSMHANDLE pSSM) +{ + int32_t rc; + uint32_t cbObj = RT_UOFFSETOF(CRTextureObj, ctxUsage); + cbObj = ((cbObj + sizeof (void*) - 1) & ~(sizeof (void*) - 1)); + rc = SSMR3GetMem(pSSM, pTexture, cbObj); + AssertRCReturn(rc, rc); + /* just make all bits are used so that we fall back to the pre-ctxUsage behavior, + * i.e. all shared resources will be destructed on last shared context termination */ + FILLDIRTY(pTexture->ctxUsage); + return rc; +} + +static int32_t crStateLoadTextureUnit_v_BEFORE_CTXUSAGE_BITS(CRTextureUnit *t, PSSMHANDLE pSSM) +{ + int32_t rc; + SHCROGL_GET_STRUCT_HEAD(t, CRTextureUnit, Saved1D); + rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->Saved1D, pSSM); + AssertRCReturn(rc, rc); + SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureUnit, Saved1D, Saved2D); + rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->Saved2D, pSSM); + AssertRCReturn(rc, rc); + SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureUnit, Saved2D, Saved3D); + rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->Saved3D, pSSM); + AssertRCReturn(rc, rc); +#ifdef CR_ARB_texture_cube_map + SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureUnit, Saved3D, SavedCubeMap); + rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->SavedCubeMap, pSSM); + AssertRCReturn(rc, rc); +# define SHCROGL_INTERNAL_LAST_FIELD SavedCubeMap +#else +# define SHCROGL_INTERNAL_LAST_FIELD Saved3D +#endif +#ifdef CR_NV_texture_rectangle + SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureUnit, SHCROGL_INTERNAL_LAST_FIELD, SavedRect); + rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->SavedRect, pSSM); + AssertRCReturn(rc, rc); +# undef SHCROGL_INTERNAL_LAST_FIELD +# define SHCROGL_INTERNAL_LAST_FIELD SavedRect +#endif + SHCROGL_CUT_TAIL_ALIGNMENT(CRTextureUnit, SHCROGL_INTERNAL_LAST_FIELD); +#undef SHCROGL_INTERNAL_LAST_FIELD + return rc; +} + +static int crStateLoadStencilPoint_v_37(CRPointState *pPoint, PSSMHANDLE pSSM) +{ + int rc = VINF_SUCCESS; + SHCROGL_GET_STRUCT_HEAD(pPoint, CRPointState, spriteCoordOrigin); + pPoint->spriteCoordOrigin = (GLfloat)GL_UPPER_LEFT; + return rc; +} + +static int32_t crStateLoadStencilState_v_33(CRStencilState *s, PSSMHANDLE pSSM) +{ + CRStencilState_v_33 stencilV33; + int32_t rc = SSMR3GetMem(pSSM, &stencilV33, sizeof (stencilV33)); + AssertRCReturn(rc, rc); + s->stencilTest = stencilV33.stencilTest; + s->stencilTwoSideEXT = GL_FALSE; + s->activeStencilFace = GL_FRONT; + s->clearValue = stencilV33.clearValue; + s->writeMask = stencilV33.writeMask; + s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func = stencilV33.func; + s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask = stencilV33.mask; + s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref = stencilV33.ref; + s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail = stencilV33.fail; + s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail = stencilV33.passDepthFail; + s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass = stencilV33.passDepthPass; + s->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK] = s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT]; + crStateStencilBufferInit(&s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK]); + return VINF_SUCCESS; +} + +static int32_t crStateLoadTextureState_v_BEFORE_CTXUSAGE_BITS(CRTextureState *t, PSSMHANDLE pSSM) +{ + GLint i; + int32_t rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->base1D, pSSM); + AssertRCReturn(rc, rc); + SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, base1D, base2D); + rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->base2D, pSSM); + AssertRCReturn(rc, rc); + rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->base3D, pSSM); + SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, base2D, base3D); + AssertRCReturn(rc, rc); +#ifdef CR_ARB_texture_cube_map + SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, base3D, baseCubeMap); + rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->baseCubeMap, pSSM); + AssertRCReturn(rc, rc); +# define SHCROGL_INTERNAL_LAST_FIELD baseCubeMap +#else +# define SHCROGL_INTERNAL_LAST_FIELD base3D +#endif +#ifdef CR_NV_texture_rectangle + SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, SHCROGL_INTERNAL_LAST_FIELD, baseRect); + rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->baseRect, pSSM); + AssertRCReturn(rc, rc); +# undef SHCROGL_INTERNAL_LAST_FIELD +# define SHCROGL_INTERNAL_LAST_FIELD baseRect +#endif + SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, SHCROGL_INTERNAL_LAST_FIELD, proxy1D); + rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->proxy1D, pSSM); + AssertRCReturn(rc, rc); +#undef SHCROGL_INTERNAL_LAST_FIELD + SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, proxy1D, proxy2D); + rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->proxy2D, pSSM); + AssertRCReturn(rc, rc); + SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, proxy2D, proxy3D); + rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->proxy3D, pSSM); + AssertRCReturn(rc, rc); +#ifdef CR_ARB_texture_cube_map + SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, proxy3D, proxyCubeMap); + rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->proxyCubeMap, pSSM); + AssertRCReturn(rc, rc); +# define SHCROGL_INTERNAL_LAST_FIELD proxyCubeMap +#else +# define SHCROGL_INTERNAL_LAST_FIELD proxy3D +#endif +#ifdef CR_NV_texture_rectangle + SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, SHCROGL_INTERNAL_LAST_FIELD, proxyRect); + rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->proxyRect, pSSM); + AssertRCReturn(rc, rc); +# undef SHCROGL_INTERNAL_LAST_FIELD +# define SHCROGL_INTERNAL_LAST_FIELD proxyRect +#endif + SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, SHCROGL_INTERNAL_LAST_FIELD, curTextureUnit); +# undef SHCROGL_INTERNAL_LAST_FIELD + SHCROGL_GET_STRUCT_PART(t, CRTextureState, curTextureUnit, unit); + + for (i = 0; i < CR_MAX_TEXTURE_UNITS; ++i) + { + rc = crStateLoadTextureUnit_v_BEFORE_CTXUSAGE_BITS(&t->unit[i], pSSM); + AssertRCReturn(rc, rc); + } + + SHCROGL_CUT_TAIL_ALIGNMENT(CRTextureState, unit); + + return VINF_SUCCESS; +} + +static int32_t crStateStencilBufferStack_v_33(CRStencilBufferStack *s, PSSMHANDLE pSSM) +{ + CRStencilBufferStack_v_33 stackV33; + int32_t rc = SSMR3GetMem(pSSM, &stackV33, sizeof(stackV33)); + AssertLogRelReturn(rc, rc); + + s->stencilTest = stackV33.stencilTest; + s->stencilTwoSideEXT = GL_FALSE; + s->activeStencilFace = GL_FRONT; + s->clearValue = stackV33.clearValue; + s->writeMask = stackV33.writeMask; + s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func = stackV33.func; + s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask = stackV33.mask; + s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref = stackV33.ref; + s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail = stackV33.fail; + s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail = stackV33.passDepthFail; + s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass = stackV33.passDepthPass; + s->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK] = s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT]; + + s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].func = GL_ALWAYS; + s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].mask = 0xFFFFFFFF; + s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].ref = 0; + s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].fail = GL_KEEP; + s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthFail = GL_KEEP; + s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthPass = GL_KEEP; + + return VINF_SUCCESS; +} + +static int32_t crStateLoadAttribState_v_33(CRAttribState *t, PSSMHANDLE pSSM) +{ + int32_t i, rc; + SHCROGL_GET_STRUCT_HEAD(t, CRAttribState, stencilBufferStack); + for (i = 0; i < CR_MAX_ATTRIB_STACK_DEPTH; ++i) + { + rc = crStateStencilBufferStack_v_33(&t->stencilBufferStack[i], pSSM); + AssertRCReturn(rc, rc); + } + SHCROGL_GET_STRUCT_TAIL(t, CRAttribState, textureStackDepth); + return rc; +} + +static int32_t crStateLoadTextureStack_v_BEFORE_CTXUSAGE_BITS(CRTextureStack *t, PSSMHANDLE pSSM) +{ + int32_t i, rc; + SHCROGL_GET_STRUCT_HEAD(t, CRTextureStack, unit); + for (i = 0; i < CR_MAX_TEXTURE_UNITS; ++i) + { + rc = crStateLoadTextureUnit_v_BEFORE_CTXUSAGE_BITS(&t->unit[i], pSSM); + AssertRCReturn(rc, rc); + } + SHCROGL_CUT_TAIL_ALIGNMENT(CRTextureStack, unit); + return rc; +} + +static int32_t crStateLoadAttribState_v_BEFORE_CTXUSAGE_BITS(CRAttribState *t, PSSMHANDLE pSSM) +{ + int32_t i, rc; + + SHCROGL_GET_STRUCT_HEAD(t, CRAttribState, stencilBufferStack); + for (i = 0; i < CR_MAX_ATTRIB_STACK_DEPTH; ++i) + { + rc = crStateStencilBufferStack_v_33(&t->stencilBufferStack[i], pSSM); + AssertRCReturn(rc, rc); + } + SHCROGL_GET_STRUCT_PART(t, CRAttribState, textureStackDepth, textureStack); + for (i = 0; i < CR_MAX_ATTRIB_STACK_DEPTH; ++i) + { + rc = crStateLoadTextureStack_v_BEFORE_CTXUSAGE_BITS(&t->textureStack[i], pSSM); + AssertRCReturn(rc, rc); + } + SHCROGL_GET_STRUCT_TAIL(t, CRAttribState, transformStackDepth); + return rc; +} + + +static int32_t crStateLoadTextureObj(CRTextureObj *pTexture, PSSMHANDLE pSSM, uint32_t u32Version) +{ + int32_t rc; + if (u32Version == SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS) + return crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(pTexture, pSSM); + rc = SSMR3GetMem(pSSM, pTexture, sizeof (*pTexture)); + AssertRCReturn(rc, rc); + return rc; +} + +static int32_t crStateLoadBufferObject(CRBufferObject *pBufferObj, PSSMHANDLE pSSM, uint32_t u32Version) +{ + int32_t rc; + if (u32Version == SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS) + { + uint32_t cbObj = RT_UOFFSETOF(CRBufferObject, ctxUsage); + cbObj = ((cbObj + sizeof (void*) - 1) & ~(sizeof (void*) - 1)); + rc = SSMR3GetMem(pSSM, pBufferObj, cbObj); + AssertRCReturn(rc, rc); + /* just make all bits are used so that we fall back to the pre-ctxUsage behavior, + * i.e. all shared resources will be destructed on last shared context termination */ + FILLDIRTY(pBufferObj->ctxUsage); + } + else + { + rc = SSMR3GetMem(pSSM, pBufferObj, sizeof(*pBufferObj)); + AssertRCReturn(rc, rc); + } + return rc; +} + +static int32_t crStateLoadFramebufferObject(CRFramebufferObject *pFBO, PSSMHANDLE pSSM, uint32_t u32Version) +{ + int32_t rc; + if (u32Version == SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS) + { + uint32_t cbObj = RT_UOFFSETOF(CRFramebufferObject, ctxUsage); + cbObj = ((cbObj + sizeof (void*) - 1) & ~(sizeof (void*) - 1)); + rc = SSMR3GetMem(pSSM, pFBO, cbObj); + AssertRCReturn(rc, rc); + /* just make all bits are used so that we fall back to the pre-ctxUsage behavior, + * i.e. all shared resources will be destructed on last shared context termination */ + FILLDIRTY(pFBO->ctxUsage); + } + else + { + rc = SSMR3GetMem(pSSM, pFBO, sizeof(*pFBO)); + AssertRCReturn(rc, rc); + } + return rc; +} + +static int32_t crStateLoadRenderbufferObject(CRRenderbufferObject *pRBO, PSSMHANDLE pSSM, uint32_t u32Version) +{ + int32_t rc; + if (u32Version == SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS) + { + uint32_t cbObj = RT_UOFFSETOF(CRRenderbufferObject, ctxUsage); + cbObj = ((cbObj + sizeof (void*) - 1) & ~(sizeof (void*) - 1)); + rc = SSMR3GetMem(pSSM, pRBO, cbObj); + AssertRCReturn(rc, rc); + /* just make all bits are used so that we fall back to the pre-ctxUsage behavior, + * i.e. all shared resources will be destructed on last shared context termination */ + FILLDIRTY(pRBO->ctxUsage); + } + else + { + rc = SSMR3GetMem(pSSM, pRBO, sizeof(*pRBO)); + AssertRCReturn(rc, rc); + } + return rc; +} + +static int32_t crStateSaveTextureObjData(CRTextureObj *pTexture, PSSMHANDLE pSSM) +{ + int32_t rc, face, i; + GLint bound = 0; + + CRASSERT(pTexture && pSSM); + + crDebug("crStateSaveTextureObjData %u. START", pTexture->id); + + for (face = 0; face < 6; face++) { + CRASSERT(pTexture->level[face]); + + for (i = 0; i < CR_MAX_MIPMAP_LEVELS; i++) { + CRTextureLevel *ptl = &(pTexture->level[face][i]); + rc = SSMR3PutMem(pSSM, ptl, sizeof(*ptl)); + AssertRCReturn(rc, rc); + if (ptl->img) + { + CRASSERT(ptl->bytes); + rc = SSMR3PutMem(pSSM, ptl->img, ptl->bytes); + AssertRCReturn(rc, rc); + } +#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE + /* Note, this is not a bug. + * Even with CR_STATE_NO_TEXTURE_IMAGE_STORE defined, it's possible that ptl->img!=NULL. + * For ex. we're saving snapshot right after it was loaded + * and some context hasn't been used by the guest application yet + * (pContext->shared->bTexResyncNeeded==GL_TRUE). + */ + else if (ptl->bytes) + { + char *pImg; + GLenum target; + + if (!bound) + { + GLenum getEnum; + diff_api.BindTexture(pTexture->target, pTexture->hwid); + bound = 1; + + /* osx nvidia drivers seem to have a bug that 1x1 TEXTURE_2D texture becmes inaccessible for some reason + * saw that for 1x1 dummy textures generated by wine + * to avoid crashes we skip texture data save if that is the case */ + switch (pTexture->target) + { + case GL_TEXTURE_1D: + getEnum = GL_TEXTURE_BINDING_1D; + break; + case GL_TEXTURE_2D: + getEnum = GL_TEXTURE_BINDING_2D; + break; + case GL_TEXTURE_3D: + getEnum = GL_TEXTURE_BINDING_3D; + break; + case GL_TEXTURE_RECTANGLE_ARB: + getEnum = GL_TEXTURE_BINDING_RECTANGLE_ARB; + break; + case GL_TEXTURE_CUBE_MAP_ARB: + getEnum = GL_TEXTURE_BINDING_CUBE_MAP_ARB; + break; + default: + crWarning("unknown texture target: 0x%x", pTexture->target); + getEnum = 0; + break; + } + + if (getEnum) + { + GLint curTex; + diff_api.GetIntegerv(getEnum, &curTex); + if ((GLuint)curTex != pTexture->hwid) + { + crWarning("texture not bound properly: expected %d, but was %d. Texture state data: target(0x%x), id(%d), w(%d), h(%d)", + pTexture->hwid, curTex, + pTexture->target, + pTexture->id, + ptl->width, + ptl->height); + bound = -1; + } + } + + } + + if (pTexture->target!=GL_TEXTURE_CUBE_MAP_ARB) + { + target = pTexture->target; + } + else + { + target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face; + } + +#ifdef DEBUG + pImg = crAlloc(ptl->bytes+4); +#else + pImg = crAlloc(ptl->bytes); +#endif + if (!pImg) return VERR_NO_MEMORY; + +#ifdef DEBUG + *(int*)((char*)pImg+ptl->bytes) = 0xDEADDEAD; +#endif + if (bound > 0) + { +#ifdef DEBUG + { + GLint w,h=0; + crDebug("get image: compressed %i, face %i, level %i, width %i, height %i, bytes %i", + ptl->compressed, face, i, ptl->width, ptl->height, ptl->bytes); + diff_api.GetTexLevelParameteriv(target, i, GL_TEXTURE_WIDTH, &w); + diff_api.GetTexLevelParameteriv(target, i, GL_TEXTURE_HEIGHT, &h); + if (w!=ptl->width || h!=ptl->height) + { + crWarning("!!!tex size mismatch %i, %i!!!", w, h); + } + } +#endif + + /** @todo ugly workaround for crashes inside ati driver, + * they overwrite their own allocated memory in cases where texlevel >=4 + and width or height <=2. + */ + if (i<4 || (ptl->width>2 && ptl->height>2)) + { + if (!ptl->compressed) + { + diff_api.GetTexImage(target, i, ptl->format, ptl->type, pImg); + } + else + { + diff_api.GetCompressedTexImageARB(target, i, pImg); + } + } + } + else + { + crMemset(pImg, 0, ptl->bytes); + } + +#ifdef DEBUG + if (*(int*)((char*)pImg+ptl->bytes) != 0xDEADDEAD) + { + crWarning("Texture is bigger than expected!!!"); + } +#endif + + rc = SSMR3PutMem(pSSM, pImg, ptl->bytes); + crFree(pImg); + AssertRCReturn(rc, rc); + } +#endif + } + } + + crDebug("crStateSaveTextureObjData %u. END", pTexture->id); + + return VINF_SUCCESS; +} + +static int32_t crStateLoadTextureObjData(CRTextureObj *pTexture, PSSMHANDLE pSSM) +{ + int32_t rc, face, i; + + CRASSERT(pTexture && pSSM); + + for (face = 0; face < 6; face++) { + CRASSERT(pTexture->level[face]); + + for (i = 0; i < CR_MAX_MIPMAP_LEVELS; i++) { + CRTextureLevel *ptl = &(pTexture->level[face][i]); + CRASSERT(!ptl->img); + + rc = SSMR3GetMem(pSSM, ptl, sizeof(*ptl)); + AssertRCReturn(rc, rc); + if (ptl->img) + { + CRASSERT(ptl->bytes); + + ptl->img = crAlloc(ptl->bytes); + if (!ptl->img) return VERR_NO_MEMORY; + + rc = SSMR3GetMem(pSSM, ptl->img, ptl->bytes); + AssertRCReturn(rc, rc); + } +#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE + /* Same story as in crStateSaveTextureObjData */ + else if (ptl->bytes) + { + ptl->img = crAlloc(ptl->bytes); + if (!ptl->img) return VERR_NO_MEMORY; + + rc = SSMR3GetMem(pSSM, ptl->img, ptl->bytes); + AssertRCReturn(rc, rc); + } +#endif + crStateTextureInitTextureFormat(ptl, ptl->internalFormat); + } + } + + return VINF_SUCCESS; +} + +static void crStateSaveSharedTextureCB(unsigned long key, void *data1, void *data2) +{ + CRTextureObj *pTexture = (CRTextureObj *) data1; + PSSMHANDLE pSSM = (PSSMHANDLE) data2; + int32_t rc; + + CRASSERT(pTexture && pSSM); + + rc = SSMR3PutMem(pSSM, &key, sizeof(key)); + CRASSERT(rc == VINF_SUCCESS); + rc = SSMR3PutMem(pSSM, pTexture, sizeof(*pTexture)); + CRASSERT(rc == VINF_SUCCESS); + rc = crStateSaveTextureObjData(pTexture, pSSM); + CRASSERT(rc == VINF_SUCCESS); +} + +static int32_t crStateSaveMatrixStack(CRMatrixStack *pStack, PSSMHANDLE pSSM) +{ + return SSMR3PutMem(pSSM, pStack->stack, sizeof(CRmatrix) * pStack->maxDepth); +} + +static int32_t crStateLoadMatrixStack(CRMatrixStack *pStack, PSSMHANDLE pSSM) +{ + int32_t rc; + + CRASSERT(pStack && pSSM); + + rc = SSMR3GetMem(pSSM, pStack->stack, sizeof(CRmatrix) * pStack->maxDepth); + /* fixup stack top pointer */ + pStack->top = &pStack->stack[pStack->depth]; + return rc; +} + +static int32_t crStateSaveTextureObjPtr(CRTextureObj *pTexture, PSSMHANDLE pSSM) +{ + /* Current texture pointer can't be NULL for real texture unit states, + * but it could be NULL for unused attribute stack depths. + */ + if (pTexture) + return SSMR3PutU32(pSSM, pTexture->id); + else + return VINF_SUCCESS; +} + +static int32_t crStateLoadTextureObjPtr(CRTextureObj **pTexture, CRContext *pContext, GLenum target, PSSMHANDLE pSSM) +{ + uint32_t texName; + int32_t rc; + + /* We're loading attrib stack with unused state */ + if (!*pTexture) + return VINF_SUCCESS; + + rc = SSMR3GetU32(pSSM, &texName); + AssertRCReturn(rc, rc); + + if (texName) + { + *pTexture = (CRTextureObj *) crHashtableSearch(pContext->shared->textureTable, texName); + } + else + { + switch (target) + { + case GL_TEXTURE_1D: + *pTexture = &(pContext->texture.base1D); + break; + case GL_TEXTURE_2D: + *pTexture = &(pContext->texture.base2D); + break; +#ifdef CR_OPENGL_VERSION_1_2 + case GL_TEXTURE_3D: + *pTexture = &(pContext->texture.base3D); + break; +#endif +#ifdef CR_ARB_texture_cube_map + case GL_TEXTURE_CUBE_MAP_ARB: + *pTexture = &(pContext->texture.baseCubeMap); + break; +#endif +#ifdef CR_NV_texture_rectangle + case GL_TEXTURE_RECTANGLE_NV: + *pTexture = &(pContext->texture.baseRect); + break; +#endif + default: + crError("LoadTextureObjPtr: Unknown texture target %d", target); + } + } + + return rc; +} + +static int32_t crStateSaveTexUnitCurrentTexturePtrs(CRTextureUnit *pTexUnit, PSSMHANDLE pSSM) +{ + int32_t rc; + + rc = crStateSaveTextureObjPtr(pTexUnit->currentTexture1D, pSSM); + AssertRCReturn(rc, rc); + rc = crStateSaveTextureObjPtr(pTexUnit->currentTexture2D, pSSM); + AssertRCReturn(rc, rc); + rc = crStateSaveTextureObjPtr(pTexUnit->currentTexture3D, pSSM); + AssertRCReturn(rc, rc); +#ifdef CR_ARB_texture_cube_map + rc = crStateSaveTextureObjPtr(pTexUnit->currentTextureCubeMap, pSSM); + AssertRCReturn(rc, rc); +#endif +#ifdef CR_NV_texture_rectangle + rc = crStateSaveTextureObjPtr(pTexUnit->currentTextureRect, pSSM); + AssertRCReturn(rc, rc); +#endif + + return rc; +} + +static int32_t crStateLoadTexUnitCurrentTexturePtrs(CRTextureUnit *pTexUnit, CRContext *pContext, PSSMHANDLE pSSM) +{ + int32_t rc; + + rc = crStateLoadTextureObjPtr(&pTexUnit->currentTexture1D, pContext, GL_TEXTURE_1D, pSSM); + AssertRCReturn(rc, rc); + rc = crStateLoadTextureObjPtr(&pTexUnit->currentTexture2D, pContext, GL_TEXTURE_1D, pSSM); + AssertRCReturn(rc, rc); + rc = crStateLoadTextureObjPtr(&pTexUnit->currentTexture3D, pContext, GL_TEXTURE_2D, pSSM); + AssertRCReturn(rc, rc); +#ifdef CR_ARB_texture_cube_map + rc = crStateLoadTextureObjPtr(&pTexUnit->currentTextureCubeMap, pContext, GL_TEXTURE_CUBE_MAP_ARB, pSSM); + AssertRCReturn(rc, rc); +#endif +#ifdef CR_NV_texture_rectangle + rc = crStateLoadTextureObjPtr(&pTexUnit->currentTextureRect, pContext, GL_TEXTURE_RECTANGLE_NV, pSSM); + AssertRCReturn(rc, rc); +#endif + + return rc; +} + +static int32_t crSateSaveEvalCoeffs1D(CREvaluator1D *pEval, PSSMHANDLE pSSM) +{ + int32_t rc, i; + + for (i=0; i<GLEVAL_TOT; ++i) + { + if (pEval[i].coeff) + { + rc = SSMR3PutMem(pSSM, pEval[i].coeff, pEval[i].order * gleval_sizes[i] * sizeof(GLfloat)); + AssertRCReturn(rc, rc); + } + } + + return VINF_SUCCESS; +} + +static int32_t crSateSaveEvalCoeffs2D(CREvaluator2D *pEval, PSSMHANDLE pSSM) +{ + int32_t rc, i; + + for (i=0; i<GLEVAL_TOT; ++i) + { + if (pEval[i].coeff) + { + rc = SSMR3PutMem(pSSM, pEval[i].coeff, pEval[i].uorder * pEval[i].vorder * gleval_sizes[i] * sizeof(GLfloat)); + AssertRCReturn(rc, rc); + } + } + + return VINF_SUCCESS; +} + +static int32_t crSateLoadEvalCoeffs1D(CREvaluator1D *pEval, GLboolean bReallocMem, PSSMHANDLE pSSM) +{ + int32_t rc, i; + size_t size; + + for (i=0; i<GLEVAL_TOT; ++i) + { + if (pEval[i].coeff) + { + size = pEval[i].order * gleval_sizes[i] * sizeof(GLfloat); + if (bReallocMem) + { + pEval[i].coeff = (GLfloat*) crAlloc((unsigned int /* this case is just so stupid */)size); + if (!pEval[i].coeff) return VERR_NO_MEMORY; + } + rc = SSMR3GetMem(pSSM, pEval[i].coeff, size); + AssertRCReturn(rc, rc); + } + } + + return VINF_SUCCESS; +} + +static int32_t crSateLoadEvalCoeffs2D(CREvaluator2D *pEval, GLboolean bReallocMem, PSSMHANDLE pSSM) +{ + int32_t rc, i; + size_t size; + + for (i=0; i<GLEVAL_TOT; ++i) + { + if (pEval[i].coeff) + { + size = pEval[i].uorder * pEval[i].vorder * gleval_sizes[i] * sizeof(GLfloat); + if (bReallocMem) + { + pEval[i].coeff = (GLfloat*) crAlloc((unsigned int /* this case is just so stupid */)size); + if (!pEval[i].coeff) return VERR_NO_MEMORY; + } + rc = SSMR3GetMem(pSSM, pEval[i].coeff, size); + AssertRCReturn(rc, rc); + } + } + + return VINF_SUCCESS; +} + +static void crStateCopyEvalPtrs1D(CREvaluator1D *pDst, CREvaluator1D *pSrc) +{ + int32_t i; + + for (i=0; i<GLEVAL_TOT; ++i) + pDst[i].coeff = pSrc[i].coeff; + + /* + pDst[GL_MAP1_VERTEX_3-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_VERTEX_3-GL_MAP1_COLOR_4].coeff; + pDst[GL_MAP1_VERTEX_4-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_VERTEX_4-GL_MAP1_COLOR_4].coeff; + pDst[GL_MAP1_INDEX-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_INDEX-GL_MAP1_COLOR_4].coeff; + pDst[GL_MAP1_COLOR_4-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_COLOR_4-GL_MAP1_COLOR_4].coeff; + pDst[GL_MAP1_NORMAL-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_NORMAL-GL_MAP1_COLOR_4].coeff; + pDst[GL_MAP1_TEXTURE_COORD_1-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_1-GL_MAP1_COLOR_4].coeff; + pDst[GL_MAP1_TEXTURE_COORD_2-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_2-GL_MAP1_COLOR_4].coeff; + pDst[GL_MAP1_TEXTURE_COORD_3-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_3-GL_MAP1_COLOR_4].coeff; + pDst[GL_MAP1_TEXTURE_COORD_4-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_4-GL_MAP1_COLOR_4].coeff; + */ +} + +static void crStateCopyEvalPtrs2D(CREvaluator2D *pDst, CREvaluator2D *pSrc) +{ + int32_t i; + + for (i=0; i<GLEVAL_TOT; ++i) + pDst[i].coeff = pSrc[i].coeff; + + /* + pDst[GL_MAP2_VERTEX_3-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_VERTEX_3-GL_MAP2_COLOR_4].coeff; + pDst[GL_MAP2_VERTEX_4-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_VERTEX_4-GL_MAP2_COLOR_4].coeff; + pDst[GL_MAP2_INDEX-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_INDEX-GL_MAP2_COLOR_4].coeff; + pDst[GL_MAP2_COLOR_4-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_COLOR_4-GL_MAP2_COLOR_4].coeff; + pDst[GL_MAP2_NORMAL-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_NORMAL-GL_MAP2_COLOR_4].coeff; + pDst[GL_MAP2_TEXTURE_COORD_1-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_1-GL_MAP2_COLOR_4].coeff; + pDst[GL_MAP2_TEXTURE_COORD_2-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_2-GL_MAP2_COLOR_4].coeff; + pDst[GL_MAP2_TEXTURE_COORD_3-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_3-GL_MAP2_COLOR_4].coeff; + pDst[GL_MAP2_TEXTURE_COORD_4-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_4-GL_MAP2_COLOR_4].coeff; + */ +} + +static void crStateSaveBufferObjectCB(unsigned long key, void *data1, void *data2) +{ + CRBufferObject *pBufferObj = (CRBufferObject *) data1; + PSSMHANDLE pSSM = (PSSMHANDLE) data2; + int32_t rc; + + CRASSERT(pBufferObj && pSSM); + + rc = SSMR3PutMem(pSSM, &key, sizeof(key)); + CRASSERT(rc == VINF_SUCCESS); + rc = SSMR3PutMem(pSSM, pBufferObj, sizeof(*pBufferObj)); + CRASSERT(rc == VINF_SUCCESS); + + if (pBufferObj->data) + { + /*We could get here even though retainBufferData is false on host side, in case when we're taking snapshot + after state load and before this context was ever made current*/ + CRASSERT(pBufferObj->size>0); + rc = SSMR3PutMem(pSSM, pBufferObj->data, pBufferObj->size); + CRASSERT(rc == VINF_SUCCESS); + } + else if (pBufferObj->id!=0 && pBufferObj->size>0) + { + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, pBufferObj->hwid); + pBufferObj->pointer = diff_api.MapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB); + rc = SSMR3PutMem(pSSM, &pBufferObj->pointer, sizeof(pBufferObj->pointer)); + CRASSERT(rc == VINF_SUCCESS); + if (pBufferObj->pointer) + { + rc = SSMR3PutMem(pSSM, pBufferObj->pointer, pBufferObj->size); + CRASSERT(rc == VINF_SUCCESS); + } + diff_api.UnmapBufferARB(GL_ARRAY_BUFFER_ARB); + pBufferObj->pointer = NULL; + } +} + +static void crStateSaveProgramCB(unsigned long key, void *data1, void *data2) +{ + CRProgram *pProgram = (CRProgram *) data1; + PSSMHANDLE pSSM = (PSSMHANDLE) data2; + CRProgramSymbol *pSymbol; + int32_t rc; + + CRASSERT(pProgram && pSSM); + + rc = SSMR3PutMem(pSSM, &key, sizeof(key)); + CRASSERT(rc == VINF_SUCCESS); + rc = SSMR3PutMem(pSSM, pProgram, sizeof(*pProgram)); + CRASSERT(rc == VINF_SUCCESS); + if (pProgram->string) + { + CRASSERT(pProgram->length); + rc = SSMR3PutMem(pSSM, pProgram->string, pProgram->length); + CRASSERT(rc == VINF_SUCCESS); + } + + for (pSymbol = pProgram->symbolTable; pSymbol; pSymbol=pSymbol->next) + { + rc = SSMR3PutMem(pSSM, pSymbol, sizeof(*pSymbol)); + CRASSERT(rc == VINF_SUCCESS); + if (pSymbol->name) + { + CRASSERT(pSymbol->cbName>0); + rc = SSMR3PutMem(pSSM, pSymbol->name, pSymbol->cbName); + CRASSERT(rc == VINF_SUCCESS); + } + } +} + +static void crStateSaveFramebuffersCB(unsigned long key, void *data1, void *data2) +{ + CRFramebufferObject *pFBO = (CRFramebufferObject*) data1; + PSSMHANDLE pSSM = (PSSMHANDLE) data2; + int32_t rc; + + rc = SSMR3PutMem(pSSM, &key, sizeof(key)); + CRASSERT(rc == VINF_SUCCESS); + + rc = SSMR3PutMem(pSSM, pFBO, sizeof(*pFBO)); + CRASSERT(rc == VINF_SUCCESS); +} + +static void crStateSaveRenderbuffersCB(unsigned long key, void *data1, void *data2) +{ + CRRenderbufferObject *pRBO = (CRRenderbufferObject*) data1; + PSSMHANDLE pSSM = (PSSMHANDLE) data2; + int32_t rc; + + rc = SSMR3PutMem(pSSM, &key, sizeof(key)); + CRASSERT(rc == VINF_SUCCESS); + + rc = SSMR3PutMem(pSSM, pRBO, sizeof(*pRBO)); + CRASSERT(rc == VINF_SUCCESS); +} + +static int32_t crStateLoadProgram(CRProgram **ppProgram, PSSMHANDLE pSSM) +{ + CRProgramSymbol **ppSymbol; + int32_t rc; + unsigned long key; + + rc = SSMR3GetMem(pSSM, &key, sizeof(key)); + AssertRCReturn(rc, rc); + + /* we're loading default vertex or pixel program*/ + if (*ppProgram) + { + if (key!=0) return VERR_SSM_UNEXPECTED_DATA; + } + else + { + *ppProgram = (CRProgram*) crAlloc(sizeof(CRProgram)); + if (!ppProgram) return VERR_NO_MEMORY; + if (key==0) return VERR_SSM_UNEXPECTED_DATA; + } + + rc = SSMR3GetMem(pSSM, *ppProgram, sizeof(**ppProgram)); + AssertRCReturn(rc, rc); + + if ((*ppProgram)->string) + { + CRASSERT((*ppProgram)->length); + (*ppProgram)->string = crAlloc((*ppProgram)->length); + if (!(*ppProgram)->string) return VERR_NO_MEMORY; + rc = SSMR3GetMem(pSSM, (void*) (*ppProgram)->string, (*ppProgram)->length); + AssertRCReturn(rc, rc); + } + + for (ppSymbol = &(*ppProgram)->symbolTable; *ppSymbol; ppSymbol=&(*ppSymbol)->next) + { + *ppSymbol = crAlloc(sizeof(CRProgramSymbol)); + if (!ppSymbol) return VERR_NO_MEMORY; + + rc = SSMR3GetMem(pSSM, *ppSymbol, sizeof(**ppSymbol)); + AssertRCReturn(rc, rc); + + if ((*ppSymbol)->name) + { + CRASSERT((*ppSymbol)->cbName>0); + (*ppSymbol)->name = crAlloc((*ppSymbol)->cbName); + if (!(*ppSymbol)->name) return VERR_NO_MEMORY; + + rc = SSMR3GetMem(pSSM, (void*) (*ppSymbol)->name, (*ppSymbol)->cbName); + AssertRCReturn(rc, rc); + } + } + + return VINF_SUCCESS; +} + +static void crStateSaveString(const char *pStr, PSSMHANDLE pSSM) +{ + int32_t len; + int32_t rc; + + if (pStr) + { + len = crStrlen(pStr)+1; + + rc = SSMR3PutS32(pSSM, len); + CRASSERT(rc == VINF_SUCCESS); + + rc = SSMR3PutMem(pSSM, pStr, len*sizeof(*pStr)); + CRASSERT(rc == VINF_SUCCESS); + } + else + { + rc = SSMR3PutS32(pSSM, 0); + CRASSERT(rc == VINF_SUCCESS); + } +} + +static char* crStateLoadString(PSSMHANDLE pSSM) +{ + int32_t len, rc; + char* pStr = NULL; + + rc = SSMR3GetS32(pSSM, &len); + CRASSERT(rc == VINF_SUCCESS); + + if (len!=0) + { + pStr = crAlloc(len*sizeof(*pStr)); + + rc = SSMR3GetMem(pSSM, pStr, len*sizeof(*pStr)); + CRASSERT(rc == VINF_SUCCESS); + } + + return pStr; +} + +static void crStateSaveGLSLShaderCB(unsigned long key, void *data1, void *data2) +{ + CRGLSLShader *pShader = (CRGLSLShader*) data1; + PSSMHANDLE pSSM = (PSSMHANDLE) data2; + int32_t rc; + + rc = SSMR3PutMem(pSSM, &key, sizeof(key)); + CRASSERT(rc == VINF_SUCCESS); + + rc = SSMR3PutMem(pSSM, pShader, sizeof(*pShader)); + CRASSERT(rc == VINF_SUCCESS); + + if (pShader->source) + { + crStateSaveString(pShader->source, pSSM); + } + else + { + GLint sLen=0; + GLchar *source=NULL; + + diff_api.GetShaderiv(pShader->hwid, GL_SHADER_SOURCE_LENGTH, &sLen); + if (sLen>0) + { + source = (GLchar*) crAlloc(sLen); + diff_api.GetShaderSource(pShader->hwid, sLen, NULL, source); + } + + crStateSaveString(source, pSSM); + if (source) crFree(source); + } +} + +static CRGLSLShader* crStateLoadGLSLShader(PSSMHANDLE pSSM) +{ + CRGLSLShader *pShader; + int32_t rc; + unsigned long key; + + pShader = crAlloc(sizeof(*pShader)); + if (!pShader) return NULL; + + rc = SSMR3GetMem(pSSM, &key, sizeof(key)); + CRASSERT(rc == VINF_SUCCESS); + + rc = SSMR3GetMem(pSSM, pShader, sizeof(*pShader)); + CRASSERT(rc == VINF_SUCCESS); + + pShader->source = crStateLoadString(pSSM); + + return pShader; +} + + +static void crStateSaveGLSLShaderKeyCB(unsigned long key, void *data1, void *data2) +{ + //CRGLSLShader *pShader = (CRGLSLShader*) data1; + PSSMHANDLE pSSM = (PSSMHANDLE) data2; + int32_t rc; + + rc = SSMR3PutMem(pSSM, &key, sizeof(key)); + CRASSERT(rc == VINF_SUCCESS); +} + +static void crStateSaveGLSLProgramAttribs(CRGLSLProgramState *pState, PSSMHANDLE pSSM) +{ + GLuint i; + int32_t rc; + + for (i=0; i<pState->cAttribs; ++i) + { + rc = SSMR3PutMem(pSSM, &pState->pAttribs[i].index, sizeof(pState->pAttribs[i].index)); + CRASSERT(rc == VINF_SUCCESS); + crStateSaveString(pState->pAttribs[i].name, pSSM); + } +} + +static void crStateSaveGLSLProgramCB(unsigned long key, void *data1, void *data2) +{ + CRGLSLProgram *pProgram = (CRGLSLProgram*) data1; + PSSMHANDLE pSSM = (PSSMHANDLE) data2; + int32_t rc; + uint32_t ui32; + GLint maxUniformLen, activeUniforms=0, uniformsCount=0, i, j; + GLchar *name = NULL; + GLenum type; + GLint size, location; + + rc = SSMR3PutMem(pSSM, &key, sizeof(key)); + CRASSERT(rc == VINF_SUCCESS); + + rc = SSMR3PutMem(pSSM, pProgram, sizeof(*pProgram)); + CRASSERT(rc == VINF_SUCCESS); + + ui32 = crHashtableNumElements(pProgram->currentState.attachedShaders); + rc = SSMR3PutU32(pSSM, ui32); + CRASSERT(rc == VINF_SUCCESS); + + crHashtableWalk(pProgram->currentState.attachedShaders, crStateSaveGLSLShaderKeyCB, pSSM); + + if (pProgram->activeState.attachedShaders) + { + ui32 = crHashtableNumElements(pProgram->activeState.attachedShaders); + rc = SSMR3PutU32(pSSM, ui32); + CRASSERT(rc == VINF_SUCCESS); + crHashtableWalk(pProgram->currentState.attachedShaders, crStateSaveGLSLShaderCB, pSSM); + } + + crStateSaveGLSLProgramAttribs(&pProgram->currentState, pSSM); + crStateSaveGLSLProgramAttribs(&pProgram->activeState, pSSM); + + diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen); + diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORMS, &activeUniforms); + + if (!maxUniformLen) + { + if (activeUniforms) + { + crWarning("activeUniforms (%d), while maxUniformLen is zero", activeUniforms); + activeUniforms = 0; + } + } + + if (activeUniforms>0) + { + name = (GLchar *) crAlloc((maxUniformLen+8)*sizeof(GLchar)); + + if (!name) + { + crWarning("crStateSaveGLSLProgramCB: out of memory"); + return; + } + } + + for (i=0; i<activeUniforms; ++i) + { + diff_api.GetActiveUniform(pProgram->hwid, i, maxUniformLen, NULL, &size, &type, name); + uniformsCount += size; + } + CRASSERT(uniformsCount>=activeUniforms); + + rc = SSMR3PutS32(pSSM, uniformsCount); + CRASSERT(rc == VINF_SUCCESS); + + if (activeUniforms>0) + { + GLfloat fdata[16]; + GLint idata[16]; + char *pIndexStr=NULL; + + for (i=0; i<activeUniforms; ++i) + { + diff_api.GetActiveUniform(pProgram->hwid, i, maxUniformLen, NULL, &size, &type, name); + + if (size>1) + { + pIndexStr = crStrchr(name, '['); + if (!pIndexStr) + { + pIndexStr = name+crStrlen(name); + } + } + + for (j=0; j<size; ++j) + { + if (size>1) + { + sprintf(pIndexStr, "[%i]", j); + } + location = diff_api.GetUniformLocation(pProgram->hwid, name); + + rc = SSMR3PutMem(pSSM, &type, sizeof(type)); + CRASSERT(rc == VINF_SUCCESS); + + crStateSaveString(name, pSSM); + + if (crStateIsIntUniform(type)) + { + diff_api.GetUniformiv(pProgram->hwid, location, &idata[0]); + rc = SSMR3PutMem(pSSM, &idata[0], crStateGetUniformSize(type)*sizeof(idata[0])); + CRASSERT(rc == VINF_SUCCESS); + } + else + { + diff_api.GetUniformfv(pProgram->hwid, location, &fdata[0]); + rc = SSMR3PutMem(pSSM, &fdata[0], crStateGetUniformSize(type)*sizeof(fdata[0])); + CRASSERT(rc == VINF_SUCCESS); + } + } + } + + crFree(name); + } +} + +static int32_t crStateSaveClientPointer(CRVertexArrays *pArrays, int32_t index, PSSMHANDLE pSSM) +{ + int32_t rc; + CRClientPointer *cp; + + cp = crStateGetClientPointerByIndex(index, pArrays); + + if (cp->buffer) + rc = SSMR3PutU32(pSSM, cp->buffer->id); + else + rc = SSMR3PutU32(pSSM, 0); + + AssertRCReturn(rc, rc); + +#ifdef CR_EXT_compiled_vertex_array + if (cp->locked) + { + CRASSERT(cp->p); + rc = SSMR3PutMem(pSSM, cp->p, cp->stride*(pArrays->lockFirst+pArrays->lockCount)); + AssertRCReturn(rc, rc); + } +#endif + + return VINF_SUCCESS; +} + +static int32_t crStateLoadClientPointer(CRVertexArrays *pArrays, int32_t index, CRContext *pContext, PSSMHANDLE pSSM) +{ + int32_t rc; + uint32_t ui; + CRClientPointer *cp; + + cp = crStateGetClientPointerByIndex(index, pArrays); + + rc = SSMR3GetU32(pSSM, &ui); + AssertRCReturn(rc, rc); + cp->buffer = ui==0 ? pContext->bufferobject.nullBuffer : crHashtableSearch(pContext->shared->buffersTable, ui); + + if (!cp->buffer) + { + crWarning("crStateLoadClientPointer: ui=%d loaded as NULL buffer!", ui); + } + +#ifdef CR_EXT_compiled_vertex_array + if (cp->locked) + { + rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&cp->p, cp->stride*(pArrays->lockFirst+pArrays->lockCount)); + AssertRCReturn(rc, rc); + } +#endif + + return VINF_SUCCESS; +} + +static int32_t crStateSaveCurrentBits(CRStateBits *pBits, PSSMHANDLE pSSM) +{ + int32_t rc, i; + + rc = SSMR3PutMem(pSSM, pBits, sizeof(*pBits)); + AssertRCReturn(rc, rc); + + rc = SSMR3PutMem(pSSM, pBits->client.v, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + AssertRCReturn(rc, rc); + rc = SSMR3PutMem(pSSM, pBits->client.n, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + AssertRCReturn(rc, rc); + rc = SSMR3PutMem(pSSM, pBits->client.c, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + AssertRCReturn(rc, rc); + rc = SSMR3PutMem(pSSM, pBits->client.s, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + AssertRCReturn(rc, rc); + rc = SSMR3PutMem(pSSM, pBits->client.i, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + AssertRCReturn(rc, rc); + for (i=0; i<CR_MAX_TEXTURE_UNITS; i++) + { + rc = SSMR3PutMem(pSSM, pBits->client.t[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + AssertRCReturn(rc, rc); + } + rc = SSMR3PutMem(pSSM, pBits->client.e, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + AssertRCReturn(rc, rc); + rc = SSMR3PutMem(pSSM, pBits->client.f, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + AssertRCReturn(rc, rc); +#ifdef CR_NV_vertex_program + for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++) + { + rc = SSMR3PutMem(pSSM, pBits->client.a[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + AssertRCReturn(rc, rc); + } +#endif + + rc = SSMR3PutMem(pSSM, pBits->lighting.light, CR_MAX_LIGHTS*sizeof(pBits->lighting.light)); + AssertRCReturn(rc, rc); + + return VINF_SUCCESS; +} + +static int32_t crStateLoadCurrentBits(CRStateBits *pBits, PSSMHANDLE pSSM) +{ + int32_t rc, i; + CRClientBits client; + CRLightingBits lighting; + + CRASSERT(pBits); + + client.v = pBits->client.v; + client.n = pBits->client.n; + client.c = pBits->client.c; + client.s = pBits->client.s; + client.i = pBits->client.i; + client.e = pBits->client.e; + client.f = pBits->client.f; + for (i=0; i<CR_MAX_TEXTURE_UNITS; i++) + { + client.t[i] = pBits->client.t[i]; + } +#ifdef CR_NV_vertex_program + for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++) + { + client.a[i] = pBits->client.a[i]; + } +#endif + lighting.light = pBits->lighting.light; + + rc = SSMR3GetMem(pSSM, pBits, sizeof(*pBits)); + AssertRCReturn(rc, rc); + + pBits->client.v = client.v; + rc = SSMR3GetMem(pSSM, pBits->client.v, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + AssertRCReturn(rc, rc); + pBits->client.n = client.n; + rc = SSMR3GetMem(pSSM, pBits->client.n, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + AssertRCReturn(rc, rc); + pBits->client.c = client.c; + rc = SSMR3GetMem(pSSM, pBits->client.c, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + AssertRCReturn(rc, rc); + pBits->client.s = client.s; + rc = SSMR3GetMem(pSSM, pBits->client.s, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + AssertRCReturn(rc, rc); + pBits->client.i = client.i; + rc = SSMR3GetMem(pSSM, pBits->client.i, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + AssertRCReturn(rc, rc); + pBits->client.e = client.e; + rc = SSMR3GetMem(pSSM, pBits->client.e, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + AssertRCReturn(rc, rc); + pBits->client.f = client.f; + rc = SSMR3GetMem(pSSM, pBits->client.f, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + AssertRCReturn(rc, rc); + for (i=0; i<CR_MAX_TEXTURE_UNITS; i++) + { + pBits->client.t[i] = client.t[i]; + rc = SSMR3GetMem(pSSM, pBits->client.t[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + AssertRCReturn(rc, rc); + } +#ifdef CR_NV_vertex_program + for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++) + { + pBits->client.a[i] = client.a[i]; + rc = SSMR3GetMem(pSSM, pBits->client.a[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue)); + AssertRCReturn(rc, rc); + } +#endif + + pBits->lighting.light = lighting.light; + rc = SSMR3GetMem(pSSM, pBits->lighting.light, CR_MAX_LIGHTS*sizeof(pBits->lighting.light)); + AssertRCReturn(rc, rc); + + return VINF_SUCCESS; +} + +static void crStateSaveKeysCB(unsigned long firstKey, unsigned long count, void *data) +{ + PSSMHANDLE pSSM = (PSSMHANDLE)data; + int rc; + CRASSERT(firstKey); + CRASSERT(count); + rc = SSMR3PutU32(pSSM, firstKey); + CRASSERT(RT_SUCCESS(rc)); + rc = SSMR3PutU32(pSSM, count); + CRASSERT(RT_SUCCESS(rc)); +} + +static int32_t crStateSaveKeys(CRHashTable *pHash, PSSMHANDLE pSSM) +{ + crHashtableWalkKeys(pHash, crStateSaveKeysCB , pSSM); + /* use null terminator */ + SSMR3PutU32(pSSM, 0); + return VINF_SUCCESS; +} + +static int32_t crStateLoadKeys(CRHashTable *pHash, PSSMHANDLE pSSM, uint32_t u32Version) +{ + uint32_t u32Key, u32Count, i; + int rc; + for(;;) + { + rc = SSMR3GetU32(pSSM, &u32Key); + AssertRCReturn(rc, rc); + + if (!u32Key) + return rc; + + rc = SSMR3GetU32(pSSM, &u32Count); + AssertRCReturn(rc, rc); + + CRASSERT(u32Count); + + if (u32Version > SHCROGL_SSM_VERSION_WITH_BUGGY_KEYS) + { + for (i = u32Key; i < u32Count + u32Key; ++i) + { + GLboolean fIsNew = crHashtableAllocRegisterKey(pHash, i); NOREF(fIsNew); +#if 0 //def DEBUG_misha + CRASSERT(fIsNew); +#endif + } + } + } + /* not reached*/ +} + + +int32_t crStateSaveContext(CRContext *pContext, PSSMHANDLE pSSM) +{ + int32_t rc, i; + uint32_t ui32, j; + GLboolean bSaveShared = GL_TRUE; + + CRASSERT(pContext && pSSM); + + CRASSERT(pContext->client.attribStackDepth == 0); + + /* this stuff is not used anymore, zero it up for sanity */ + pContext->buffer.storedWidth = 0; + pContext->buffer.storedHeight = 0; + + CRASSERT(VBoxTlsRefIsFunctional(pContext)); + + /* make sure the gl error state is captured by our state mechanism to store the correct gl error value */ + crStateSyncHWErrorState(pContext); + + rc = SSMR3PutMem(pSSM, pContext, sizeof (*pContext)); + AssertRCReturn(rc, rc); + + if (crHashtableNumElements(pContext->shared->dlistTable)>0) + crWarning("Saving state with %d display lists, unsupported", crHashtableNumElements(pContext->shared->dlistTable)); + + if (crHashtableNumElements(pContext->program.programHash)>0) + crDebug("Saving state with %d programs", crHashtableNumElements(pContext->program.programHash)); + + rc = SSMR3PutS32(pSSM, pContext->shared->id); + AssertRCReturn(rc, rc); + + rc = SSMR3PutS32(pSSM, crStateContextIsShared(pContext)); + AssertRCReturn(rc, rc); + + if (pContext->shared->refCount>1) + { + bSaveShared = pContext->shared->saveCount==0; + + ++pContext->shared->saveCount; + if (pContext->shared->saveCount == pContext->shared->refCount) + { + pContext->shared->saveCount=0; + } + } + + /* Save transform state */ + rc = SSMR3PutMem(pSSM, pContext->transform.clipPlane, sizeof(GLvectord)*CR_MAX_CLIP_PLANES); + AssertRCReturn(rc, rc); + rc = SSMR3PutMem(pSSM, pContext->transform.clip, sizeof(GLboolean)*CR_MAX_CLIP_PLANES); + AssertRCReturn(rc, rc); + rc = crStateSaveMatrixStack(&pContext->transform.modelViewStack, pSSM); + AssertRCReturn(rc, rc); + rc = crStateSaveMatrixStack(&pContext->transform.projectionStack, pSSM); + AssertRCReturn(rc, rc); + rc = crStateSaveMatrixStack(&pContext->transform.colorStack, pSSM); + AssertRCReturn(rc, rc); + for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++) + { + rc = crStateSaveMatrixStack(&pContext->transform.textureStack[i], pSSM); + AssertRCReturn(rc, rc); + } + for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++) + { + rc = crStateSaveMatrixStack(&pContext->transform.programStack[i], pSSM); + AssertRCReturn(rc, rc); + } + + /* Save textures */ + rc = crStateSaveTextureObjData(&pContext->texture.base1D, pSSM); + AssertRCReturn(rc, rc); + rc = crStateSaveTextureObjData(&pContext->texture.base2D, pSSM); + AssertRCReturn(rc, rc); + rc = crStateSaveTextureObjData(&pContext->texture.base3D, pSSM); + AssertRCReturn(rc, rc); + rc = crStateSaveTextureObjData(&pContext->texture.proxy1D, pSSM); + AssertRCReturn(rc, rc); + rc = crStateSaveTextureObjData(&pContext->texture.proxy2D, pSSM); + AssertRCReturn(rc, rc); + rc = crStateSaveTextureObjData(&pContext->texture.proxy3D, pSSM); +#ifdef CR_ARB_texture_cube_map + rc = crStateSaveTextureObjData(&pContext->texture.baseCubeMap, pSSM); + AssertRCReturn(rc, rc); + rc = crStateSaveTextureObjData(&pContext->texture.proxyCubeMap, pSSM); + AssertRCReturn(rc, rc); +#endif +#ifdef CR_NV_texture_rectangle + rc = crStateSaveTextureObjData(&pContext->texture.baseRect, pSSM); + AssertRCReturn(rc, rc); + rc = crStateSaveTextureObjData(&pContext->texture.proxyRect, pSSM); + AssertRCReturn(rc, rc); +#endif + + /* Save shared textures */ + if (bSaveShared) + { + CRASSERT(pContext->shared && pContext->shared->textureTable); + rc = crStateSaveKeys(pContext->shared->textureTable, pSSM); + AssertRCReturn(rc, rc); + ui32 = crHashtableNumElements(pContext->shared->textureTable); + rc = SSMR3PutU32(pSSM, ui32); + AssertRCReturn(rc, rc); + crHashtableWalk(pContext->shared->textureTable, crStateSaveSharedTextureCB, pSSM); + +#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE + /* Restore previous texture bindings via diff_api */ + if (ui32) + { + CRTextureUnit *pTexUnit; + + pTexUnit = &pContext->texture.unit[pContext->texture.curTextureUnit]; + + diff_api.BindTexture(GL_TEXTURE_1D, pTexUnit->currentTexture1D->hwid); + diff_api.BindTexture(GL_TEXTURE_2D, pTexUnit->currentTexture2D->hwid); + diff_api.BindTexture(GL_TEXTURE_3D, pTexUnit->currentTexture3D->hwid); +#ifdef CR_ARB_texture_cube_map + diff_api.BindTexture(GL_TEXTURE_CUBE_MAP_ARB, pTexUnit->currentTextureCubeMap->hwid); +#endif +#ifdef CR_NV_texture_rectangle + diff_api.BindTexture(GL_TEXTURE_RECTANGLE_NV, pTexUnit->currentTextureRect->hwid); +#endif + } +#endif + } + + /* Save current texture pointers */ + for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i) + { + rc = crStateSaveTexUnitCurrentTexturePtrs(&pContext->texture.unit[i], pSSM); + AssertRCReturn(rc, rc); + } + + /* Save lights */ + CRASSERT(pContext->lighting.light); + rc = SSMR3PutMem(pSSM, pContext->lighting.light, CR_MAX_LIGHTS * sizeof(*pContext->lighting.light)); + AssertRCReturn(rc, rc); + + /* Save attrib stack*/ + /** @todo could go up to used stack depth here?*/ + for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++) + { + if (pContext->attrib.enableStack[i].clip) + { + rc = SSMR3PutMem(pSSM, pContext->attrib.enableStack[i].clip, + pContext->limits.maxClipPlanes*sizeof(GLboolean)); + AssertRCReturn(rc, rc); + } + + if (pContext->attrib.enableStack[i].light) + { + rc = SSMR3PutMem(pSSM, pContext->attrib.enableStack[i].light, + pContext->limits.maxLights*sizeof(GLboolean)); + AssertRCReturn(rc, rc); + } + + if (pContext->attrib.lightingStack[i].light) + { + rc = SSMR3PutMem(pSSM, pContext->attrib.lightingStack[i].light, + pContext->limits.maxLights*sizeof(CRLight)); + AssertRCReturn(rc, rc); + } + + for (j=0; j<pContext->limits.maxTextureUnits; ++j) + { + rc = crStateSaveTexUnitCurrentTexturePtrs(&pContext->attrib.textureStack[i].unit[j], pSSM); + AssertRCReturn(rc, rc); + } + + if (pContext->attrib.transformStack[i].clip) + { + rc = SSMR3PutMem(pSSM, pContext->attrib.transformStack[i].clip, + pContext->limits.maxClipPlanes*sizeof(GLboolean)); + AssertRCReturn(rc, rc); + } + + if (pContext->attrib.transformStack[i].clipPlane) + { + rc = SSMR3PutMem(pSSM, pContext->attrib.transformStack[i].clipPlane, + pContext->limits.maxClipPlanes*sizeof(GLvectord)); + AssertRCReturn(rc, rc); + } + + rc = crSateSaveEvalCoeffs1D(pContext->attrib.evalStack[i].eval1D, pSSM); + AssertRCReturn(rc, rc); + rc = crSateSaveEvalCoeffs2D(pContext->attrib.evalStack[i].eval2D, pSSM); + AssertRCReturn(rc, rc); + } + + /* Save evaluator coeffs */ + rc = crSateSaveEvalCoeffs1D(pContext->eval.eval1D, pSSM); + AssertRCReturn(rc, rc); + rc = crSateSaveEvalCoeffs2D(pContext->eval.eval2D, pSSM); + AssertRCReturn(rc, rc); + +#ifdef CR_ARB_vertex_buffer_object + /* Save buffer objects */ + if (bSaveShared) + { + rc = crStateSaveKeys(pContext->shared->buffersTable, pSSM); + AssertRCReturn(rc, rc); + } + ui32 = bSaveShared? crHashtableNumElements(pContext->shared->buffersTable):0; + rc = SSMR3PutU32(pSSM, ui32); + AssertRCReturn(rc, rc); + + /* Save default one*/ + crStateSaveBufferObjectCB(0, pContext->bufferobject.nullBuffer, pSSM); + + if (bSaveShared) + { + /* Save all the rest */ + crHashtableWalk(pContext->shared->buffersTable, crStateSaveBufferObjectCB, pSSM); + } + + /* Restore binding */ + diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, pContext->bufferobject.arrayBuffer->hwid); + + /* Save pointers */ + rc = SSMR3PutU32(pSSM, pContext->bufferobject.arrayBuffer->id); + AssertRCReturn(rc, rc); + rc = SSMR3PutU32(pSSM, pContext->bufferobject.elementsBuffer->id); + AssertRCReturn(rc, rc); +#ifdef CR_ARB_pixel_buffer_object + rc = SSMR3PutU32(pSSM, pContext->bufferobject.packBuffer->id); + AssertRCReturn(rc, rc); + rc = SSMR3PutU32(pSSM, pContext->bufferobject.unpackBuffer->id); + AssertRCReturn(rc, rc); +#endif + /* Save clint pointers and buffer bindings*/ + for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i) + { + rc = crStateSaveClientPointer(&pContext->client.array, i, pSSM); + AssertRCReturn(rc, rc); + } + + crDebug("client.vertexArrayStackDepth %i", pContext->client.vertexArrayStackDepth); + for (i=0; i<pContext->client.vertexArrayStackDepth; ++i) + { + CRVertexArrays *pArray = &pContext->client.vertexArrayStack[i]; + for (j=0; j<CRSTATECLIENT_MAX_VERTEXARRAYS; ++j) + { + rc = crStateSaveClientPointer(pArray, j, pSSM); + AssertRCReturn(rc, rc); + } + } +#endif /*CR_ARB_vertex_buffer_object*/ + + /* Save pixel/vertex programs */ + ui32 = crHashtableNumElements(pContext->program.programHash); + rc = SSMR3PutU32(pSSM, ui32); + AssertRCReturn(rc, rc); + /* Save defaults programs */ + crStateSaveProgramCB(0, pContext->program.defaultVertexProgram, pSSM); + crStateSaveProgramCB(0, pContext->program.defaultFragmentProgram, pSSM); + /* Save all the rest */ + crHashtableWalk(pContext->program.programHash, crStateSaveProgramCB, pSSM); + /* Save Pointers */ + rc = SSMR3PutU32(pSSM, pContext->program.currentVertexProgram->id); + AssertRCReturn(rc, rc); + rc = SSMR3PutU32(pSSM, pContext->program.currentFragmentProgram->id); + AssertRCReturn(rc, rc); + /* This one is unused it seems*/ + CRASSERT(!pContext->program.errorString); + +#ifdef CR_EXT_framebuffer_object + /* Save FBOs */ + if (bSaveShared) + { + rc = crStateSaveKeys(pContext->shared->fbTable, pSSM); + AssertRCReturn(rc, rc); + ui32 = crHashtableNumElements(pContext->shared->fbTable); + rc = SSMR3PutU32(pSSM, ui32); + AssertRCReturn(rc, rc); + crHashtableWalk(pContext->shared->fbTable, crStateSaveFramebuffersCB, pSSM); + + rc = crStateSaveKeys(pContext->shared->rbTable, pSSM); + AssertRCReturn(rc, rc); + ui32 = crHashtableNumElements(pContext->shared->rbTable); + rc = SSMR3PutU32(pSSM, ui32); + AssertRCReturn(rc, rc); + crHashtableWalk(pContext->shared->rbTable, crStateSaveRenderbuffersCB, pSSM); + } + rc = SSMR3PutU32(pSSM, pContext->framebufferobject.drawFB?pContext->framebufferobject.drawFB->id:0); + AssertRCReturn(rc, rc); + rc = SSMR3PutU32(pSSM, pContext->framebufferobject.readFB?pContext->framebufferobject.readFB->id:0); + AssertRCReturn(rc, rc); + rc = SSMR3PutU32(pSSM, pContext->framebufferobject.renderbuffer?pContext->framebufferobject.renderbuffer->id:0); + AssertRCReturn(rc, rc); +#endif + +#ifdef CR_OPENGL_VERSION_2_0 + /* Save GLSL related info */ + ui32 = crHashtableNumElements(pContext->glsl.shaders); + rc = SSMR3PutU32(pSSM, ui32); + AssertRCReturn(rc, rc); + crHashtableWalk(pContext->glsl.shaders, crStateSaveGLSLShaderCB, pSSM); + ui32 = crHashtableNumElements(pContext->glsl.programs); + rc = SSMR3PutU32(pSSM, ui32); + AssertRCReturn(rc, rc); + crHashtableWalk(pContext->glsl.programs, crStateSaveGLSLProgramCB, pSSM); + rc = SSMR3PutU32(pSSM, pContext->glsl.activeProgram?pContext->glsl.activeProgram->id:0); + AssertRCReturn(rc, rc); +#endif + + return VINF_SUCCESS; +} + +typedef struct _crFindSharedCtxParms { + PFNCRSTATE_CONTEXT_GET pfnCtxGet; + CRContext *pSrcCtx, *pDstCtx; +} crFindSharedCtxParms_t; + +static void crStateFindSharedCB(unsigned long key, void *data1, void *data2) +{ + crFindSharedCtxParms_t *pParms = (crFindSharedCtxParms_t *) data2; + CRContext *pContext = pParms->pfnCtxGet(data1); + (void) key; + + if (pContext!=pParms->pSrcCtx && pContext->shared->id==pParms->pSrcCtx->shared->id) + { + pParms->pDstCtx->shared = pContext->shared; + } +} + +int32_t crStateSaveGlobals(PSSMHANDLE pSSM) +{ + /* don't need that for now */ +#if 0 + CRStateBits *pBits; + int rc; + + CRASSERT(g_cContexts >= 1); + if (g_cContexts <= 1) + return VINF_SUCCESS; + + pBits = GetCurrentBits(); +#define CRSTATE_BITS_OP(_var, _size) \ + rc = SSMR3PutMem(pSSM, (pBits->_var), _size); \ + AssertRCReturn(rc, rc); +#include "state_bits_globalop.h" +#undef CRSTATE_BITS_OP +#endif + return VINF_SUCCESS; +} + +int32_t crStateLoadGlobals(PSSMHANDLE pSSM, uint32_t u32Version) +{ + CRStateBits *pBits; + int rc; + CRASSERT(g_cContexts >= 1); + if (g_cContexts <= 1) + return VINF_SUCCESS; + + pBits = GetCurrentBits(); + + if (u32Version >= SHCROGL_SSM_VERSION_WITH_STATE_BITS) + { +#define CRSTATE_BITS_OP(_var, _size) \ + rc = SSMR3GetMem(pSSM, (pBits->_var), _size); \ + AssertRCReturn(rc, rc); + + if (u32Version < SHCROGL_SSM_VERSION_WITH_FIXED_STENCIL) + { +#define CRSTATE_BITS_OP_VERSION (SHCROGL_SSM_VERSION_WITH_FIXED_STENCIL - 1) +#define CRSTATE_BITS_OP_STENCIL_FUNC_V_33(_i, _var) do {} while (0) +#define CRSTATE_BITS_OP_STENCIL_OP_V_33(_i, _var) do {} while (0) +#include "state_bits_globalop.h" +#undef CRSTATE_BITS_OP_VERSION +#undef CRSTATE_BITS_OP_STENCIL_FUNC_V_33 +#undef CRSTATE_BITS_OP_STENCIL_OP_V_33 + } + else if (u32Version < SHCROGL_SSM_VERSION_WITH_SPRITE_COORD_ORIGIN) + { +#define CRSTATE_BITS_OP_VERSION (SHCROGL_SSM_VERSION_WITH_SPRITE_COORD_ORIGIN - 1) +#include "state_bits_globalop.h" +#undef CRSTATE_BITS_OP_VERSION + } + else + { + /* we do not put dirty bits to state anymore, + * nop */ +//#include "state_bits_globalop.h" + } +#undef CRSTATE_BITS_OP + /* always dirty all bits */ + /* return VINF_SUCCESS; */ + } + +#define CRSTATE_BITS_OP(_var, _size) FILLDIRTY(pBits->_var); +#include "state_bits_globalop.h" +#undef CRSTATE_BITS_OP + return VINF_SUCCESS; +} + + +#define SLC_COPYPTR(ptr) pTmpContext->ptr = pContext->ptr +#define SLC_ASSSERT_NULL_PTR(ptr) CRASSERT(!pContext->ptr) + +AssertCompile(VBOXTLSREFDATA_SIZE() <= CR_MAX_BITARRAY); +AssertCompile(VBOXTLSREFDATA_STATE_INITIALIZED != 0); +AssertCompile(RTASSERT_OFFSET_OF(CRContext, shared) >= VBOXTLSREFDATA_ASSERT_OFFSET(CRContext) + + VBOXTLSREFDATA_SIZE() + + RT_SIZEOFMEMB(CRContext, bitid) + + RT_SIZEOFMEMB(CRContext, neg_bitid)); + +int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRSTATE_CONTEXT_GET pfnCtxGet, PSSMHANDLE pSSM, uint32_t u32Version) +{ + CRContext* pTmpContext; + int32_t rc, i, j; + uint32_t uiNumElems, ui, k; + unsigned long key; + GLboolean bLoadShared = GL_TRUE; + GLenum err; + + CRASSERT(pContext && pSSM); + + /* This one is rather big for stack allocation and causes macs to crash */ + pTmpContext = (CRContext*)crAlloc(sizeof(*pTmpContext)); + if (!pTmpContext) + return VERR_NO_MEMORY; + + CRASSERT(VBoxTlsRefIsFunctional(pContext)); + + if (u32Version <= SHCROGL_SSM_VERSION_WITH_INVALID_ERROR_STATE) + { + union { + CRbitvalue bitid[CR_MAX_BITARRAY]; + struct { + VBOXTLSREFDATA + } tlsRef; + } bitid; + + /* do not increment the saved state version due to VBOXTLSREFDATA addition to CRContext */ + rc = SSMR3GetMem(pSSM, pTmpContext, VBOXTLSREFDATA_OFFSET(CRContext)); + AssertRCReturn(rc, rc); + + /* VBox 4.1.8 had a bug that VBOXTLSREFDATA was also stored in the snapshot, + * thus the saved state data format was changed w/o changing the saved state version. + * here we determine whether the saved state contains VBOXTLSREFDATA, and if so, treat it accordingly */ + rc = SSMR3GetMem(pSSM, &bitid, sizeof (bitid)); + AssertRCReturn(rc, rc); + + /* the bitid array has one bit set only. this is why if bitid.tlsRef has both cTlsRefs + * and enmTlsRefState non-zero - this is definitely NOT a bit id and is a VBOXTLSREFDATA */ + if (bitid.tlsRef.enmTlsRefState == VBOXTLSREFDATA_STATE_INITIALIZED + && bitid.tlsRef.cTlsRefs) + { + /* VBOXTLSREFDATA is stored, skip it */ + crMemcpy(&pTmpContext->bitid, ((uint8_t*)&bitid) + VBOXTLSREFDATA_SIZE(), sizeof (bitid) - VBOXTLSREFDATA_SIZE()); + rc = SSMR3GetMem(pSSM, ((uint8_t*)&pTmpContext->bitid) + sizeof (pTmpContext->bitid) - VBOXTLSREFDATA_SIZE(), sizeof (pTmpContext->neg_bitid) + VBOXTLSREFDATA_SIZE()); + AssertRCReturn(rc, rc); + + ui = VBOXTLSREFDATA_OFFSET(CRContext) + VBOXTLSREFDATA_SIZE() + sizeof (pTmpContext->bitid) + sizeof (pTmpContext->neg_bitid); + ui = RT_UOFFSETOF(CRContext, shared) - ui; + } + else + { + /* VBOXTLSREFDATA is NOT stored */ + crMemcpy(&pTmpContext->bitid, &bitid, sizeof (bitid)); + rc = SSMR3GetMem(pSSM, &pTmpContext->neg_bitid, sizeof (pTmpContext->neg_bitid)); + AssertRCReturn(rc, rc); + + /* the pre-VBOXTLSREFDATA CRContext structure might have additional allignment bits before the CRContext::shared */ + ui = VBOXTLSREFDATA_OFFSET(CRContext) + sizeof (pTmpContext->bitid) + sizeof (pTmpContext->neg_bitid); + + ui &= (sizeof (void*) - 1); + } + + if (ui) + { + void* pTmp = NULL; + rc = SSMR3GetMem(pSSM, &pTmp, ui); + AssertRCReturn(rc, rc); + } + + if (u32Version == SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS) + { + SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, shared, attrib); + rc = crStateLoadAttribState_v_BEFORE_CTXUSAGE_BITS(&pTmpContext->attrib, pSSM); + AssertRCReturn(rc, rc); + SHCROGL_CUT_FIELD_ALIGNMENT(CRContext, attrib, buffer); + SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, buffer, point); + rc = crStateLoadStencilPoint_v_37(&pTmpContext->point, pSSM); + AssertRCReturn(rc, rc); + SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, polygon, stencil); + rc = crStateLoadStencilState_v_33(&pTmpContext->stencil, pSSM); + AssertRCReturn(rc, rc); + SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT(CRContext, stencil, CRStencilState_v_33, sizeof (void*)); + rc = crStateLoadTextureState_v_BEFORE_CTXUSAGE_BITS(&pTmpContext->texture, pSSM); + AssertRCReturn(rc, rc); + SHCROGL_CUT_FIELD_ALIGNMENT(CRContext, texture, transform); + SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, transform); + } + else + { + SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, shared, attrib); + rc = crStateLoadAttribState_v_33(&pTmpContext->attrib, pSSM); + AssertRCReturn(rc, rc); + SHCROGL_CUT_FIELD_ALIGNMENT(CRContext, attrib, buffer); + SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, buffer, point); + rc = crStateLoadStencilPoint_v_37(&pTmpContext->point, pSSM); + AssertRCReturn(rc, rc); + SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, polygon, stencil); + rc = crStateLoadStencilState_v_33(&pTmpContext->stencil, pSSM); + AssertRCReturn(rc, rc); + SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT(CRContext, stencil, CRStencilState_v_33, sizeof (void*)); + SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, texture); + } + + pTmpContext->error = GL_NO_ERROR; /* <- the error state contained some random error data here + * treat as no error */ + } + else if (u32Version < SHCROGL_SSM_VERSION_WITH_FIXED_STENCIL) + { + SHCROGL_GET_STRUCT_HEAD(pTmpContext, CRContext, attrib); + rc = crStateLoadAttribState_v_33(&pTmpContext->attrib, pSSM); + AssertRCReturn(rc, rc); + SHCROGL_CUT_FIELD_ALIGNMENT(CRContext, attrib, buffer); + SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, buffer, point); + rc = crStateLoadStencilPoint_v_37(&pTmpContext->point, pSSM); + AssertRCReturn(rc, rc); + SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, polygon, stencil); + rc = crStateLoadStencilState_v_33(&pTmpContext->stencil, pSSM); + AssertRCReturn(rc, rc); + SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT(CRContext, stencil, CRStencilState_v_33, sizeof (void*)); + SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, texture); + } + else if (u32Version < SHCROGL_SSM_VERSION_WITH_SPRITE_COORD_ORIGIN) + { + SHCROGL_GET_STRUCT_HEAD(pTmpContext, CRContext, point); + crStateLoadStencilPoint_v_37(&pTmpContext->point, pSSM); + SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, polygon); + } + else + { + rc = SSMR3GetMem(pSSM, pTmpContext, sizeof (*pTmpContext)); + AssertRCReturn(rc, rc); + } + + /* preserve the error to restore it at the end of context creation, + * it should not normally change, but just in case it it changed */ + err = pTmpContext->error; + + /* we will later do crMemcpy from entire pTmpContext to pContext, + * for simplicity store the VBOXTLSREFDATA from the pContext to pTmpContext */ + VBOXTLSREFDATA_COPY(pTmpContext, pContext); + + /* Deal with shared state */ + { + crFindSharedCtxParms_t parms; + int32_t shared; + + rc = SSMR3GetS32(pSSM, &pContext->shared->id); + AssertRCReturn(rc, rc); + + rc = SSMR3GetS32(pSSM, &shared); + AssertRCReturn(rc, rc); + + pTmpContext->shared = NULL; + parms.pfnCtxGet = pfnCtxGet; + parms.pSrcCtx = pContext; + parms.pDstCtx = pTmpContext; + crHashtableWalk(pCtxTable, crStateFindSharedCB, &parms); + + if (pTmpContext->shared) + { + CRASSERT(pContext->shared->refCount==1); + bLoadShared = GL_FALSE; + crStateFreeShared(pContext, pContext->shared); + pContext->shared = NULL; + pTmpContext->shared->refCount++; + } + else + { + SLC_COPYPTR(shared); + } + + if (bLoadShared && shared) + { + crStateSetSharedContext(pTmpContext); + } + } + + SLC_COPYPTR(flush_func); + SLC_COPYPTR(flush_arg); + + /* We're supposed to be loading into an empty context, so those pointers should be NULL */ + for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++) + { + SLC_ASSSERT_NULL_PTR(attrib.enableStack[i].clip); + SLC_ASSSERT_NULL_PTR(attrib.enableStack[i].light); + + SLC_ASSSERT_NULL_PTR(attrib.lightingStack[i].light); + SLC_ASSSERT_NULL_PTR(attrib.transformStack[i].clip); + SLC_ASSSERT_NULL_PTR(attrib.transformStack[i].clipPlane); + + for (j=0; j<GLEVAL_TOT; ++j) + { + SLC_ASSSERT_NULL_PTR(attrib.evalStack[i].eval1D[j].coeff); + SLC_ASSSERT_NULL_PTR(attrib.evalStack[i].eval2D[j].coeff); + } + } + +#ifdef CR_ARB_vertex_buffer_object + SLC_COPYPTR(bufferobject.nullBuffer); +#endif + +/*@todo, that should be removed probably as those should hold the offset values, so loading should be fine + but better check*/ +#if 0 +#ifdef CR_EXT_compiled_vertex_array + SLC_COPYPTR(client.array.v.prevPtr); + SLC_COPYPTR(client.array.c.prevPtr); + SLC_COPYPTR(client.array.f.prevPtr); + SLC_COPYPTR(client.array.s.prevPtr); + SLC_COPYPTR(client.array.e.prevPtr); + SLC_COPYPTR(client.array.i.prevPtr); + SLC_COPYPTR(client.array.n.prevPtr); + for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++) + { + SLC_COPYPTR(client.array.t[i].prevPtr); + } + +# ifdef CR_NV_vertex_program + for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++) + { + SLC_COPYPTR(client.array.a[i].prevPtr); + } +# endif +#endif +#endif + +#ifdef CR_ARB_vertex_buffer_object + /*That just sets those pointers to NULL*/ + SLC_COPYPTR(client.array.v.buffer); + SLC_COPYPTR(client.array.c.buffer); + SLC_COPYPTR(client.array.f.buffer); + SLC_COPYPTR(client.array.s.buffer); + SLC_COPYPTR(client.array.e.buffer); + SLC_COPYPTR(client.array.i.buffer); + SLC_COPYPTR(client.array.n.buffer); + for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++) + { + SLC_COPYPTR(client.array.t[i].buffer); + } +# ifdef CR_NV_vertex_program + for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++) + { + SLC_COPYPTR(client.array.a[i].buffer); + } +# endif +#endif /*CR_ARB_vertex_buffer_object*/ + + /** @todo CR_NV_vertex_program*/ + crStateCopyEvalPtrs1D(pTmpContext->eval.eval1D, pContext->eval.eval1D); + crStateCopyEvalPtrs2D(pTmpContext->eval.eval2D, pContext->eval.eval2D); + + SLC_COPYPTR(feedback.buffer); /** @todo */ + SLC_COPYPTR(selection.buffer); /** @todo */ + + SLC_COPYPTR(lighting.light); + + /*This one could be tricky if we're loading snapshot on host with different GPU*/ + SLC_COPYPTR(limits.extensions); + +#if CR_ARB_occlusion_query + SLC_COPYPTR(occlusion.objects); /** @todo */ +#endif + + SLC_COPYPTR(program.errorString); + SLC_COPYPTR(program.programHash); + SLC_COPYPTR(program.defaultVertexProgram); + SLC_COPYPTR(program.defaultFragmentProgram); + + /* Texture pointers */ + for (i=0; i<6; ++i) + { + SLC_COPYPTR(texture.base1D.level[i]); + SLC_COPYPTR(texture.base2D.level[i]); + SLC_COPYPTR(texture.base3D.level[i]); + SLC_COPYPTR(texture.proxy1D.level[i]); + SLC_COPYPTR(texture.proxy2D.level[i]); + SLC_COPYPTR(texture.proxy3D.level[i]); +#ifdef CR_ARB_texture_cube_map + SLC_COPYPTR(texture.baseCubeMap.level[i]); + SLC_COPYPTR(texture.proxyCubeMap.level[i]); +#endif +#ifdef CR_NV_texture_rectangle + SLC_COPYPTR(texture.baseRect.level[i]); + SLC_COPYPTR(texture.proxyRect.level[i]); +#endif + } + + /* Load transform state */ + SLC_COPYPTR(transform.clipPlane); + SLC_COPYPTR(transform.clip); + /* Don't have to worry about pContext->transform.current as it'd be set in crStateSetCurrent call */ + /*SLC_COPYPTR(transform.currentStack);*/ + SLC_COPYPTR(transform.modelViewStack.stack); + SLC_COPYPTR(transform.projectionStack.stack); + SLC_COPYPTR(transform.colorStack.stack); + + for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++) + { + SLC_COPYPTR(transform.textureStack[i].stack); + } + for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++) + { + SLC_COPYPTR(transform.programStack[i].stack); + } + +#ifdef CR_OPENGL_VERSION_2_0 + SLC_COPYPTR(glsl.shaders); + SLC_COPYPTR(glsl.programs); +#endif + + /* Have to preserve original context id */ + CRASSERT(pTmpContext->id == pContext->id); + CRASSERT(VBOXTLSREFDATA_EQUAL(pContext, pTmpContext)); + /* Copy ordinary state to real context */ + crMemcpy(pContext, pTmpContext, sizeof(*pTmpContext)); + crFree(pTmpContext); + pTmpContext = NULL; + + /* Now deal with pointers */ + + /* Load transform state */ + rc = SSMR3GetMem(pSSM, pContext->transform.clipPlane, sizeof(GLvectord)*CR_MAX_CLIP_PLANES); + AssertRCReturn(rc, rc); + rc = SSMR3GetMem(pSSM, pContext->transform.clip, sizeof(GLboolean)*CR_MAX_CLIP_PLANES); + AssertRCReturn(rc, rc); + rc = crStateLoadMatrixStack(&pContext->transform.modelViewStack, pSSM); + AssertRCReturn(rc, rc); + rc = crStateLoadMatrixStack(&pContext->transform.projectionStack, pSSM); + AssertRCReturn(rc, rc); + rc = crStateLoadMatrixStack(&pContext->transform.colorStack, pSSM); + AssertRCReturn(rc, rc); + for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++) + { + rc = crStateLoadMatrixStack(&pContext->transform.textureStack[i], pSSM); + AssertRCReturn(rc, rc); + } + for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++) + { + rc = crStateLoadMatrixStack(&pContext->transform.programStack[i], pSSM); + AssertRCReturn(rc, rc); + } + + /* Load Textures */ + rc = crStateLoadTextureObjData(&pContext->texture.base1D, pSSM); + AssertRCReturn(rc, rc); + rc = crStateLoadTextureObjData(&pContext->texture.base2D, pSSM); + AssertRCReturn(rc, rc); + rc = crStateLoadTextureObjData(&pContext->texture.base3D, pSSM); + AssertRCReturn(rc, rc); + rc = crStateLoadTextureObjData(&pContext->texture.proxy1D, pSSM); + AssertRCReturn(rc, rc); + rc = crStateLoadTextureObjData(&pContext->texture.proxy2D, pSSM); + AssertRCReturn(rc, rc); + rc = crStateLoadTextureObjData(&pContext->texture.proxy3D, pSSM); + AssertRCReturn(rc, rc); +#ifdef CR_ARB_texture_cube_map + rc = crStateLoadTextureObjData(&pContext->texture.baseCubeMap, pSSM); + AssertRCReturn(rc, rc); + rc = crStateLoadTextureObjData(&pContext->texture.proxyCubeMap, pSSM); + AssertRCReturn(rc, rc); +#endif +#ifdef CR_NV_texture_rectangle + rc = crStateLoadTextureObjData(&pContext->texture.baseRect, pSSM); + AssertRCReturn(rc, rc); + rc = crStateLoadTextureObjData(&pContext->texture.proxyRect, pSSM); + AssertRCReturn(rc, rc); +#endif + + if (bLoadShared) + { + /* Load shared textures */ + CRASSERT(pContext->shared && pContext->shared->textureTable); + + if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS) + { + rc = crStateLoadKeys(pContext->shared->buffersTable, pSSM, u32Version); + AssertRCReturn(rc, rc); + } + + rc = SSMR3GetU32(pSSM, &uiNumElems); + AssertRCReturn(rc, rc); + for (ui=0; ui<uiNumElems; ++ui) + { + CRTextureObj *pTexture; + + rc = SSMR3GetMem(pSSM, &key, sizeof(key)); + AssertRCReturn(rc, rc); + + pTexture = (CRTextureObj *) crCalloc(sizeof(CRTextureObj)); + if (!pTexture) return VERR_NO_MEMORY; + + rc = crStateLoadTextureObj(pTexture, pSSM, u32Version); + AssertRCReturn(rc, rc); + + pTexture->hwid = 0; + + /*allocate actual memory*/ + for (i=0; i<6; ++i) { + pTexture->level[i] = (CRTextureLevel *) crCalloc(sizeof(CRTextureLevel) * CR_MAX_MIPMAP_LEVELS); + if (!pTexture->level[i]) return VERR_NO_MEMORY; + } + + rc = crStateLoadTextureObjData(pTexture, pSSM); + AssertRCReturn(rc, rc); + + crHashtableAdd(pContext->shared->textureTable, key, pTexture); + } + } + + /* Load current texture pointers */ + for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i) + { + rc = crStateLoadTexUnitCurrentTexturePtrs(&pContext->texture.unit[i], pContext, pSSM); + AssertRCReturn(rc, rc); + } + + /* Mark textures for resending to GPU */ + pContext->shared->bTexResyncNeeded = GL_TRUE; + + /* Load lights */ + CRASSERT(pContext->lighting.light); + rc = SSMR3GetMem(pSSM, pContext->lighting.light, CR_MAX_LIGHTS * sizeof(*pContext->lighting.light)); + AssertRCReturn(rc, rc); + + /* Load attrib stack*/ + for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++) + { + if (pContext->attrib.enableStack[i].clip) + { + rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.enableStack[i].clip, + pContext->limits.maxClipPlanes*sizeof(GLboolean)); + AssertRCReturn(rc, rc); + } + + if (pContext->attrib.enableStack[i].light) + { + rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.enableStack[i].light, + pContext->limits.maxLights*sizeof(GLboolean)); + AssertRCReturn(rc, rc); + } + + if (pContext->attrib.lightingStack[i].light) + { + rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.lightingStack[i].light, + pContext->limits.maxLights*sizeof(CRLight)); + AssertRCReturn(rc, rc); + } + + for (k=0; k<pContext->limits.maxTextureUnits; ++k) + { + rc = crStateLoadTexUnitCurrentTexturePtrs(&pContext->attrib.textureStack[i].unit[k], pContext, pSSM); + AssertRCReturn(rc, rc); + } + + if (pContext->attrib.transformStack[i].clip) + { + rc = crStateAllocAndSSMR3GetMem(pSSM, (void*)&pContext->attrib.transformStack[i].clip, + pContext->limits.maxClipPlanes*sizeof(GLboolean)); + AssertRCReturn(rc, rc); + } + + if (pContext->attrib.transformStack[i].clipPlane) + { + rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.transformStack[i].clipPlane, + pContext->limits.maxClipPlanes*sizeof(GLvectord)); + AssertRCReturn(rc, rc); + } + rc = crSateLoadEvalCoeffs1D(pContext->attrib.evalStack[i].eval1D, GL_TRUE, pSSM); + AssertRCReturn(rc, rc); + rc = crSateLoadEvalCoeffs2D(pContext->attrib.evalStack[i].eval2D, GL_TRUE, pSSM); + AssertRCReturn(rc, rc); + } + + /* Load evaluator coeffs */ + rc = crSateLoadEvalCoeffs1D(pContext->eval.eval1D, GL_FALSE, pSSM); + AssertRCReturn(rc, rc); + rc = crSateLoadEvalCoeffs2D(pContext->eval.eval2D, GL_FALSE, pSSM); + AssertRCReturn(rc, rc); + + /* Load buffer objects */ +#ifdef CR_ARB_vertex_buffer_object + if (bLoadShared) + { + if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS) + { + rc = crStateLoadKeys(pContext->shared->textureTable, pSSM, u32Version); + AssertRCReturn(rc, rc); + } + } + + rc = SSMR3GetU32(pSSM, &uiNumElems); + AssertRCReturn(rc, rc); + for (ui=0; ui<=uiNumElems; ++ui) /*ui<=uiNumElems to load nullBuffer in same loop*/ + { + CRBufferObject *pBufferObj; + + rc = SSMR3GetMem(pSSM, &key, sizeof(key)); + AssertRCReturn(rc, rc); + + /* default one should be already allocated */ + if (key==0) + { + pBufferObj = pContext->bufferobject.nullBuffer; + if (!pBufferObj) return VERR_SSM_UNEXPECTED_DATA; + } + else + { + pBufferObj = (CRBufferObject *) crCalloc(sizeof(*pBufferObj)); + if (!pBufferObj) return VERR_NO_MEMORY; + } + + rc = crStateLoadBufferObject(pBufferObj, pSSM, u32Version); + AssertRCReturn(rc, rc); + + pBufferObj->hwid = 0; + + if (pBufferObj->data) + { + CRASSERT(pBufferObj->size>0); + pBufferObj->data = crAlloc(pBufferObj->size); + rc = SSMR3GetMem(pSSM, pBufferObj->data, pBufferObj->size); + AssertRCReturn(rc, rc); + } + else if (pBufferObj->id!=0 && pBufferObj->size>0) + { + rc = SSMR3GetMem(pSSM, &pBufferObj->data, sizeof(pBufferObj->data)); + AssertRCReturn(rc, rc); + + if (pBufferObj->data) + { + pBufferObj->data = crAlloc(pBufferObj->size); + rc = SSMR3GetMem(pSSM, pBufferObj->data, pBufferObj->size); + AssertRCReturn(rc, rc); + } + } + + + if (key!=0) + crHashtableAdd(pContext->shared->buffersTable, key, pBufferObj); + } + /* Load pointers */ +#define CRS_GET_BO(name) (((name)==0) ? (pContext->bufferobject.nullBuffer) : crHashtableSearch(pContext->shared->buffersTable, name)) + rc = SSMR3GetU32(pSSM, &ui); + AssertRCReturn(rc, rc); + pContext->bufferobject.arrayBuffer = CRS_GET_BO(ui); + rc = SSMR3GetU32(pSSM, &ui); + AssertRCReturn(rc, rc); + pContext->bufferobject.elementsBuffer = CRS_GET_BO(ui); +#ifdef CR_ARB_pixel_buffer_object + rc = SSMR3GetU32(pSSM, &ui); + AssertRCReturn(rc, rc); + pContext->bufferobject.packBuffer = CRS_GET_BO(ui); + rc = SSMR3GetU32(pSSM, &ui); + AssertRCReturn(rc, rc); + pContext->bufferobject.unpackBuffer = CRS_GET_BO(ui); +#endif +#undef CRS_GET_BO + + /* Load client pointers and array buffer bindings*/ + for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i) + { + rc = crStateLoadClientPointer(&pContext->client.array, i, pContext, pSSM); + AssertRCReturn(rc, rc); + } + for (j=0; j<pContext->client.vertexArrayStackDepth; ++j) + { + CRVertexArrays *pArray = &pContext->client.vertexArrayStack[j]; + for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i) + { + rc = crStateLoadClientPointer(pArray, i, pContext, pSSM); + AssertRCReturn(rc, rc); + } + } + + pContext->shared->bVBOResyncNeeded = GL_TRUE; +#endif + + /* Load pixel/vertex programs */ + rc = SSMR3GetU32(pSSM, &uiNumElems); + AssertRCReturn(rc, rc); + /* Load defaults programs */ + rc = crStateLoadProgram(&pContext->program.defaultVertexProgram, pSSM); + AssertRCReturn(rc, rc); + rc = crStateLoadProgram(&pContext->program.defaultFragmentProgram, pSSM); + AssertRCReturn(rc, rc); + /* Load all the rest */ + for (ui=0; ui<uiNumElems; ++ui) + { + CRProgram *pProgram = NULL; + rc = crStateLoadProgram(&pProgram, pSSM); + AssertRCReturn(rc, rc); + crHashtableAdd(pContext->program.programHash, pProgram->id, pProgram); + //DIRTY(pProgram->dirtyProgram, pContext->neg_bitid); + + } + /* Load Pointers */ + rc = SSMR3GetU32(pSSM, &ui); + AssertRCReturn(rc, rc); + pContext->program.currentVertexProgram = ui==0 ? pContext->program.defaultVertexProgram + : crHashtableSearch(pContext->program.programHash, ui); + rc = SSMR3GetU32(pSSM, &ui); + AssertRCReturn(rc, rc); + pContext->program.currentFragmentProgram = ui==0 ? pContext->program.defaultFragmentProgram + : crHashtableSearch(pContext->program.programHash, ui); + + /* Mark programs for resending to GPU */ + pContext->program.bResyncNeeded = GL_TRUE; + +#ifdef CR_EXT_framebuffer_object + /* Load FBOs */ + if (bLoadShared) + { + if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS) + { + rc = crStateLoadKeys(pContext->shared->fbTable, pSSM, u32Version); + AssertRCReturn(rc, rc); + } + + rc = SSMR3GetU32(pSSM, &uiNumElems); + AssertRCReturn(rc, rc); + for (ui=0; ui<uiNumElems; ++ui) + { + CRFramebufferObject *pFBO; + pFBO = crAlloc(sizeof(*pFBO)); + if (!pFBO) return VERR_NO_MEMORY; + + rc = SSMR3GetMem(pSSM, &key, sizeof(key)); + AssertRCReturn(rc, rc); + + rc = crStateLoadFramebufferObject(pFBO, pSSM, u32Version); + AssertRCReturn(rc, rc); + + Assert(key == pFBO->id); + + crHashtableAdd(pContext->shared->fbTable, key, pFBO); + } + + if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS) + { + rc = crStateLoadKeys(pContext->shared->rbTable, pSSM, u32Version); + AssertRCReturn(rc, rc); + } + + rc = SSMR3GetU32(pSSM, &uiNumElems); + AssertRCReturn(rc, rc); + for (ui=0; ui<uiNumElems; ++ui) + { + CRRenderbufferObject *pRBO; + pRBO = crAlloc(sizeof(*pRBO)); + if (!pRBO) return VERR_NO_MEMORY; + + rc = SSMR3GetMem(pSSM, &key, sizeof(key)); + AssertRCReturn(rc, rc); + + rc = crStateLoadRenderbufferObject(pRBO, pSSM, u32Version); + AssertRCReturn(rc, rc); + + crHashtableAdd(pContext->shared->rbTable, key, pRBO); + } + } + + rc = SSMR3GetU32(pSSM, &ui); + AssertRCReturn(rc, rc); + pContext->framebufferobject.drawFB = ui==0 ? NULL + : crHashtableSearch(pContext->shared->fbTable, ui); + + rc = SSMR3GetU32(pSSM, &ui); + AssertRCReturn(rc, rc); + pContext->framebufferobject.readFB = ui==0 ? NULL + : crHashtableSearch(pContext->shared->fbTable, ui); + + rc = SSMR3GetU32(pSSM, &ui); + AssertRCReturn(rc, rc); + pContext->framebufferobject.renderbuffer = ui==0 ? NULL + : crHashtableSearch(pContext->shared->rbTable, ui); + + /* Mark FBOs/RBOs for resending to GPU */ + pContext->shared->bFBOResyncNeeded = GL_TRUE; +#endif + +#ifdef CR_OPENGL_VERSION_2_0 + /* Load GLSL related info */ + rc = SSMR3GetU32(pSSM, &uiNumElems); + AssertRCReturn(rc, rc); + + for (ui=0; ui<uiNumElems; ++ui) + { + CRGLSLShader *pShader = crStateLoadGLSLShader(pSSM); + GLboolean fNewKeyCheck; + if (!pShader) return VERR_SSM_UNEXPECTED_DATA; + fNewKeyCheck = crHashtableAllocRegisterKey(pContext->glsl.programs, pShader->id); + CRASSERT(fNewKeyCheck); + crHashtableAdd(pContext->glsl.shaders, pShader->id, pShader); + } + + rc = SSMR3GetU32(pSSM, &uiNumElems); + AssertRCReturn(rc, rc); + + for (ui=0; ui<uiNumElems; ++ui) + { + CRGLSLProgram *pProgram; + uint32_t numShaders; + + pProgram = crAlloc(sizeof(*pProgram)); + if (!pProgram) return VERR_NO_MEMORY; + + rc = SSMR3GetMem(pSSM, &key, sizeof(key)); + AssertRCReturn(rc, rc); + + rc = SSMR3GetMem(pSSM, pProgram, sizeof(*pProgram)); + AssertRCReturn(rc, rc); + + crHashtableAdd(pContext->glsl.programs, key, pProgram); + + pProgram->currentState.attachedShaders = crAllocHashtable(); + + rc = SSMR3GetU32(pSSM, &numShaders); + AssertRCReturn(rc, rc); + + for (k=0; k<numShaders; ++k) + { + rc = SSMR3GetMem(pSSM, &key, sizeof(key)); + AssertRCReturn(rc, rc); + crHashtableAdd(pProgram->currentState.attachedShaders, key, crHashtableSearch(pContext->glsl.shaders, key)); + } + + if (pProgram->activeState.attachedShaders) + { + pProgram->activeState.attachedShaders = crAllocHashtable(); + + rc = SSMR3GetU32(pSSM, &numShaders); + AssertRCReturn(rc, rc); + + for (k=0; k<numShaders; ++k) + { + CRGLSLShader *pShader = crStateLoadGLSLShader(pSSM); + if (!pShader) return VERR_SSM_UNEXPECTED_DATA; + crHashtableAdd(pProgram->activeState.attachedShaders, pShader->id, pShader); + } + } + + if (pProgram->currentState.cAttribs) + pProgram->currentState.pAttribs = (CRGLSLAttrib*) crAlloc(pProgram->currentState.cAttribs*sizeof(CRGLSLAttrib)); + for (k=0; k<pProgram->currentState.cAttribs; ++k) + { + rc = SSMR3GetMem(pSSM, &pProgram->currentState.pAttribs[k].index, sizeof(pProgram->currentState.pAttribs[k].index)); + AssertRCReturn(rc, rc); + pProgram->currentState.pAttribs[k].name = crStateLoadString(pSSM); + } + + if (pProgram->activeState.cAttribs) + pProgram->activeState.pAttribs = (CRGLSLAttrib*) crAlloc(pProgram->activeState.cAttribs*sizeof(CRGLSLAttrib)); + for (k=0; k<pProgram->activeState.cAttribs; ++k) + { + rc = SSMR3GetMem(pSSM, &pProgram->activeState.pAttribs[k].index, sizeof(pProgram->activeState.pAttribs[k].index)); + AssertRCReturn(rc, rc); + pProgram->activeState.pAttribs[k].name = crStateLoadString(pSSM); + } + + { + int32_t cUniforms; + rc = SSMR3GetS32(pSSM, &cUniforms); + pProgram->cUniforms = cUniforms; + AssertRCReturn(rc, rc); + } + + if (pProgram->cUniforms) + { + pProgram->pUniforms = crAlloc(pProgram->cUniforms*sizeof(CRGLSLUniform)); + if (!pProgram->pUniforms) return VERR_NO_MEMORY; + + for (k=0; k<pProgram->cUniforms; ++k) + { + size_t itemsize, datasize; + + rc = SSMR3GetMem(pSSM, &pProgram->pUniforms[k].type, sizeof(GLenum)); + AssertRCReturn(rc, rc); + pProgram->pUniforms[k].name = crStateLoadString(pSSM); + + if (crStateIsIntUniform(pProgram->pUniforms[k].type)) + { + itemsize = sizeof(GLint); + } else itemsize = sizeof(GLfloat); + + datasize = crStateGetUniformSize(pProgram->pUniforms[k].type)*itemsize; + pProgram->pUniforms[k].data = crAlloc((unsigned int /* this case is just so stupid */)datasize); + if (!pProgram->pUniforms[k].data) return VERR_NO_MEMORY; + + rc = SSMR3GetMem(pSSM, pProgram->pUniforms[k].data, datasize); + AssertRCReturn(rc, rc); + } + } + } + + rc = SSMR3GetU32(pSSM, &ui); + AssertRCReturn(rc, rc); + pContext->glsl.activeProgram = ui==0 ? NULL + : crHashtableSearch(pContext->glsl.programs, ui); + + /*Mark for resending to GPU*/ + pContext->glsl.bResyncNeeded = GL_TRUE; +#endif + + if (pContext->error != err) + { + crWarning("context error state changed on context restore, was 0x%x, but became 0x%x, resetting to its original value", + err, pContext->error); + pContext->error = err; + } + + return VINF_SUCCESS; +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_special b/src/VBox/GuestHost/OpenGL/state_tracker/state_special new file mode 100644 index 00000000..46b6805a --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_special @@ -0,0 +1,385 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +Begin +End +GetString +PixelStoref +PixelStorei +PixelTransferf +PixelTransferi +PixelZoom +PixelMapfv +PixelMapuiv +PixelMapusv +PopClientAttrib +PushClientAttrib +GetPixelMapfv +GetPixelMapuiv +GetPixelMapusv +AlphaFunc +DepthFunc +BlendFunc +BlendColorEXT +BlendEquationEXT +BlendFuncSeparateEXT +LogicOp +DrawBuffer +ReadBuffer +IndexMask +ColorMask +ClearColor +ClearIndex +ClearDepth +ClearAccum +DepthMask +Enable +Disable +Map1d +Map1f +Map2d +Map2f +MapGrid1d +MapGrid1f +MapGrid2d +MapGrid2f +GetMapdv +GetMapfv +GetMapiv +Fogi +Fogf +Fogiv +Fogfv +ShadeModel +ColorMaterial +LightModelf +LightModeli +LightModelfv +LightModeliv +Lightf +Lighti +Lightfv +Lightiv +GetLightfv +GetLightiv +Materialf +Materiali +Materialfv +Materialiv +GetMaterialfv +GetMaterialiv +ShadeModel +ColorMaterial +LightModelf +LightModeli +LightModelfv +LightModeliv +Lightf +Lighti +Lightfv +Lightiv +Materialf +Materiali +Materialfv +Materialiv +ClipPlane +GetClipPlane +MatrixMode +LoadIdentity +PopMatrix +PushMatrix +LoadMatrixf +LoadMatrixd +LoadTransposeMatrixfARB +LoadTransposeMatrixdARB +MultMatrixf +MultMatrixd +MultTransposeMatrixfARB +MultTransposeMatrixdARB +Translatef +Translated +Rotatef +Rotated +Scalef +Scaled +Frustum +Ortho +PointSize +LineWidth +LineStipple +CullFace +FrontFace +PolygonMode +PolygonOffset +PolygonStipple +GetPolygonStipple +GenTextures +DeleteTextures +BindTexture +TexImage1D +TexImage2D +TexImage3D +TexImage3DEXT +TexSubImage1D +TexSubImage2D +TexSubImage3D +TexParameterfv +TexParameteriv +TexParameterf +TexParameteri +TexEnvfv +TexEnviv +TexEnvf +TexEnvi +GetTexEnvfv +GetTexEnviv +TexGendv +TexGenfv +TexGeniv +TexGend +TexGenf +TexGeni +GetTexGendv +GetTexGenfv +GetTexGeniv +GetTexImage +GetTexLevelParameterfv +GetTexLevelParameteriv +GetTexParameterfv +GetTexParameteriv +PrioritizeTextures +AreTexturesResident +GetBooleanv +GetDoublev +GetFloatv +GetIntegerv +GetError +StencilFunc +StencilOp +StencilFuncSeparate +StencilOpSeparate +ActiveStencilFaceEXT +ClearStencil +StencilMask +Viewport +DepthRange +Scissor +IsEnabled +RasterPos2d +RasterPos2f +RasterPos2i +RasterPos2s +RasterPos3d +RasterPos3f +RasterPos3i +RasterPos3s +RasterPos4d +RasterPos4f +RasterPos4i +RasterPos4s +RasterPos2dv +RasterPos2fv +RasterPos2iv +RasterPos2sv +RasterPos3dv +RasterPos3fv +RasterPos3iv +RasterPos3sv +RasterPos4dv +RasterPos4fv +RasterPos4iv +RasterPos4sv +GenLists +NewList +EndList +DeleteLists +IsList +IsTexture +ListBase +EnableClientState +DisableClientState +VertexPointer +ColorPointer +SecondaryColorPointerEXT +IndexPointer +NormalPointer +TexCoordPointer +EdgeFlagPointer +InterleavedArrays +GetPointerv +PushAttrib +PopAttrib +Bitmap +ActiveTextureARB +ClientActiveTextureARB +CombinerParameterfvNV +CombinerParameterivNV +CombinerParameterfNV +CombinerParameteriNV +CombinerInputNV +CombinerOutputNV +FinalCombinerInputNV +GetCombinerInputParameterfvNV +GetCombinerInputParameterivNV +GetCombinerOutputParameterfvNV +GetCombinerOutputParameterivNV +GetFinalCombinerInputParameterfvNV +GetFinalCombinerInputParameterivNV +CombinerStageParameterfvNV +GetCombinerStageParameterfvNV +Color3f +Color3fv +Color4f +Color4fv +Hint +FeedbackBuffer +SelectBuffer +RenderMode +InitNames +LoadName +PushName +PopName +PassThrough +FogCoordPointerEXT +VertexAttribPointerNV +PointParameterfARB +PointParameterfvARB +PointParameteri +PointParameteriv +SampleCoverageARB +WindowPos2dARB +WindowPos2dvARB +WindowPos2fARB +WindowPos2fvARB +WindowPos2iARB +WindowPos2ivARB +WindowPos2sARB +WindowPos2svARB +WindowPos3dARB +WindowPos3dvARB +WindowPos3fARB +WindowPos3fvARB +WindowPos3iARB +WindowPos3ivARB +WindowPos3sARB +WindowPos3svARB +CompressedTexImage3DARB +CompressedTexImage2DARB +CompressedTexImage1DARB +CompressedTexSubImage3DARB +CompressedTexSubImage2DARB +CompressedTexSubImage1DARB +GetCompressedTexImageARB +BindProgramNV +ExecuteProgramNV +GenProgramsNV +AreProgramsResidentNV +RequestResidentProgramsNV +LoadProgramNV +GetProgramivNV +GetProgramStringNV +ProgramParameter4dNV +ProgramParameter4dvNV +ProgramParameter4fNV +ProgramParameter4fvNV +ProgramParameters4dvNV +ProgramParameters4fvNV +GetProgramParameterfvNV +GetProgramParameterdvNV +TrackMatrixNV +GetTrackMatrixivNV +GetVertexAttribdvNV +GetVertexAttribfvNV +GetVertexAttribivNV +GetVertexAttribPointervNV +ProgramNamedParameter4fNV +ProgramNamedParameter4dNV +ProgramNamedParameter4fvNV +ProgramNamedParameter4dvNV +GetProgramNamedParameterfvNV +GetProgramNamedParameterdvNV +GetProgramStringARB +ProgramLocalParameter4dARB +ProgramLocalParameter4dvARB +ProgramLocalParameter4fARB +ProgramLocalParameter4fvARB +GetProgramLocalParameterfvARB +GetProgramLocalParameterdvARB +GetVertexAttribdvARB +GetVertexAttribfvARB +GetVertexAttribivARB +EnableVertexAttribArrayARB +DisableVertexAttribArrayARB +ProgramStringARB +BindProgramARB +DeleteProgramsARB +GenProgramsARB +ProgramEnvParameter4dARB +ProgramEnvParameter4dvARB +ProgramEnvParameter4fARB +ProgramEnvParameter4fvARB +GetProgramEnvParameterdvARB +GetProgramEnvParameterfvARB +GetProgramivARB +GetProgramStringARB +IsProgramARB +VertexAttribPointerARB +GetVertexAttribPointervARB +GenFencesNV +DeleteFencesNV +SetFenceNV +TestFenceNV +FinishFenceNV +IsFenceNV +GetFenceivNV +VertexArrayRangeNV +FlushVertexArrayRangeNV +BindBufferARB +GenBuffersARB +IsBufferARB +GetBufferParameterivARB +GetBufferPointervARB +GetBufferSubDataARB +DeleteBuffersARB +BufferDataARB +BufferSubDataARB +MapBufferARB +UnmapBufferARB +GenQueriesARB +DeleteQueriesARB +IsQueryARB +BeginQueryARB +EndQueryARB +GetQueryivARB +GetQueryObjectivARB +GetQueryObjectuivARB +BindRenderbufferEXT +DeleteRenderbuffersEXT +RenderbufferStorageEXT +BindFramebufferEXT +DeleteFramebuffersEXT +FramebufferTexture1DEXT +FramebufferTexture2DEXT +FramebufferTexture3DEXT +FramebufferRenderbufferEXT +GetFramebufferAttachmentParameterivEXT +GenerateMipmapEXT +LockArraysEXT +UnlockArraysEXT +CompileShader +DeleteShader +AttachShader +DetachShader +LinkProgram +UseProgram +DeleteProgram +ValidateProgram +BindAttribLocation +GetAttribLocation +GetUniformLocation +CopyTexImage2D +GenFramebuffersEXT +GenRenderbuffersEXT +IsRenderbufferEXT +IsFramebufferEXT diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c new file mode 100644 index 00000000..2fc438cd --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c @@ -0,0 +1,1450 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include <stdio.h> +#include "state.h" +#include "state/cr_statetypes.h" +#include "state_internals.h" + + +static GLint crStateStencilBufferGetIdxAndCount(CRStencilState *s, GLenum face, GLint *pIdx, GLint *pBitsIdx) +{ + switch (face) + { + case GL_FRONT_AND_BACK: + *pIdx = 0; + *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK; + return 2; + case GL_FRONT: + *pIdx = CRSTATE_STENCIL_BUFFER_ID_FRONT; + *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_FRONT; + return 1; + case GL_BACK: + *pIdx = CRSTATE_STENCIL_BUFFER_ID_BACK; + *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_BACK; + return 1; + case 0: + if (!s->stencilTwoSideEXT || s->activeStencilFace == GL_FRONT) + { + /* both front and back */ + *pIdx = 0; + *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK; + return 2; + } + *pIdx = CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK; + *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK; + return 1; + default: + crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateStencilBufferGetIdxAndCount"); + return 0; + } +#ifndef VBOX /* unreachable */ + crError("should never be here!"); + return 0; +#endif +} + +void crStateStencilBufferInit(CRStencilBufferState *s) +{ + s->func = GL_ALWAYS; + s->mask = 0xFFFFFFFF; + s->ref = 0; + + s->fail = GL_KEEP; + s->passDepthFail = GL_KEEP; + s->passDepthPass = GL_KEEP; +} + +static void crStateStencilBufferRefBitsInit(CRContext *ctx, CRStencilBufferRefBits *sb) +{ + RESET(sb->func, ctx->bitid); + RESET(sb->op, ctx->bitid); +} + +void crStateStencilInit(CRContext *ctx) +{ + CRStencilState *s = &ctx->stencil; + CRStateBits *stateb = GetCurrentBits(); + CRStencilBits *sb = &(stateb->stencil); + int i; + + s->stencilTest = GL_FALSE; + RESET(sb->enable, ctx->bitid); + + s->stencilTwoSideEXT = GL_FALSE; + RESET(sb->enableTwoSideEXT, ctx->bitid); + + s->activeStencilFace = GL_FRONT; + RESET(sb->activeStencilFace, ctx->bitid); + + s->clearValue = 0; + RESET(sb->clearValue, ctx->bitid); + + s->writeMask = 0xFFFFFFFF; + RESET(sb->writeMask, ctx->bitid); + + RESET(sb->dirty, ctx->bitid); + + for (i = 0; i < CRSTATE_STENCIL_BUFFER_COUNT; ++i) + { + crStateStencilBufferInit(&s->buffers[i]); + } + + for (i = 0; i < CRSTATE_STENCIL_BUFFER_REF_COUNT; ++i) + { + crStateStencilBufferRefBitsInit(ctx, &sb->bufferRefs[i]); + } +} + +static void crStateStencilBufferFunc(CRContext *g, CRStencilBufferState *s, GLenum func, GLint ref, GLuint mask) +{ + (void)g; + s->func = func; + s->ref = ref; + s->mask = mask; +} + +static void crStateStencilFuncPerform(GLenum face, GLenum func, GLint ref, GLuint mask) +{ + CRContext *g = GetCurrentContext(); + CRStencilState *s = &(g->stencil); + CRStateBits *stateb = GetCurrentBits(); + CRStencilBits *sb = &(stateb->stencil); + GLint idx, bitsIdx, count, i; + + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glStencilFunc called in begin/end"); + return; + } + + FLUSH(); + + if (func != GL_NEVER && + func != GL_LESS && + func != GL_LEQUAL && + func != GL_GREATER && + func != GL_GEQUAL && + func != GL_EQUAL && + func != GL_NOTEQUAL && + func != GL_ALWAYS) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glStencilFunc called with bogu func: %d", func); + return; + } + + count = crStateStencilBufferGetIdxAndCount(s, face, &idx, &bitsIdx); + if (count) + { + for (i = idx; i < idx + count; ++i) + { + crStateStencilBufferFunc(g, &s->buffers[i], func, ref, mask); + } + DIRTY(sb->bufferRefs[bitsIdx].func, g->neg_bitid); + + DIRTY(sb->dirty, g->neg_bitid); + } +} + +void STATE_APIENTRY crStateStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) +{ + if (!face) + { + /* crStateStencilFuncPerform accepts 0 value, while glStencilFuncSeparate does not, + * filter it out here */ + crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateStencilFuncSeparate"); + return; + } + crStateStencilFuncPerform(face, func, ref, mask); +} + +void STATE_APIENTRY crStateStencilFunc(GLenum func, GLint ref, GLuint mask) +{ + crStateStencilFuncPerform(0, func, ref, mask); +} + +static void STATE_APIENTRY crStateStencilBufferOp (CRContext *g, CRStencilBufferState *s, GLenum fail, GLenum zfail, GLenum zpass) +{ + (void)g; + s->fail = fail; + s->passDepthFail = zfail; + s->passDepthPass = zpass; +} + +static void crStateStencilOpPerform (GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ + CRContext *g = GetCurrentContext(); + CRStencilState *s = &(g->stencil); + CRStateBits *stateb = GetCurrentBits(); + CRStencilBits *sb = &(stateb->stencil); + GLint idx, bitsIdx, count, i; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glStencilOp called in begin/end"); + return; + } + + FLUSH(); + + switch (fail) { + case GL_KEEP: + case GL_ZERO: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: +#ifdef CR_EXT_stencil_wrap + case GL_INCR_WRAP_EXT: + case GL_DECR_WRAP_EXT: +#endif + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glStencilOp called with bogus fail: %d", fail); + return; + } + + switch (zfail) { + case GL_KEEP: + case GL_ZERO: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: +#ifdef CR_EXT_stencil_wrap + case GL_INCR_WRAP_EXT: + case GL_DECR_WRAP_EXT: +#endif + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glStencilOp called with bogus zfail: %d", zfail); + return; + } + + switch (zpass) { + case GL_KEEP: + case GL_ZERO: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: +#ifdef CR_EXT_stencil_wrap + case GL_INCR_WRAP_EXT: + case GL_DECR_WRAP_EXT: +#endif + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glStencilOp called with bogus zpass: %d", zpass); + return; + } + + count = crStateStencilBufferGetIdxAndCount(s, face, &idx, &bitsIdx); + if (count) + { + for (i = idx; i < idx + count; ++i) + { + crStateStencilBufferOp(g, &s->buffers[i], fail, zfail, zpass); + } + + DIRTY(sb->bufferRefs[bitsIdx].op, g->neg_bitid); + + DIRTY(sb->dirty, g->neg_bitid); + } +} + +void STATE_APIENTRY crStateStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ + if (!face) + { + /* crStateStencilOpPerform accepts 0 value, while glStencilOpSeparate does not, + * filter it out here */ + crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateStencilOpSeparate"); + return; + } + crStateStencilOpPerform (0, fail, zfail, zpass); +} + +void STATE_APIENTRY crStateStencilOp (GLenum fail, GLenum zfail, GLenum zpass) +{ + crStateStencilOpPerform (0, fail, zfail, zpass); +} + +void STATE_APIENTRY crStateClearStencil (GLint c) +{ + CRContext *g = GetCurrentContext(); + CRStencilState *s = &(g->stencil); + CRStateBits *stateb = GetCurrentBits(); + CRStencilBits *sb = &(stateb->stencil); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glClearStencil called in begin/end"); + return; + } + + FLUSH(); + + s->clearValue = c; + + DIRTY(sb->clearValue, g->neg_bitid); + DIRTY(sb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateStencilMask (GLuint mask) +{ + CRContext *g = GetCurrentContext(); + CRStencilState *s = &(g->stencil); + CRStateBits *stateb = GetCurrentBits(); + CRStencilBits *sb = &(stateb->stencil); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glStencilMask called in begin/end"); + return; + } + + FLUSH(); + + s->writeMask = mask; + + DIRTY(sb->writeMask, g->neg_bitid); + DIRTY(sb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateActiveStencilFaceEXT (GLenum face) +{ + CRContext *g = GetCurrentContext(); + CRStencilState *s = &(g->stencil); + CRStateBits *stateb = GetCurrentBits(); + CRStencilBits *sb = &(stateb->stencil); + + switch (face) + { + case GL_FRONT: + case GL_BACK: + s->activeStencilFace = face; + break; + default: + crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateActiveStencilFaceEXT"); + return; + } + + DIRTY(sb->activeStencilFace, g->neg_bitid); + DIRTY(sb->dirty, g->neg_bitid); +} + +#ifdef CRSTATE_DEBUG_STENCIL_ERR +#define CRSTATE_CLEARERR() do { \ + while (diff_api.GetError() != GL_NO_ERROR) {} \ + } while (0) + +#define CRSTATE_CHECKGLERR(_op) do {\ + GLenum _glErr; \ + CRSTATE_CLEARERR(); \ + _op; \ + while ((_glErr = diff_api.GetError()) != GL_NO_ERROR) { Assert(0);} \ + }while (0) +#else +#define CRSTATE_CHECKGLERR(_op) do { _op; } while (0) +#endif + +#define CR_STATE_STENCIL_FUNC_MATCH(_s1, _i1, _s2, _i2) (\ + (_s1)->buffers[(_i1)].func == (_s2)->buffers[(_i2)].func && \ + (_s1)->buffers[(_i1)].ref == (_s2)->buffers[(_i2)].ref && \ + (_s1)->buffers[(_i1)].mask == (_s2)->buffers[(_i2)].mask) + +#define CR_STATE_STENCIL_FUNC_COPY(_s1, _i1, _s2, _i2) do { \ + (_s1)->buffers[(_i1)].func = (_s2)->buffers[(_i2)].func; \ + (_s1)->buffers[(_i1)].ref = (_s2)->buffers[(_i2)].ref; \ + (_s1)->buffers[(_i1)].mask = (_s2)->buffers[(_i2)].mask; \ + } while (0) + + +#define CR_STATE_STENCIL_OP_MATCH(_s1, _i1, _s2, _i2) (\ + (_s1)->buffers[(_i1)].fail == (_s2)->buffers[(_i2)].fail && \ + (_s1)->buffers[(_i1)].passDepthFail == (_s2)->buffers[(_i2)].passDepthFail && \ + (_s1)->buffers[(_i1)].passDepthPass == (_s2)->buffers[(_i2)].passDepthPass) + +#define CR_STATE_STENCIL_OP_COPY(_s1, _i1, _s2, _i2) do { \ + (_s1)->buffers[(_i1)].fail = (_s2)->buffers[(_i2)].fail; \ + (_s1)->buffers[(_i1)].passDepthFail = (_s2)->buffers[(_i2)].passDepthFail; \ + (_s1)->buffers[(_i1)].passDepthPass = (_s2)->buffers[(_i2)].passDepthPass; \ + } while (0) + + +void crStateStencilDiff(CRStencilBits *b, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + CRStencilState *from = &(fromCtx->stencil); + CRStencilState *to = &(toCtx->stencil); + unsigned int j, i; + GLenum activeFace; + GLboolean backIsSet = GL_FALSE, frontIsSet = GL_FALSE, frontBackDirty, frontDirty, backDirty; + GLchar frontMatch = -1, backMatch = -1, toFrontBackMatch = -1; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + for (j=0;j<CR_MAX_BITARRAY;j++) + nbitID[j] = ~bitID[j]; + i = 0; /* silence compiler */ + + if (CHECKDIRTY(b->enable, bitID)) + { + glAble able[2]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + if (from->stencilTest != to->stencilTest) + { + able[to->stencilTest](GL_STENCIL_TEST); + from->stencilTest = to->stencilTest; + } + CLEARDIRTY(b->enable, nbitID); + } + + if (CHECKDIRTY(b->enableTwoSideEXT, bitID)) + { + glAble able[2]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + if (from->stencilTwoSideEXT != to->stencilTwoSideEXT) + { + able[to->stencilTwoSideEXT](GL_STENCIL_TEST_TWO_SIDE_EXT); + from->stencilTwoSideEXT = to->stencilTwoSideEXT; + } + CLEARDIRTY(b->enableTwoSideEXT, nbitID); + } + + if (CHECKDIRTY(b->clearValue, bitID)) + { + if (from->clearValue != to->clearValue) + { + diff_api.ClearStencil (to->clearValue); + from->clearValue = to->clearValue; + } + CLEARDIRTY(b->clearValue, nbitID); + } + + activeFace = to->activeStencilFace; + + + /* func */ + frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, bitID); + frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, bitID); + backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, bitID); +#define CR_STATE_STENCIL_FUNC_FRONT_MATCH() ( \ + frontMatch >= 0 ? \ + frontMatch \ + : (frontMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT))) + +#define CR_STATE_STENCIL_FUNC_BACK_MATCH() ( \ + backMatch >= 0 ? \ + backMatch \ + : (backMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK))) + +#define CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH() ( \ + toFrontBackMatch >= 0 ? \ + toFrontBackMatch \ + : (toFrontBackMatch = CR_STATE_STENCIL_FUNC_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK))) + + if (frontBackDirty) + { + if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH() + || !CR_STATE_STENCIL_FUNC_BACK_MATCH()) + { + if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH()) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask); + + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask); + + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + frontIsSet = GL_TRUE; + } + else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH()) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask); + + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK); + + backIsSet = GL_TRUE; + } + } + + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, nbitID); + } + + if (frontDirty) + { + if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()) + { + if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH()) + { + if (!frontIsSet || !backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask); + + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()) + { + if (!frontIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask); + + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + frontIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH()) + { + if (!backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask); + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK); + backIsSet = GL_TRUE; + } + } + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, nbitID); + } + + + if (backDirty) + { + if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()) + { + if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH()) + { + if (!frontIsSet || !backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask); + + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()) + { + if (!frontIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask); + + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + frontIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH()) + { + if (!backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask); + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK); + backIsSet = GL_TRUE; + } + } + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, nbitID); + } + + if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, bitID)) + { + if (!CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK)) + { + if (activeFace == GL_FRONT) + { + diff_api.ActiveStencilFaceEXT(GL_BACK); + activeFace = GL_BACK; + } + + diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].mask); + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK); + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, nbitID); + } + +#undef CR_STATE_STENCIL_FUNC_FRONT_MATCH +#undef CR_STATE_STENCIL_FUNC_BACK_MATCH +#undef CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH + + /* op */ + backIsSet = GL_FALSE, frontIsSet = GL_FALSE; + frontMatch = -1, backMatch = -1, toFrontBackMatch = -1; + frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, bitID); + frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, bitID); + backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, bitID); + +#define CR_STATE_STENCIL_OP_FRONT_MATCH() ( \ + frontMatch >= 0 ? \ + frontMatch \ + : (frontMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT))) + +#define CR_STATE_STENCIL_OP_BACK_MATCH() ( \ + backMatch >= 0 ? \ + backMatch \ + : (backMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK))) + +#define CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH() ( \ + toFrontBackMatch >= 0 ? \ + toFrontBackMatch \ + : (toFrontBackMatch = CR_STATE_STENCIL_OP_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK))) + + if (frontBackDirty) + { + if (!CR_STATE_STENCIL_OP_FRONT_MATCH() + || !CR_STATE_STENCIL_OP_BACK_MATCH()) + { + if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH()) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass); + + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + else if (!CR_STATE_STENCIL_OP_FRONT_MATCH()) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass); + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + frontIsSet = GL_TRUE; + } + else if (!CR_STATE_STENCIL_OP_BACK_MATCH()) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass); + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK); + backIsSet = GL_TRUE; + } + } + + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, nbitID); + } + + if (frontDirty) + { + if (!CR_STATE_STENCIL_OP_FRONT_MATCH()) + { + if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH()) + { + if (!frontIsSet || !backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass); + + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_OP_FRONT_MATCH()) + { + if (!frontIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass); + + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + + frontIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_OP_BACK_MATCH()) + { + if (!backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass); + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK); + backIsSet = GL_TRUE; + } + } + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, nbitID); + } + + + if (backDirty) + { + if (!CR_STATE_STENCIL_OP_FRONT_MATCH()) + { + if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH()) + { + if (!frontIsSet || !backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass); + + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_OP_FRONT_MATCH()) + { + if (!frontIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass); + + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + + frontIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_OP_BACK_MATCH()) + { + if (!backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass); + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK); + backIsSet = GL_TRUE; + } + } + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, nbitID); + } + + if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, bitID)) + { + if (!CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK)) + { + if (activeFace == GL_FRONT) + { + diff_api.ActiveStencilFaceEXT(GL_BACK); + activeFace = GL_BACK; + } + + diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthPass); + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK); + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, nbitID); + } + +#undef CR_STATE_STENCIL_OP_FRONT_MATCH +#undef CR_STATE_STENCIL_OP_BACK_MATCH +#undef CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH + + + if (activeFace != to->activeStencilFace) + { + diff_api.ActiveStencilFaceEXT(activeFace); + } + + if (CHECKDIRTY(b->activeStencilFace, bitID)) + { + if (from->activeStencilFace != to->activeStencilFace) + { + /* we already did it ( see above )*/ + /* diff_api.ActiveStencilFaceEXT(to->activeStencilFace); */ + from->activeStencilFace = to->activeStencilFace; + } + CLEARDIRTY(b->activeStencilFace, nbitID); + } + + if (CHECKDIRTY(b->writeMask, bitID)) + { + if (from->writeMask != to->writeMask) + { + diff_api.StencilMask (to->writeMask); + from->writeMask = to->writeMask; + } + CLEARDIRTY(b->writeMask, nbitID); + } + CLEARDIRTY(b->dirty, nbitID); +} + +void crStateStencilSwitch(CRStencilBits *b, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + CRStencilState *from = &(fromCtx->stencil); + CRStencilState *to = &(toCtx->stencil); + unsigned int j, i; + GLenum activeFace; + GLboolean backIsSet = GL_FALSE, frontIsSet = GL_FALSE, frontBackDirty, frontDirty, backDirty; + GLchar frontMatch = -1, backMatch = -1, toFrontBackMatch = -1; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + for (j=0;j<CR_MAX_BITARRAY;j++) + nbitID[j] = ~bitID[j]; + i = 0; /* silence compiler */ + + if (CHECKDIRTY(b->enable, bitID)) + { + glAble able[2]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + if (from->stencilTest != to->stencilTest) + { + CRSTATE_CHECKGLERR(able[to->stencilTest](GL_STENCIL_TEST)); + FILLDIRTY(b->enable); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->enable, nbitID); + } + if (CHECKDIRTY(b->enableTwoSideEXT, bitID)) + { + glAble able[2]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + if (from->stencilTwoSideEXT != to->stencilTwoSideEXT) + { + CRSTATE_CHECKGLERR(able[to->stencilTwoSideEXT](GL_STENCIL_TEST_TWO_SIDE_EXT)); + FILLDIRTY(b->enableTwoSideEXT); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->enableTwoSideEXT, nbitID); + } + if (CHECKDIRTY(b->clearValue, bitID)) + { + if (from->clearValue != to->clearValue) + { + CRSTATE_CHECKGLERR(diff_api.ClearStencil (to->clearValue)); + FILLDIRTY(b->clearValue); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->clearValue, nbitID); + } + + activeFace = from->activeStencilFace; + + /* func */ + frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, bitID); + frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, bitID); + backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, bitID); +#define CR_STATE_STENCIL_FUNC_FRONT_MATCH() ( \ + frontMatch >= 0 ? \ + frontMatch \ + : (frontMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT))) + +#define CR_STATE_STENCIL_FUNC_BACK_MATCH() ( \ + backMatch >= 0 ? \ + backMatch \ + : (backMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK))) + +#define CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH() ( \ + toFrontBackMatch >= 0 ? \ + toFrontBackMatch \ + : (toFrontBackMatch = CR_STATE_STENCIL_FUNC_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK))) + + if (frontBackDirty) + { + if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH() + || !CR_STATE_STENCIL_FUNC_BACK_MATCH()) + { + if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH()) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask)); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask)); + frontIsSet = GL_TRUE; + } + else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH()) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask)); + backIsSet = GL_TRUE; + } + FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func); + FILLDIRTY(b->dirty); + } + + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, nbitID); + } + + if (frontDirty) + { + if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()) + { + if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH()) + { + if (!frontIsSet || !backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask)); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()) + { + if (!frontIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask)); + frontIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH()) + { + if (!backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask)); + backIsSet = GL_TRUE; + } + } + FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, nbitID); + } + + + if (backDirty) + { + if (!CR_STATE_STENCIL_FUNC_BACK_MATCH()) + { + if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH()) + { + if (!frontIsSet || !backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask)); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()) + { + if (!frontIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask)); + frontIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH()) + { + if (!backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask)); + backIsSet = GL_TRUE; + } + } + FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, nbitID); + } + + if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, bitID)) + { + if (!CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK)) + { + if (activeFace == GL_FRONT) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_BACK)); + activeFace = GL_BACK; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].mask)); + + FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, nbitID); + } + +#undef CR_STATE_STENCIL_FUNC_FRONT_MATCH +#undef CR_STATE_STENCIL_FUNC_BACK_MATCH +#undef CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH + + /* op */ + backIsSet = GL_FALSE, frontIsSet = GL_FALSE; + frontMatch = -1, backMatch = -1, toFrontBackMatch = -1; + frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, bitID); + frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, bitID); + backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, bitID); + +#define CR_STATE_STENCIL_OP_FRONT_MATCH() ( \ + frontMatch >= 0 ? \ + frontMatch \ + : (frontMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT))) + +#define CR_STATE_STENCIL_OP_BACK_MATCH() ( \ + backMatch >= 0 ? \ + backMatch \ + : (backMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK))) + +#define CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH() ( \ + toFrontBackMatch >= 0 ? \ + toFrontBackMatch \ + : (toFrontBackMatch = CR_STATE_STENCIL_OP_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK))) + + if (frontBackDirty) + { + if (!CR_STATE_STENCIL_OP_FRONT_MATCH() + || !CR_STATE_STENCIL_OP_BACK_MATCH()) + { + if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH()) + { + if (activeFace == GL_BACK) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT)); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass)); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + else if (!CR_STATE_STENCIL_OP_FRONT_MATCH()) + { + if (activeFace == GL_BACK) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT)); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass)); + frontIsSet = GL_TRUE; + } + else if (!CR_STATE_STENCIL_OP_BACK_MATCH()) + { + if (activeFace == GL_BACK) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT)); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass)); + backIsSet = GL_TRUE; + } + FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op); + FILLDIRTY(b->dirty); + } + + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, nbitID); + } + + if (frontDirty) + { + if (!CR_STATE_STENCIL_OP_FRONT_MATCH()) + { + if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH()) + { + if (!frontIsSet || !backIsSet) + { + if (activeFace == GL_BACK) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT)); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass)); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_OP_FRONT_MATCH()) + { + if (!frontIsSet) + { + if (activeFace == GL_BACK) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT)); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass)); + frontIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_OP_BACK_MATCH()) + { + if (!backIsSet) + { + if (activeFace == GL_BACK) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT)); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass)); + backIsSet = GL_TRUE; + } + } + + FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, nbitID); + } + + + if (backDirty) + { + if (!CR_STATE_STENCIL_OP_BACK_MATCH()) + { + if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH()) + { + if (!frontIsSet || !backIsSet) + { + if (activeFace == GL_BACK) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT)); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass)); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_OP_FRONT_MATCH()) + { + if (!frontIsSet) + { + if (activeFace == GL_BACK) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT)); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass)); + frontIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_OP_BACK_MATCH()) + { + if (!backIsSet) + { + if (activeFace == GL_BACK) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT)); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass)); + backIsSet = GL_TRUE; + } + } + + FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, nbitID); + } + + if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, bitID)) + { + if (!CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK)) + { + if (activeFace == GL_FRONT) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_BACK)); + activeFace = GL_BACK; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthPass)); + + FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, nbitID); + } + +#undef CR_STATE_STENCIL_OP_FRONT_MATCH +#undef CR_STATE_STENCIL_OP_BACK_MATCH +#undef CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH + + if (activeFace != to->activeStencilFace) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(activeFace)); + } + + if (CHECKDIRTY(b->activeStencilFace, bitID)) + { + if (from->activeStencilFace != to->activeStencilFace) + { + /* we already did it ( see above )*/ + /* diff_api.ActiveStencilFaceEXT(to->activeStencilFace); */ + FILLDIRTY(b->activeStencilFace); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->activeStencilFace, nbitID); + } + + if (CHECKDIRTY(b->writeMask, bitID)) + { + if (from->writeMask != to->writeMask) + { + CRSTATE_CHECKGLERR(diff_api.StencilMask (to->writeMask)); + FILLDIRTY(b->writeMask); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->writeMask, nbitID); + } + + CLEARDIRTY(b->dirty, nbitID); +} + diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.txt new file mode 100644 index 00000000..9632e0c3 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +:enable:stencilTest:GL_STENCIL_TEST +:clearValue:clearValue:ClearStencil +stencilTest:func:func,ref,mask:StencilFunc +stencilTest:op:fail,passDepthFail,passDepthPass:StencilOp +stencilTest:writeMask:writeMask:StencilMask diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c new file mode 100644 index 00000000..6854334b --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c @@ -0,0 +1,1469 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "state.h" +#include "state/cr_statetypes.h" +#include "state/cr_texture.h" +#include "cr_hash.h" +#include "cr_string.h" +#include "cr_mem.h" +#include "cr_version.h" +#include "state_internals.h" + + +#define UNIMPLEMENTED() crStateError(__LINE__,__FILE__,GL_INVALID_OPERATION, "Unimplemented something or other" ) + + +#if 0 /* NOT USED??? */ +void crStateTextureObjSwitchCallback( unsigned long key, void *data1, void *data2 ) +{ + CRTextureObj *tobj = (CRTextureObj *) data1; + CRContext *fromCtx = (CRContext *) data2; + unsigned int i = 0; + unsigned int j = 0; + CRbitvalue *bitID = fromCtx->bitid; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + + for (j=0;j<CR_MAX_BITARRAY;j++) + nbitID[j] = ~bitID[j]; + + if (!tobj) return; + + FILLDIRTY(tobj->dirty); + FILLDIRTY(tobj->imageBit); + + for (i = 0; i < fromCtx->limits.maxTextureUnits; i++) + { + int j; + + FILLDIRTY(tobj->paramsBit[i]); + + switch (tobj->target) + { + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + for (j = 0; j <= fromCtx->texture.maxLevel; j++) + { + CRTextureLevel *tl = &(tobj->level[j]); + FILLDIRTY(tl->dirty); + } + break; +#ifdef CR_OPENGL_VERSION_1_2 + case GL_TEXTURE_3D: +#endif + for (j = 0; j <= fromCtx->texture.max3DLevel; j++) + { + CRTextureLevel *tl = &(tobj->level[j]); + FILLDIRTY(tl->dirty); + } + break; +#ifdef CR_ARB_texture_cube_map + case GL_TEXTURE_CUBE_MAP_ARB: + for (j = 0; j <= fromCtx->texture.maxCubeMapLevel; j++) + { + CRTextureLevel *tl; + /* Positive X */ + tl = &(tobj->level[j]); + FILLDIRTY(tl->dirty); + /* Negative X */ + tl = &(tobj->negativeXlevel[j]); + FILLDIRTY(tl->dirty); + /* Positive Y */ + tl = &(tobj->positiveYlevel[j]); + FILLDIRTY(tl->dirty); + /* Negative Y */ + tl = &(tobj->negativeYlevel[j]); + FILLDIRTY(tl->dirty); + /* Positive Z */ + tl = &(tobj->positiveZlevel[j]); + FILLDIRTY(tl->dirty); + /* Negative Z */ + tl = &(tobj->negativeZlevel[j]); + FILLDIRTY(tl->dirty); + } + break; +#endif + default: + UNIMPLEMENTED(); + } + } +} +#endif + + +void crStateTextureSwitch( CRTextureBits *tb, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx ) +{ + CRTextureState *from = &(fromCtx->texture); + const CRTextureState *to = &(toCtx->texture); + unsigned int i,j; + glAble able[2]; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + unsigned int activeUnit = (unsigned int) -1; + + for (j=0;j<CR_MAX_BITARRAY;j++) + nbitID[j] = ~bitID[j]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + + for (i = 0; i < fromCtx->limits.maxTextureUnits; i++) + { + if (CHECKDIRTY(tb->enable[i], bitID)) + { + if (activeUnit != i) { + diff_api.ActiveTextureARB( i + GL_TEXTURE0_ARB ); + activeUnit = i; + } + if (from->unit[i].enabled1D != to->unit[i].enabled1D) + { + able[to->unit[i].enabled1D](GL_TEXTURE_1D); + FILLDIRTY(tb->enable[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].enabled2D != to->unit[i].enabled2D) + { + able[to->unit[i].enabled2D](GL_TEXTURE_2D); + FILLDIRTY(tb->enable[i]); + FILLDIRTY(tb->dirty); + } +#ifdef CR_OPENGL_VERSION_1_2 + if (from->unit[i].enabled3D != to->unit[i].enabled3D) + { + able[to->unit[i].enabled3D](GL_TEXTURE_3D); + FILLDIRTY(tb->enable[i]); + FILLDIRTY(tb->dirty); + } +#endif +#ifdef CR_ARB_texture_cube_map + if (fromCtx->extensions.ARB_texture_cube_map && + from->unit[i].enabledCubeMap != to->unit[i].enabledCubeMap) + { + able[to->unit[i].enabledCubeMap](GL_TEXTURE_CUBE_MAP_ARB); + FILLDIRTY(tb->enable[i]); + FILLDIRTY(tb->dirty); + } +#endif +#ifdef CR_NV_texture_rectangle + if (fromCtx->extensions.NV_texture_rectangle && + from->unit[i].enabledRect != to->unit[i].enabledRect) + { + able[to->unit[i].enabledRect](GL_TEXTURE_RECTANGLE_NV); + FILLDIRTY(tb->enable[i]); + FILLDIRTY(tb->dirty); + } +#endif + if (from->unit[i].textureGen.s != to->unit[i].textureGen.s || + from->unit[i].textureGen.t != to->unit[i].textureGen.t || + from->unit[i].textureGen.r != to->unit[i].textureGen.r || + from->unit[i].textureGen.q != to->unit[i].textureGen.q) + { + able[to->unit[i].textureGen.s](GL_TEXTURE_GEN_S); + able[to->unit[i].textureGen.t](GL_TEXTURE_GEN_T); + able[to->unit[i].textureGen.r](GL_TEXTURE_GEN_R); + able[to->unit[i].textureGen.q](GL_TEXTURE_GEN_Q); + FILLDIRTY(tb->enable[i]); + FILLDIRTY(tb->dirty); + } + CLEARDIRTY(tb->enable[i], nbitID); + } + + /* + ** A thought on switching with textures: + ** Since we are only performing a switch + ** and not a sync, we won't need to + ** update individual textures, just + ** the bindings.... + */ + + if (CHECKDIRTY(tb->current[i], bitID)) + { + if (activeUnit != i) { + diff_api.ActiveTextureARB( i + GL_TEXTURE0_ARB ); + activeUnit = i; + } + if (from->unit[i].currentTexture1D->hwid != to->unit[i].currentTexture1D->hwid) + { + diff_api.BindTexture(GL_TEXTURE_1D, crStateGetTextureObjHWID(to->unit[i].currentTexture1D)); + FILLDIRTY(tb->current[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].currentTexture2D->hwid != to->unit[i].currentTexture2D->hwid) + { + diff_api.BindTexture(GL_TEXTURE_2D, crStateGetTextureObjHWID(to->unit[i].currentTexture2D)); + FILLDIRTY(tb->current[i]); + FILLDIRTY(tb->dirty); + } +#ifdef CR_OPENGL_VERSION_1_2 + if (from->unit[i].currentTexture3D->hwid != to->unit[i].currentTexture3D->hwid) + { + diff_api.BindTexture(GL_TEXTURE_3D, crStateGetTextureObjHWID(to->unit[i].currentTexture3D)); + FILLDIRTY(tb->current[i]); + FILLDIRTY(tb->dirty); + } +#endif +#ifdef CR_ARB_texture_cube_map + if (fromCtx->extensions.ARB_texture_cube_map && + from->unit[i].currentTextureCubeMap->hwid != to->unit[i].currentTextureCubeMap->hwid) + { + diff_api.BindTexture(GL_TEXTURE_CUBE_MAP_ARB, crStateGetTextureObjHWID(to->unit[i].currentTextureCubeMap)); + FILLDIRTY(tb->current[i]); + FILLDIRTY(tb->dirty); + } +#endif +#ifdef CR_NV_texture_rectangle + if (fromCtx->extensions.NV_texture_rectangle && + from->unit[i].currentTextureRect->hwid != to->unit[i].currentTextureRect->hwid) + { + diff_api.BindTexture(GL_TEXTURE_RECTANGLE_NV, crStateGetTextureObjHWID(to->unit[i].currentTextureRect)); + FILLDIRTY(tb->current[i]); + FILLDIRTY(tb->dirty); + } +#endif + CLEARDIRTY(tb->current[i], nbitID); + } + + if (CHECKDIRTY(tb->objGen[i], bitID)) + { + if (activeUnit != i) { + diff_api.ActiveTextureARB( i + GL_TEXTURE0_ARB ); + activeUnit = i; + } + if (from->unit[i].objSCoeff.x != to->unit[i].objSCoeff.x || + from->unit[i].objSCoeff.y != to->unit[i].objSCoeff.y || + from->unit[i].objSCoeff.z != to->unit[i].objSCoeff.z || + from->unit[i].objSCoeff.w != to->unit[i].objSCoeff.w) + { + GLfloat f[4]; + f[0] = to->unit[i].objSCoeff.x; + f[1] = to->unit[i].objSCoeff.y; + f[2] = to->unit[i].objSCoeff.z; + f[3] = to->unit[i].objSCoeff.w; + diff_api.TexGenfv (GL_S, GL_OBJECT_PLANE, (const GLfloat *) f); + FILLDIRTY(tb->objGen[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].objTCoeff.x != to->unit[i].objTCoeff.x || + from->unit[i].objTCoeff.y != to->unit[i].objTCoeff.y || + from->unit[i].objTCoeff.z != to->unit[i].objTCoeff.z || + from->unit[i].objTCoeff.w != to->unit[i].objTCoeff.w) { + GLfloat f[4]; + f[0] = to->unit[i].objTCoeff.x; + f[1] = to->unit[i].objTCoeff.y; + f[2] = to->unit[i].objTCoeff.z; + f[3] = to->unit[i].objTCoeff.w; + diff_api.TexGenfv (GL_T, GL_OBJECT_PLANE, (const GLfloat *) f); + FILLDIRTY(tb->objGen[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].objRCoeff.x != to->unit[i].objRCoeff.x || + from->unit[i].objRCoeff.y != to->unit[i].objRCoeff.y || + from->unit[i].objRCoeff.z != to->unit[i].objRCoeff.z || + from->unit[i].objRCoeff.w != to->unit[i].objRCoeff.w) { + GLfloat f[4]; + f[0] = to->unit[i].objRCoeff.x; + f[1] = to->unit[i].objRCoeff.y; + f[2] = to->unit[i].objRCoeff.z; + f[3] = to->unit[i].objRCoeff.w; + diff_api.TexGenfv (GL_R, GL_OBJECT_PLANE, (const GLfloat *) f); + FILLDIRTY(tb->objGen[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].objQCoeff.x != to->unit[i].objQCoeff.x || + from->unit[i].objQCoeff.y != to->unit[i].objQCoeff.y || + from->unit[i].objQCoeff.z != to->unit[i].objQCoeff.z || + from->unit[i].objQCoeff.w != to->unit[i].objQCoeff.w) { + GLfloat f[4]; + f[0] = to->unit[i].objQCoeff.x; + f[1] = to->unit[i].objQCoeff.y; + f[2] = to->unit[i].objQCoeff.z; + f[3] = to->unit[i].objQCoeff.w; + diff_api.TexGenfv (GL_Q, GL_OBJECT_PLANE, (const GLfloat *) f); + FILLDIRTY(tb->objGen[i]); + FILLDIRTY(tb->dirty); + } + CLEARDIRTY(tb->objGen[i], nbitID); + } + if (CHECKDIRTY(tb->eyeGen[i], bitID)) + { + if (activeUnit != i) { + diff_api.ActiveTextureARB( i + GL_TEXTURE0_ARB ); + activeUnit = i; + } + diff_api.MatrixMode(GL_MODELVIEW); + diff_api.PushMatrix(); + diff_api.LoadIdentity(); + if (from->unit[i].eyeSCoeff.x != to->unit[i].eyeSCoeff.x || + from->unit[i].eyeSCoeff.y != to->unit[i].eyeSCoeff.y || + from->unit[i].eyeSCoeff.z != to->unit[i].eyeSCoeff.z || + from->unit[i].eyeSCoeff.w != to->unit[i].eyeSCoeff.w) { + GLfloat f[4]; + f[0] = to->unit[i].eyeSCoeff.x; + f[1] = to->unit[i].eyeSCoeff.y; + f[2] = to->unit[i].eyeSCoeff.z; + f[3] = to->unit[i].eyeSCoeff.w; + diff_api.TexGenfv (GL_S, GL_EYE_PLANE, (const GLfloat *) f); + FILLDIRTY(tb->eyeGen[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].eyeTCoeff.x != to->unit[i].eyeTCoeff.x || + from->unit[i].eyeTCoeff.y != to->unit[i].eyeTCoeff.y || + from->unit[i].eyeTCoeff.z != to->unit[i].eyeTCoeff.z || + from->unit[i].eyeTCoeff.w != to->unit[i].eyeTCoeff.w) { + GLfloat f[4]; + f[0] = to->unit[i].eyeTCoeff.x; + f[1] = to->unit[i].eyeTCoeff.y; + f[2] = to->unit[i].eyeTCoeff.z; + f[3] = to->unit[i].eyeTCoeff.w; + diff_api.TexGenfv (GL_T, GL_EYE_PLANE, (const GLfloat *) f); + FILLDIRTY(tb->eyeGen[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].eyeRCoeff.x != to->unit[i].eyeRCoeff.x || + from->unit[i].eyeRCoeff.y != to->unit[i].eyeRCoeff.y || + from->unit[i].eyeRCoeff.z != to->unit[i].eyeRCoeff.z || + from->unit[i].eyeRCoeff.w != to->unit[i].eyeRCoeff.w) { + GLfloat f[4]; + f[0] = to->unit[i].eyeRCoeff.x; + f[1] = to->unit[i].eyeRCoeff.y; + f[2] = to->unit[i].eyeRCoeff.z; + f[3] = to->unit[i].eyeRCoeff.w; + diff_api.TexGenfv (GL_R, GL_EYE_PLANE, (const GLfloat *) f); + FILLDIRTY(tb->eyeGen[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].eyeQCoeff.x != to->unit[i].eyeQCoeff.x || + from->unit[i].eyeQCoeff.y != to->unit[i].eyeQCoeff.y || + from->unit[i].eyeQCoeff.z != to->unit[i].eyeQCoeff.z || + from->unit[i].eyeQCoeff.w != to->unit[i].eyeQCoeff.w) { + GLfloat f[4]; + f[0] = to->unit[i].eyeQCoeff.x; + f[1] = to->unit[i].eyeQCoeff.y; + f[2] = to->unit[i].eyeQCoeff.z; + f[3] = to->unit[i].eyeQCoeff.w; + diff_api.TexGenfv (GL_Q, GL_EYE_PLANE, (const GLfloat *) f); + FILLDIRTY(tb->eyeGen[i]); + FILLDIRTY(tb->dirty); + } + diff_api.PopMatrix(); + CLEARDIRTY(tb->eyeGen[i], nbitID); + } + if (CHECKDIRTY(tb->genMode[i], bitID)) + { + if (activeUnit != i) { + diff_api.ActiveTextureARB( i + GL_TEXTURE0_ARB ); + activeUnit = i; + } + if (from->unit[i].gen.s != to->unit[i].gen.s || + from->unit[i].gen.t != to->unit[i].gen.t || + from->unit[i].gen.r != to->unit[i].gen.r || + from->unit[i].gen.q != to->unit[i].gen.q) + { + diff_api.TexGeni (GL_S, GL_TEXTURE_GEN_MODE, to->unit[i].gen.s); + diff_api.TexGeni (GL_T, GL_TEXTURE_GEN_MODE, to->unit[i].gen.t); + diff_api.TexGeni (GL_R, GL_TEXTURE_GEN_MODE, to->unit[i].gen.r); + diff_api.TexGeni (GL_Q, GL_TEXTURE_GEN_MODE, to->unit[i].gen.q); + FILLDIRTY(tb->genMode[i]); + FILLDIRTY(tb->dirty); + } + CLEARDIRTY(tb->genMode[i], nbitID); + } + CLEARDIRTY(tb->dirty, nbitID); + + /* Texture enviroment */ + if (CHECKDIRTY(tb->envBit[i], bitID)) + { + if (activeUnit != i) { + diff_api.ActiveTextureARB( i + GL_TEXTURE0_ARB ); + activeUnit = i; + } + if (from->unit[i].envMode != to->unit[i].envMode) + { + diff_api.TexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, to->unit[i].envMode); + FILLDIRTY(tb->envBit[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].envColor.r != to->unit[i].envColor.r || + from->unit[i].envColor.g != to->unit[i].envColor.g || + from->unit[i].envColor.b != to->unit[i].envColor.b || + from->unit[i].envColor.a != to->unit[i].envColor.a) + { + GLfloat f[4]; + f[0] = to->unit[i].envColor.r; + f[1] = to->unit[i].envColor.g; + f[2] = to->unit[i].envColor.b; + f[3] = to->unit[i].envColor.a; + diff_api.TexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (const GLfloat *) f); + FILLDIRTY(tb->envBit[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].combineModeRGB != to->unit[i].combineModeRGB) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, to->unit[i].combineModeRGB); + FILLDIRTY(tb->envBit[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].combineModeA != to->unit[i].combineModeA) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, to->unit[i].combineModeA); + FILLDIRTY(tb->envBit[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].combineSourceRGB[0] != to->unit[i].combineSourceRGB[0]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, to->unit[i].combineSourceRGB[0]); + FILLDIRTY(tb->envBit[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].combineSourceRGB[1] != to->unit[i].combineSourceRGB[1]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, to->unit[i].combineSourceRGB[1]); + FILLDIRTY(tb->envBit[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].combineSourceRGB[2] != to->unit[i].combineSourceRGB[2]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, to->unit[i].combineSourceRGB[2]); + FILLDIRTY(tb->envBit[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].combineSourceA[0] != to->unit[i].combineSourceA[0]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, to->unit[i].combineSourceA[0]); + FILLDIRTY(tb->envBit[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].combineSourceA[1] != to->unit[i].combineSourceA[1]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, to->unit[i].combineSourceA[1]); + FILLDIRTY(tb->envBit[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].combineSourceA[2] != to->unit[i].combineSourceA[2]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, to->unit[i].combineSourceA[2]); + FILLDIRTY(tb->envBit[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].combineOperandRGB[0] != to->unit[i].combineOperandRGB[0]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, to->unit[i].combineOperandRGB[0]); + FILLDIRTY(tb->envBit[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].combineOperandRGB[1] != to->unit[i].combineOperandRGB[1]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, to->unit[i].combineOperandRGB[1]); + FILLDIRTY(tb->envBit[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].combineOperandRGB[2] != to->unit[i].combineOperandRGB[2]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, to->unit[i].combineOperandRGB[2]); + FILLDIRTY(tb->envBit[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].combineOperandA[0] != to->unit[i].combineOperandA[0]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, to->unit[i].combineOperandA[0]); + FILLDIRTY(tb->envBit[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].combineOperandA[1] != to->unit[i].combineOperandA[1]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, to->unit[i].combineOperandA[1]); + FILLDIRTY(tb->envBit[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].combineOperandA[2] != to->unit[i].combineOperandA[2]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, to->unit[i].combineOperandA[2]); + FILLDIRTY(tb->envBit[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].combineScaleRGB != to->unit[i].combineScaleRGB) + { + diff_api.TexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, to->unit[i].combineScaleRGB); + FILLDIRTY(tb->envBit[i]); + FILLDIRTY(tb->dirty); + } + if (from->unit[i].combineScaleA != to->unit[i].combineScaleA) + { + diff_api.TexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, to->unit[i].combineScaleA); + FILLDIRTY(tb->envBit[i]); + FILLDIRTY(tb->dirty); + } + CLEARDIRTY(tb->envBit[i], nbitID); + } + } + + /* Resend texture images */ + if (toCtx->shared->bTexResyncNeeded) + { + toCtx->shared->bTexResyncNeeded = GL_FALSE; + + crStateDiffAllTextureObjects(toCtx, bitID, GL_TRUE); + } + + /* After possible fiddling put them back now */ + if (activeUnit != toCtx->texture.curTextureUnit) { + diff_api.ActiveTextureARB( toCtx->texture.curTextureUnit + GL_TEXTURE0_ARB ); + } + diff_api.MatrixMode(toCtx->transform.matrixMode); +} + + +/* + * Check the dirty bits for the specified texture on a given unit to + * determine if any of its images are dirty. + * Return: 1 -- dirty, 0 -- clean + */ +int crStateTextureCheckDirtyImages(CRContext *from, CRContext *to, GLenum target, int textureUnit) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *tsto; + CRbitvalue *bitID; + CRTextureObj *tobj = NULL; + int maxLevel = 0, i; + int face, numFaces; + + CRASSERT(to); + CRASSERT(from); + + tsto = &(to->texture); + bitID = from->bitid; + + CRASSERT(tsto); + + switch(target) + { + case GL_TEXTURE_1D: + tobj = tsto->unit[textureUnit].currentTexture1D; + maxLevel = tsto->maxLevel; + break; + case GL_TEXTURE_2D: + tobj = tsto->unit[textureUnit].currentTexture2D; + maxLevel = tsto->maxLevel; + break; +#ifdef CR_OPENGL_VERSION_1_2 + case GL_TEXTURE_3D: + tobj = tsto->unit[textureUnit].currentTexture3D; + maxLevel = tsto->max3DLevel; + break; +#endif +#ifdef CR_ARB_texture_cube_map + case GL_TEXTURE_CUBE_MAP: + if (g->extensions.ARB_texture_cube_map) { + tobj = tsto->unit[textureUnit].currentTextureCubeMap; + maxLevel = tsto->maxCubeMapLevel; + } + break; +#endif +#ifdef CR_NV_texture_rectangle + case GL_TEXTURE_RECTANGLE_NV: + if (g->extensions.NV_texture_rectangle) { + tobj = tsto->unit[textureUnit].currentTextureRect; + maxLevel = 1; + } + break; +#endif + default: + crError("Bad texture target in crStateTextureCheckDirtyImages()"); + return 0; + } + + if (!tobj) + { + return 0; + } + + numFaces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; + + for (face = 0; face < numFaces; face++) { + for (i = 0; i < maxLevel; i++) { + if (CHECKDIRTY(tobj->level[face][i].dirty, bitID)) + return 1; + } + } + + return 0; +} + + +/* + * Do texture state differencing for the given texture object. + */ +void +crStateTextureObjectDiff(CRContext *fromCtx, + const CRbitvalue *bitID, const CRbitvalue *nbitID, + CRTextureObj *tobj, GLboolean alwaysDirty) +{ + CRTextureState *from = &(fromCtx->texture); + glAble able[2]; + int u = 0; /* always use texture unit 0 for diff'ing */ + GLuint hwid = crStateGetTextureObjHWID(tobj); + + if (!hwid) + return; + + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + +#if 0 + /* XXX disabling this code fixed Wes Bethel's problem with missing/white + * textures. Setting the active texture unit here can screw up the + * current texture object bindings. + */ + /* Set active texture unit, and bind this texture object */ + if (from->curTextureUnit != u) { + diff_api.ActiveTextureARB( u + GL_TEXTURE0_ARB ); + from->curTextureUnit = u; + } +#endif + + diff_api.BindTexture(tobj->target, hwid); + + if (alwaysDirty || CHECKDIRTY(tobj->paramsBit[u], bitID)) + { + GLfloat f[4]; + f[0] = tobj->borderColor.r; + f[1] = tobj->borderColor.g; + f[2] = tobj->borderColor.b; + f[3] = tobj->borderColor.a; + diff_api.TexParameteri(tobj->target, GL_TEXTURE_BASE_LEVEL, tobj->baseLevel); + diff_api.TexParameteri(tobj->target, GL_TEXTURE_MAX_LEVEL, tobj->maxLevel); + diff_api.TexParameteri(tobj->target, GL_TEXTURE_MIN_FILTER, tobj->minFilter); + diff_api.TexParameteri(tobj->target, GL_TEXTURE_MAG_FILTER, tobj->magFilter); + diff_api.TexParameteri(tobj->target, GL_TEXTURE_WRAP_S, tobj->wrapS); + diff_api.TexParameteri(tobj->target, GL_TEXTURE_WRAP_T, tobj->wrapT); +#ifdef CR_OPENGL_VERSION_1_2 + diff_api.TexParameteri(tobj->target, GL_TEXTURE_WRAP_R, tobj->wrapR); + diff_api.TexParameterf(tobj->target, GL_TEXTURE_PRIORITY, tobj->priority); +#endif + diff_api.TexParameterfv(tobj->target, GL_TEXTURE_BORDER_COLOR, (const GLfloat *) f); +#ifdef CR_EXT_texture_filter_anisotropic + if (fromCtx->extensions.EXT_texture_filter_anisotropic) { + diff_api.TexParameterf(tobj->target, GL_TEXTURE_MAX_ANISOTROPY_EXT, tobj->maxAnisotropy); + } +#endif +#ifdef CR_ARB_depth_texture + if (fromCtx->extensions.ARB_depth_texture) + diff_api.TexParameteri(tobj->target, GL_DEPTH_TEXTURE_MODE_ARB, tobj->depthMode); +#endif +#ifdef CR_ARB_shadow + if (fromCtx->extensions.ARB_shadow) { + diff_api.TexParameteri(tobj->target, GL_TEXTURE_COMPARE_MODE_ARB, tobj->compareMode); + diff_api.TexParameteri(tobj->target, GL_TEXTURE_COMPARE_FUNC_ARB, tobj->compareFunc); + } +#endif +#ifdef CR_ARB_shadow_ambient + if (fromCtx->extensions.ARB_shadow_ambient) { + diff_api.TexParameterf(tobj->target, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, tobj->compareFailValue); + } +#endif +#ifdef CR_SGIS_generate_mipmap + if (fromCtx->extensions.SGIS_generate_mipmap) { + diff_api.TexParameteri(tobj->target, GL_GENERATE_MIPMAP_SGIS, tobj->generateMipmap); + } +#endif + if (!alwaysDirty) + CLEARDIRTY(tobj->paramsBit[u], nbitID); + } + + /* now, if the texture images are dirty */ + if (alwaysDirty || CHECKDIRTY(tobj->imageBit, bitID)) + { + int lvl; + int face; + + switch (tobj->target) + { + case GL_TEXTURE_1D: + for (lvl = 0; lvl <= from->maxLevel; lvl++) + { + CRTextureLevel *tl = &(tobj->level[0][lvl]); + if (alwaysDirty || CHECKDIRTY(tl->dirty, bitID)) + { + if (tl->generateMipmap) { + diff_api.TexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, 1); + } + if (tl->width) + { + if (tl->compressed) { + diff_api.CompressedTexImage1DARB(GL_TEXTURE_1D, lvl, + tl->internalFormat, tl->width, + tl->border, tl->bytes, tl->img); + } + else { + /* alignment must be one */ + diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, 0); + diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, 0); + diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, 1); + if (tl->generateMipmap) { + diff_api.TexParameteri(GL_TEXTURE_1D, GL_GENERATE_MIPMAP_SGIS, 1); + } + diff_api.TexImage1D(GL_TEXTURE_1D, lvl, + tl->internalFormat, + tl->width, tl->border, + tl->format, tl->type, tl->img); + } + } + if (!alwaysDirty) + { + CLEARDIRTY(tl->dirty, nbitID); + } +#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE + else + { + crFree(tl->img); + tl->img = NULL; + } +#endif + } + } + break; + case GL_TEXTURE_2D: + for (lvl = 0; lvl <= from->maxLevel; lvl++) + { + CRTextureLevel *tl = &(tobj->level[0][lvl]); + if (alwaysDirty || CHECKDIRTY(tl->dirty, bitID)) + { + if (tl->generateMipmap) { + diff_api.TexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, 1); + } + + if (tl->width && tl->height) + { + if (tl->compressed) { + diff_api.CompressedTexImage2DARB(GL_TEXTURE_2D, lvl, + tl->internalFormat, tl->width, + tl->height, tl->border, + tl->bytes, tl->img); + } + else { + /* alignment must be one */ + diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, 0); + diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, 0); + diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, 1); + diff_api.TexImage2D(GL_TEXTURE_2D, lvl, + tl->internalFormat, + tl->width, tl->height, tl->border, + tl->format, tl->type, tl->img); + } + } + + if (!alwaysDirty) + { + CLEARDIRTY(tl->dirty, nbitID); + } +#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE + else + { + crFree(tl->img); + tl->img = NULL; + } +#endif + } + } + break; +#ifdef CR_OPENGL_VERSION_1_2 + case GL_TEXTURE_3D: + for (lvl = 0; lvl <= from->max3DLevel; lvl++) + { + CRTextureLevel *tl = &(tobj->level[0][lvl]); + if (alwaysDirty || CHECKDIRTY(tl->dirty, bitID)) + { + if (tl->generateMipmap) { + diff_api.TexParameteri(GL_TEXTURE_3D, GL_GENERATE_MIPMAP_SGIS, 1); + } + + if (tl->width && tl->height) + { + if (tl->compressed) { + diff_api.CompressedTexImage3DARB(GL_TEXTURE_3D, lvl, + tl->internalFormat, tl->width, + tl->height, tl->depth, + tl->border, tl->bytes, tl->img); + } + else { + /* alignment must be one */ + diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, 0); + diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, 0); + diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, 1); + diff_api.TexImage3D(GL_TEXTURE_3D, lvl, + tl->internalFormat, + tl->width, tl->height, tl->depth, + tl->border, tl->format, + tl->type, tl->img); + } + } + + if (!alwaysDirty) + { + CLEARDIRTY(tl->dirty, nbitID); + } +#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE + else + { + crFree(tl->img); + tl->img = NULL; + } +#endif + } + } + break; +#endif +#ifdef CR_NV_texture_rectangle + case GL_TEXTURE_RECTANGLE_NV: + /* only one level */ + for (lvl = 0; lvl <= from->maxRectLevel; lvl++) + { + CRTextureLevel *tl = &(tobj->level[0][lvl]); + if (alwaysDirty || CHECKDIRTY(tl->dirty, bitID)) + { + if (tl->width && tl->height) + { + if (tl->compressed) { + diff_api.CompressedTexImage2DARB(GL_TEXTURE_RECTANGLE_NV, lvl, + tl->internalFormat, tl->width, + tl->height, tl->border, + tl->bytes, tl->img); + } + else { + /* alignment must be one */ + diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, 0); + diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, 0); + diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, 1); + diff_api.TexImage2D(GL_TEXTURE_RECTANGLE_NV, lvl, + tl->internalFormat, + tl->width, tl->height, tl->border, + tl->format, tl->type, tl->img); + } + } + + if (!alwaysDirty) + { + CLEARDIRTY(tl->dirty, nbitID); + } +#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE + else + { + crFree(tl->img); + tl->img = NULL; + } +#endif + } + } + break; +#endif +#ifdef CR_ARB_texture_cube_map + case GL_TEXTURE_CUBE_MAP_ARB: + for (face = 0; face < 6; face++) + { + const GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face; + for (lvl = 0; lvl <= from->maxCubeMapLevel; lvl++) + { + CRTextureLevel *tl = &(tobj->level[face][lvl]); + if (alwaysDirty || CHECKDIRTY(tl->dirty, bitID)) + { + if (tl->generateMipmap) { + diff_api.TexParameteri(GL_TEXTURE_CUBE_MAP_ARB, + GL_GENERATE_MIPMAP_SGIS, 1); + } + + if (tl->width && tl->height) + { + if (tl->compressed) { + diff_api.CompressedTexImage2DARB(target, + lvl, tl->internalFormat, + tl->width, tl->height, + tl->border, tl->bytes, tl->img); + } + else { + /* alignment must be one */ + diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, 0); + diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, 0); + diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, 1); + diff_api.TexImage2D(target, lvl, + tl->internalFormat, + tl->width, tl->height, tl->border, + tl->format, tl->type, tl->img); + } + } + + if (!alwaysDirty) + { + CLEARDIRTY(tl->dirty, nbitID); + } +#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE + else + { + crFree(tl->img); + tl->img = NULL; + } +#endif + } + } /* for lvl */ + } /* for face */ + break; +#endif + default: + UNIMPLEMENTED(); + + } /* switch */ + } /* if (CHECKDIRTY(tobj->imageBit, bitID)) */ +} + + + +void +crStateTextureDiff( CRTextureBits *tb, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx ) +{ + CRTextureState *from = &(fromCtx->texture); + CRTextureState *to = &(toCtx->texture); + unsigned int u, t, j; + glAble able[2]; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + const GLboolean haveFragProg = fromCtx->extensions.ARB_fragment_program || fromCtx->extensions.NV_fragment_program; + + for (j=0;j<CR_MAX_BITARRAY;j++) + nbitID[j] = ~bitID[j]; + + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + + /* loop over texture units */ + for (u = 0; u < fromCtx->limits.maxTextureUnits; u++) + { + CRTextureObj **fromBinding = NULL; + CRTextureObj *tobj; + + /* take care of enables/disables */ + if (CHECKDIRTY(tb->enable[u], bitID)) + { + + /* Activate texture unit u if needed */ + if (fromCtx->texture.curTextureUnit != u) { + diff_api.ActiveTextureARB( GL_TEXTURE0_ARB + u); + fromCtx->texture.curTextureUnit = u; + } + + if (from->unit[u].enabled1D != to->unit[u].enabled1D) + { + able[to->unit[u].enabled1D](GL_TEXTURE_1D); + from->unit[u].enabled1D = to->unit[u].enabled1D; + } + if (from->unit[u].enabled2D != to->unit[u].enabled2D) + { + able[to->unit[u].enabled2D](GL_TEXTURE_2D); + from->unit[u].enabled2D = to->unit[u].enabled2D; + } +#ifdef CR_OPENGL_VERSION_1_2 + if (from->unit[u].enabled3D != to->unit[u].enabled3D) + { + able[to->unit[u].enabled3D](GL_TEXTURE_3D); + from->unit[u].enabled3D = to->unit[u].enabled3D; + } +#endif +#ifdef CR_ARB_texture_cube_map + if (fromCtx->extensions.ARB_texture_cube_map && + from->unit[u].enabledCubeMap != to->unit[u].enabledCubeMap) + { + able[to->unit[u].enabledCubeMap](GL_TEXTURE_CUBE_MAP_ARB); + from->unit[u].enabledCubeMap = to->unit[u].enabledCubeMap; + } +#endif +#ifdef CR_NV_texture_rectangle + if (fromCtx->extensions.NV_texture_rectangle && + from->unit[u].enabledRect != to->unit[u].enabledRect) + { + able[to->unit[u].enabledRect](GL_TEXTURE_RECTANGLE_NV); + from->unit[u].enabledRect = to->unit[u].enabledRect; + } +#endif + + /* texgen enables */ + if (from->unit[u].textureGen.s != to->unit[u].textureGen.s || + from->unit[u].textureGen.t != to->unit[u].textureGen.t || + from->unit[u].textureGen.r != to->unit[u].textureGen.r || + from->unit[u].textureGen.q != to->unit[u].textureGen.q) + { + able[to->unit[u].textureGen.s](GL_TEXTURE_GEN_S); + able[to->unit[u].textureGen.t](GL_TEXTURE_GEN_T); + able[to->unit[u].textureGen.r](GL_TEXTURE_GEN_R); + able[to->unit[u].textureGen.q](GL_TEXTURE_GEN_Q); + from->unit[u].textureGen = to->unit[u].textureGen; + } + CLEARDIRTY(tb->enable[u], nbitID); + } + + + /* Texgen coefficients */ + if (CHECKDIRTY(tb->objGen[u], bitID)) + { + if (fromCtx->texture.curTextureUnit != u) { + diff_api.ActiveTextureARB( u + GL_TEXTURE0_ARB ); + fromCtx->texture.curTextureUnit = u; + } + if (from->unit[u].objSCoeff.x != to->unit[u].objSCoeff.x || + from->unit[u].objSCoeff.y != to->unit[u].objSCoeff.y || + from->unit[u].objSCoeff.z != to->unit[u].objSCoeff.z || + from->unit[u].objSCoeff.w != to->unit[u].objSCoeff.w) + { + GLfloat f[4]; + f[0] = to->unit[u].objSCoeff.x; + f[1] = to->unit[u].objSCoeff.y; + f[2] = to->unit[u].objSCoeff.z; + f[3] = to->unit[u].objSCoeff.w; + diff_api.TexGenfv (GL_S, GL_OBJECT_PLANE, (const GLfloat *) f); + from->unit[u].objSCoeff = to->unit[u].objSCoeff; + } + if (from->unit[u].objTCoeff.x != to->unit[u].objTCoeff.x || + from->unit[u].objTCoeff.y != to->unit[u].objTCoeff.y || + from->unit[u].objTCoeff.z != to->unit[u].objTCoeff.z || + from->unit[u].objTCoeff.w != to->unit[u].objTCoeff.w) + { + GLfloat f[4]; + f[0] = to->unit[u].objTCoeff.x; + f[1] = to->unit[u].objTCoeff.y; + f[2] = to->unit[u].objTCoeff.z; + f[3] = to->unit[u].objTCoeff.w; + diff_api.TexGenfv (GL_T, GL_OBJECT_PLANE, (const GLfloat *) f); + from->unit[u].objTCoeff = to->unit[u].objTCoeff; + } + if (from->unit[u].objRCoeff.x != to->unit[u].objRCoeff.x || + from->unit[u].objRCoeff.y != to->unit[u].objRCoeff.y || + from->unit[u].objRCoeff.z != to->unit[u].objRCoeff.z || + from->unit[u].objRCoeff.w != to->unit[u].objRCoeff.w) + { + GLfloat f[4]; + f[0] = to->unit[u].objRCoeff.x; + f[1] = to->unit[u].objRCoeff.y; + f[2] = to->unit[u].objRCoeff.z; + f[3] = to->unit[u].objRCoeff.w; + diff_api.TexGenfv (GL_R, GL_OBJECT_PLANE, (const GLfloat *) f); + from->unit[u].objRCoeff = to->unit[u].objRCoeff; + } + if (from->unit[u].objQCoeff.x != to->unit[u].objQCoeff.x || + from->unit[u].objQCoeff.y != to->unit[u].objQCoeff.y || + from->unit[u].objQCoeff.z != to->unit[u].objQCoeff.z || + from->unit[u].objQCoeff.w != to->unit[u].objQCoeff.w) + { + GLfloat f[4]; + f[0] = to->unit[u].objQCoeff.x; + f[1] = to->unit[u].objQCoeff.y; + f[2] = to->unit[u].objQCoeff.z; + f[3] = to->unit[u].objQCoeff.w; + diff_api.TexGenfv (GL_Q, GL_OBJECT_PLANE, (const GLfloat *) f); + from->unit[u].objQCoeff = to->unit[u].objQCoeff; + } + CLEARDIRTY(tb->objGen[u], nbitID); + } + if (CHECKDIRTY(tb->eyeGen[u], bitID)) + { + if (fromCtx->texture.curTextureUnit != u) { + diff_api.ActiveTextureARB( u + GL_TEXTURE0_ARB ); + fromCtx->texture.curTextureUnit = u; + } + if (fromCtx->transform.matrixMode != GL_MODELVIEW) { + diff_api.MatrixMode(GL_MODELVIEW); + fromCtx->transform.matrixMode = GL_MODELVIEW; + } + diff_api.PushMatrix(); + diff_api.LoadIdentity(); + if (from->unit[u].eyeSCoeff.x != to->unit[u].eyeSCoeff.x || + from->unit[u].eyeSCoeff.y != to->unit[u].eyeSCoeff.y || + from->unit[u].eyeSCoeff.z != to->unit[u].eyeSCoeff.z || + from->unit[u].eyeSCoeff.w != to->unit[u].eyeSCoeff.w) + { + GLfloat f[4]; + f[0] = to->unit[u].eyeSCoeff.x; + f[1] = to->unit[u].eyeSCoeff.y; + f[2] = to->unit[u].eyeSCoeff.z; + f[3] = to->unit[u].eyeSCoeff.w; + diff_api.TexGenfv (GL_S, GL_EYE_PLANE, (const GLfloat *) f); + from->unit[u].eyeSCoeff = to->unit[u].eyeSCoeff; + } + if (from->unit[u].eyeTCoeff.x != to->unit[u].eyeTCoeff.x || + from->unit[u].eyeTCoeff.y != to->unit[u].eyeTCoeff.y || + from->unit[u].eyeTCoeff.z != to->unit[u].eyeTCoeff.z || + from->unit[u].eyeTCoeff.w != to->unit[u].eyeTCoeff.w) + { + GLfloat f[4]; + f[0] = to->unit[u].eyeTCoeff.x; + f[1] = to->unit[u].eyeTCoeff.y; + f[2] = to->unit[u].eyeTCoeff.z; + f[3] = to->unit[u].eyeTCoeff.w; + diff_api.TexGenfv (GL_T, GL_EYE_PLANE, (const GLfloat *) f); + from->unit[u].eyeTCoeff = to->unit[u].eyeTCoeff; + } + if (from->unit[u].eyeRCoeff.x != to->unit[u].eyeRCoeff.x || + from->unit[u].eyeRCoeff.y != to->unit[u].eyeRCoeff.y || + from->unit[u].eyeRCoeff.z != to->unit[u].eyeRCoeff.z || + from->unit[u].eyeRCoeff.w != to->unit[u].eyeRCoeff.w) + { + GLfloat f[4]; + f[0] = to->unit[u].eyeRCoeff.x; + f[1] = to->unit[u].eyeRCoeff.y; + f[2] = to->unit[u].eyeRCoeff.z; + f[3] = to->unit[u].eyeRCoeff.w; + diff_api.TexGenfv (GL_R, GL_EYE_PLANE, (const GLfloat *) f); + from->unit[u].eyeRCoeff = to->unit[u].eyeRCoeff; + } + if (from->unit[u].eyeQCoeff.x != to->unit[u].eyeQCoeff.x || + from->unit[u].eyeQCoeff.y != to->unit[u].eyeQCoeff.y || + from->unit[u].eyeQCoeff.z != to->unit[u].eyeQCoeff.z || + from->unit[u].eyeQCoeff.w != to->unit[u].eyeQCoeff.w) + { + GLfloat f[4]; + f[0] = to->unit[u].eyeQCoeff.x; + f[1] = to->unit[u].eyeQCoeff.y; + f[2] = to->unit[u].eyeQCoeff.z; + f[3] = to->unit[u].eyeQCoeff.w; + diff_api.TexGenfv (GL_Q, GL_EYE_PLANE, (const GLfloat *) f); + from->unit[u].eyeQCoeff = to->unit[u].eyeQCoeff; + } + diff_api.PopMatrix(); + CLEARDIRTY(tb->eyeGen[u], nbitID); + } + if (CHECKDIRTY(tb->genMode[u], bitID)) + { + if (fromCtx->texture.curTextureUnit != u) { + diff_api.ActiveTextureARB( u + GL_TEXTURE0_ARB ); + fromCtx->texture.curTextureUnit = u; + } + if (from->unit[u].gen.s != to->unit[u].gen.s || + from->unit[u].gen.t != to->unit[u].gen.t || + from->unit[u].gen.r != to->unit[u].gen.r || + from->unit[u].gen.q != to->unit[u].gen.q) + { + diff_api.TexGeni (GL_S, GL_TEXTURE_GEN_MODE, to->unit[u].gen.s); + diff_api.TexGeni (GL_T, GL_TEXTURE_GEN_MODE, to->unit[u].gen.t); + diff_api.TexGeni (GL_R, GL_TEXTURE_GEN_MODE, to->unit[u].gen.r); + diff_api.TexGeni (GL_Q, GL_TEXTURE_GEN_MODE, to->unit[u].gen.q); + from->unit[u].gen = to->unit[u].gen; + } + CLEARDIRTY(tb->genMode[u], nbitID); + } + + /* Texture enviroment */ + if (CHECKDIRTY(tb->envBit[u], bitID)) + { + if (from->unit[u].envMode != to->unit[u].envMode) + { + diff_api.TexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, to->unit[u].envMode); + from->unit[u].envMode = to->unit[u].envMode; + } + if (from->unit[u].envColor.r != to->unit[u].envColor.r || + from->unit[u].envColor.g != to->unit[u].envColor.g || + from->unit[u].envColor.b != to->unit[u].envColor.b || + from->unit[u].envColor.a != to->unit[u].envColor.a) + { + GLfloat f[4]; + f[0] = to->unit[u].envColor.r; + f[1] = to->unit[u].envColor.g; + f[2] = to->unit[u].envColor.b; + f[3] = to->unit[u].envColor.a; + diff_api.TexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (const GLfloat *) f); + from->unit[u].envColor = to->unit[u].envColor; + } +#ifdef CR_ARB_texture_env_combine + if (from->unit[u].combineModeRGB != to->unit[u].combineModeRGB) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, to->unit[u].combineModeRGB); + from->unit[u].combineModeRGB = to->unit[u].combineModeRGB; + } + if (from->unit[u].combineModeA != to->unit[u].combineModeA) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, to->unit[u].combineModeA); + from->unit[u].combineModeA = to->unit[u].combineModeA; + } + if (from->unit[u].combineSourceRGB[0] != to->unit[u].combineSourceRGB[0]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, to->unit[u].combineSourceRGB[0]); + from->unit[u].combineSourceRGB[0] = to->unit[u].combineSourceRGB[0]; + } + if (from->unit[u].combineSourceRGB[1] != to->unit[u].combineSourceRGB[1]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, to->unit[u].combineSourceRGB[1]); + from->unit[u].combineSourceRGB[1] = to->unit[u].combineSourceRGB[1]; + } + if (from->unit[u].combineSourceRGB[2] != to->unit[u].combineSourceRGB[2]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, to->unit[u].combineSourceRGB[2]); + from->unit[u].combineSourceRGB[2] = to->unit[u].combineSourceRGB[2]; + } + if (from->unit[u].combineSourceA[0] != to->unit[u].combineSourceA[0]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, to->unit[u].combineSourceA[0]); + from->unit[u].combineSourceA[0] = to->unit[u].combineSourceA[0]; + } + if (from->unit[u].combineSourceA[1] != to->unit[u].combineSourceA[1]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, to->unit[u].combineSourceA[1]); + from->unit[u].combineSourceA[1] = to->unit[u].combineSourceA[1]; + } + if (from->unit[u].combineSourceA[2] != to->unit[u].combineSourceA[2]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, to->unit[u].combineSourceA[2]); + from->unit[u].combineSourceA[2] = to->unit[u].combineSourceA[2]; + } + if (from->unit[u].combineOperandRGB[0] != to->unit[u].combineOperandRGB[0]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, to->unit[u].combineOperandRGB[0]); + from->unit[u].combineOperandRGB[0] = to->unit[u].combineOperandRGB[0]; + } + if (from->unit[u].combineOperandRGB[1] != to->unit[u].combineOperandRGB[1]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, to->unit[u].combineOperandRGB[1]); + from->unit[u].combineOperandRGB[1] = to->unit[u].combineOperandRGB[1]; + } + if (from->unit[u].combineOperandRGB[2] != to->unit[u].combineOperandRGB[2]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, to->unit[u].combineOperandRGB[2]); + from->unit[u].combineOperandRGB[2] = to->unit[u].combineOperandRGB[2]; + } + if (from->unit[u].combineOperandA[0] != to->unit[u].combineOperandA[0]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, to->unit[u].combineOperandA[0]); + from->unit[u].combineOperandA[0] = to->unit[u].combineOperandA[0]; + } + if (from->unit[u].combineOperandA[1] != to->unit[u].combineOperandA[1]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, to->unit[u].combineOperandA[1]); + from->unit[u].combineOperandA[1] = to->unit[u].combineOperandA[1]; + } + if (from->unit[u].combineOperandA[2] != to->unit[u].combineOperandA[2]) + { + diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, to->unit[u].combineOperandA[2]); + from->unit[u].combineOperandA[2] = to->unit[u].combineOperandA[2]; + } + if (from->unit[u].combineScaleRGB != to->unit[u].combineScaleRGB) + { + diff_api.TexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, to->unit[u].combineScaleRGB); + from->unit[u].combineScaleRGB = to->unit[u].combineScaleRGB; + } + if (from->unit[u].combineScaleA != to->unit[u].combineScaleA) + { + diff_api.TexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, to->unit[u].combineScaleA); + from->unit[u].combineScaleA = to->unit[u].combineScaleA; + } +#endif +#if CR_EXT_texture_lod_bias + if (from->unit[u].lodBias != to->unit[u].lodBias) + { + diff_api.TexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, to->unit[u].lodBias); + from->unit[u].lodBias = to->unit[u].lodBias; + } +#endif + CLEARDIRTY(tb->envBit[u], nbitID); + } + + /* loop over texture targets */ + for (t = 0; t < 5; t++) + { + tobj = NULL; + + switch (t) { + case 0: + if (to->unit[u].enabled1D || haveFragProg) { + tobj = to->unit[u].currentTexture1D; + fromBinding = &(from->unit[u].currentTexture1D); + } + break; + case 1: + if (to->unit[u].enabled2D || haveFragProg) { + tobj = to->unit[u].currentTexture2D; + fromBinding = &(from->unit[u].currentTexture2D); + } + break; +#ifdef CR_OPENGL_VERSION_1_2 + case 2: + if (to->unit[u].enabled3D || haveFragProg) { + tobj = to->unit[u].currentTexture3D; + fromBinding = &(from->unit[u].currentTexture3D); + } + break; +#endif +#ifdef CR_ARB_texture_cube_map + case 3: + if (fromCtx->extensions.ARB_texture_cube_map && + (to->unit[u].enabledCubeMap || haveFragProg)) { + tobj = to->unit[u].currentTextureCubeMap; + fromBinding = &(from->unit[u].currentTextureCubeMap); + } + break; +#endif +#ifdef CR_NV_texture_rectangle + case 4: + if (fromCtx->extensions.NV_texture_rectangle && + (to->unit[u].enabledRect || haveFragProg)) { + tobj = to->unit[u].currentTextureRect; + fromBinding = &(from->unit[u].currentTextureRect); + } + break; +#endif + default: + /* maybe don't support cube maps or rects */ + continue; + } + + if (!tobj) { + continue; /* with next target */ + } + + /* Activate texture unit u if needed */ + if (fromCtx->texture.curTextureUnit != u) { + diff_api.ActiveTextureARB( GL_TEXTURE0_ARB + u); + fromCtx->texture.curTextureUnit = u; + } + + /* bind this texture if needed */ + if (CHECKDIRTY(tb->current[u], bitID)) + { + if (*fromBinding != tobj) + { + diff_api.BindTexture(tobj->target, crStateGetTextureObjHWID(tobj)); + *fromBinding = tobj; + } + } + + /* now, if the texture object is dirty */ + if (CHECKDIRTY(tobj->dirty, bitID)) + { + crStateTextureObjectDiff(fromCtx, bitID, nbitID, tobj, GL_FALSE); + } + CLEARDIRTY(tobj->dirty, nbitID); + + } /* loop over targets */ + + CLEARDIRTY(tb->current[u], nbitID); + + } /* loop over units */ + + /* After possible fiddling with the active unit, put it back now */ + if (fromCtx->texture.curTextureUnit != toCtx->texture.curTextureUnit) { + diff_api.ActiveTextureARB( toCtx->texture.curTextureUnit + GL_TEXTURE0_ARB ); + fromCtx->texture.curTextureUnit = toCtx->texture.curTextureUnit; + } + if (fromCtx->transform.matrixMode != toCtx->transform.matrixMode) { + diff_api.MatrixMode(toCtx->transform.matrixMode); + fromCtx->transform.matrixMode = toCtx->transform.matrixMode; + } + + CLEARDIRTY(tb->dirty, nbitID); +} + + + +struct callback_info +{ + CRbitvalue *bitID, *nbitID; + CRContext *g; + GLboolean bForceUpdate; +}; + + +/* Called by crHashtableWalk() below */ +static void +DiffTextureObjectCallback( unsigned long key, void *texObj , void *cbData) +{ + struct callback_info *info = (struct callback_info *) cbData; + CRTextureObj *tobj = (CRTextureObj *) texObj; + (void)key; + + /* + printf(" Checking %d 0x%x bitid=0x%x\n",tobj->name, tobj->dirty[0], info->bitID[0]); + */ + if (info->bForceUpdate || CHECKDIRTY(tobj->dirty, info->bitID)) { + /* + printf(" Found Dirty! %d\n", tobj->name); + */ + crStateTextureObjectDiff(info->g, info->bitID, info->nbitID, tobj, info->bForceUpdate); + CLEARDIRTY(tobj->dirty, info->nbitID); + } +} + + +/* + * This isn't used right now, but will be used in the future to fix some + * potential display list problems. Specifically, if glBindTexture is + * in a display list, we have to be sure that all outstanding texture object + * updates are resolved before the list is called. If we don't, we may + * wind up binding texture objects that are stale. + */ +void +crStateDiffAllTextureObjects( CRContext *g, CRbitvalue *bitID, GLboolean bForceUpdate ) +{ + CRbitvalue nbitID[CR_MAX_BITARRAY]; + struct callback_info info; + int j; + int origUnit, orig1D, orig2D, orig3D, origCube, origRect; + + for (j = 0; j < CR_MAX_BITARRAY; j++) + nbitID[j] = ~bitID[j]; + + info.bitID = bitID; + info.nbitID = nbitID; + info.g = g; + info.bForceUpdate = bForceUpdate; + + /* save current texture bindings */ + origUnit = g->texture.curTextureUnit; + orig1D = crStateGetTextureObjHWID(g->texture.unit[0].currentTexture1D); + orig2D = crStateGetTextureObjHWID(g->texture.unit[0].currentTexture2D); + orig3D = crStateGetTextureObjHWID(g->texture.unit[0].currentTexture3D); +#ifdef CR_ARB_texture_cube_map + origCube = crStateGetTextureObjHWID(g->texture.unit[0].currentTextureCubeMap); +#endif +#ifdef CR_NV_texture_rectangle + origRect = crStateGetTextureObjHWID(g->texture.unit[0].currentTextureRect); +#endif + + /* use texture unit 0 for updates */ + diff_api.ActiveTextureARB(GL_TEXTURE0_ARB); + + /* diff all the textures */ + crHashtableWalk(g->shared->textureTable, DiffTextureObjectCallback, (void *) &info); + + /* default ones */ + crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.base1D, GL_TRUE); + crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.base2D, GL_TRUE); + crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.base3D, GL_TRUE); + crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.proxy1D, GL_TRUE); + crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.proxy2D, GL_TRUE); + crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.proxy3D, GL_TRUE); +#ifdef CR_ARB_texture_cube_map + crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.baseCubeMap, GL_TRUE); + crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.proxyCubeMap, GL_TRUE); +#endif +#ifdef CR_NV_texture_rectangle + if (g->extensions.NV_texture_rectangle) + { + crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.baseRect, GL_TRUE); + crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.proxyRect, GL_TRUE); + } +#endif + + /* restore bindings */ + /* first restore unit 0 bindings the unit 0 is active currently */ + diff_api.BindTexture(GL_TEXTURE_1D, orig1D); + diff_api.BindTexture(GL_TEXTURE_2D, orig2D); + diff_api.BindTexture(GL_TEXTURE_3D, orig3D); +#ifdef CR_ARB_texture_cube_map + diff_api.BindTexture(GL_TEXTURE_CUBE_MAP_ARB, origCube); +#endif +#ifdef CR_NV_texture_rectangle + diff_api.BindTexture(GL_TEXTURE_RECTANGLE_NV, origRect); +#endif + /* now restore the proper active unit */ + diff_api.ActiveTextureARB(GL_TEXTURE0_ARB + origUnit); +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c new file mode 100644 index 00000000..295ea36f --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c @@ -0,0 +1,1762 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + + +#include "state.h" +#include "state/cr_statetypes.h" +#include "state/cr_texture.h" +#include "cr_pixeldata.h" +#include "cr_string.h" +#include "cr_mem.h" +#include "cr_version.h" +#include "state_internals.h" + +#ifndef IN_GUEST +/*# define CR_DUMP_TEXTURES_2D*/ +#endif + +#ifdef CR_DUMP_TEXTURES_2D +static int _tnum = 0; + +#pragma pack(1) +typedef struct tgaheader_tag +{ + char idlen; + + char colormap; + + char imagetype; + + short cm_index; + short cm_len; + char cm_entrysize; + + short x, y, w, h; + char depth; + char imagedesc; + +} tgaheader_t; +#pragma pack() + +static crDumpTGA(short w, short h, char* data) +{ + char fname[200]; + tgaheader_t header; + FILE *out; + + if (!w || !h) return; + + sprintf(fname, "tex%i.tga", _tnum++); + out = fopen(fname, "w"); + if (!out) crError("can't create %s!", fname); + + header.idlen = 0; + header.colormap = 0; + header.imagetype = 2; + header.cm_index = 0; + header.cm_len = 0; + header.cm_entrysize = 0; + header.x = 0; + header.y = 0; + header.w = w; + header.h = h; + header.depth = 32; + header.imagedesc = 0x08; + fwrite(&header, sizeof(header), 1, out); + + fwrite(data, w*h*4, 1, out); + + fclose(out); +} +#endif + + +static int +bitcount(int value) +{ + int bits = 0; + for (; value > 0; value >>= 1) { + if (value & 0x1) + bits++; + } + return bits; +} + + +/** + * Return 1 if the target is a proxy target, 0 otherwise. + */ +static GLboolean +IsProxyTarget(GLenum target) +{ + return (target == GL_PROXY_TEXTURE_1D || + target == GL_PROXY_TEXTURE_2D || + target == GL_PROXY_TEXTURE_3D || + target == GL_PROXY_TEXTURE_RECTANGLE_NV || + target == GL_PROXY_TEXTURE_CUBE_MAP); +} + + +/** + * Test if a texture width, height or depth is legal. + * It must be true that 0 <= size <= max. + * Furthermore, if the ARB_texture_non_power_of_two extension isn't + * present, size must also be a power of two. + */ +static GLboolean +isLegalSize(CRContext *g, GLsizei size, GLsizei max) +{ + if (size < 0 || size > max) + return GL_FALSE; + if (!g->extensions.ARB_texture_non_power_of_two) { + /* check for power of two */ + if (size > 0 && bitcount(size) != 1) + return GL_FALSE; + } + return GL_TRUE; +} + + +/** + * Return the max legal texture level parameter for the given target. + */ +static GLint +MaxTextureLevel(CRContext *g, GLenum target) +{ + CRTextureState *t = &(g->texture); + switch (target) { + case GL_TEXTURE_1D: + case GL_PROXY_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_PROXY_TEXTURE_2D: + return t->maxLevel; + case GL_TEXTURE_3D: + case GL_PROXY_TEXTURE_3D: + return t->max3DLevel; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + case GL_PROXY_TEXTURE_CUBE_MAP_ARB: + return t->maxCubeMapLevel; + case GL_TEXTURE_RECTANGLE_NV: + case GL_PROXY_TEXTURE_RECTANGLE_NV: + return t->maxRectLevel; + default: + return 0; + } +} + + +/** + * If GL_GENERATE_MIPMAP_SGIS is true and we modify the base level texture + * image we have to finish the mipmap. + * All we really have to do is fill in the width/height/format/etc for the + * remaining image levels. The image data doesn't matter here - the back- + * end OpenGL library will fill those in. + */ +static void +generate_mipmap(CRTextureObj *tobj, GLenum target) +{ + CRTextureLevel *levels; + GLint level, width, height, depth; + + if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { + levels = tobj->level[target - GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB]; + } + else { + levels = tobj->level[0]; + } + + width = levels[tobj->baseLevel].width; + height = levels[tobj->baseLevel].height; + depth = levels[tobj->baseLevel].depth; + + for (level = tobj->baseLevel + 1; level <= tobj->maxLevel; level++) + { + if (width > 1) + width /= 2; + if (height > 1) + height /= 2; + if (depth > 1) + depth /= 2; + levels[level].width = width; + levels[level].height = height; + levels[level].depth = depth; + levels[level].internalFormat = levels[tobj->baseLevel].internalFormat; + levels[level].format = levels[tobj->baseLevel].format; + levels[level].type = levels[tobj->baseLevel].type; +#ifdef CR_ARB_texture_compression + levels[level].compressed = levels[tobj->baseLevel].compressed; +#endif + levels[level].texFormat = levels[tobj->baseLevel].texFormat; + if (width == 1 && height == 1 && depth == 1) + break; + } + + /* Set this flag so when we do the state diff, we enable GENERATE_MIPMAP + * prior to calling diff.TexImage(). + */ + levels[tobj->baseLevel].generateMipmap = GL_TRUE; +} + + +/** + * Given a texture target and level, return pointers to the corresponding + * texture object and texture image level. + */ +void +crStateGetTextureObjectAndImage(CRContext *g, GLenum texTarget, GLint level, + CRTextureObj **obj, CRTextureLevel **img) +{ + CRTextureState *t = &(g->texture); + CRTextureUnit *unit = t->unit + t->curTextureUnit; + + switch (texTarget) { + case GL_TEXTURE_1D: + *obj = unit->currentTexture1D; + *img = unit->currentTexture1D->level[0] + level; + return; + case GL_PROXY_TEXTURE_1D: + *obj = &(t->proxy1D); + *img = t->proxy1D.level[0] + level; + return; + case GL_TEXTURE_2D: + *obj = unit->currentTexture2D; + *img = unit->currentTexture2D->level[0] + level; + return; + case GL_PROXY_TEXTURE_2D: + *obj = &(t->proxy2D); + *img = t->proxy2D.level[0] + level; + return; + case GL_TEXTURE_3D: + *obj = unit->currentTexture3D; + *img = unit->currentTexture3D->level[0] + level; + return; + case GL_PROXY_TEXTURE_3D: + *obj = &(t->proxy3D); + *img = t->proxy3D.level[0] + level; + return; + default: + /* fall-through */ + ; + } + +#ifdef CR_NV_texture_rectangle + if (g->extensions.NV_texture_rectangle) { + switch (texTarget) { + case GL_PROXY_TEXTURE_RECTANGLE_NV: + *obj = &(t->proxyRect); + *img = t->proxyRect.level[0] + level; + return; + case GL_TEXTURE_RECTANGLE_NV: + *obj = unit->currentTextureRect; + *img = unit->currentTextureRect->level[0] + level; + return; + default: + /* fall-through */ + ; + } + } +#endif + +#ifdef CR_ARB_texture_cube_map + if (g->extensions.ARB_texture_cube_map) { + switch (texTarget) { + case GL_PROXY_TEXTURE_CUBE_MAP_ARB: + *obj = &(t->proxyCubeMap); + *img = t->proxyCubeMap.level[0] + level; + return; + case GL_TEXTURE_CUBE_MAP_ARB: + *obj = unit->currentTextureCubeMap; + *img = NULL; + return; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + *obj = unit->currentTextureCubeMap; + *img = unit->currentTextureCubeMap->level[0] + level; + return; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + *obj = unit->currentTextureCubeMap; + *img = unit->currentTextureCubeMap->level[1] + level; + return; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + *obj = unit->currentTextureCubeMap; + *img = unit->currentTextureCubeMap->level[2] + level; + return; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + *obj = unit->currentTextureCubeMap; + *img = unit->currentTextureCubeMap->level[3] + level; + return; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + *obj = unit->currentTextureCubeMap; + *img = unit->currentTextureCubeMap->level[4] + level; + return; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + *obj = unit->currentTextureCubeMap; + *img = unit->currentTextureCubeMap->level[5] + level; + return; + default: + /* fall-through */ + ; + } + } +#endif + + crWarning("unexpected texTarget 0x%x", texTarget); + *obj = NULL; + *img = NULL; +} + + +/** + * Do parameter error checking for glTexImagexD functions. + * We'll call crStateError if we detect any errors, unless it's a proxy target. + * Return GL_TRUE if any errors, GL_FALSE if no errors. + */ +static GLboolean +ErrorCheckTexImage(GLuint dims, GLenum target, GLint level, + GLsizei width, GLsizei height, GLsizei depth, GLint border) +{ + CRContext *g = GetCurrentContext(); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glTexImage%uD called in Begin/End", dims); + return GL_TRUE; + } + + /* + * Test target + */ + switch (target) + { + case GL_TEXTURE_1D: + case GL_PROXY_TEXTURE_1D: + if (dims != 1) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexImage(invalid target=0x%x)", target); + return GL_TRUE; + } + break; + case GL_TEXTURE_2D: + case GL_PROXY_TEXTURE_2D: + if (dims != 2) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexImage(invalid target=0x%x)", target); + return GL_TRUE; + } + break; + case GL_TEXTURE_3D: + case GL_PROXY_TEXTURE_3D: + if (dims != 3) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexImage(invalid target=0x%x)", target); + return GL_TRUE; + } + break; +#ifdef CR_NV_texture_rectangle + case GL_TEXTURE_RECTANGLE_NV: + case GL_PROXY_TEXTURE_RECTANGLE_NV: + if (dims != 2 || !g->extensions.NV_texture_rectangle) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexImage2D(invalid target=0x%x)", target); + return GL_TRUE; + } + break; +#endif +#ifdef CR_ARB_texture_cube_map + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + case GL_PROXY_TEXTURE_CUBE_MAP_ARB: + if (dims != 2 || !g->extensions.ARB_texture_cube_map) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexImage2D(invalid target=0x%x)", target); + return GL_TRUE; + } + break; +#endif + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexImage%uD(invalid target=0x%x)", dims, target); + return GL_TRUE; + } + + /* + * Test level + */ + if (level < 0 || level > MaxTextureLevel(g, target)) { + if (!IsProxyTarget(target)) + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glTexImage%uD(level=%d)", dims, level); + return GL_TRUE; + } + + /* + * Test border + */ + if (border != 0 && border != 1) { + if (!IsProxyTarget(target)) + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glTexImage%uD(border=%d)", dims, border); + return GL_TRUE; + } + + if ((target == GL_PROXY_TEXTURE_RECTANGLE_NV || + target == GL_TEXTURE_RECTANGLE_NV) && border != 0) { + if (!IsProxyTarget(target)) + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glTexImage2D(border=%d)", border); + return GL_TRUE; + } + + /* + * Test width, height, depth + */ + if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) { + if (!isLegalSize(g, width - 2 * border, g->limits.maxTextureSize)) { + if (!IsProxyTarget(target)) + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glTexImage1D(width=%d)", width); + return GL_TRUE; + } + } + else if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) { + if (!isLegalSize(g, width - 2 * border, g->limits.maxTextureSize) || + !isLegalSize(g, height - 2 * border, g->limits.maxTextureSize)) { + if (!IsProxyTarget(target)) + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glTexImage2D(width=%d, height=%d)", width, height); + return GL_TRUE; + } + } + else if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) { + if (!isLegalSize(g, width - 2 * border, g->limits.max3DTextureSize) || + !isLegalSize(g, height - 2 * border, g->limits.max3DTextureSize) || + !isLegalSize(g, depth - 2 * border, g->limits.max3DTextureSize)) { + if (!IsProxyTarget(target)) + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glTexImage3D(width=%d, height=%d, depth=%d)", + width, height, depth); + return GL_TRUE; + } + } + else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV || + target == GL_TEXTURE_RECTANGLE_NV) { + if (width < 0 || width > (int) g->limits.maxRectTextureSize || + height < 0 || height > (int) g->limits.maxRectTextureSize) { + if (!IsProxyTarget(target)) + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glTexImage2D(width=%d, height=%d)", width, height); + return GL_TRUE; + } + } + else { + /* cube map */ + if (!isLegalSize(g, width - 2*border, g->limits.maxCubeMapTextureSize) || + !isLegalSize(g, height - 2*border, g->limits.maxCubeMapTextureSize) || + width != height) { + if (!IsProxyTarget(target)) + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glTexImage2D(width=%d, height=%d)", width, height); + return GL_TRUE; + } + } + + /* OK, no errors */ + return GL_FALSE; +} + + +/** + * Do error check for glTexSubImage() functions. + * We'll call crStateError if we detect any errors. + * Return GL_TRUE if any errors, GL_FALSE if no errors. + */ +static GLboolean +ErrorCheckTexSubImage(GLuint dims, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth) +{ + CRContext *g = GetCurrentContext(); + CRTextureObj *tobj; + CRTextureLevel *tl; + + if (g->current.inBeginEnd) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glTexSubImage%uD called in Begin/End", dims); + return GL_TRUE; + } + + if (dims == 1) { + if (target != GL_TEXTURE_1D) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexSubImage1D(target=0x%x)", target); + return GL_TRUE; + } + } + else if (dims == 2) { + if (target != GL_TEXTURE_2D && + target != GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + target != GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB && + target != GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB && + target != GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB && + target != GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB && + target != GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && + target != GL_TEXTURE_RECTANGLE_NV) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexSubImage2D(target=0x%x)", target); + return GL_TRUE; + } + } + else if (dims == 3) { + if (target != GL_TEXTURE_3D) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexSubImage3D(target=0x%x)", target); + return GL_TRUE; + } + } + + /* test level */ + if (level < 0 || level > MaxTextureLevel(g, target)) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glTexSubImage%uD(level=%d)", dims, level); + return GL_TRUE; + } + + crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl); + if (!tobj || !tl) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glTexSubImage%uD(target or level)", dims); + return GL_TRUE; + } + + /* test x/y/zoffset and size */ + if (xoffset < -tl->border || xoffset + width > tl->width) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glTexSubImage%uD(xoffset=%d + width=%d > %d)", + dims, xoffset, width, tl->width); + return GL_TRUE; + } + if (dims > 1 && (yoffset < -tl->border || yoffset + height > tl->height)) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glTexSubImage%uD(yoffset=%d + height=%d > %d)", + dims, yoffset, height, tl->height); + return GL_TRUE; + } + if (dims > 2 && (zoffset < -tl->border || zoffset + depth > tl->depth)) { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glTexSubImage%uD(zoffset=%d and/or depth=%d)", + dims, zoffset, depth); + return GL_TRUE; + } + + /* OK, no errors */ + return GL_FALSE; +} + + + +void STATE_APIENTRY +crStateTexImage1D(GLenum target, GLint level, GLint internalFormat, + GLsizei width, GLint border, GLenum format, + GLenum type, const GLvoid * pixels) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + CRClientState *c = &(g->client); +#endif + CRTextureObj *tobj; + CRTextureLevel *tl; + CRStateBits *sb = GetCurrentBits(); + CRTextureBits *tb = &(sb->texture); +#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE + (void)pixels; +#endif + + FLUSH(); + + if (ErrorCheckTexImage(1, target, level, width, 1, 1, border)) { + if (IsProxyTarget(target)) { + /* clear all state, but don't generate error */ + crStateTextureInitTextureObj(g, &(t->proxy1D), 0, GL_TEXTURE_1D); + } + else { + /* error was already recorded */ + } + return; + } + + crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl); + CRASSERT(tobj); + CRASSERT(tl); + + if (IsProxyTarget(target)) + tl->bytes = 0; + else + tl->bytes = crImageSize(format, type, width, 1); + +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + if (tl->bytes) + { + /* this is not a proxy texture target so alloc storage */ + if (tl->img) + crFree(tl->img); + tl->img = (GLubyte *) crAlloc(tl->bytes); + if (!tl->img) + { + crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, + "glTexImage1D out of memory"); + return; + } + if (pixels) + crPixelCopy1D((GLvoid *) tl->img, format, type, + pixels, format, type, width, &(c->unpack)); + } +#endif + + tl->width = width; + tl->height = 1; + tl->depth = 1; + tl->format = format; + tl->border = border; + tl->internalFormat = internalFormat; + crStateTextureInitTextureFormat(tl, internalFormat); + tl->type = type; + tl->compressed = GL_FALSE; + if (width) + tl->bytesPerPixel = tl->bytes / width; + else + tl->bytesPerPixel = 0; + +#ifdef CR_SGIS_generate_mipmap + if (level == tobj->baseLevel && tobj->generateMipmap) { + generate_mipmap(tobj, target); + } + else { + tl->generateMipmap = GL_FALSE; + } +#endif + + /* XXX may need to do some fine-tuning here for proxy textures */ + DIRTY(tobj->dirty, g->neg_bitid); + DIRTY(tobj->imageBit, g->neg_bitid); + DIRTY(tl->dirty, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + +static void crStateNukeMipmaps(CRTextureObj *tobj) +{ + int i, face; + + for (face = 0; face < 6; face++) + { + CRTextureLevel *levels = tobj->level[face]; + + if (levels) + { + for (i = 0; i < CR_MAX_MIPMAP_LEVELS; i++) + { + if (levels[i].img) + { + crFree(levels[i].img); + } + levels[i].img = NULL; + levels[i].bytes = 0; + levels[i].internalFormat = GL_ONE; + levels[i].format = GL_RGBA; + levels[i].type = GL_UNSIGNED_BYTE; + + } + } + } +} + +void STATE_APIENTRY +crStateCopyTexImage2D(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +{ + CRContext *g = GetCurrentContext(); + CRTextureObj *tobj = NULL; + CRTextureLevel *tl = NULL; + (void)x; (void)y; + + crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl); + CRASSERT(tobj); + CRASSERT(tl); + + if (tobj == NULL || tl == NULL) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "crStateCopyTexImage2D: invalid target: 0x%x", target); + return; + } + + crStateNukeMipmaps(tobj); + + tl->bytes = crImageSize(GL_RGBA, GL_UNSIGNED_BYTE, width, height); + + tl->width = width; + tl->height = height; + tl->depth = 1; + tl->format = GL_RGBA; + tl->internalFormat = internalFormat; + crStateTextureInitTextureFormat(tl, internalFormat); + tl->border = border; + tl->type = GL_UNSIGNED_BYTE; + tl->compressed = GL_FALSE; + if (width && height) + { + tl->bytesPerPixel = tl->bytes / (width * height); + } + else + tl->bytesPerPixel = 0; + +#ifdef CR_SGIS_generate_mipmap + if (level == tobj->baseLevel && tobj->generateMipmap) { + generate_mipmap(tobj, target); + } + else { + tl->generateMipmap = GL_FALSE; + } +#endif +} + +void STATE_APIENTRY +crStateTexImage2D(GLenum target, GLint level, GLint internalFormat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, const GLvoid * pixels) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + CRClientState *c = &(g->client); +#endif + CRTextureObj *tobj = NULL; + CRTextureLevel *tl = NULL; + CRStateBits *sb = GetCurrentBits(); + CRTextureBits *tb = &(sb->texture); + // Distributed textures are not used by VBox + const int is_distrib = 0; // ((type == GL_TRUE) || (type == GL_FALSE)); + + FLUSH(); + + /* NOTE: we skip parameter error checking if this is a distributed + * texture! The user better provide correct parameters!!! + */ + if (!is_distrib + && ErrorCheckTexImage(2, target, level, width, height, 1, border)) { + if (IsProxyTarget(target)) { + /* clear all state, but don't generate error */ + crStateTextureInitTextureObj(g, &(t->proxy2D), 0, GL_TEXTURE_2D); + } + else { + /* error was already recorded */ + } + return; + } + + crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl); + CRASSERT(tobj); + CRASSERT(tl); + + if (level==tobj->baseLevel && (tl->width!=width || tl->height!=height)) + { + crStateNukeMipmaps(tobj); + } + + /* compute size of image buffer */ + if (is_distrib) { + tl->bytes = crStrlen((char *) pixels) + 1; + tl->bytes += crImageSize(format, GL_UNSIGNED_BYTE, width, height); + } + else if (IsProxyTarget(target)) { + tl->bytes = 0; + } + else { + tl->bytes = crImageSize(format, type, width, height); + } + +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + /* allocate the image buffer and fill it */ + if (tl->bytes) + { + /* this is not a proxy texture target so alloc storage */ + if (tl->img) + crFree(tl->img); + tl->img = (GLubyte *) crAlloc(tl->bytes); + if (!tl->img) + { + crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, + "glTexImage2D out of memory"); + return; + } + if (pixels) + { + if (is_distrib) + { + crMemcpy((void *) tl->img, (void *) pixels, tl->bytes); + } + else + { + crPixelCopy2D(width, height, + (GLvoid *) tl->img, format, type, NULL, /* dst */ + pixels, format, type, &(c->unpack)); /* src */ + } + } + } +#endif + + tl->width = width; + tl->height = height; + tl->depth = 1; + tl->format = format; + tl->internalFormat = internalFormat; + crStateTextureInitTextureFormat(tl, internalFormat); + tl->border = border; + tl->type = type; + tl->compressed = GL_FALSE; + if (width && height) + { + if (is_distrib) + tl->bytesPerPixel = 3; /* only support GL_RGB */ + else + tl->bytesPerPixel = tl->bytes / (width * height); + } + else + tl->bytesPerPixel = 0; + +#ifdef CR_SGIS_generate_mipmap + if (level == tobj->baseLevel && tobj->generateMipmap) { + generate_mipmap(tobj, target); + } + else { + tl->generateMipmap = GL_FALSE; + } +#endif + + /* XXX may need to do some fine-tuning here for proxy textures */ + DIRTY(tobj->dirty, g->neg_bitid); + DIRTY(tobj->imageBit, g->neg_bitid); + DIRTY(tl->dirty, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); + +#ifdef CR_DUMP_TEXTURES_2D + if (pixels) + { + GLint w,h; + char *data; + + diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &w); + diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &h); + + data = crAlloc(w*h*4); + if (!data) crError("no memory!"); + diff_api.GetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, data); + crDumpTGA(w, h, data); + crFree(data); + } +#endif +} + +#if defined( CR_OPENGL_VERSION_1_2 ) || defined( GL_EXT_texture3D ) +void STATE_APIENTRY +crStateTexImage3D(GLenum target, GLint level, + GLint internalFormat, + GLsizei width, GLsizei height, + GLsizei depth, GLint border, + GLenum format, GLenum type, const GLvoid * pixels) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + CRClientState *c = &(g->client); +#endif + CRTextureObj *tobj = NULL; + CRTextureLevel *tl = NULL; + CRStateBits *sb = GetCurrentBits(); + CRTextureBits *tb = &(sb->texture); + (void)pixels; + + FLUSH(); + + if (ErrorCheckTexImage(3, target, level, width, height, depth, border)) { + if (IsProxyTarget(target)) { + /* clear all state, but don't generate error */ + crStateTextureInitTextureObj(g, &(t->proxy3D), 0, GL_TEXTURE_3D); + } + else { + /* error was already recorded */ + } + return; + } + + crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl); + CRASSERT(tobj); + CRASSERT(tl); + + if (IsProxyTarget(target)) + tl->bytes = 0; + else + tl->bytes = crTextureSize(format, type, width, height, depth); + +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + if (tl->bytes) + { + /* this is not a proxy texture target so alloc storage */ + if (tl->img) + crFree(tl->img); + tl->img = (GLubyte *) crAlloc(tl->bytes); + if (!tl->img) + { + crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, + "glTexImage3D out of memory"); + return; + } + if (pixels) + crPixelCopy3D(width, height, depth, (GLvoid *) (tl->img), format, type, + NULL, pixels, format, type, &(c->unpack)); + } +#endif + + tl->internalFormat = internalFormat; + tl->border = border; + tl->width = width; + tl->height = height; + tl->depth = depth; + tl->format = format; + tl->type = type; + tl->compressed = GL_FALSE; + +#ifdef CR_SGIS_generate_mipmap + if (level == tobj->baseLevel && tobj->generateMipmap) { + generate_mipmap(tobj, target); + } + else { + tl->generateMipmap = GL_FALSE; + } +#endif + + /* XXX may need to do some fine-tuning here for proxy textures */ + DIRTY(tobj->dirty, g->neg_bitid); + DIRTY(tobj->imageBit, g->neg_bitid); + DIRTY(tl->dirty, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} +#endif /* CR_OPENGL_VERSION_1_2 || GL_EXT_texture3D */ + + +#ifdef GL_EXT_texture3D +void STATE_APIENTRY +crStateTexImage3DEXT(GLenum target, GLint level, + GLenum internalFormat, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, GLenum format, GLenum type, + const GLvoid * pixels) +{ + crStateTexImage3D(target, level, (GLint) internalFormat, width, height, + depth, border, format, type, pixels); +} +#endif /* GL_EXT_texture3D */ + + +void STATE_APIENTRY +crStateTexSubImage1D(GLenum target, GLint level, GLint xoffset, + GLsizei width, GLenum format, + GLenum type, const GLvoid * pixels) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + CRClientState *c = &(g->client); +#endif + CRStateBits *sb = GetCurrentBits(); + CRTextureBits *tb = &(sb->texture); + CRTextureUnit *unit = t->unit + t->curTextureUnit; + CRTextureObj *tobj = unit->currentTexture1D; + CRTextureLevel *tl = tobj->level[0] + level; + (void)format; (void)type; (void)pixels; + + FLUSH(); + + if (ErrorCheckTexSubImage(1, target, level, xoffset, 0, 0, + width, 1, 1)) { + return; /* GL error state already set */ + } + +#ifdef DEBUG_misha + CRASSERT(tl->bytes); + CRASSERT(tl->height); + CRASSERT(tl->width); + CRASSERT(tl->depth); +#endif + +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + xoffset += tl->border; + + crPixelCopy1D((void *) (tl->img + xoffset * tl->bytesPerPixel), + tl->format, tl->type, + pixels, format, type, width, &(c->unpack)); +#endif + +#ifdef CR_SGIS_generate_mipmap + if (level == tobj->baseLevel && tobj->generateMipmap) { + generate_mipmap(tobj, target); + } + else { + tl->generateMipmap = GL_FALSE; + } +#endif + + DIRTY(tobj->dirty, g->neg_bitid); + DIRTY(tobj->imageBit, g->neg_bitid); + DIRTY(tl->dirty, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + + +void STATE_APIENTRY +crStateTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, const GLvoid * pixels) +{ + CRContext *g = GetCurrentContext(); + CRStateBits *sb = GetCurrentBits(); + CRTextureBits *tb = &(sb->texture); + CRTextureObj *tobj; + CRTextureLevel *tl; +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + CRClientState *c = &(g->client); + GLubyte *subimg = NULL; + GLubyte *img = NULL; + GLubyte *src; + int i; +#endif + (void)format; (void)type; (void)pixels; + + FLUSH(); + + if (ErrorCheckTexSubImage(2, target, level, xoffset, yoffset, 0, + width, height, 1)) { + return; /* GL error state already set */ + } + + crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl); + CRASSERT(tobj); + CRASSERT(tl); + +#ifdef DEBUG_misha + CRASSERT(tl->bytes); + CRASSERT(tl->height); + CRASSERT(tl->width); + CRASSERT(tl->depth); +#endif + +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + xoffset += tl->border; + yoffset += tl->border; + + subimg = (GLubyte *) crAlloc(crImageSize(tl->format, tl->type, width, height)); + + crPixelCopy2D(width, height, subimg, tl->format, tl->type, NULL, /* dst */ + pixels, format, type, &(c->unpack)); /* src */ + + img = tl->img + + xoffset * tl->bytesPerPixel + yoffset * tl->width * tl->bytesPerPixel; + + src = subimg; + + /* Copy the data into the texture */ + for (i = 0; i < height; i++) + { + crMemcpy(img, src, tl->bytesPerPixel * width); + img += tl->width * tl->bytesPerPixel; + src += width * tl->bytesPerPixel; + } + + crFree(subimg); +#endif + +#ifdef CR_SGIS_generate_mipmap + if (level == tobj->baseLevel && tobj->generateMipmap) { + generate_mipmap(tobj, target); + } + else { + tl->generateMipmap = GL_FALSE; + } +#endif + + DIRTY(tobj->dirty, g->neg_bitid); + DIRTY(tobj->imageBit, g->neg_bitid); + DIRTY(tl->dirty, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); + +#ifdef CR_DUMP_TEXTURES_2D + { + GLint w,h; + char *data; + + diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &w); + diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &h); + + data = crAlloc(w*h*4); + if (!data) crError("no memory!"); + diff_api.GetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, data); + crDumpTGA(w, h, data); + crFree(data); + } +#endif +} + +#if defined( CR_OPENGL_VERSION_1_2 ) +void STATE_APIENTRY +crStateTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLint zoffset, GLsizei width, GLsizei height, + GLsizei depth, GLenum format, GLenum type, + const GLvoid * pixels) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + CRStateBits *sb = GetCurrentBits(); + CRTextureBits *tb = &(sb->texture); + CRTextureUnit *unit = t->unit + t->curTextureUnit; + CRTextureObj *tobj = unit->currentTexture3D; + CRTextureLevel *tl = tobj->level[0] + level; +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + CRClientState *c = &(g->client); + GLubyte *subimg = NULL; + GLubyte *img = NULL; + GLubyte *src; + int i; +#endif + (void)format; (void)type; (void)pixels; + + FLUSH(); + + if (ErrorCheckTexSubImage(3, target, level, xoffset, yoffset, zoffset, + width, height, depth)) { + return; /* GL error state already set */ + } + +#ifdef DEBUG_misha + CRASSERT(target == GL_TEXTURE_3D); + CRASSERT(tl->bytes); + CRASSERT(tl->height); + CRASSERT(tl->width); + CRASSERT(tl->depth); +#endif + +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + xoffset += tl->border; + yoffset += tl->border; + zoffset += tl->border; + + subimg = + (GLubyte *) + crAlloc(crTextureSize(tl->format, tl->type, width, height, depth)); + + crPixelCopy3D(width, height, depth, subimg, tl->format, tl->type, NULL, + pixels, format, type, &(c->unpack)); + + img = tl->img + xoffset * tl->bytesPerPixel + + yoffset * tl->width * tl->bytesPerPixel + + zoffset * tl->width * tl->height * tl->bytesPerPixel; + + src = subimg; + + /* Copy the data into the texture */ + for (i = 0; i < depth; i++) + { + crMemcpy(img, src, tl->bytesPerPixel * width * height); + img += tl->width * tl->height * tl->bytesPerPixel; + src += width * height * tl->bytesPerPixel; + } + + crFree(subimg); +#endif + +#ifdef CR_SGIS_generate_mipmap + if (level == tobj->baseLevel && tobj->generateMipmap) { + generate_mipmap(tobj, target); + } + else { + tl->generateMipmap = GL_FALSE; + } +#endif + + DIRTY(tobj->dirty, g->neg_bitid); + DIRTY(tobj->imageBit, g->neg_bitid); + DIRTY(tl->dirty, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} +#endif /* CR_OPENGL_VERSION_1_2 || GL_EXT_texture3D */ + + +void STATE_APIENTRY +crStateCompressedTexImage1DARB(GLenum target, GLint level, + GLenum internalFormat, GLsizei width, + GLint border, GLsizei imageSize, + const GLvoid * data) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + CRTextureObj *tobj; + CRTextureLevel *tl; + CRStateBits *sb = GetCurrentBits(); + CRTextureBits *tb = &(sb->texture); + (void)data; + + FLUSH(); + + if (ErrorCheckTexImage(1, target, level, width, 1, 1, border)) { + if (IsProxyTarget(target)) { + /* clear all state, but don't generate error */ + crStateTextureInitTextureObj(g, &(t->proxy1D), 0, GL_TEXTURE_1D); + } + else { + /* error was already recorded */ + } + return; + } + + crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl); + CRASSERT(tobj); + CRASSERT(tl); + + if (IsProxyTarget(target)) + tl->bytes = 0; + else + tl->bytes = imageSize; + +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + if (tl->bytes) + { + /* this is not a proxy texture target so alloc storage */ + if (tl->img) + crFree(tl->img); + tl->img = (GLubyte *) crAlloc(tl->bytes); + if (!tl->img) + { + crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, + "glTexImage1D out of memory"); + return; + } + if (data) + crMemcpy(tl->img, data, imageSize); + } +#endif + + tl->width = width; + tl->height = 1; + tl->depth = 1; + tl->border = border; + tl->format = GL_NONE; + tl->type = GL_NONE; + tl->internalFormat = internalFormat; + crStateTextureInitTextureFormat(tl, internalFormat); + tl->compressed = GL_TRUE; + tl->bytesPerPixel = 0; /* n/a */ + +#ifdef CR_SGIS_generate_mipmap + if (level == tobj->baseLevel && tobj->generateMipmap) { + generate_mipmap(tobj, target); + } + else { + tl->generateMipmap = GL_FALSE; + } +#endif + + DIRTY(tobj->dirty, g->neg_bitid); + DIRTY(tobj->imageBit, g->neg_bitid); + DIRTY(tl->dirty, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + + +void STATE_APIENTRY +crStateCompressedTexImage2DARB(GLenum target, GLint level, + GLenum internalFormat, GLsizei width, + GLsizei height, GLint border, + GLsizei imageSize, const GLvoid * data) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + CRTextureObj *tobj = NULL; + CRTextureLevel *tl = NULL; + CRStateBits *sb = GetCurrentBits(); + CRTextureBits *tb = &(sb->texture); + (void)data; + + FLUSH(); + + if (ErrorCheckTexImage(2, target, level, width, height, 1, border)) { + if (IsProxyTarget(target)) { + /* clear all state, but don't generate error */ + crStateTextureInitTextureObj(g, &(t->proxy2D), 0, GL_TEXTURE_2D); + } + else { + /* error was already recorded */ + } + return; + } + + crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl); + CRASSERT(tobj); + CRASSERT(tl); + + if (IsProxyTarget(target)) + tl->bytes = 0; + else + tl->bytes = imageSize; + +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + if (tl->bytes) + { + /* this is not a proxy texture target so alloc storage */ + if (tl->img) + crFree(tl->img); + tl->img = (GLubyte *) crAlloc(tl->bytes); + if (!tl->img) + { + crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, + "glTexImage2D out of memory"); + return; + } + if (data) + crMemcpy(tl->img, data, imageSize); + } +#endif + + tl->width = width; + tl->height = height; + tl->depth = 1; + tl->border = border; + tl->format = GL_NONE; + tl->type = GL_NONE; + tl->internalFormat = internalFormat; + crStateTextureInitTextureFormat(tl, internalFormat); + tl->compressed = GL_TRUE; + tl->bytesPerPixel = 0; /* n/a */ + +#ifdef CR_SGIS_generate_mipmap + if (level == tobj->baseLevel && tobj->generateMipmap) { + generate_mipmap(tobj, target); + } + else { + tl->generateMipmap = GL_FALSE; + } +#endif + + /* XXX may need to do some fine-tuning here for proxy textures */ + DIRTY(tobj->dirty, g->neg_bitid); + DIRTY(tobj->imageBit, g->neg_bitid); + DIRTY(tl->dirty, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + + +void STATE_APIENTRY +crStateCompressedTexImage3DARB(GLenum target, GLint level, + GLenum internalFormat, GLsizei width, + GLsizei height, GLsizei depth, GLint border, + GLsizei imageSize, const GLvoid * data) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + CRTextureObj *tobj = NULL; + CRTextureLevel *tl = NULL; + CRStateBits *sb = GetCurrentBits(); + CRTextureBits *tb = &(sb->texture); + (void)data; + + FLUSH(); + + if (ErrorCheckTexImage(3, target, level, width, height, depth, border)) { + if (IsProxyTarget(target)) { + /* clear all state, but don't generate error */ + crStateTextureInitTextureObj(g, &(t->proxy3D), 0, GL_TEXTURE_3D); + } + else { + /* error was already recorded */ + } + return; + } + + crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl); + CRASSERT(tobj); + CRASSERT(tl); + + if (IsProxyTarget(target)) + tl->bytes = 0; + else + tl->bytes = imageSize; + +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + if (tl->bytes) + { + /* this is not a proxy texture target so alloc storage */ + if (tl->img) + crFree(tl->img); + tl->img = (GLubyte *) crAlloc(tl->bytes); + if (!tl->img) + { + crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, + "glCompressedTexImage3D out of memory"); + return; + } + if (data) + crMemcpy(tl->img, data, imageSize); + } +#endif + + tl->width = width; + tl->height = height; + tl->depth = depth; + tl->border = border; + tl->format = GL_NONE; + tl->type = GL_NONE; + tl->internalFormat = internalFormat; + crStateTextureInitTextureFormat(tl, internalFormat); + tl->compressed = GL_TRUE; + tl->bytesPerPixel = 0; /* n/a */ + +#ifdef CR_SGIS_generate_mipmap + if (level == tobj->baseLevel && tobj->generateMipmap) { + generate_mipmap(tobj, target); + } + else { + tl->generateMipmap = GL_FALSE; + } +#endif + + /* XXX may need to do some fine-tuning here for proxy textures */ + DIRTY(tobj->dirty, g->neg_bitid); + DIRTY(tobj->imageBit, g->neg_bitid); + DIRTY(tl->dirty, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + + +void STATE_APIENTRY +crStateCompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, + GLsizei width, GLenum format, + GLsizei imageSize, const GLvoid * data) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + CRStateBits *sb = GetCurrentBits(); + CRTextureBits *tb = &(sb->texture); + CRTextureUnit *unit = t->unit + t->curTextureUnit; + CRTextureObj *tobj = unit->currentTexture1D; + CRTextureLevel *tl = tobj->level[0] + level; + (void)format; (void)imageSize; (void)data; + + FLUSH(); + + if (ErrorCheckTexSubImage(1, target, level, xoffset, 0, 0, width, 1, 1)) { + return; /* GL error state already set */ + } + +#ifdef DEBUG_misha + CRASSERT(target == GL_TEXTURE_1D); + CRASSERT(tl->bytes); + CRASSERT(tl->height); + CRASSERT(tl->width); + CRASSERT(tl->depth); +#endif + +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + xoffset += tl->border; + + if (xoffset == 0 && width == tl->width) { + /* just memcpy */ + crMemcpy(tl->img, data, imageSize); + } + else { + /* XXX this depends on the exact compression method */ + crWarning("Not implemented part crStateCompressedTexSubImage1DARB"); + } +#endif + +#ifdef CR_SGIS_generate_mipmap + if (level == tobj->baseLevel && tobj->generateMipmap) { + generate_mipmap(tobj, target); + } + else { + tl->generateMipmap = GL_FALSE; + } +#endif + + DIRTY(tobj->dirty, g->neg_bitid); + DIRTY(tobj->imageBit, g->neg_bitid); + DIRTY(tl->dirty, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + + +void STATE_APIENTRY +crStateCompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLsizei width, + GLsizei height, GLenum format, + GLsizei imageSize, const GLvoid * data) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + CRStateBits *sb = GetCurrentBits(); + CRTextureBits *tb = &(sb->texture); + CRTextureUnit *unit = t->unit + t->curTextureUnit; + CRTextureObj *tobj = unit->currentTexture2D; + CRTextureLevel *tl = tobj->level[0] + level; + (void)format; (void)imageSize; (void)data; + + FLUSH(); + +#ifdef DEBUG_misha + CRASSERT(target == GL_TEXTURE_2D); + CRASSERT(tl->bytes); + CRASSERT(tl->height); + CRASSERT(tl->width); + CRASSERT(tl->depth); +#endif + + if (ErrorCheckTexSubImage(2, target, level, xoffset, yoffset, 0, + width, height, 1)) { + return; /* GL error state already set */ + } + +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + xoffset += tl->border; + yoffset += tl->border; + + if (xoffset == 0 && width == tl->width + && yoffset == 0 && height == tl->height) + { + /* just memcpy */ + crMemcpy(tl->img, data, imageSize); + } + else { + /* XXX this depends on the exact compression method */ + crWarning("Not implemented part crStateCompressedTexSubImage2DARB"); + } +#endif + +#ifdef CR_SGIS_generate_mipmap + if (level == tobj->baseLevel && tobj->generateMipmap) { + generate_mipmap(tobj, target); + } + else { + tl->generateMipmap = GL_FALSE; + } +#endif + + DIRTY(tobj->dirty, g->neg_bitid); + DIRTY(tobj->imageBit, g->neg_bitid); + DIRTY(tl->dirty, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + + +void STATE_APIENTRY +crStateCompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, + GLenum format, GLsizei imageSize, + const GLvoid * data) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + CRStateBits *sb = GetCurrentBits(); + CRTextureBits *tb = &(sb->texture); + CRTextureUnit *unit = t->unit + t->curTextureUnit; + CRTextureObj *tobj = unit->currentTexture3D; + CRTextureLevel *tl = tobj->level[0] + level; + (void)format; (void)imageSize; (void)data; + + FLUSH(); + +#ifdef DEBUG_misha + CRASSERT(target == GL_TEXTURE_3D); + CRASSERT(tl->bytes); + CRASSERT(tl->height); + CRASSERT(tl->width); + CRASSERT(tl->depth); +#endif + + if (ErrorCheckTexSubImage(3, target, level, xoffset, yoffset, zoffset, + width, height, depth)) { + return; /* GL error state already set */ + } + +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + xoffset += tl->border; + yoffset += tl->border; + zoffset += tl->border; + + if (xoffset == 0 && width == tl->width && + yoffset == 0 && height == tl->height && + zoffset == 0 && depth == tl->depth) { + /* just memcpy */ + crMemcpy(tl->img, data, imageSize); + } + else { + /* XXX this depends on the exact compression method */ + crWarning("Not implemented part crStateCompressedTexSubImage3DARB"); + } +#endif + +#ifdef CR_SGIS_generate_mipmap + if (level == tobj->baseLevel && tobj->generateMipmap) { + generate_mipmap(tobj, target); + } + else { + tl->generateMipmap = GL_FALSE; + } +#endif + + DIRTY(tobj->dirty, g->neg_bitid); + DIRTY(tobj->imageBit, g->neg_bitid); + DIRTY(tl->dirty, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + + +void STATE_APIENTRY +crStateGetCompressedTexImageARB(GLenum target, GLint level, GLvoid * img) +{ + CRContext *g = GetCurrentContext(); + CRTextureObj *tobj; + CRTextureLevel *tl; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetCompressedTexImage called in begin/end"); + return; + } + + crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl); + if (!tobj || !tl) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetCompressedTexImage(invalid target or level)"); + return; + } + + if (!tl->compressed) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetCompressedTexImage(not a compressed texture)"); + return; + } + +#ifdef DEBUG_misha + CRASSERT(tl->bytes); + CRASSERT(tl->height); + CRASSERT(tl->width); + CRASSERT(tl->depth); +#endif + +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + crMemcpy(img, tl->img, tl->bytes); +#else + diff_api.GetCompressedTexImageARB(target, level, img); +#endif +} + + +void STATE_APIENTRY +crStateGetTexImage(GLenum target, GLint level, GLenum format, + GLenum type, GLvoid * pixels) +{ + CRContext *g = GetCurrentContext(); +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE + CRClientState *c = &(g->client); +#endif + CRTextureObj *tobj; + CRTextureLevel *tl; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetTexImage called in begin/end"); + return; + } + + crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl); + if (!tobj || !tl) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexImage(invalid target or level)"); + return; + } + + if (tl->compressed) { + crWarning("glGetTexImage cannot decompress a compressed texture!"); + return; + } + +#ifdef DEBUG_misha + CRASSERT(tl->bytes); + CRASSERT(tl->height); + CRASSERT(tl->width); + CRASSERT(tl->depth); +#endif + + switch (format) + { + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_RGB: + case GL_RGBA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexImage called with bogus format: %d", format); + return; + } + + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_BYTE: + case GL_UNSIGNED_SHORT: + case GL_SHORT: + case GL_UNSIGNED_INT: + case GL_INT: + case GL_FLOAT: + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexImage called with bogus type: %d", type); + return; + } + +#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE +#ifdef CR_OPENGL_VERSION_1_2 + if (target == GL_TEXTURE_3D) + { + crPixelCopy3D(tl->width, tl->height, tl->depth, (GLvoid *) pixels, format, + type, NULL, (tl->img), format, type, &(c->pack)); + } + else +#endif + if ((target == GL_TEXTURE_1D) || (target == GL_TEXTURE_2D)) + { + crPixelCopy2D(tl->width, tl->height, (GLvoid *) pixels, format, type, NULL, /* dst */ + tl->img, format, type, &(c->pack)); /* src */ + } +#else + diff_api.GetTexImage(target, level, format, type, pixels); +#endif +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c new file mode 100644 index 00000000..5184feb6 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c @@ -0,0 +1,3418 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "state.h" +#include "state/cr_statetypes.h" +#include "state/cr_texture.h" +#include "cr_hash.h" +#include "cr_string.h" +#include "cr_mem.h" +#include "cr_version.h" +#include "state_internals.h" + +#ifdef DEBUG_misha +#include <iprt/assert.h> +#endif + +#define UNUSED(x) ((void) (x)) + +#define GET_TOBJ(tobj, state, id) \ + tobj = (CRTextureObj *) crHashtableSearch(g->shared->textureTable, id); + + +void crStateTextureDestroy(CRContext *ctx) +{ + crStateDeleteTextureObjectData(&ctx->texture.base1D); + crStateDeleteTextureObjectData(&ctx->texture.proxy1D); + crStateDeleteTextureObjectData(&ctx->texture.base2D); + crStateDeleteTextureObjectData(&ctx->texture.proxy2D); +#ifdef CR_OPENGL_VERSION_1_2 + crStateDeleteTextureObjectData(&ctx->texture.base3D); + crStateDeleteTextureObjectData(&ctx->texture.proxy3D); +#endif +#ifdef CR_ARB_texture_cube_map + crStateDeleteTextureObjectData(&ctx->texture.baseCubeMap); + crStateDeleteTextureObjectData(&ctx->texture.proxyCubeMap); +#endif +#ifdef CR_NV_texture_rectangle + crStateDeleteTextureObjectData(&ctx->texture.baseRect); + crStateDeleteTextureObjectData(&ctx->texture.proxyRect); +#endif +} + + +void crStateTextureInit(CRContext *ctx) +{ + CRLimitsState *limits = &ctx->limits; + CRTextureState *t = &ctx->texture; + CRStateBits *sb = GetCurrentBits(); + CRTextureBits *tb = &(sb->texture); + unsigned int i; + unsigned int a; + GLvectorf zero_vector = {0.0f, 0.0f, 0.0f, 0.0f}; + GLcolorf zero_color = {0.0f, 0.0f, 0.0f, 0.0f}; + GLvectorf x_vector = {1.0f, 0.0f, 0.0f, 0.0f}; + GLvectorf y_vector = {0.0f, 1.0f, 0.0f, 0.0f}; + + /* compute max levels from max sizes */ + for (i=0, a=limits->maxTextureSize; a; i++, a=a>>1); + t->maxLevel = i-1; + for (i=0, a=limits->max3DTextureSize; a; i++, a=a>>1); + t->max3DLevel = i-1; +#ifdef CR_ARB_texture_cube_map + for (i=0, a=limits->maxCubeMapTextureSize; a; i++, a=a>>1); + t->maxCubeMapLevel = i-1; +#endif +#ifdef CR_NV_texture_rectangle + for (i=0, a=limits->maxRectTextureSize; a; i++, a=a>>1); + t->maxRectLevel = i-1; +#endif + + crStateTextureInitTextureObj(ctx, &(t->base1D), 0, GL_TEXTURE_1D); + crStateTextureInitTextureObj(ctx, &(t->base2D), 0, GL_TEXTURE_2D); +#ifdef CR_OPENGL_VERSION_1_2 + crStateTextureInitTextureObj(ctx, &(t->base3D), 0, GL_TEXTURE_3D); +#endif +#ifdef CR_ARB_texture_cube_map + crStateTextureInitTextureObj(ctx, &(t->baseCubeMap), 0, + GL_TEXTURE_CUBE_MAP_ARB); +#endif +#ifdef CR_NV_texture_rectangle + crStateTextureInitTextureObj(ctx, &(t->baseRect), 0, + GL_TEXTURE_RECTANGLE_NV); +#endif + + crStateTextureInitTextureObj(ctx, &(t->proxy1D), 0, GL_TEXTURE_1D); + crStateTextureInitTextureObj(ctx, &(t->proxy2D), 0, GL_TEXTURE_2D); +#ifdef CR_OPENGL_VERSION_1_2 + crStateTextureInitTextureObj(ctx, &(t->proxy3D), 0, GL_TEXTURE_3D); +#endif +#ifdef CR_ARB_texture_cube_map + crStateTextureInitTextureObj(ctx, &(t->proxyCubeMap), 0, + GL_TEXTURE_CUBE_MAP_ARB); +#endif +#ifdef CR_NV_texture_rectangle + crStateTextureInitTextureObj(ctx, &(t->proxyRect), 0, + GL_TEXTURE_RECTANGLE_NV); +#endif + + t->curTextureUnit = 0; + + /* Per-unit initialization */ + for (i = 0; i < limits->maxTextureUnits; i++) + { + t->unit[i].currentTexture1D = &(t->base1D); + t->unit[i].currentTexture2D = &(t->base2D); + t->unit[i].currentTexture3D = &(t->base3D); +#ifdef CR_ARB_texture_cube_map + t->unit[i].currentTextureCubeMap = &(t->baseCubeMap); +#endif +#ifdef CR_NV_texture_rectangle + t->unit[i].currentTextureRect = &(t->baseRect); +#endif + + t->unit[i].enabled1D = GL_FALSE; + t->unit[i].enabled2D = GL_FALSE; + t->unit[i].enabled3D = GL_FALSE; + t->unit[i].enabledCubeMap = GL_FALSE; +#ifdef CR_NV_texture_rectangle + t->unit[i].enabledRect = GL_FALSE; +#endif + t->unit[i].textureGen.s = GL_FALSE; + t->unit[i].textureGen.t = GL_FALSE; + t->unit[i].textureGen.r = GL_FALSE; + t->unit[i].textureGen.q = GL_FALSE; + + t->unit[i].gen.s = GL_EYE_LINEAR; + t->unit[i].gen.t = GL_EYE_LINEAR; + t->unit[i].gen.r = GL_EYE_LINEAR; + t->unit[i].gen.q = GL_EYE_LINEAR; + + t->unit[i].objSCoeff = x_vector; + t->unit[i].objTCoeff = y_vector; + t->unit[i].objRCoeff = zero_vector; + t->unit[i].objQCoeff = zero_vector; + + t->unit[i].eyeSCoeff = x_vector; + t->unit[i].eyeTCoeff = y_vector; + t->unit[i].eyeRCoeff = zero_vector; + t->unit[i].eyeQCoeff = zero_vector; + t->unit[i].envMode = GL_MODULATE; + t->unit[i].envColor = zero_color; + + t->unit[i].combineModeRGB = GL_MODULATE; + t->unit[i].combineModeA = GL_MODULATE; + t->unit[i].combineSourceRGB[0] = GL_TEXTURE; + t->unit[i].combineSourceRGB[1] = GL_PREVIOUS_EXT; + t->unit[i].combineSourceRGB[2] = GL_CONSTANT_EXT; + t->unit[i].combineSourceA[0] = GL_TEXTURE; + t->unit[i].combineSourceA[1] = GL_PREVIOUS_EXT; + t->unit[i].combineSourceA[2] = GL_CONSTANT_EXT; + t->unit[i].combineOperandRGB[0] = GL_SRC_COLOR; + t->unit[i].combineOperandRGB[1] = GL_SRC_COLOR; + t->unit[i].combineOperandRGB[2] = GL_SRC_ALPHA; + t->unit[i].combineOperandA[0] = GL_SRC_ALPHA; + t->unit[i].combineOperandA[1] = GL_SRC_ALPHA; + t->unit[i].combineOperandA[2] = GL_SRC_ALPHA; + t->unit[i].combineScaleRGB = 1.0F; + t->unit[i].combineScaleA = 1.0F; +#ifdef CR_EXT_texture_lod_bias + t->unit[i].lodBias = 0.0F; +#endif + RESET(tb->enable[i], ctx->bitid); + RESET(tb->current[i], ctx->bitid); + RESET(tb->objGen[i], ctx->bitid); + RESET(tb->eyeGen[i], ctx->bitid); + RESET(tb->genMode[i], ctx->bitid); + RESET(tb->envBit[i], ctx->bitid); + } + RESET(tb->dirty, ctx->bitid); +} + + +void +crStateTextureInitTextureObj(CRContext *ctx, CRTextureObj *tobj, + GLuint name, GLenum target) +{ + const CRTextureState *t = &(ctx->texture); + int i, face; + + tobj->borderColor.r = 0.0f; + tobj->borderColor.g = 0.0f; + tobj->borderColor.b = 0.0f; + tobj->borderColor.a = 0.0f; + tobj->minFilter = GL_NEAREST_MIPMAP_LINEAR; + tobj->magFilter = GL_LINEAR; + tobj->wrapS = GL_REPEAT; + tobj->wrapT = GL_REPEAT; +#ifdef CR_OPENGL_VERSION_1_2 + tobj->wrapR = GL_REPEAT; + tobj->priority = 1.0f; + tobj->minLod = -1000.0; + tobj->maxLod = 1000.0; + tobj->baseLevel = 0; + tobj->maxLevel = t->maxLevel; +#endif + tobj->target = target; + tobj->id = name; + tobj->hwid = 0; + +#ifndef IN_GUEST + crStateGetTextureObjHWID(tobj); +#endif + + CRASSERT(t->maxLevel); + + /* XXX don't always need all six faces */ + for (face = 0; face < 6; face++) { + /* allocate array of mipmap levels */ + CRASSERT(t->maxLevel < CR_MAX_MIPMAP_LEVELS); + tobj->level[face] = (CRTextureLevel *) + crCalloc(sizeof(CRTextureLevel) * CR_MAX_MIPMAP_LEVELS); + + if (!tobj->level[face]) + return; /* out of memory */ + + /* init non-zero fields */ + for (i = 0; i <= t->maxLevel; i++) { + CRTextureLevel *tl = &(tobj->level[face][i]); + tl->internalFormat = GL_ONE; + tl->format = GL_RGBA; + tl->type = GL_UNSIGNED_BYTE; + crStateTextureInitTextureFormat( tl, tl->internalFormat ); + } + } + +#ifdef CR_EXT_texture_filter_anisotropic + tobj->maxAnisotropy = 1.0f; +#endif + +#ifdef CR_ARB_depth_texture + tobj->depthMode = GL_LUMINANCE; +#endif + +#ifdef CR_ARB_shadow + tobj->compareMode = GL_NONE; + tobj->compareFunc = GL_LEQUAL; +#endif + +#ifdef CR_ARB_shadow_ambient + tobj->compareFailValue = 0.0; +#endif + + RESET(tobj->dirty, ctx->bitid); + RESET(tobj->imageBit, ctx->bitid); + for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) + { + RESET(tobj->paramsBit[i], ctx->bitid); + } + + CR_STATE_SHAREDOBJ_USAGE_INIT(tobj); + CR_STATE_SHAREDOBJ_USAGE_SET(tobj, ctx); +} + + +/* ================================================================ + * Texture internal formats: + */ + +const CRTextureFormat _texformat_rgba8888 = { + 8, /* RedBits */ + 8, /* GreenBits */ + 8, /* BlueBits */ + 8, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ +}; + +const CRTextureFormat _texformat_argb8888 = { + 8, /* RedBits */ + 8, /* GreenBits */ + 8, /* BlueBits */ + 8, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ +}; + +const CRTextureFormat _texformat_rgb888 = { + 8, /* RedBits */ + 8, /* GreenBits */ + 8, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ +}; + +const CRTextureFormat _texformat_rgb565 = { + 5, /* RedBits */ + 6, /* GreenBits */ + 5, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ +}; + +const CRTextureFormat _texformat_argb4444 = { + 4, /* RedBits */ + 4, /* GreenBits */ + 4, /* BlueBits */ + 4, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ +}; + +const CRTextureFormat _texformat_argb1555 = { + 5, /* RedBits */ + 5, /* GreenBits */ + 5, /* BlueBits */ + 1, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ +}; + +const CRTextureFormat _texformat_al88 = { + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 8, /* AlphaBits */ + 8, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ +}; + +const CRTextureFormat _texformat_rgb332 = { + 3, /* RedBits */ + 3, /* GreenBits */ + 2, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ +}; + +const CRTextureFormat _texformat_a8 = { + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 8, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ +}; + +const CRTextureFormat _texformat_l8 = { + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 8, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ +}; + +const CRTextureFormat _texformat_i8 = { + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 8, /* IntensityBits */ + 0, /* IndexBits */ +}; + +const CRTextureFormat _texformat_ci8 = { + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 8, /* IndexBits */ +}; + + +/** + * Given an internal texture format enum or 1, 2, 3, 4 initialize the + * texture levels texture format. This basically just indicates the + * number of red, green, blue, alpha, luminance, etc. bits are used to + * store the image. + */ +void +crStateTextureInitTextureFormat( CRTextureLevel *tl, GLenum internalFormat ) +{ + switch (internalFormat) { + case 4: + case GL_RGBA: + case GL_COMPRESSED_RGBA_ARB: +#ifdef CR_EXT_texture_sRGB + case GL_SRGB_ALPHA_EXT: + case GL_SRGB8_ALPHA8_EXT: + case GL_COMPRESSED_SRGB_ALPHA_EXT: +#endif + tl->texFormat = &_texformat_rgba8888; + break; + + case 3: + case GL_RGB: + case GL_COMPRESSED_RGB_ARB: +#ifdef CR_EXT_texture_sRGB + case GL_SRGB_EXT: + case GL_SRGB8_EXT: + case GL_COMPRESSED_SRGB_EXT: +#endif + tl->texFormat = &_texformat_rgb888; + break; + + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + tl->texFormat = &_texformat_rgba8888; + break; + + case GL_R3_G3_B2: + tl->texFormat = &_texformat_rgb332; + break; + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + tl->texFormat = &_texformat_rgb888; + break; + + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + case GL_COMPRESSED_ALPHA_ARB: + tl->texFormat = &_texformat_a8; + break; + + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + case GL_COMPRESSED_LUMINANCE_ARB: +#ifdef CR_EXT_texture_sRGB + case GL_SLUMINANCE_EXT: + case GL_SLUMINANCE8_EXT: + case GL_COMPRESSED_SLUMINANCE_EXT: +#endif + tl->texFormat = &_texformat_l8; + break; + + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + case GL_COMPRESSED_LUMINANCE_ALPHA_ARB: +#ifdef CR_EXT_texture_sRGB + case GL_SLUMINANCE_ALPHA_EXT: + case GL_SLUMINANCE8_ALPHA8_EXT: + case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: +#endif + tl->texFormat = &_texformat_al88; + break; + + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + case GL_COMPRESSED_INTENSITY_ARB: + tl->texFormat = &_texformat_i8; + break; + + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + tl->texFormat = &_texformat_ci8; + break; + + default: + return; + } +} + +#if 0 +void crStateTextureInitTexture (GLuint name) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + CRTextureObj *tobj; + + GET_TOBJ(tobj, name); + if (!tobj) return; + + crStateTextureInitTextureObj(g, tobj, name, GL_NONE); +} +#endif + + + +/** + * Return the texture object corresponding to the given target and ID. + */ +CRTextureObj * +crStateTextureGet(GLenum target, GLuint name) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + CRTextureObj *tobj; + + if (name == 0) + { + switch (target) { + case GL_TEXTURE_1D: + return &t->base1D; + case GL_TEXTURE_2D: + return &t->base2D; + case GL_TEXTURE_3D: + return &t->base3D; +#ifdef CR_ARB_texture_cube_map + case GL_TEXTURE_CUBE_MAP_ARB: + return &t->baseCubeMap; +#endif +#ifdef CR_NV_texture_rectangle + case GL_TEXTURE_RECTANGLE_NV: + return &t->baseRect; +#endif + default: + return NULL; + } + } + + GET_TOBJ(tobj, g, name); + + return tobj; +} + + +/* + * Allocate a new texture object with the given name. + * Also insert into hash table. + */ +static CRTextureObj * +crStateTextureAllocate_t(CRContext *ctx, GLuint name) +{ + CRTextureObj *tobj; + + if (!name) + return NULL; + + tobj = crCalloc(sizeof(CRTextureObj)); + if (!tobj) + return NULL; + + crHashtableAdd( ctx->shared->textureTable, name, (void *) tobj ); + + crStateTextureInitTextureObj(ctx, tobj, name, GL_NONE); + + return tobj; +} + + +/** + * Delete all the data that hangs off a CRTextureObj, but don't + * delete the texture object itself, since it may not have been + * dynamically allocated. + */ +void +crStateDeleteTextureObjectData(CRTextureObj *tobj) +{ + int k; + int face; + + CRASSERT(tobj); + + /* Free the texture images */ + for (face = 0; face < 6; face++) { + CRTextureLevel *levels = NULL; + levels = tobj->level[face]; + if (levels) { + /* free all mipmap levels for this face */ + for (k = 0; k < CR_MAX_MIPMAP_LEVELS; k++) { + CRTextureLevel *tl = levels + k; + if (tl->img) { + crFree(tl->img); + tl->img = NULL; + tl->bytes = 0; + } + } + crFree(levels); + } + tobj->level[face] = NULL; + } +} + + +void +crStateDeleteTextureObject(CRTextureObj *tobj) +{ + crStateDeleteTextureObjectData(tobj); + crFree(tobj); +} + +void crStateRegNames(CRContext *g, CRHashTable *table, GLsizei n, GLuint *names) +{ + GLint i; + (void)g; + for (i = 0; i < n; i++) + { + if (names[i]) + { + GLboolean isNewKey = crHashtableAllocRegisterKey(table, names[i]); + CRASSERT(isNewKey); + } + else + crWarning("RegNames: requested to register a null name"); + } +} + +void crStateRegTextures(GLsizei n, GLuint *names) +{ + CRContext *g = GetCurrentContext(); + crStateRegNames(g, g->shared->textureTable, n, names); +} + +void crStateGenNames(CRContext *g, CRHashTable *table, GLsizei n, GLuint *names) +{ + GLint start; + + FLUSH(); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "crStateGenNames called in Begin/End"); + return; + } + + if (n < 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "Negative n passed to crStateGenNames: %d", n); + return; + } + + start = crHashtableAllocKeys(table, n); + if (start) + { + GLint i; + for (i = 0; i < n; i++) + names[i] = (GLuint) (start + i); + } + else + { + crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glGenTextures"); + } +} + +void STATE_APIENTRY crStateGenTextures(GLsizei n, GLuint *textures) +{ + CRContext *g = GetCurrentContext(); + crStateGenNames(g, g->shared->textureTable, n, textures); +} + +static void crStateTextureCheckFBOAPs(GLenum target, GLuint texture) +{ + GLuint u; + CRFBOAttachmentPoint *ap; + CRContext *g = GetCurrentContext(); + CRFramebufferObjectState *fbo = &g->framebufferobject; + CRFramebufferObject *pFBO; + + pFBO = GL_READ_FRAMEBUFFER==target ? fbo->readFB : fbo->drawFB; + if (!pFBO) return; + + for (u=0; u<CR_MAX_COLOR_ATTACHMENTS; ++u) + { + ap = &pFBO->color[u]; + if (ap->type==GL_TEXTURE && ap->name==texture) + { + crStateFramebufferTexture1DEXT(target, u+GL_COLOR_ATTACHMENT0_EXT, 0, 0, 0); + } + } + + ap = &pFBO->depth; + if (ap->type==GL_TEXTURE && ap->name==texture) + { + crStateFramebufferTexture1DEXT(target, GL_DEPTH_ATTACHMENT_EXT, 0, 0, 0); + } + + ap = &pFBO->stencil; + if (ap->type==GL_TEXTURE && ap->name==texture) + { + crStateFramebufferTexture1DEXT(target, GL_STENCIL_ATTACHMENT_EXT, 0, 0, 0); + } +} + +static void crStateCleanupTextureRefs(CRContext *g, CRTextureObj *tObj) +{ + CRTextureState *t = &(g->texture); + GLuint u; + + /* + ** reset back to the base texture. + */ + for (u = 0; u < g->limits.maxTextureUnits; u++) + { + if (tObj == t->unit[u].currentTexture1D) + { + t->unit[u].currentTexture1D = &(t->base1D); + } + if (tObj == t->unit[u].currentTexture2D) + { + t->unit[u].currentTexture2D = &(t->base2D); + } +#ifdef CR_OPENGL_VERSION_1_2 + if (tObj == t->unit[u].currentTexture3D) + { + t->unit[u].currentTexture3D = &(t->base3D); + } +#endif +#ifdef CR_ARB_texture_cube_map + if (tObj == t->unit[u].currentTextureCubeMap) + { + t->unit[u].currentTextureCubeMap = &(t->baseCubeMap); + } +#endif +#ifdef CR_NV_texture_rectangle + if (tObj == t->unit[u].currentTextureRect) + { + t->unit[u].currentTextureRect = &(t->baseRect); + } +#endif + +#ifdef CR_EXT_framebuffer_object + crStateTextureCheckFBOAPs(GL_DRAW_FRAMEBUFFER, tObj->id); + crStateTextureCheckFBOAPs(GL_READ_FRAMEBUFFER, tObj->id); +#endif + } +} + +void STATE_APIENTRY crStateDeleteTextures(GLsizei n, const GLuint *textures) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + CRStateBits *sb = GetCurrentBits(); + CRTextureBits *tb = &(sb->texture); + int i; + + FLUSH(); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glDeleteTextures called in Begin/End"); + return; + } + + if (n < 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "Negative n passed to glDeleteTextures: %d", n); + return; + } + + for (i=0; i<n; i++) + { + GLuint name = textures[i]; + CRTextureObj *tObj; + if (!name) + continue; + + GET_TOBJ(tObj, g, name); + if (tObj) + { + GLuint j; + + crStateCleanupTextureRefs(g, tObj); + + CR_STATE_SHAREDOBJ_USAGE_CLEAR(tObj, g); + + CR_STATE_SHAREDOBJ_USAGE_FOREACH_USED_IDX(tObj, j) + { + /* saved state version <= SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS does not have usage bits info, + * so on restore, we set mark bits as used. + * This is why g_pAvailableContexts[j] could be NULL + * also g_pAvailableContexts[0] will hold default context, which we should discard */ + CRContext *ctx = g_pAvailableContexts[j]; + if (j && ctx) + { + crStateCleanupTextureRefs(ctx, tObj); + CR_STATE_SHAREDOBJ_USAGE_CLEAR(tObj, g); + } + else + CR_STATE_SHAREDOBJ_USAGE_CLEAR_IDX(tObj, j); + } + + /* on the host side, ogl texture object is deleted by a separate cr_server.head_spu->dispatch_table.DeleteTextures(n, newTextures); + * in crServerDispatchDeleteTextures, we just delete a state object here, which crStateDeleteTextureObject does */ + crHashtableDelete(g->shared->textureTable, name, (CRHashtableCallback)crStateDeleteTextureObject); + } + else + { + /* call crHashtableDelete in any way, to ensure the allocated key is freed */ + Assert(crHashtableIsKeyUsed(g->shared->textureTable, name)); + crHashtableDelete(g->shared->textureTable, name, NULL); + } + } + + DIRTY(tb->dirty, g->neg_bitid); + DIRTY(tb->current[t->curTextureUnit], g->neg_bitid); +} + + + +void STATE_APIENTRY crStateClientActiveTextureARB( GLenum texture ) +{ + CRContext *g = GetCurrentContext(); + CRClientState *c = &(g->client); + + FLUSH(); + + if (!g->extensions.ARB_multitexture) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glClientActiveTextureARB not available"); + return; + } + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glClientActiveTextureARB called in Begin/End"); + return; + } + + if ( texture < GL_TEXTURE0_ARB || + texture >= GL_TEXTURE0_ARB + g->limits.maxTextureUnits) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "crStateClientActiveTexture: unit = %d (max is %d)", + texture, g->limits.maxTextureUnits ); + return; + } + + c->curClientTextureUnit = texture - GL_TEXTURE0_ARB; + + DIRTY(GetCurrentBits()->client.dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateActiveTextureARB( GLenum texture ) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + + FLUSH(); + + if (!g->extensions.ARB_multitexture) { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glActiveTextureARB not available"); + return; + } + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glActiveTextureARB called in Begin/End"); + return; + } + + if ( texture < GL_TEXTURE0_ARB || texture >= GL_TEXTURE0_ARB + g->limits.maxTextureUnits) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "Bad texture unit passed to crStateActiveTexture: %d (max is %d)", texture, g->limits.maxTextureUnits ); + return; + } + + t->curTextureUnit = texture - GL_TEXTURE0_ARB; + + /* update the current matrix pointer, etc. */ + if (g->transform.matrixMode == GL_TEXTURE) { + crStateMatrixMode(GL_TEXTURE); + } +} + +#ifndef IN_GUEST +# ifdef DEBUG +static uint32_t gDbgNumPinned = 0; +# endif + +DECLEXPORT(void) crStatePinTexture(GLuint texture, GLboolean pin) +{ + CRTextureObj * pTobj; + CRSharedState *pShared = crStateGlobalSharedAcquire(); + if (pShared) + { + pTobj = (CRTextureObj*)crHashtableSearch(pShared->textureTable, texture); + + if (pTobj) + { +# ifdef DEBUG + if (!pTobj->pinned != !pin) + { + if (pin) + ++gDbgNumPinned; + else + { + Assert(gDbgNumPinned); + --gDbgNumPinned; + } + } +# endif + pTobj->pinned = !!pin; + if (!pin) + { + if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pTobj)) + crStateOnTextureUsageRelease(pShared, pTobj); + } + } + else + WARN(("texture %d not defined", texture)); + + crStateGlobalSharedRelease(); + } + else + WARN(("no global shared")); +} +#endif + +DECLEXPORT(void) crStateSetTextureUsed(GLuint texture, GLboolean used) +{ + CRContext *g = GetCurrentContext(); + CRTextureObj *tobj; + + if (!texture) + { + crWarning("crStateSetTextureUsed: null texture name specified!"); + return; + } + + GET_TOBJ(tobj, g, texture); + if (!tobj) + { +#ifdef IN_GUEST + if (used) + { + tobj = crStateTextureAllocate_t(g, texture); + } + else +#endif + { + WARN(("crStateSetTextureUsed: failed to fined a HW name for texture(%d)!", texture)); + return; + } + } + + if (used) + CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g); + else + { + CRStateBits *sb = GetCurrentBits(); + CRTextureBits *tb = &(sb->texture); + CRTextureState *t = &(g->texture); + + crStateCleanupTextureRefs(g, tobj); + + crStateReleaseTexture(g, tobj); + + DIRTY(tb->dirty, g->neg_bitid); + DIRTY(tb->current[t->curTextureUnit], g->neg_bitid); + } +} + +void STATE_APIENTRY crStateBindTexture(GLenum target, GLuint texture) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + CRTextureObj *tobj; + CRStateBits *sb = GetCurrentBits(); + CRTextureBits *tb = &(sb->texture); + + FLUSH(); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glBindTexture called in Begin/End"); + return; + } + + /* Special Case name = 0 */ + if (!texture) + { + switch (target) + { + case GL_TEXTURE_1D: + t->unit[t->curTextureUnit].currentTexture1D = &(t->base1D); + break; + case GL_TEXTURE_2D: + t->unit[t->curTextureUnit].currentTexture2D = &(t->base2D); + break; +#ifdef CR_OPENGL_VERSION_1_2 + case GL_TEXTURE_3D: + t->unit[t->curTextureUnit].currentTexture3D = &(t->base3D); + break; +#endif +#ifdef CR_ARB_texture_cube_map + case GL_TEXTURE_CUBE_MAP_ARB: + if (!g->extensions.ARB_texture_cube_map) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "Invalid target passed to glBindTexture: %d", target); + return; + } + t->unit[t->curTextureUnit].currentTextureCubeMap = &(t->baseCubeMap); + break; +#endif +#ifdef CR_NV_texture_rectangle + case GL_TEXTURE_RECTANGLE_NV: + if (!g->extensions.NV_texture_rectangle) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "Invalid target passed to glBindTexture: %d", target); + return; + } + t->unit[t->curTextureUnit].currentTextureRect = &(t->baseRect); + break; +#endif + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid target passed to glBindTexture: %d", target); + return; + } + + DIRTY(tb->dirty, g->neg_bitid); + DIRTY(tb->current[t->curTextureUnit], g->neg_bitid); + return; + } + + /* texture != 0 */ + /* Get the texture */ + GET_TOBJ(tobj, g, texture); + if (!tobj) + { + Assert(crHashtableIsKeyUsed(g->shared->textureTable, texture)); + tobj = crStateTextureAllocate_t(g, texture); + } + + CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g); + + /* Check the targets */ + if (tobj->target == GL_NONE) + { + /* Target isn't set so set it now.*/ + tobj->target = target; + } + else if ((tobj->target != target) + && !((target==GL_TEXTURE_RECTANGLE_NV && tobj->target==GL_TEXTURE_2D) + ||(target==GL_TEXTURE_2D && tobj->target==GL_TEXTURE_RECTANGLE_NV))) + { + crWarning( "You called glBindTexture with a target of 0x%x, but the texture you wanted was target 0x%x [1D: %x 2D: %x 3D: %x cube: %x]", (int) target, (int) tobj->target, GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP ); + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "Attempt to bind a texture of different dimensions"); + return; + } + + /* Set the current texture */ + switch (target) + { + case GL_TEXTURE_1D: + t->unit[t->curTextureUnit].currentTexture1D = tobj; + break; + case GL_TEXTURE_2D: + t->unit[t->curTextureUnit].currentTexture2D = tobj; + break; +#ifdef CR_OPENGL_VERSION_1_2 + case GL_TEXTURE_3D: + t->unit[t->curTextureUnit].currentTexture3D = tobj; + break; +#endif +#ifdef CR_ARB_texture_cube_map + case GL_TEXTURE_CUBE_MAP_ARB: + t->unit[t->curTextureUnit].currentTextureCubeMap = tobj; + break; +#endif +#ifdef CR_NV_texture_rectangle + case GL_TEXTURE_RECTANGLE_NV: + t->unit[t->curTextureUnit].currentTextureRect = tobj; + break; +#endif + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "Invalid target passed to glBindTexture: %d", target); + return; + } + + DIRTY(tb->dirty, g->neg_bitid); + DIRTY(tb->current[t->curTextureUnit], g->neg_bitid); +} + + +void STATE_APIENTRY +crStateTexParameterfv(GLenum target, GLenum pname, const GLfloat *param) +{ + CRContext *g = GetCurrentContext(); + CRTextureObj *tobj = NULL; + CRTextureLevel *tl = NULL; + GLenum e = (GLenum) *param; + CRStateBits *sb = GetCurrentBits(); + CRTextureBits *tb = &(sb->texture); + unsigned int i; + + FLUSH(); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "TexParameterfv called in Begin/End"); + return; + } + + crStateGetTextureObjectAndImage(g, target, 0, &tobj, &tl); + if (!tobj) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "TexParamterfv(invalid target=0x%x)", target); + return; + } + + switch (pname) + { + case GL_TEXTURE_MIN_FILTER: + if (e != GL_NEAREST && + e != GL_LINEAR && + e != GL_NEAREST_MIPMAP_NEAREST && + e != GL_LINEAR_MIPMAP_NEAREST && + e != GL_NEAREST_MIPMAP_LINEAR && + e != GL_LINEAR_MIPMAP_LINEAR) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "TexParamterfv: GL_TEXTURE_MIN_FILTER invalid param: %d", e); + return; + } + tobj->minFilter = e; + break; + case GL_TEXTURE_MAG_FILTER: + if (e != GL_NEAREST && e != GL_LINEAR) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "TexParamterfv: GL_TEXTURE_MAG_FILTER invalid param: %d", e); + return; + } + tobj->magFilter = e; + break; + case GL_TEXTURE_WRAP_S: + if (e == GL_CLAMP || e == GL_REPEAT) { + tobj->wrapS = e; + } +#ifdef CR_OPENGL_VERSION_1_2 + else if (e == GL_CLAMP_TO_EDGE) { + tobj->wrapS = e; + } +#endif +#ifdef GL_CLAMP_TO_EDGE_EXT + else if (e == GL_CLAMP_TO_EDGE_EXT && g->extensions.EXT_texture_edge_clamp) { + tobj->wrapS = e; + } +#endif +#ifdef CR_ARB_texture_border_clamp + else if (e == GL_CLAMP_TO_BORDER_ARB && g->extensions.ARB_texture_border_clamp) { + tobj->wrapS = e; + } +#endif +#ifdef CR_ARB_texture_mirrored_repeat + else if (e == GL_MIRRORED_REPEAT_ARB && g->extensions.ARB_texture_mirrored_repeat) { + tobj->wrapS = e; + } +#endif +#ifdef CR_ATI_texture_mirror_once + else if ((e == GL_MIRROR_CLAMP_ATI || e == GL_MIRROR_CLAMP_TO_EDGE_ATI) && g->extensions.ATI_texture_mirror_once) { + tobj->wrapS = e; + } +#endif + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "TexParameterfv: GL_TEXTURE_WRAP_S invalid param: 0x%x", e); + return; + } + break; + case GL_TEXTURE_WRAP_T: + if (e == GL_CLAMP || e == GL_REPEAT) { + tobj->wrapT = e; + } +#ifdef CR_OPENGL_VERSION_1_2 + else if (e == GL_CLAMP_TO_EDGE) { + tobj->wrapT = e; + } +#endif +#ifdef GL_CLAMP_TO_EDGE_EXT + else if (e == GL_CLAMP_TO_EDGE_EXT && g->extensions.EXT_texture_edge_clamp) { + tobj->wrapT = e; + } +#endif +#ifdef CR_ARB_texture_border_clamp + else if (e == GL_CLAMP_TO_BORDER_ARB && g->extensions.ARB_texture_border_clamp) { + tobj->wrapT = e; + } +#endif +#ifdef CR_ARB_texture_mirrored_repeat + else if (e == GL_MIRRORED_REPEAT_ARB && g->extensions.ARB_texture_mirrored_repeat) { + tobj->wrapT = e; + } +#endif +#ifdef CR_ATI_texture_mirror_once + else if ((e == GL_MIRROR_CLAMP_ATI || e == GL_MIRROR_CLAMP_TO_EDGE_ATI) && g->extensions.ATI_texture_mirror_once) { + tobj->wrapT = e; + } +#endif + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "TexParameterfv: GL_TEXTURE_WRAP_T invalid param: 0x%x", e); + return; + } + break; +#ifdef CR_OPENGL_VERSION_1_2 + case GL_TEXTURE_WRAP_R: + if (e == GL_CLAMP || e == GL_REPEAT) { + tobj->wrapR = e; + } + else if (e == GL_CLAMP_TO_EDGE) { + tobj->wrapR = e; + } +#ifdef GL_CLAMP_TO_EDGE_EXT + else if (e == GL_CLAMP_TO_EDGE_EXT && g->extensions.EXT_texture_edge_clamp) { + tobj->wrapR = e; + } +#endif +#ifdef CR_ARB_texture_border_clamp + else if (e == GL_CLAMP_TO_BORDER_ARB && g->extensions.ARB_texture_border_clamp) { + tobj->wrapR = e; + } +#endif +#ifdef CR_ARB_texture_mirrored_repeat + else if (e == GL_MIRRORED_REPEAT_ARB && g->extensions.ARB_texture_mirrored_repeat) { + tobj->wrapR = e; + } +#endif +#ifdef CR_ATI_texture_mirror_once + else if ((e == GL_MIRROR_CLAMP_ATI || e == GL_MIRROR_CLAMP_TO_EDGE_ATI) && g->extensions.ATI_texture_mirror_once) { + tobj->wrapR = e; + } +#endif + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "TexParameterfv: GL_TEXTURE_WRAP_R invalid param: 0x%x", e); + return; + } + break; + case GL_TEXTURE_PRIORITY: + tobj->priority = param[0]; + break; + case GL_TEXTURE_MIN_LOD: + tobj->minLod = param[0]; + break; + case GL_TEXTURE_MAX_LOD: + tobj->maxLod = param[0]; + break; + case GL_TEXTURE_BASE_LEVEL: + if (e < 0.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "TexParameterfv: GL_TEXTURE_BASE_LEVEL invalid param: 0x%x", e); + return; + } + tobj->baseLevel = e; + break; + case GL_TEXTURE_MAX_LEVEL: + if (e < 0.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "TexParameterfv: GL_TEXTURE_MAX_LEVEL invalid param: 0x%x", e); + return; + } + tobj->maxLevel = e; + break; +#endif + case GL_TEXTURE_BORDER_COLOR: + tobj->borderColor.r = param[0]; + tobj->borderColor.g = param[1]; + tobj->borderColor.b = param[2]; + tobj->borderColor.a = param[3]; + break; +#ifdef CR_EXT_texture_filter_anisotropic + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (g->extensions.EXT_texture_filter_anisotropic) { + if (param[0] < 1.0f) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "TexParameterfv: GL_TEXTURE_MAX_ANISOTROPY_EXT called with parameter less than 1: %f", param[0]); + return; + } + tobj->maxAnisotropy = param[0]; + if (tobj->maxAnisotropy > g->limits.maxTextureAnisotropy) + { + tobj->maxAnisotropy = g->limits.maxTextureAnisotropy; + } + } + break; +#endif +#ifdef CR_ARB_depth_texture + case GL_DEPTH_TEXTURE_MODE_ARB: + if (g->extensions.ARB_depth_texture) { + if (param[0] == GL_LUMINANCE || + param[0] == GL_INTENSITY || + param[0] == GL_ALPHA) { + tobj->depthMode = (GLenum) param[0]; + } + else + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "TexParameterfv: GL_DEPTH_TEXTURE_MODE_ARB called with invalid parameter: 0x%x", param[0]); + return; + } + } + break; +#endif +#ifdef CR_ARB_shadow + case GL_TEXTURE_COMPARE_MODE_ARB: + if (g->extensions.ARB_shadow) { + if (param[0] == GL_NONE || + param[0] == GL_COMPARE_R_TO_TEXTURE_ARB) { + tobj->compareMode = (GLenum) param[0]; + } + else + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "TexParameterfv: GL_TEXTURE_COMPARE_MODE_ARB called with invalid parameter: 0x%x", param[0]); + return; + } + } + break; + case GL_TEXTURE_COMPARE_FUNC_ARB: + if (g->extensions.ARB_shadow) { + if (param[0] == GL_LEQUAL || + param[0] == GL_GEQUAL) { + tobj->compareFunc = (GLenum) param[0]; + } + } +#ifdef CR_EXT_shadow_funcs + else if (g->extensions.EXT_shadow_funcs) { + if (param[0] == GL_LEQUAL || + param[0] == GL_GEQUAL || + param[0] == GL_LESS || + param[0] == GL_GREATER || + param[0] == GL_ALWAYS || + param[0] == GL_NEVER ) { + tobj->compareFunc = (GLenum) param[0]; + } + } +#endif + else { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "TexParameterfv: GL_TEXTURE_COMPARE_FUNC_ARB called with invalid parameter: 0x%x", param[0]); + return; + } + break; +#endif +#ifdef CR_ARB_shadow_ambient + case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB: + if (g->extensions.ARB_shadow_ambient) { + tobj->compareFailValue = param[0]; + } + break; +#endif +#ifdef CR_SGIS_generate_mipmap + case GL_GENERATE_MIPMAP_SGIS: + if (g->extensions.SGIS_generate_mipmap) { + tobj->generateMipmap = param[0] ? GL_TRUE : GL_FALSE; + } + break; +#endif + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "TexParamterfv: Invalid pname: %d", pname); + return; + } + + DIRTY(tobj->dirty, g->neg_bitid); + for (i = 0; i < g->limits.maxTextureUnits; i++) + { + DIRTY(tobj->paramsBit[i], g->neg_bitid); + } + DIRTY(tb->dirty, g->neg_bitid); +} + + +void STATE_APIENTRY +crStateTexParameteriv(GLenum target, GLenum pname, const GLint *param) +{ + GLfloat f_param; + GLcolor f_color; + switch (pname) + { + case GL_TEXTURE_MIN_FILTER: + case GL_TEXTURE_MAG_FILTER: + case GL_TEXTURE_WRAP_S: + case GL_TEXTURE_WRAP_T: +#ifdef CR_OPENGL_VERSION_1_2 + case GL_TEXTURE_WRAP_R: + case GL_TEXTURE_PRIORITY: + case GL_TEXTURE_MIN_LOD: + case GL_TEXTURE_MAX_LOD: + case GL_TEXTURE_BASE_LEVEL: + case GL_TEXTURE_MAX_LEVEL: +#endif +#ifdef CR_EXT_texture_filter_anisotropic + case GL_TEXTURE_MAX_ANISOTROPY_EXT: +#endif +#ifdef CR_ARB_depth_texture + case GL_DEPTH_TEXTURE_MODE_ARB: +#endif +#ifdef CR_ARB_shadow + case GL_TEXTURE_COMPARE_MODE_ARB: + case GL_TEXTURE_COMPARE_FUNC_ARB: +#endif +#ifdef CR_ARB_shadow_ambinet + case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB: +#endif +#ifdef CR_SGIS_generate_mipmap + case GL_GENERATE_MIPMAP_SGIS: +#endif + f_param = (GLfloat) (*param); + crStateTexParameterfv( target, pname, &(f_param) ); + break; + case GL_TEXTURE_BORDER_COLOR: + f_color.r = ((GLfloat) param[0])/CR_MAXINT; + f_color.g = ((GLfloat) param[1])/CR_MAXINT; + f_color.b = ((GLfloat) param[2])/CR_MAXINT; + f_color.a = ((GLfloat) param[3])/CR_MAXINT; + crStateTexParameterfv( target, pname, (const GLfloat *) &(f_color) ); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "TexParamteriv: Invalid pname: %d", pname); + return; + } +} + + +void STATE_APIENTRY +crStateTexParameterf(GLenum target, GLenum pname, GLfloat param) +{ + crStateTexParameterfv( target, pname, ¶m ); +} + + +void STATE_APIENTRY +crStateTexParameteri(GLenum target, GLenum pname, GLint param) { + GLfloat f_param = (GLfloat) param; + crStateTexParameterfv( target, pname, &f_param ); +} + + +void STATE_APIENTRY +crStateTexEnvfv(GLenum target, GLenum pname, const GLfloat *param) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + CRStateBits *sb = GetCurrentBits(); + CRTextureBits *tb = &(sb->texture); + GLenum e; + GLcolorf c; + GLuint stage = 0; + + (void) stage; + + FLUSH(); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glTexEnvfv called in begin/end"); + return; + } + +#if CR_EXT_texture_lod_bias + if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { + if (!g->extensions.EXT_texture_lod_bias || pname != GL_TEXTURE_LOD_BIAS_EXT) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnv"); + } + else { + t->unit[t->curTextureUnit].lodBias = *param; + DIRTY(tb->envBit[t->curTextureUnit], g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); + } + return; + } + else +#endif +#if CR_ARB_point_sprite + if (target == GL_POINT_SPRITE_ARB) { + if (!g->extensions.ARB_point_sprite || pname != GL_COORD_REPLACE_ARB) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnv"); + } + else { + CRPointBits *pb = &(sb->point); + g->point.coordReplacement[t->curTextureUnit] = *param ? GL_TRUE : GL_FALSE; + DIRTY(pb->coordReplacement[t->curTextureUnit], g->neg_bitid); + DIRTY(pb->dirty, g->neg_bitid); + } + return; + } + else +#endif + if (target != GL_TEXTURE_ENV) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexEnvfv: target != GL_TEXTURE_ENV: %d", target); + return; + } + + switch (pname) + { + case GL_TEXTURE_ENV_MODE: + e = (GLenum) *param; + if (e != GL_MODULATE && + e != GL_DECAL && + e != GL_BLEND && + e != GL_ADD && + e != GL_REPLACE && + e != GL_COMBINE_ARB) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexEnvfv: invalid param: %f", *param); + return; + } + t->unit[t->curTextureUnit].envMode = e; + break; + case GL_TEXTURE_ENV_COLOR: + c.r = param[0]; + c.g = param[1]; + c.b = param[2]; + c.a = param[3]; + if (c.r > 1.0f) c.r = 1.0f; + if (c.g > 1.0f) c.g = 1.0f; + if (c.b > 1.0f) c.b = 1.0f; + if (c.a > 1.0f) c.a = 1.0f; + if (c.r < 0.0f) c.r = 0.0f; + if (c.g < 0.0f) c.g = 0.0f; + if (c.b < 0.0f) c.b = 0.0f; + if (c.a < 0.0f) c.a = 0.0f; + t->unit[t->curTextureUnit].envColor = c; + break; + +#ifdef CR_ARB_texture_env_combine + case GL_COMBINE_RGB_ARB: + e = (GLenum) (GLint) *param; + if (g->extensions.ARB_texture_env_combine && + (e == GL_REPLACE || + e == GL_MODULATE || + e == GL_ADD || + e == GL_ADD_SIGNED_ARB || + e == GL_INTERPOLATE_ARB || + e == GL_SUBTRACT_ARB)) { + t->unit[t->curTextureUnit].combineModeRGB = e; + } +#ifdef CR_ARB_texture_env_dot3 + else if (g->extensions.ARB_texture_env_dot3 && + (e == GL_DOT3_RGB_ARB || + e == GL_DOT3_RGBA_ARB || + e == GL_DOT3_RGB_EXT || + e == GL_DOT3_RGBA_EXT)) { + t->unit[t->curTextureUnit].combineModeRGB = e; + } +#endif + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv(param=0x%x", e); + return; + } + break; + case GL_COMBINE_ALPHA_EXT: + e = (GLenum) *param; + if (g->extensions.ARB_texture_env_combine && + (e == GL_REPLACE || + e == GL_MODULATE || + e == GL_ADD || + e == GL_ADD_SIGNED_ARB || + e == GL_INTERPOLATE_ARB || + e == GL_SUBTRACT_ARB)) { + t->unit[t->curTextureUnit].combineModeA = e; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv"); + return; + } + break; + case GL_SOURCE0_RGB_ARB: + case GL_SOURCE1_RGB_ARB: + case GL_SOURCE2_RGB_ARB: + e = (GLenum) *param; + stage = pname - GL_SOURCE0_RGB_ARB; + if (g->extensions.ARB_texture_env_combine && + (e == GL_TEXTURE || + e == GL_CONSTANT_ARB || + e == GL_PRIMARY_COLOR_ARB || + e == GL_PREVIOUS_ARB)) { + t->unit[t->curTextureUnit].combineSourceRGB[stage] = e; + } + else if (g->extensions.ARB_texture_env_crossbar && + e >= GL_TEXTURE0_ARB && + e < GL_TEXTURE0_ARB + g->limits.maxTextureUnits) { + t->unit[t->curTextureUnit].combineSourceRGB[stage] = e; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv"); + return; + } + break; + case GL_SOURCE0_ALPHA_ARB: + case GL_SOURCE1_ALPHA_ARB: + case GL_SOURCE2_ALPHA_ARB: + e = (GLenum) *param; + stage = pname - GL_SOURCE0_ALPHA_ARB; + if (g->extensions.ARB_texture_env_combine && + (e == GL_TEXTURE || + e == GL_CONSTANT_ARB || + e == GL_PRIMARY_COLOR_ARB || + e == GL_PREVIOUS_ARB)) { + t->unit[t->curTextureUnit].combineSourceA[stage] = e; + } + else if (g->extensions.ARB_texture_env_crossbar && + e >= GL_TEXTURE0_ARB && + e < GL_TEXTURE0_ARB + g->limits.maxTextureUnits) { + t->unit[t->curTextureUnit].combineSourceA[stage] = e; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv"); + return; + } + break; + case GL_OPERAND0_RGB_ARB: + case GL_OPERAND1_RGB_ARB: + case GL_OPERAND2_RGB_ARB: + e = (GLenum) *param; + stage = pname - GL_OPERAND0_RGB_ARB; + if (g->extensions.ARB_texture_env_combine && + (e == GL_SRC_COLOR || + e == GL_ONE_MINUS_SRC_COLOR || + e == GL_SRC_ALPHA || + e == GL_ONE_MINUS_SRC_ALPHA)) { + t->unit[t->curTextureUnit].combineOperandRGB[stage] = e; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv"); + return; + } + break; + case GL_OPERAND0_ALPHA_ARB: + case GL_OPERAND1_ALPHA_ARB: + case GL_OPERAND2_ALPHA_ARB: + e = (GLenum) *param; + stage = pname - GL_OPERAND0_ALPHA_ARB; + if (g->extensions.ARB_texture_env_combine && + (e == GL_SRC_ALPHA || + e == GL_ONE_MINUS_SRC_ALPHA)) { + t->unit[t->curTextureUnit].combineOperandA[stage] = e; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv(param=0x%x)", e); + return; + } + break; + case GL_RGB_SCALE_ARB: + if (g->extensions.ARB_texture_env_combine && + (*param == 1.0 || + *param == 2.0 || + *param == 4.0)) { + t->unit[t->curTextureUnit].combineScaleRGB = *param; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glTexEnvfv"); + return; + } + break; + case GL_ALPHA_SCALE: + if (g->extensions.ARB_texture_env_combine && + (*param == 1.0 || + *param == 2.0 || + *param == 4.0)) { + t->unit[t->curTextureUnit].combineScaleA = *param; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glTexEnvfv"); + return; + } + break; +#endif /* CR_ARB_texture_env_combine */ + + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexEnvfv: invalid pname: %d", pname); + return; + } + + DIRTY(tb->envBit[t->curTextureUnit], g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + + +void STATE_APIENTRY +crStateTexEnviv(GLenum target, GLenum pname, const GLint *param) +{ + GLfloat f_param; + GLcolor f_color; + + switch (pname) { + case GL_TEXTURE_ENV_MODE: + f_param = (GLfloat) (*param); + crStateTexEnvfv( target, pname, &f_param ); + break; + case GL_TEXTURE_ENV_COLOR: + f_color.r = ((GLfloat) param[0]) / CR_MAXINT; + f_color.g = ((GLfloat) param[1]) / CR_MAXINT; + f_color.b = ((GLfloat) param[2]) / CR_MAXINT; + f_color.a = ((GLfloat) param[3]) / CR_MAXINT; + crStateTexEnvfv( target, pname, (const GLfloat *) &f_color ); + break; +#ifdef CR_ARB_texture_env_combine + case GL_COMBINE_RGB_ARB: + case GL_COMBINE_ALPHA_EXT: + case GL_SOURCE0_RGB_ARB: + case GL_SOURCE1_RGB_ARB: + case GL_SOURCE2_RGB_ARB: + case GL_SOURCE0_ALPHA_ARB: + case GL_SOURCE1_ALPHA_ARB: + case GL_SOURCE2_ALPHA_ARB: + case GL_OPERAND0_RGB_ARB: + case GL_OPERAND1_RGB_ARB: + case GL_OPERAND2_RGB_ARB: + case GL_OPERAND0_ALPHA_ARB: + case GL_OPERAND1_ALPHA_ARB: + case GL_OPERAND2_ALPHA_ARB: + case GL_RGB_SCALE_ARB: + case GL_ALPHA_SCALE: + f_param = (GLfloat) (*param); + crStateTexEnvfv( target, pname, &f_param ); + break; +#endif +#ifdef CR_EXT_texture_lod_bias + case GL_TEXTURE_LOD_BIAS_EXT: + f_param = (GLfloat) (*param); + crStateTexEnvfv( target, pname, &f_param); + break; +#endif +#ifdef CR_ARB_point_sprite + case GL_COORD_REPLACE_ARB: + f_param = (GLfloat) *param; + crStateTexEnvfv( target, pname, &f_param); + break; +#endif + + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexEnvfv: invalid pname: %d", pname); + return; + } +} + + +void STATE_APIENTRY +crStateTexEnvf(GLenum target, GLenum pname, GLfloat param) +{ + crStateTexEnvfv( target, pname, ¶m ); +} + + +void STATE_APIENTRY +crStateTexEnvi(GLenum target, GLenum pname, GLint param) +{ + GLfloat f_param = (GLfloat) param; + crStateTexEnvfv( target, pname, &f_param ); +} + + +void STATE_APIENTRY +crStateGetTexEnvfv(GLenum target, GLenum pname, GLfloat *param) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__,GL_INVALID_OPERATION, + "glGetTexEnvfv called in begin/end"); + return; + } + +#if CR_EXT_texture_lod_bias + if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { + if (!g->extensions.EXT_texture_lod_bias || pname != GL_TEXTURE_LOD_BIAS_EXT) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnv"); + } + else { + *param = t->unit[t->curTextureUnit].lodBias; + } + return; + } + else +#endif +#if CR_ARB_point_sprite + if (target == GL_POINT_SPRITE_ARB) { + if (!g->extensions.ARB_point_sprite || pname != GL_COORD_REPLACE_ARB) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnv"); + } + else { + *param = (GLfloat) g->point.coordReplacement[t->curTextureUnit]; + } + return; + } + else +#endif + if (target != GL_TEXTURE_ENV) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexEnvfv: target != GL_TEXTURE_ENV: %d", target); + return; + } + + switch (pname) { + case GL_TEXTURE_ENV_MODE: + *param = (GLfloat) t->unit[t->curTextureUnit].envMode; + break; + case GL_TEXTURE_ENV_COLOR: + param[0] = t->unit[t->curTextureUnit].envColor.r; + param[1] = t->unit[t->curTextureUnit].envColor.g; + param[2] = t->unit[t->curTextureUnit].envColor.b; + param[3] = t->unit[t->curTextureUnit].envColor.a; + break; + case GL_COMBINE_RGB_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLfloat) t->unit[t->curTextureUnit].combineModeRGB; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + return; + } + break; + case GL_COMBINE_ALPHA_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLfloat) t->unit[t->curTextureUnit].combineModeA; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + return; + } + break; + case GL_SOURCE0_RGB_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLfloat) t->unit[t->curTextureUnit].combineSourceRGB[0]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + return; + } + break; + case GL_SOURCE1_RGB_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLfloat) t->unit[t->curTextureUnit].combineSourceRGB[1]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + return; + } + break; + case GL_SOURCE2_RGB_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLfloat) t->unit[t->curTextureUnit].combineSourceRGB[2]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + return; + } + break; + case GL_SOURCE0_ALPHA_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLfloat) t->unit[t->curTextureUnit].combineSourceA[0]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + return; + } + break; + case GL_SOURCE1_ALPHA_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLfloat) t->unit[t->curTextureUnit].combineSourceA[1]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + return; + } + break; + case GL_SOURCE2_ALPHA_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLfloat) t->unit[t->curTextureUnit].combineSourceA[2]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + return; + } + break; + case GL_OPERAND0_RGB_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLfloat) t->unit[t->curTextureUnit].combineOperandRGB[0]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + return; + } + break; + case GL_OPERAND1_RGB_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLfloat) t->unit[t->curTextureUnit].combineOperandRGB[1]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + return; + } + break; + case GL_OPERAND2_RGB_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLfloat) t->unit[t->curTextureUnit].combineOperandRGB[2]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + return; + } + break; + case GL_OPERAND0_ALPHA_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLfloat) t->unit[t->curTextureUnit].combineOperandA[0]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + return; + } + break; + case GL_OPERAND1_ALPHA_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLfloat) t->unit[t->curTextureUnit].combineOperandA[1]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + return; + } + break; + case GL_OPERAND2_ALPHA_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLfloat) t->unit[t->curTextureUnit].combineOperandA[2]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + return; + } + break; + case GL_RGB_SCALE_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = t->unit[t->curTextureUnit].combineScaleRGB; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + return; + } + break; + case GL_ALPHA_SCALE: + if (g->extensions.ARB_texture_env_combine) { + *param = t->unit[t->curTextureUnit].combineScaleA; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + return; + } + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexEnvfv: invalid pname: %d", pname); + return; + } +} + + +void STATE_APIENTRY +crStateGetTexEnviv(GLenum target, GLenum pname, GLint *param) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__,GL_INVALID_OPERATION, + "glGetTexEnviv called in begin/end"); + return; + } + +#if CR_EXT_texture_lod_bias + if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { + if (!g->extensions.EXT_texture_lod_bias || pname != GL_TEXTURE_LOD_BIAS_EXT) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnv"); + } + else { + *param = (GLint) t->unit[t->curTextureUnit].lodBias; + } + return; + } + else +#endif +#if CR_ARB_point_sprite + if (target == GL_POINT_SPRITE_ARB) { + if (!g->extensions.ARB_point_sprite || pname != GL_COORD_REPLACE_ARB) { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnv"); + } + else { + *param = (GLint) g->point.coordReplacement[t->curTextureUnit]; + } + return; + } + else +#endif + if (target != GL_TEXTURE_ENV) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexEnviv: target != GL_TEXTURE_ENV: %d", target); + return; + } + + switch (pname) { + case GL_TEXTURE_ENV_MODE: + *param = (GLint) t->unit[t->curTextureUnit].envMode; + break; + case GL_TEXTURE_ENV_COLOR: + param[0] = (GLint) (t->unit[t->curTextureUnit].envColor.r * CR_MAXINT); + param[1] = (GLint) (t->unit[t->curTextureUnit].envColor.g * CR_MAXINT); + param[2] = (GLint) (t->unit[t->curTextureUnit].envColor.b * CR_MAXINT); + param[3] = (GLint) (t->unit[t->curTextureUnit].envColor.a * CR_MAXINT); + break; + case GL_COMBINE_RGB_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLint) t->unit[t->curTextureUnit].combineModeRGB; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + return; + } + break; + case GL_COMBINE_ALPHA_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLint) t->unit[t->curTextureUnit].combineModeA; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + return; + } + break; + case GL_SOURCE0_RGB_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLint) t->unit[t->curTextureUnit].combineSourceRGB[0]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + return; + } + break; + case GL_SOURCE1_RGB_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLint) t->unit[t->curTextureUnit].combineSourceRGB[1]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + return; + } + break; + case GL_SOURCE2_RGB_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLint) t->unit[t->curTextureUnit].combineSourceRGB[2]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + return; + } + break; + case GL_SOURCE0_ALPHA_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLint) t->unit[t->curTextureUnit].combineSourceA[0]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + return; + } + break; + case GL_SOURCE1_ALPHA_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLint) t->unit[t->curTextureUnit].combineSourceA[1]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + return; + } + break; + case GL_SOURCE2_ALPHA_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLint) t->unit[t->curTextureUnit].combineSourceA[2]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + return; + } + break; + case GL_OPERAND0_RGB_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLint) t->unit[t->curTextureUnit].combineOperandRGB[0]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + return; + } + break; + case GL_OPERAND1_RGB_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLint) t->unit[t->curTextureUnit].combineOperandRGB[1]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + return; + } + break; + case GL_OPERAND2_RGB_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLint) t->unit[t->curTextureUnit].combineOperandRGB[2]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + return; + } + break; + case GL_OPERAND0_ALPHA_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLint) t->unit[t->curTextureUnit].combineOperandA[0]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + return; + } + break; + case GL_OPERAND1_ALPHA_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLint) t->unit[t->curTextureUnit].combineOperandA[1]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + return; + } + break; + case GL_OPERAND2_ALPHA_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLint) t->unit[t->curTextureUnit].combineOperandA[2]; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + return; + } + break; + case GL_RGB_SCALE_ARB: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLint) t->unit[t->curTextureUnit].combineScaleRGB; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + return; + } + break; + case GL_ALPHA_SCALE: + if (g->extensions.ARB_texture_env_combine) { + *param = (GLint) t->unit[t->curTextureUnit].combineScaleA; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + return; + } + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexEnviv: invalid pname: %d", pname); + return; + } +} + + +void STATE_APIENTRY +crStateTexGendv(GLenum coord, GLenum pname, const GLdouble *param) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + CRTransformState *trans = &(g->transform); + GLvectorf v; + GLenum e; + CRmatrix inv; + CRStateBits *sb = GetCurrentBits(); + CRTextureBits *tb = &(sb->texture); + + FLUSH(); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glTexGen called in begin/end"); + return; + } + + switch (coord) + { + case GL_S: + switch (pname) + { + case GL_TEXTURE_GEN_MODE: + e = (GLenum) *param; + if (e == GL_OBJECT_LINEAR || + e == GL_EYE_LINEAR || + e == GL_SPHERE_MAP +#if defined(GL_ARB_texture_cube_map) || defined(GL_EXT_texture_cube_map) || defined(GL_NV_texgen_reflection) + || ((e == GL_REFLECTION_MAP_ARB || e == GL_NORMAL_MAP_ARB) + && g->extensions.ARB_texture_cube_map) +#endif + ) { + t->unit[t->curTextureUnit].gen.s = e; + DIRTY(tb->genMode[t->curTextureUnit], g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexGendv called with bad param: %lf", *param); + return; + } + break; + case GL_OBJECT_PLANE: + v.x = (GLfloat) param[0]; + v.y = (GLfloat) param[1]; + v.z = (GLfloat) param[2]; + v.w = (GLfloat) param[3]; + t->unit[t->curTextureUnit].objSCoeff = v; + DIRTY(tb->objGen[t->curTextureUnit], g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); + break; + case GL_EYE_PLANE: + v.x = (GLfloat) param[0]; + v.y = (GLfloat) param[1]; + v.z = (GLfloat) param[2]; + v.w = (GLfloat) param[3]; + crMatrixInvertTranspose(&inv, trans->modelViewStack.top); + crStateTransformXformPointMatrixf(&inv, &v); + t->unit[t->curTextureUnit].eyeSCoeff = v; + DIRTY(tb->eyeGen[t->curTextureUnit], g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexGendv called with bogus pname: %d", pname); + return; + } + break; + case GL_T: + switch (pname) { + case GL_TEXTURE_GEN_MODE: + e = (GLenum) *param; + if (e == GL_OBJECT_LINEAR || + e == GL_EYE_LINEAR || + e == GL_SPHERE_MAP +#if defined(GL_ARB_texture_cube_map) || defined(GL_EXT_texture_cube_map) || defined(GL_NV_texgen_reflection) + || ((e == GL_REFLECTION_MAP_ARB || e == GL_NORMAL_MAP_ARB) + && g->extensions.ARB_texture_cube_map) +#endif + ) { + t->unit[t->curTextureUnit].gen.t = e; + DIRTY(tb->genMode[t->curTextureUnit], g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexGendv called with bad param: %lf", *param); + return; + } + break; + case GL_OBJECT_PLANE: + v.x = (GLfloat) param[0]; + v.y = (GLfloat) param[1]; + v.z = (GLfloat) param[2]; + v.w = (GLfloat) param[3]; + t->unit[t->curTextureUnit].objTCoeff = v; + DIRTY(tb->objGen[t->curTextureUnit], g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); + break; + case GL_EYE_PLANE: + v.x = (GLfloat) param[0]; + v.y = (GLfloat) param[1]; + v.z = (GLfloat) param[2]; + v.w = (GLfloat) param[3]; + crMatrixInvertTranspose(&inv, trans->modelViewStack.top); + crStateTransformXformPointMatrixf(&inv, &v); + t->unit[t->curTextureUnit].eyeTCoeff = v; + DIRTY(tb->eyeGen[t->curTextureUnit], g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexGen called with bogus pname: %d", pname); + return; + } + break; + case GL_R: + switch (pname) { + case GL_TEXTURE_GEN_MODE: + e = (GLenum) *param; + if (e == GL_OBJECT_LINEAR || + e == GL_EYE_LINEAR || + e == GL_SPHERE_MAP +#if defined(GL_ARB_texture_cube_map) || defined(GL_EXT_texture_cube_map) || defined(GL_NV_texgen_reflection) + || ((e == GL_REFLECTION_MAP_ARB || e == GL_NORMAL_MAP_ARB) + && g->extensions.ARB_texture_cube_map) +#endif + ) { + t->unit[t->curTextureUnit].gen.r = e; + DIRTY(tb->genMode[t->curTextureUnit], g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexGen called with bad param: %lf", *param); + return; + } + break; + case GL_OBJECT_PLANE: + v.x = (GLfloat) param[0]; + v.y = (GLfloat) param[1]; + v.z = (GLfloat) param[2]; + v.w = (GLfloat) param[3]; + t->unit[t->curTextureUnit].objRCoeff = v; + DIRTY(tb->objGen[t->curTextureUnit], g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); + break; + case GL_EYE_PLANE: + v.x = (GLfloat) param[0]; + v.y = (GLfloat) param[1]; + v.z = (GLfloat) param[2]; + v.w = (GLfloat) param[3]; + crMatrixInvertTranspose(&inv, trans->modelViewStack.top); + crStateTransformXformPointMatrixf(&inv, &v); + t->unit[t->curTextureUnit].eyeRCoeff = v; + DIRTY(tb->eyeGen[t->curTextureUnit], g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexGen called with bogus pname: %d", pname); + return; + } + break; + case GL_Q: + switch (pname) { + case GL_TEXTURE_GEN_MODE: + e = (GLenum) *param; + if (e == GL_OBJECT_LINEAR || + e == GL_EYE_LINEAR || + e == GL_SPHERE_MAP +#if defined(GL_ARB_texture_cube_map) || defined(GL_EXT_texture_cube_map) || defined(GL_NV_texgen_reflection) + || ((e == GL_REFLECTION_MAP_ARB || e == GL_NORMAL_MAP_ARB) + && g->extensions.ARB_texture_cube_map) +#endif + ) { + t->unit[t->curTextureUnit].gen.q = e; + DIRTY(tb->genMode[t->curTextureUnit], g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexGen called with bad param: %lf", *param); + return; + } + break; + case GL_OBJECT_PLANE: + v.x = (GLfloat) param[0]; + v.y = (GLfloat) param[1]; + v.z = (GLfloat) param[2]; + v.w = (GLfloat) param[3]; + t->unit[t->curTextureUnit].objQCoeff = v; + DIRTY(tb->objGen[t->curTextureUnit], g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); + break; + case GL_EYE_PLANE: + v.x = (GLfloat) param[0]; + v.y = (GLfloat) param[1]; + v.z = (GLfloat) param[2]; + v.w = (GLfloat) param[3]; + crMatrixInvertTranspose(&inv, trans->modelViewStack.top); + crStateTransformXformPointMatrixf(&inv, &v); + t->unit[t->curTextureUnit].eyeQCoeff = v; + DIRTY(tb->eyeGen[t->curTextureUnit], g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexGen called with bogus pname: %d", pname); + return; + } + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexGen called with bogus coord: %d", coord); + return; + } +} + + +void STATE_APIENTRY +crStateTexGenfv(GLenum coord, GLenum pname, const GLfloat *param) +{ + GLdouble d_param; + GLvectord d_vector; + switch (pname) + { + case GL_TEXTURE_GEN_MODE: + d_param = (GLdouble) *param; + crStateTexGendv( coord, pname, &d_param ); + break; + case GL_OBJECT_PLANE: + case GL_EYE_PLANE: + d_vector.x = (GLdouble) param[0]; + d_vector.y = (GLdouble) param[1]; + d_vector.z = (GLdouble) param[2]; + d_vector.w = (GLdouble) param[3]; + crStateTexGendv( coord, pname, (const double *) &d_vector ); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexGen called with bogus pname: %d", pname); + return; + } +} + + +void STATE_APIENTRY +crStateTexGeniv(GLenum coord, GLenum pname, const GLint *param) +{ + GLdouble d_param; + GLvectord d_vector; + switch (pname) + { + case GL_TEXTURE_GEN_MODE: + d_param = (GLdouble) *param; + crStateTexGendv( coord, pname, &d_param ); + break; + case GL_OBJECT_PLANE: + case GL_EYE_PLANE: + d_vector.x = (GLdouble) param[0]; + d_vector.y = (GLdouble) param[1]; + d_vector.z = (GLdouble) param[2]; + d_vector.w = (GLdouble) param[3]; + crStateTexGendv( coord, pname, (const double *) &d_vector ); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glTexGen called with bogus pname: %d", pname); + return; + } +} + + +void STATE_APIENTRY +crStateTexGend (GLenum coord, GLenum pname, GLdouble param) +{ + crStateTexGendv( coord, pname, ¶m ); +} + + +void STATE_APIENTRY +crStateTexGenf(GLenum coord, GLenum pname, GLfloat param) +{ + GLdouble d_param = (GLdouble) param; + crStateTexGendv( coord, pname, &d_param ); +} + + +void STATE_APIENTRY +crStateTexGeni(GLenum coord, GLenum pname, GLint param) +{ + GLdouble d_param = (GLdouble) param; + crStateTexGendv( coord, pname, &d_param ); +} + + +void STATE_APIENTRY +crStateGetTexGendv(GLenum coord, GLenum pname, GLdouble *param) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetTexGen called in begin/end"); + return; + } + + switch (pname) { + case GL_TEXTURE_GEN_MODE: + switch (coord) { + case GL_S: + *param = (GLdouble) t->unit[t->curTextureUnit].gen.s; + break; + case GL_T: + *param = (GLdouble) t->unit[t->curTextureUnit].gen.t; + break; + case GL_R: + *param = (GLdouble) t->unit[t->curTextureUnit].gen.r; + break; + case GL_Q: + *param = (GLdouble) t->unit[t->curTextureUnit].gen.q; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexGen called with bogus coord: %d", coord); + return; + } + break; + case GL_OBJECT_PLANE: + switch (coord) { + case GL_S: + param[0] = (GLdouble) t->unit[t->curTextureUnit].objSCoeff.x; + param[1] = (GLdouble) t->unit[t->curTextureUnit].objSCoeff.y; + param[2] = (GLdouble) t->unit[t->curTextureUnit].objSCoeff.z; + param[3] = (GLdouble) t->unit[t->curTextureUnit].objSCoeff.w; + break; + case GL_T: + param[0] = (GLdouble) t->unit[t->curTextureUnit].objTCoeff.x; + param[1] = (GLdouble) t->unit[t->curTextureUnit].objTCoeff.y; + param[2] = (GLdouble) t->unit[t->curTextureUnit].objTCoeff.z; + param[3] = (GLdouble) t->unit[t->curTextureUnit].objTCoeff.w; + break; + case GL_R: + param[0] = (GLdouble) t->unit[t->curTextureUnit].objRCoeff.x; + param[1] = (GLdouble) t->unit[t->curTextureUnit].objRCoeff.y; + param[2] = (GLdouble) t->unit[t->curTextureUnit].objRCoeff.z; + param[3] = (GLdouble) t->unit[t->curTextureUnit].objRCoeff.w; + break; + case GL_Q: + param[0] = (GLdouble) t->unit[t->curTextureUnit].objQCoeff.x; + param[1] = (GLdouble) t->unit[t->curTextureUnit].objQCoeff.y; + param[2] = (GLdouble) t->unit[t->curTextureUnit].objQCoeff.z; + param[3] = (GLdouble) t->unit[t->curTextureUnit].objQCoeff.w; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexGen called with bogus coord: %d", coord); + return; + } + break; + case GL_EYE_PLANE: + switch (coord) { + case GL_S: + param[0] = (GLdouble) t->unit[t->curTextureUnit].eyeSCoeff.x; + param[1] = (GLdouble) t->unit[t->curTextureUnit].eyeSCoeff.y; + param[2] = (GLdouble) t->unit[t->curTextureUnit].eyeSCoeff.z; + param[3] = (GLdouble) t->unit[t->curTextureUnit].eyeSCoeff.w; + break; + case GL_T: + param[0] = (GLdouble) t->unit[t->curTextureUnit].eyeTCoeff.x; + param[1] = (GLdouble) t->unit[t->curTextureUnit].eyeTCoeff.y; + param[2] = (GLdouble) t->unit[t->curTextureUnit].eyeTCoeff.z; + param[3] = (GLdouble) t->unit[t->curTextureUnit].eyeTCoeff.w; + break; + case GL_R: + param[0] = (GLdouble) t->unit[t->curTextureUnit].eyeRCoeff.x; + param[1] = (GLdouble) t->unit[t->curTextureUnit].eyeRCoeff.y; + param[2] = (GLdouble) t->unit[t->curTextureUnit].eyeRCoeff.z; + param[3] = (GLdouble) t->unit[t->curTextureUnit].eyeRCoeff.w; + break; + case GL_Q: + param[0] = (GLdouble) t->unit[t->curTextureUnit].eyeQCoeff.x; + param[1] = (GLdouble) t->unit[t->curTextureUnit].eyeQCoeff.y; + param[2] = (GLdouble) t->unit[t->curTextureUnit].eyeQCoeff.z; + param[3] = (GLdouble) t->unit[t->curTextureUnit].eyeQCoeff.w; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexGen called with bogus coord: %d", coord); + return; + } + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexGen called with bogus pname: %d", pname); + return; + } +} + + +void STATE_APIENTRY +crStateGetTexGenfv(GLenum coord, GLenum pname, GLfloat *param) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetTexGenfv called in begin/end"); + return; + } + + switch (pname) { + case GL_TEXTURE_GEN_MODE: + switch (coord) { + case GL_S: + *param = (GLfloat) t->unit[t->curTextureUnit].gen.s; + break; + case GL_T: + *param = (GLfloat) t->unit[t->curTextureUnit].gen.t; + break; + case GL_R: + *param = (GLfloat) t->unit[t->curTextureUnit].gen.r; + break; + case GL_Q: + *param = (GLfloat) t->unit[t->curTextureUnit].gen.q; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexGenfv called with bogus coord: %d", coord); + return; + } + break; + case GL_OBJECT_PLANE: + switch (coord) { + case GL_S: + param[0] = t->unit[t->curTextureUnit].objSCoeff.x; + param[1] = t->unit[t->curTextureUnit].objSCoeff.y; + param[2] = t->unit[t->curTextureUnit].objSCoeff.z; + param[3] = t->unit[t->curTextureUnit].objSCoeff.w; + break; + case GL_T: + param[0] = t->unit[t->curTextureUnit].objTCoeff.x; + param[1] = t->unit[t->curTextureUnit].objTCoeff.y; + param[2] = t->unit[t->curTextureUnit].objTCoeff.z; + param[3] = t->unit[t->curTextureUnit].objTCoeff.w; + break; + case GL_R: + param[0] = t->unit[t->curTextureUnit].objRCoeff.x; + param[1] = t->unit[t->curTextureUnit].objRCoeff.y; + param[2] = t->unit[t->curTextureUnit].objRCoeff.z; + param[3] = t->unit[t->curTextureUnit].objRCoeff.w; + break; + case GL_Q: + param[0] = t->unit[t->curTextureUnit].objQCoeff.x; + param[1] = t->unit[t->curTextureUnit].objQCoeff.y; + param[2] = t->unit[t->curTextureUnit].objQCoeff.z; + param[3] = t->unit[t->curTextureUnit].objQCoeff.w; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexGenfv called with bogus coord: %d", coord); + return; + } + break; + case GL_EYE_PLANE: + switch (coord) { + case GL_S: + param[0] = t->unit[t->curTextureUnit].eyeSCoeff.x; + param[1] = t->unit[t->curTextureUnit].eyeSCoeff.y; + param[2] = t->unit[t->curTextureUnit].eyeSCoeff.z; + param[3] = t->unit[t->curTextureUnit].eyeSCoeff.w; + break; + case GL_T: + param[0] = t->unit[t->curTextureUnit].eyeTCoeff.x; + param[1] = t->unit[t->curTextureUnit].eyeTCoeff.y; + param[2] = t->unit[t->curTextureUnit].eyeTCoeff.z; + param[3] = t->unit[t->curTextureUnit].eyeTCoeff.w; + break; + case GL_R: + param[0] = t->unit[t->curTextureUnit].eyeRCoeff.x; + param[1] = t->unit[t->curTextureUnit].eyeRCoeff.y; + param[2] = t->unit[t->curTextureUnit].eyeRCoeff.z; + param[3] = t->unit[t->curTextureUnit].eyeRCoeff.w; + break; + case GL_Q: + param[0] = t->unit[t->curTextureUnit].eyeQCoeff.x; + param[1] = t->unit[t->curTextureUnit].eyeQCoeff.y; + param[2] = t->unit[t->curTextureUnit].eyeQCoeff.z; + param[3] = t->unit[t->curTextureUnit].eyeQCoeff.w; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexGenfv called with bogus coord: %d", coord); + return; + } + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexGenfv called with bogus pname: %d", pname); + return; + } +} + + +void STATE_APIENTRY +crStateGetTexGeniv(GLenum coord, GLenum pname, GLint *param) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetTexGeniv called in begin/end"); + return; + } + + switch (pname) { + case GL_TEXTURE_GEN_MODE: + switch (coord) { + case GL_S: + *param = (GLint) t->unit[t->curTextureUnit].gen.s; + break; + case GL_T: + *param = (GLint) t->unit[t->curTextureUnit].gen.t; + break; + case GL_R: + *param = (GLint) t->unit[t->curTextureUnit].gen.r; + break; + case GL_Q: + *param = (GLint) t->unit[t->curTextureUnit].gen.q; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexGeniv called with bogus coord: %d", coord); + return; + } + break; + case GL_OBJECT_PLANE: + switch (coord) { + case GL_S: + param[0] = (GLint) t->unit[t->curTextureUnit].objSCoeff.x; + param[1] = (GLint) t->unit[t->curTextureUnit].objSCoeff.y; + param[2] = (GLint) t->unit[t->curTextureUnit].objSCoeff.z; + param[3] = (GLint) t->unit[t->curTextureUnit].objSCoeff.w; + break; + case GL_T: + param[0] = (GLint) t->unit[t->curTextureUnit].objTCoeff.x; + param[1] = (GLint) t->unit[t->curTextureUnit].objTCoeff.y; + param[2] = (GLint) t->unit[t->curTextureUnit].objTCoeff.z; + param[3] = (GLint) t->unit[t->curTextureUnit].objTCoeff.w; + break; + case GL_R: + param[0] = (GLint) t->unit[t->curTextureUnit].objRCoeff.x; + param[1] = (GLint) t->unit[t->curTextureUnit].objRCoeff.y; + param[2] = (GLint) t->unit[t->curTextureUnit].objRCoeff.z; + param[3] = (GLint) t->unit[t->curTextureUnit].objRCoeff.w; + break; + case GL_Q: + param[0] = (GLint) t->unit[t->curTextureUnit].objQCoeff.x; + param[1] = (GLint) t->unit[t->curTextureUnit].objQCoeff.y; + param[2] = (GLint) t->unit[t->curTextureUnit].objQCoeff.z; + param[3] = (GLint) t->unit[t->curTextureUnit].objQCoeff.w; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexGeniv called with bogus coord: %d", coord); + return; + } + break; + case GL_EYE_PLANE: + switch (coord) { + case GL_S: + param[0] = (GLint) t->unit[t->curTextureUnit].eyeSCoeff.x; + param[1] = (GLint) t->unit[t->curTextureUnit].eyeSCoeff.y; + param[2] = (GLint) t->unit[t->curTextureUnit].eyeSCoeff.z; + param[3] = (GLint) t->unit[t->curTextureUnit].eyeSCoeff.w; + break; + case GL_T: + param[0] = (GLint) t->unit[t->curTextureUnit].eyeTCoeff.x; + param[1] = (GLint) t->unit[t->curTextureUnit].eyeTCoeff.y; + param[2] = (GLint) t->unit[t->curTextureUnit].eyeTCoeff.z; + param[3] = (GLint) t->unit[t->curTextureUnit].eyeTCoeff.w; + break; + case GL_R: + param[0] = (GLint) t->unit[t->curTextureUnit].eyeRCoeff.x; + param[1] = (GLint) t->unit[t->curTextureUnit].eyeRCoeff.y; + param[2] = (GLint) t->unit[t->curTextureUnit].eyeRCoeff.z; + param[3] = (GLint) t->unit[t->curTextureUnit].eyeRCoeff.w; + break; + case GL_Q: + param[0] = (GLint) t->unit[t->curTextureUnit].eyeQCoeff.x; + param[1] = (GLint) t->unit[t->curTextureUnit].eyeQCoeff.y; + param[2] = (GLint) t->unit[t->curTextureUnit].eyeQCoeff.z; + param[3] = (GLint) t->unit[t->curTextureUnit].eyeQCoeff.w; + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexGeniv called with bogus coord: %d", coord); + return; + } + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexGen called with bogus pname: %d", pname); + return; + } +} + + +void STATE_APIENTRY +crStateGetTexLevelParameterfv(GLenum target, GLint level, + GLenum pname, GLfloat *params) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + CRTextureObj *tobj; + CRTextureLevel *timg; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetTexLevelParameterfv called in begin/end"); + return; + } + + if (level < 0 || level > t->maxLevel) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glGetTexLevelParameterfv: Invalid level: %d", level); + return; + } + + crStateGetTextureObjectAndImage(g, target, level, &tobj, &timg); + if (!timg) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "GetTexLevelParameterfv: invalid target: 0x%x or level %d", + target, level); + return; + } + + switch (pname) + { + case GL_TEXTURE_WIDTH: + *params = (GLfloat) timg->width; + break; + case GL_TEXTURE_HEIGHT: + *params = (GLfloat) timg->height; + break; +#ifdef CR_OPENGL_VERSION_1_2 + case GL_TEXTURE_DEPTH: + *params = (GLfloat) timg->depth; + break; +#endif + case GL_TEXTURE_INTERNAL_FORMAT: + *params = (GLfloat) timg->internalFormat; + break; + case GL_TEXTURE_BORDER: + *params = (GLfloat) timg->border; + break; + case GL_TEXTURE_RED_SIZE: + *params = (GLfloat) timg->texFormat->redbits; + break; + case GL_TEXTURE_GREEN_SIZE: + *params = (GLfloat) timg->texFormat->greenbits; + break; + case GL_TEXTURE_BLUE_SIZE: + *params = (GLfloat) timg->texFormat->bluebits; + break; + case GL_TEXTURE_ALPHA_SIZE: + *params = (GLfloat) timg->texFormat->alphabits; + break; + case GL_TEXTURE_INTENSITY_SIZE: + *params = (GLfloat) timg->texFormat->intensitybits; + break; + case GL_TEXTURE_LUMINANCE_SIZE: + *params = (GLfloat) timg->texFormat->luminancebits; + break; +#if CR_ARB_texture_compression + case GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB: + *params = (GLfloat) timg->bytes; + break; + case GL_TEXTURE_COMPRESSED_ARB: + *params = (GLfloat) timg->compressed; + break; +#endif + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "GetTexLevelParameterfv: invalid pname: 0x%x", + pname); + return; + } +} + + +void STATE_APIENTRY +crStateGetTexLevelParameteriv(GLenum target, GLint level, + GLenum pname, GLint *params) +{ + CRContext *g = GetCurrentContext(); + CRTextureState *t = &(g->texture); + CRTextureObj *tobj; + CRTextureLevel *timg; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetTexLevelParameteriv called in begin/end"); + return; + } + + if (level < 0 || level > t->maxLevel) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glGetTexLevelParameteriv: Invalid level: %d", level); + return; + } + + crStateGetTextureObjectAndImage(g, target, level, &tobj, &timg); + if (!timg) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "GetTexLevelParameteriv: invalid target: 0x%x", + target); + return; + } + + switch (pname) + { + case GL_TEXTURE_WIDTH: + *params = (GLint) timg->width; + break; + case GL_TEXTURE_HEIGHT: + *params = (GLint) timg->height; + break; +#ifdef CR_OPENGL_VERSION_1_2 + case GL_TEXTURE_DEPTH: + *params = (GLint) timg->depth; + break; +#endif + case GL_TEXTURE_INTERNAL_FORMAT: + *params = (GLint) timg->internalFormat; + break; + case GL_TEXTURE_BORDER: + *params = (GLint) timg->border; + break; + case GL_TEXTURE_RED_SIZE: + *params = (GLint) timg->texFormat->redbits; + break; + case GL_TEXTURE_GREEN_SIZE: + *params = (GLint) timg->texFormat->greenbits; + break; + case GL_TEXTURE_BLUE_SIZE: + *params = (GLint) timg->texFormat->bluebits; + break; + case GL_TEXTURE_ALPHA_SIZE: + *params = (GLint) timg->texFormat->alphabits; + break; + case GL_TEXTURE_INTENSITY_SIZE: + *params = (GLint) timg->texFormat->intensitybits; + break; + case GL_TEXTURE_LUMINANCE_SIZE: + *params = (GLint) timg->texFormat->luminancebits; + break; + +#if 0 + /* XXX TODO */ + case GL_TEXTURE_DEPTH_SIZE: + *params = (GLint) timg->texFormat->depthSize; + break; +#endif +#if CR_ARB_texture_compression + case GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB: + *params = (GLint) timg->bytes; + break; + case GL_TEXTURE_COMPRESSED_ARB: + *params = (GLint) timg->compressed; + break; +#endif + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "GetTexLevelParameteriv: invalid pname: 0x%x", + pname); + return; + } +} + + +void STATE_APIENTRY +crStateGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params) +{ + CRContext *g = GetCurrentContext(); + CRTextureObj *tobj; + CRTextureLevel *tl; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetTexParameterfv called in begin/end"); + return; + } + + crStateGetTextureObjectAndImage(g, target, 0, &tobj, &tl); + if (!tobj) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexParameterfv: invalid target: 0x%x", target); + return; + } + + switch (pname) + { + case GL_TEXTURE_MAG_FILTER: + *params = (GLfloat) tobj->magFilter; + break; + case GL_TEXTURE_MIN_FILTER: + *params = (GLfloat) tobj->minFilter; + break; + case GL_TEXTURE_WRAP_S: + *params = (GLfloat) tobj->wrapS; + break; + case GL_TEXTURE_WRAP_T: + *params = (GLfloat) tobj->wrapT; + break; +#ifdef CR_OPENGL_VERSION_1_2 + case GL_TEXTURE_WRAP_R: + *params = (GLfloat) tobj->wrapR; + break; + case GL_TEXTURE_PRIORITY: + *params = (GLfloat) tobj->priority; + break; +#endif + case GL_TEXTURE_BORDER_COLOR: + params[0] = tobj->borderColor.r; + params[1] = tobj->borderColor.g; + params[2] = tobj->borderColor.b; + params[3] = tobj->borderColor.a; + break; +#ifdef CR_EXT_texture_filter_anisotropic + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (g->extensions.EXT_texture_filter_anisotropic) { + *params = (GLfloat) tobj->maxAnisotropy; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexParameterfv: invalid pname: 0x%x", pname); + return; + } + break; +#endif +#ifdef CR_ARB_depth_texture + case GL_DEPTH_TEXTURE_MODE_ARB: + if (g->extensions.ARB_depth_texture) { + *params = (GLfloat) tobj->depthMode; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexParameter: invalid pname: 0x%x", pname); + return; + } + break; +#endif +#ifdef CR_ARB_shadow + case GL_TEXTURE_COMPARE_MODE_ARB: + if (g->extensions.ARB_shadow) { + *params = (GLfloat) tobj->compareMode; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexParameter: invalid pname: 0x%x", pname); + return; + } + break; + case GL_TEXTURE_COMPARE_FUNC_ARB: + if (g->extensions.ARB_shadow) { + *params = (GLfloat) tobj->compareFunc; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexParameter: invalid pname: 0x%x", pname); + return; + } + break; +#endif +#ifdef CR_ARB_shadow_ambient + case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB: + if (g->extensions.ARB_shadow_ambient) { + *params = (GLfloat) tobj->compareFailValue; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexParameter: invalid pname: 0x%x", pname); + return; + } + break; +#endif +#ifdef CR_SGIS_generate_mipmap + case GL_GENERATE_MIPMAP_SGIS: + if (g->extensions.SGIS_generate_mipmap) { + *params = (GLfloat) tobj->generateMipmap; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexParameter: invalid pname: 0x%x", pname); + return; + } + break; +#endif +#ifdef CR_OPENGL_VERSION_1_2 + case GL_TEXTURE_MIN_LOD: + *params = (GLfloat) tobj->minLod; + break; + case GL_TEXTURE_MAX_LOD: + *params = (GLfloat) tobj->maxLod; + break; + case GL_TEXTURE_BASE_LEVEL: + *params = (GLfloat) tobj->baseLevel; + break; + case GL_TEXTURE_MAX_LEVEL: + *params = (GLfloat) tobj->maxLevel; + break; +#endif +#if 0 + case GL_TEXTURE_LOD_BIAS_EXT: + /* XXX todo */ + *params = (GLfloat) tobj->lodBias; + break; +#endif + case GL_TEXTURE_RESIDENT: + /* XXX todo */ + crWarning("glGetTexParameterfv GL_TEXTURE_RESIDENT is unimplemented"); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexParameterfv: invalid pname: %d", pname); + return; + } +} + + +void STATE_APIENTRY +crStateGetTexParameteriv(GLenum target, GLenum pname, GLint *params) +{ + CRContext *g = GetCurrentContext(); + CRTextureObj *tobj; + CRTextureLevel *tl; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetTexParameter called in begin/end"); + return; + } + + crStateGetTextureObjectAndImage(g, target, 0, &tobj, &tl); + if (!tobj) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexParameteriv: invalid target: 0x%x", target); + return; + } + + switch (pname) + { + case GL_TEXTURE_MAG_FILTER: + *params = (GLint) tobj->magFilter; + break; + case GL_TEXTURE_MIN_FILTER: + *params = (GLint) tobj->minFilter; + break; + case GL_TEXTURE_WRAP_S: + *params = (GLint) tobj->wrapS; + break; + case GL_TEXTURE_WRAP_T: + *params = (GLint) tobj->wrapT; + break; +#ifdef CR_OPENGL_VERSION_1_2 + case GL_TEXTURE_WRAP_R: + *params = (GLint) tobj->wrapR; + break; + case GL_TEXTURE_PRIORITY: + *params = (GLint) tobj->priority; + break; +#endif + case GL_TEXTURE_BORDER_COLOR: + params[0] = (GLint) (tobj->borderColor.r * CR_MAXINT); + params[1] = (GLint) (tobj->borderColor.g * CR_MAXINT); + params[2] = (GLint) (tobj->borderColor.b * CR_MAXINT); + params[3] = (GLint) (tobj->borderColor.a * CR_MAXINT); + break; +#ifdef CR_OPENGL_VERSION_1_2 + case GL_TEXTURE_MIN_LOD: + *params = (GLint) tobj->minLod; + break; + case GL_TEXTURE_MAX_LOD: + *params = (GLint) tobj->maxLod; + break; + case GL_TEXTURE_BASE_LEVEL: + *params = (GLint) tobj->baseLevel; + break; + case GL_TEXTURE_MAX_LEVEL: + *params = (GLint) tobj->maxLevel; + break; +#endif +#ifdef CR_EXT_texture_filter_anisotropic + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (g->extensions.EXT_texture_filter_anisotropic) { + *params = (GLint) tobj->maxAnisotropy; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexParameter: invalid pname: 0x%x", pname); + return; + } + break; +#endif +#ifdef CR_ARB_depth_texture + case GL_DEPTH_TEXTURE_MODE_ARB: + if (g->extensions.ARB_depth_texture) { + *params = (GLint) tobj->depthMode; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexParameter: invalid pname: 0x%x", pname); + return; + } + break; +#endif +#ifdef CR_ARB_shadow + case GL_TEXTURE_COMPARE_MODE_ARB: + if (g->extensions.ARB_shadow) { + *params = (GLint) tobj->compareMode; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexParameter: invalid pname: 0x%x", pname); + return; + } + break; + case GL_TEXTURE_COMPARE_FUNC_ARB: + if (g->extensions.ARB_shadow) { + *params = (GLint) tobj->compareFunc; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexParameter: invalid pname: 0x%x", pname); + return; + } + break; +#endif +#ifdef CR_ARB_shadow_ambient + case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB: + if (g->extensions.ARB_shadow_ambient) { + *params = (GLint) tobj->compareFailValue; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexParameter: invalid pname: 0x%x", pname); + return; + } + break; +#endif +#ifdef CR_SGIS_generate_mipmap + case GL_GENERATE_MIPMAP_SGIS: + if (g->extensions.SGIS_generate_mipmap) { + *params = (GLint) tobj->generateMipmap; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexParameter: invalid pname: 0x%x", pname); + return; + } + break; +#endif + case GL_TEXTURE_RESIDENT: + /* XXX todo */ + crWarning("glGetTexParameteriv GL_TEXTURE_RESIDENT is unimplemented"); + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glGetTexParameter: invalid pname: %d", pname); + return; + } +} + + +void STATE_APIENTRY +crStatePrioritizeTextures(GLsizei n, const GLuint *textures, + const GLclampf *priorities) +{ + CRContext *g = GetCurrentContext(); + CRTextureObj *tobj; + GLsizei i; + UNUSED(priorities); + + for (i = 0; i < n; ++i) + { + GLuint tex = textures[i]; + GET_TOBJ(tobj, g, tex); + if (!tobj) + { + Assert(crHashtableIsKeyUsed(g->shared->textureTable, tex)); + tobj = crStateTextureAllocate_t(g, tex); + } + + /* so far the code just ensures the tex object is created to make + * the crserverlib code be able to pass it to host ogl */ + + /** @todo store texture priorities in the state data to be able to restore it properly + * on save state load */ + } + + return; +} + + +GLboolean STATE_APIENTRY +crStateAreTexturesResident(GLsizei n, const GLuint *textures, + GLboolean *residences) +{ + UNUSED(n); + UNUSED(textures); + UNUSED(residences); + /** @todo */ + return GL_TRUE; +} + + +GLboolean STATE_APIENTRY +crStateIsTexture(GLuint texture) +{ + CRContext *g = GetCurrentContext(); + CRTextureObj *tobj; + + GET_TOBJ(tobj, g, texture); + return tobj != NULL; +} + +static void crStateCheckTextureHWIDCB(unsigned long key, void *data1, void *data2) +{ + CRTextureObj *pTex = (CRTextureObj *) data1; + crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2; + (void) key; + + if (crStateGetTextureObjHWID(pTex)==pParms->hwid) + pParms->id = pTex->id; +} + +DECLEXPORT(GLuint) STATE_APIENTRY crStateTextureHWIDtoID(GLuint hwid) +{ + CRContext *g = GetCurrentContext(); + crCheckIDHWID_t parms; + + parms.id = hwid; + parms.hwid = hwid; + + crHashtableWalk(g->shared->textureTable, crStateCheckTextureHWIDCB, &parms); + return parms.id; +} + +DECLEXPORT(GLuint) STATE_APIENTRY crStateGetTextureHWID(GLuint id) +{ + CRContext *g = GetCurrentContext(); + CRTextureObj *tobj; + + GET_TOBJ(tobj, g, id); + +#ifdef DEBUG_misha + if (id) + { + Assert(tobj); + } + else + { + Assert(!tobj); + } + if (tobj) + { +/* crDebug("tex id(%d), hwid(%d)", tobj->id, tobj->hwid);*/ + } +#endif + + + return tobj ? crStateGetTextureObjHWID(tobj) : 0; +} + +DECLEXPORT(GLuint) STATE_APIENTRY crStateGetTextureObjHWID(CRTextureObj *tobj) +{ + CRASSERT(tobj); + +#ifndef IN_GUEST + if (tobj->id && !tobj->hwid) + { + CRASSERT(diff_api.GenTextures); + diff_api.GenTextures(1, &tobj->hwid); +#if 0 /*def DEBUG_misha*/ + crDebug("tex id(%d), hwid(%d)", tobj->id, tobj->hwid); +#endif + CRASSERT(tobj->hwid); + } +#endif + + return tobj->hwid; +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_transform.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_transform.c new file mode 100644 index 00000000..642561bd --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_transform.c @@ -0,0 +1,1392 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "cr_bits.h" +#include "cr_mem.h" +#include "state.h" +#include "state/cr_statetypes.h" +#include "state_internals.h" + +#ifdef WINDOWS +#pragma warning( disable : 4514 ) +#endif + +/* + * This used to be a macro. + */ +static INLINE void +LOADMATRIX( const CRmatrix *a ) +{ + if (a->m00 == 1.0F && a->m01 == 0.0F && a->m02 == 0.0F && a->m03 == 0.0F && + a->m10 == 0.0F && a->m11 == 1.0F && a->m12 == 0.0F && a->m13 == 0.0F && + a->m20 == 0.0F && a->m21 == 0.0F && a->m22 == 1.0F && a->m23 == 0.0F && + a->m30 == 0.0F && a->m31 == 0.0F && a->m32 == 0.0F && a->m33 == 1.0F) { + diff_api.LoadIdentity(); + } + else { + GLfloat f[16]; + f[0] = a->m00; f[1] = a->m01; f[2] = a->m02; f[3] = a->m03; + f[4] = a->m10; f[5] = a->m11; f[6] = a->m12; f[7] = a->m13; + f[8] = a->m20; f[9] = a->m21; f[10] = a->m22; f[11] = a->m23; + f[12] = a->m30; f[13] = a->m31; f[14] = a->m32; f[15] = a->m33; + diff_api.LoadMatrixf(f); + } +} + + +static void _math_transposef( GLfloat to[16], const GLfloat from[16] ) +{ + to[0] = from[0]; + to[1] = from[4]; + to[2] = from[8]; + to[3] = from[12]; + to[4] = from[1]; + to[5] = from[5]; + to[6] = from[9]; + to[7] = from[13]; + to[8] = from[2]; + to[9] = from[6]; + to[10] = from[10]; + to[11] = from[14]; + to[12] = from[3]; + to[13] = from[7]; + to[14] = from[11]; + to[15] = from[15]; +} + +static void _math_transposed( GLdouble to[16], const GLdouble from[16] ) +{ + to[0] = from[0]; + to[1] = from[4]; + to[2] = from[8]; + to[3] = from[12]; + to[4] = from[1]; + to[5] = from[5]; + to[6] = from[9]; + to[7] = from[13]; + to[8] = from[2]; + to[9] = from[6]; + to[10] = from[10]; + to[11] = from[14]; + to[12] = from[3]; + to[13] = from[7]; + to[14] = from[11]; + to[15] = from[15]; +} + + +void +crStateInitMatrixStack(CRMatrixStack *stack, int maxDepth) +{ + stack->maxDepth = maxDepth; + stack->depth = 0; + stack->stack = crAlloc(maxDepth * sizeof(CRmatrix)); + crMatrixInit(&stack->stack[0]); + stack->top = stack->stack; +} + +static void +free_matrix_stack_data(CRMatrixStack *stack) +{ + crFree(stack->stack); +} + +void crStateTransformDestroy(CRContext *ctx) +{ + CRTransformState *t = &ctx->transform; + unsigned int i; + + free_matrix_stack_data(&(t->modelViewStack)); + free_matrix_stack_data(&(t->projectionStack)); + free_matrix_stack_data(&(t->colorStack)); + for (i = 0 ; i < ctx->limits.maxTextureUnits; i++) + free_matrix_stack_data(&(t->textureStack[i])); + for (i = 0; i < CR_MAX_PROGRAM_MATRICES; i++) + free_matrix_stack_data(&(t->programStack[i])); + + crFree( t->clipPlane ); + crFree( t->clip ); +} + +void crStateTransformInit(CRContext *ctx) +{ + CRLimitsState *limits = &ctx->limits; + CRTransformState *t = &ctx->transform; + CRStateBits *sb = GetCurrentBits(); + CRTransformBits *tb = &(sb->transform); + unsigned int i; + + t->matrixMode = GL_MODELVIEW; + RESET(tb->matrixMode, ctx->bitid); + + crStateInitMatrixStack(&t->modelViewStack, CR_MAX_MODELVIEW_STACK_DEPTH); + crStateInitMatrixStack(&t->projectionStack, CR_MAX_PROJECTION_STACK_DEPTH); + crStateInitMatrixStack(&t->colorStack, CR_MAX_COLOR_STACK_DEPTH); + for (i = 0 ; i < limits->maxTextureUnits ; i++) + crStateInitMatrixStack(&t->textureStack[i], CR_MAX_TEXTURE_STACK_DEPTH); + for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++) + crStateInitMatrixStack(&t->programStack[i], CR_MAX_PROGRAM_MATRIX_STACK_DEPTH); + t->currentStack = &(t->modelViewStack); + + /* dirty bits */ + RESET(tb->modelviewMatrix, ctx->bitid); + RESET(tb->projectionMatrix, ctx->bitid); + RESET(tb->colorMatrix, ctx->bitid); + RESET(tb->textureMatrix, ctx->bitid); + RESET(tb->programMatrix, ctx->bitid); + tb->currentMatrix = tb->modelviewMatrix; + + t->normalize = GL_FALSE; + RESET(tb->enable, ctx->bitid); + + t->clipPlane = (GLvectord *) crCalloc (sizeof (GLvectord) * CR_MAX_CLIP_PLANES); + t->clip = (GLboolean *) crCalloc (sizeof (GLboolean) * CR_MAX_CLIP_PLANES); + for (i = 0; i < CR_MAX_CLIP_PLANES; i++) + { + t->clipPlane[i].x = 0.0f; + t->clipPlane[i].y = 0.0f; + t->clipPlane[i].z = 0.0f; + t->clipPlane[i].w = 0.0f; + t->clip[i] = GL_FALSE; + } + RESET(tb->clipPlane, ctx->bitid); + +#ifdef CR_OPENGL_VERSION_1_2 + t->rescaleNormals = GL_FALSE; +#endif +#ifdef CR_IBM_rasterpos_clip + t->rasterPositionUnclipped = GL_FALSE; +#endif + + t->modelViewProjectionValid = 0; + + RESET(tb->dirty, ctx->bitid); +} + + +/* + * Compute the product of the modelview and projection matrices + */ +void crStateTransformUpdateTransform(CRTransformState *t) +{ + const CRmatrix *m1 = t->projectionStack.top; + const CRmatrix *m2 = t->modelViewStack.top; + CRmatrix *m = &(t->modelViewProjection); + crMatrixMultiply(m, m1, m2); + t->modelViewProjectionValid = 1; +} + +void crStateTransformXformPoint(CRTransformState *t, GLvectorf *p) +{ + /* XXX is this flag really needed? We may be covering a bug elsewhere */ + if (!t->modelViewProjectionValid) + crStateTransformUpdateTransform(t); + + crStateTransformXformPointMatrixf(&(t->modelViewProjection), p); +} + +void crStateTransformXformPointMatrixf(const CRmatrix *m, GLvectorf *p) +{ + GLfloat x = p->x; + GLfloat y = p->y; + GLfloat z = p->z; + GLfloat w = p->w; + + p->x = m->m00*x + m->m10*y + m->m20*z + m->m30*w; + p->y = m->m01*x + m->m11*y + m->m21*z + m->m31*w; + p->z = m->m02*x + m->m12*y + m->m22*z + m->m32*w; + p->w = m->m03*x + m->m13*y + m->m23*z + m->m33*w; +} + +void crStateTransformXformPointMatrixd(const CRmatrix *m, GLvectord *p) +{ + GLdouble x = p->x; + GLdouble y = p->y; + GLdouble z = p->z; + GLdouble w = p->w; + + p->x = (GLdouble) (m->m00*x + m->m10*y + m->m20*z + m->m30*w); + p->y = (GLdouble) (m->m01*x + m->m11*y + m->m21*z + m->m31*w); + p->z = (GLdouble) (m->m02*x + m->m12*y + m->m22*z + m->m32*w); + p->w = (GLdouble) (m->m03*x + m->m13*y + m->m23*z + m->m33*w); +} + +void STATE_APIENTRY crStateClipPlane (GLenum plane, const GLdouble *equation) +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &g->transform; + CRStateBits *sb = GetCurrentBits(); + CRTransformBits *tb = &(sb->transform); + GLvectord e; + unsigned int i; + CRmatrix inv; + + e.x = equation[0]; + e.y = equation[1]; + e.z = equation[2]; + e.w = equation[3]; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "ClipPlane called in begin/end"); + return; + } + + FLUSH(); + + i = plane - GL_CLIP_PLANE0; + if (i >= g->limits.maxClipPlanes) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "ClipPlane called with bad enumerant: %d", plane); + return; + } + + crMatrixInvertTranspose(&inv, t->modelViewStack.top); + crStateTransformXformPointMatrixd (&inv, &e); + t->clipPlane[i] = e; + DIRTY(tb->clipPlane, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateMatrixMode(GLenum e) +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &(g->transform); + CRTextureState *tex = &(g->texture); + CRStateBits *sb = GetCurrentBits(); + CRTransformBits *tb = &(sb->transform); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "MatrixMode called in begin/end"); + return; + } + + FLUSH(); + + switch (e) + { + case GL_MODELVIEW: + t->currentStack = &(t->modelViewStack); + t->matrixMode = GL_MODELVIEW; + tb->currentMatrix = tb->modelviewMatrix; + break; + case GL_PROJECTION: + t->currentStack = &(t->projectionStack); + t->matrixMode = GL_PROJECTION; + tb->currentMatrix = tb->projectionMatrix; + break; + case GL_TEXTURE: + t->currentStack = &(t->textureStack[tex->curTextureUnit]); + t->matrixMode = GL_TEXTURE; + tb->currentMatrix = tb->textureMatrix; + break; + case GL_COLOR: + t->currentStack = &(t->colorStack); + t->matrixMode = GL_COLOR; + tb->currentMatrix = tb->colorMatrix; + break; + case GL_MATRIX0_NV: + case GL_MATRIX1_NV: + case GL_MATRIX2_NV: + case GL_MATRIX3_NV: + case GL_MATRIX4_NV: + case GL_MATRIX5_NV: + case GL_MATRIX6_NV: + case GL_MATRIX7_NV: + if (g->extensions.NV_vertex_program) { + const GLint i = e - GL_MATRIX0_NV; + t->currentStack = &(t->programStack[i]); + t->matrixMode = e; + tb->currentMatrix = tb->programMatrix; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid matrix mode: %d", e); + return; + } + break; + case GL_MATRIX0_ARB: + case GL_MATRIX1_ARB: + case GL_MATRIX2_ARB: + case GL_MATRIX3_ARB: + case GL_MATRIX4_ARB: + case GL_MATRIX5_ARB: + case GL_MATRIX6_ARB: + case GL_MATRIX7_ARB: + /* Note: the NV and ARB program matrices are the same, but + * use different enumerants. + */ + if (g->extensions.ARB_vertex_program) { + const GLint i = e - GL_MATRIX0_ARB; + t->currentStack = &(t->programStack[i]); + t->matrixMode = e; + tb->currentMatrix = tb->programMatrix; + } + else { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid matrix mode: %d", e); + return; + } + break; + default: + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid matrix mode: %d", e); + return; + } + DIRTY(tb->matrixMode, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); + + CRASSERT(t->currentStack->top == t->currentStack->stack + t->currentStack->depth); +} + +void STATE_APIENTRY crStateLoadIdentity() +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &(g->transform); + CRStateBits *sb = GetCurrentBits(); + CRTransformBits *tb = &(sb->transform); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "LoadIdentity called in begin/end"); + return; + } + + FLUSH(); + + crMatrixInit(t->currentStack->top); + t->modelViewProjectionValid = 0; + + DIRTY(tb->currentMatrix, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStatePopMatrix() +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &g->transform; + CRStateBits *sb = GetCurrentBits(); + CRTransformBits *tb = &(sb->transform); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "PopMatrix called in begin/end"); + return; + } + + FLUSH(); + + if (t->currentStack->depth == 0) + { + crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "PopMatrix of empty stack."); + return; + } + + CRASSERT(t->currentStack->top == t->currentStack->stack + t->currentStack->depth); + + t->currentStack->depth--; + t->currentStack->top = t->currentStack->stack + t->currentStack->depth; + + t->modelViewProjectionValid = 0; + + DIRTY(tb->currentMatrix, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStatePushMatrix() +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &g->transform; + CRStateBits *sb = GetCurrentBits(); + CRTransformBits *tb = &(sb->transform); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "PushMatrix called in begin/end"); + return; + } + + FLUSH(); + + if (t->currentStack->depth + 1 >= t->currentStack->maxDepth) + { + crStateError(__LINE__, __FILE__, GL_STACK_OVERFLOW, "PushMatrix pass the end of allocated stack"); + return; + } + + CRASSERT(t->currentStack->top == t->currentStack->stack + t->currentStack->depth); + /* Perform the copy */ + *(t->currentStack->top + 1) = *(t->currentStack->top); + + /* Move the stack pointer */ + t->currentStack->depth++; + t->currentStack->top = t->currentStack->stack + t->currentStack->depth; + + DIRTY(tb->currentMatrix, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + + +/* Load a CRMatrix */ +void crStateLoadMatrix(const CRmatrix *m) +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &(g->transform); + CRStateBits *sb = GetCurrentBits(); + CRTransformBits *tb = &(sb->transform); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "LoadMatrix called in begin/end"); + return; + } + + FLUSH(); + + CRASSERT(t->currentStack->top == t->currentStack->stack + t->currentStack->depth); + *t->currentStack->top = *m; + t->modelViewProjectionValid = 0; + DIRTY(tb->currentMatrix, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + + + +void STATE_APIENTRY crStateLoadMatrixf(const GLfloat *m1) +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &(g->transform); + CRStateBits *sb = GetCurrentBits(); + CRTransformBits *tb = &(sb->transform); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "LoadMatrixf called in begin/end"); + return; + } + + FLUSH(); + + crMatrixInitFromFloats(t->currentStack->top, m1); + t->modelViewProjectionValid = 0; + DIRTY(tb->currentMatrix, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + + +void STATE_APIENTRY crStateLoadMatrixd(const GLdouble *m1) +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &(g->transform); + CRStateBits *sb = GetCurrentBits(); + CRTransformBits *tb = &(sb->transform); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "LoadMatrixd called in begin/end"); + return; + } + + FLUSH(); + + crMatrixInitFromDoubles(t->currentStack->top, m1); + t->modelViewProjectionValid = 0; + DIRTY(tb->currentMatrix, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + + +void STATE_APIENTRY crStateLoadTransposeMatrixfARB(const GLfloat *m1) +{ + GLfloat tm[16]; + if (!m1) return; + _math_transposef(tm, m1); + crStateLoadMatrixf(tm); +} + +void STATE_APIENTRY crStateLoadTransposeMatrixdARB(const GLdouble *m1) +{ + GLdouble tm[16]; + if (!m1) return; + _math_transposed(tm, m1); + crStateLoadMatrixd(tm); +} + +/* This code is based on the Pomegranate stuff. + ** The theory is that by preloading everything, + ** the compiler could do optimizations that + ** were not doable in the array version + ** I'm not too sure with a PII with 4 registers + ** that this really helps. + */ +void STATE_APIENTRY crStateMultMatrixf(const GLfloat *m1) +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &(g->transform); + CRStateBits *sb = GetCurrentBits(); + CRTransformBits *tb = &(sb->transform); + CRmatrix *m = t->currentStack->top; + + const GLdefault lm00 = m->m00; + const GLdefault lm01 = m->m01; + const GLdefault lm02 = m->m02; + const GLdefault lm03 = m->m03; + const GLdefault lm10 = m->m10; + const GLdefault lm11 = m->m11; + const GLdefault lm12 = m->m12; + const GLdefault lm13 = m->m13; + const GLdefault lm20 = m->m20; + const GLdefault lm21 = m->m21; + const GLdefault lm22 = m->m22; + const GLdefault lm23 = m->m23; + const GLdefault lm30 = m->m30; + const GLdefault lm31 = m->m31; + const GLdefault lm32 = m->m32; + const GLdefault lm33 = m->m33; + const GLdefault rm00 = (GLdefault) m1[0]; + const GLdefault rm01 = (GLdefault) m1[1]; + const GLdefault rm02 = (GLdefault) m1[2]; + const GLdefault rm03 = (GLdefault) m1[3]; + const GLdefault rm10 = (GLdefault) m1[4]; + const GLdefault rm11 = (GLdefault) m1[5]; + const GLdefault rm12 = (GLdefault) m1[6]; + const GLdefault rm13 = (GLdefault) m1[7]; + const GLdefault rm20 = (GLdefault) m1[8]; + const GLdefault rm21 = (GLdefault) m1[9]; + const GLdefault rm22 = (GLdefault) m1[10]; + const GLdefault rm23 = (GLdefault) m1[11]; + const GLdefault rm30 = (GLdefault) m1[12]; + const GLdefault rm31 = (GLdefault) m1[13]; + const GLdefault rm32 = (GLdefault) m1[14]; + const GLdefault rm33 = (GLdefault) m1[15]; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "MultMatrixf called in begin/end"); + return; + } + + FLUSH(); + + m->m00 = lm00*rm00 + lm10*rm01 + lm20*rm02 + lm30*rm03; + m->m01 = lm01*rm00 + lm11*rm01 + lm21*rm02 + lm31*rm03; + m->m02 = lm02*rm00 + lm12*rm01 + lm22*rm02 + lm32*rm03; + m->m03 = lm03*rm00 + lm13*rm01 + lm23*rm02 + lm33*rm03; + m->m10 = lm00*rm10 + lm10*rm11 + lm20*rm12 + lm30*rm13; + m->m11 = lm01*rm10 + lm11*rm11 + lm21*rm12 + lm31*rm13; + m->m12 = lm02*rm10 + lm12*rm11 + lm22*rm12 + lm32*rm13; + m->m13 = lm03*rm10 + lm13*rm11 + lm23*rm12 + lm33*rm13; + m->m20 = lm00*rm20 + lm10*rm21 + lm20*rm22 + lm30*rm23; + m->m21 = lm01*rm20 + lm11*rm21 + lm21*rm22 + lm31*rm23; + m->m22 = lm02*rm20 + lm12*rm21 + lm22*rm22 + lm32*rm23; + m->m23 = lm03*rm20 + lm13*rm21 + lm23*rm22 + lm33*rm23; + m->m30 = lm00*rm30 + lm10*rm31 + lm20*rm32 + lm30*rm33; + m->m31 = lm01*rm30 + lm11*rm31 + lm21*rm32 + lm31*rm33; + m->m32 = lm02*rm30 + lm12*rm31 + lm22*rm32 + lm32*rm33; + m->m33 = lm03*rm30 + lm13*rm31 + lm23*rm32 + lm33*rm33; + + t->modelViewProjectionValid = 0; + + DIRTY(tb->currentMatrix, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateMultMatrixd(const GLdouble *m1) +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &(g->transform); + CRStateBits *sb = GetCurrentBits(); + CRTransformBits *tb = &(sb->transform); + CRmatrix *m = t->currentStack->top; + const GLdefault lm00 = m->m00; + const GLdefault lm01 = m->m01; + const GLdefault lm02 = m->m02; + const GLdefault lm03 = m->m03; + const GLdefault lm10 = m->m10; + const GLdefault lm11 = m->m11; + const GLdefault lm12 = m->m12; + const GLdefault lm13 = m->m13; + const GLdefault lm20 = m->m20; + const GLdefault lm21 = m->m21; + const GLdefault lm22 = m->m22; + const GLdefault lm23 = m->m23; + const GLdefault lm30 = m->m30; + const GLdefault lm31 = m->m31; + const GLdefault lm32 = m->m32; + const GLdefault lm33 = m->m33; + const GLdefault rm00 = (GLdefault) m1[0]; + const GLdefault rm01 = (GLdefault) m1[1]; + const GLdefault rm02 = (GLdefault) m1[2]; + const GLdefault rm03 = (GLdefault) m1[3]; + const GLdefault rm10 = (GLdefault) m1[4]; + const GLdefault rm11 = (GLdefault) m1[5]; + const GLdefault rm12 = (GLdefault) m1[6]; + const GLdefault rm13 = (GLdefault) m1[7]; + const GLdefault rm20 = (GLdefault) m1[8]; + const GLdefault rm21 = (GLdefault) m1[9]; + const GLdefault rm22 = (GLdefault) m1[10]; + const GLdefault rm23 = (GLdefault) m1[11]; + const GLdefault rm30 = (GLdefault) m1[12]; + const GLdefault rm31 = (GLdefault) m1[13]; + const GLdefault rm32 = (GLdefault) m1[14]; + const GLdefault rm33 = (GLdefault) m1[15]; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "MultMatrixd called in begin/end"); + return; + } + + FLUSH(); + + m->m00 = lm00*rm00 + lm10*rm01 + lm20*rm02 + lm30*rm03; + m->m01 = lm01*rm00 + lm11*rm01 + lm21*rm02 + lm31*rm03; + m->m02 = lm02*rm00 + lm12*rm01 + lm22*rm02 + lm32*rm03; + m->m03 = lm03*rm00 + lm13*rm01 + lm23*rm02 + lm33*rm03; + m->m10 = lm00*rm10 + lm10*rm11 + lm20*rm12 + lm30*rm13; + m->m11 = lm01*rm10 + lm11*rm11 + lm21*rm12 + lm31*rm13; + m->m12 = lm02*rm10 + lm12*rm11 + lm22*rm12 + lm32*rm13; + m->m13 = lm03*rm10 + lm13*rm11 + lm23*rm12 + lm33*rm13; + m->m20 = lm00*rm20 + lm10*rm21 + lm20*rm22 + lm30*rm23; + m->m21 = lm01*rm20 + lm11*rm21 + lm21*rm22 + lm31*rm23; + m->m22 = lm02*rm20 + lm12*rm21 + lm22*rm22 + lm32*rm23; + m->m23 = lm03*rm20 + lm13*rm21 + lm23*rm22 + lm33*rm23; + m->m30 = lm00*rm30 + lm10*rm31 + lm20*rm32 + lm30*rm33; + m->m31 = lm01*rm30 + lm11*rm31 + lm21*rm32 + lm31*rm33; + m->m32 = lm02*rm30 + lm12*rm31 + lm22*rm32 + lm32*rm33; + m->m33 = lm03*rm30 + lm13*rm31 + lm23*rm32 + lm33*rm33; + + t->modelViewProjectionValid = 0; + + DIRTY(tb->currentMatrix, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateMultTransposeMatrixfARB(const GLfloat *m1) +{ + GLfloat tm[16]; + if (!m1) return; + _math_transposef(tm, m1); + crStateMultMatrixf(tm); +} + +void STATE_APIENTRY crStateMultTransposeMatrixdARB(const GLdouble *m1) +{ + GLdouble tm[16]; + if (!m1) return; + _math_transposed(tm, m1); + crStateMultMatrixd(tm); +} + +void STATE_APIENTRY crStateTranslatef(GLfloat x_arg, GLfloat y_arg, GLfloat z_arg) +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &(g->transform); + CRStateBits *sb = GetCurrentBits(); + CRTransformBits *tb = &(sb->transform); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "Translatef called in begin/end"); + return; + } + + FLUSH(); + + crMatrixTranslate(t->currentStack->top, x_arg, y_arg, z_arg); + t->modelViewProjectionValid = 0; + DIRTY(tb->currentMatrix, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + + +void STATE_APIENTRY crStateTranslated(GLdouble x_arg, GLdouble y_arg, GLdouble z_arg) +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &(g->transform); + CRStateBits *sb = GetCurrentBits(); + CRTransformBits *tb = &(sb->transform); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "Translated called in begin/end"); + return; + } + + FLUSH(); + + crMatrixTranslate(t->currentStack->top, (float)x_arg, (float)y_arg, (float)z_arg); + t->modelViewProjectionValid = 0; + DIRTY(tb->currentMatrix, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + + +void STATE_APIENTRY crStateRotatef(GLfloat ang, GLfloat x, GLfloat y, GLfloat z) +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &(g->transform); + CRStateBits *sb = GetCurrentBits(); + CRTransformBits *tb = &(sb->transform); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "Rotatef called in begin/end"); + return; + } + + FLUSH(); + + crMatrixRotate(t->currentStack->top, ang, x, y, z); + t->modelViewProjectionValid = 0; + DIRTY(tb->currentMatrix, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateRotated(GLdouble ang, GLdouble x, GLdouble y, GLdouble z) +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &(g->transform); + CRStateBits *sb = GetCurrentBits(); + CRTransformBits *tb = &(sb->transform); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "Rotated called in begin/end"); + return; + } + + FLUSH(); + + crMatrixRotate(t->currentStack->top, (float)ang, (float)x, (float)y, (float)z); + t->modelViewProjectionValid = 0; + DIRTY(tb->currentMatrix, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateScalef (GLfloat x_arg, GLfloat y_arg, GLfloat z_arg) +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &(g->transform); + CRStateBits *sb = GetCurrentBits(); + CRTransformBits *tb = &(sb->transform); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "Scalef called in begin/end"); + return; + } + + FLUSH(); + + crMatrixScale(t->currentStack->top, x_arg, y_arg, z_arg); + t->modelViewProjectionValid = 0; + DIRTY(tb->currentMatrix, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateScaled (GLdouble x_arg, GLdouble y_arg, GLdouble z_arg) +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &(g->transform); + CRStateBits *sb = GetCurrentBits(); + CRTransformBits *tb = &(sb->transform); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "Scaled called in begin/end"); + return; + } + + FLUSH(); + + crMatrixScale(t->currentStack->top, (float)x_arg, (float)y_arg, (float)z_arg); + t->modelViewProjectionValid = 0; + DIRTY(tb->currentMatrix, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateFrustum(GLdouble left, GLdouble right, + GLdouble bottom, GLdouble top, + GLdouble zNear, GLdouble zFar) +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &(g->transform); + CRStateBits *sb = GetCurrentBits(); + CRTransformBits *tb = &(sb->transform); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "Frustum called in begin/end"); + return; + } + + FLUSH(); + + crMatrixFrustum(t->currentStack->top, (float)left, (float)right, (float)bottom, (float)top, (float)zNear, (float)zFar); + t->modelViewProjectionValid = 0; + DIRTY(tb->currentMatrix, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateOrtho(GLdouble left, GLdouble right, + GLdouble bottom, GLdouble top, + GLdouble zNear, GLdouble zFar) +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &(g->transform); + CRStateBits *sb = GetCurrentBits(); + CRTransformBits *tb = &(sb->transform); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "Ortho called in begin/end"); + return; + } + + FLUSH(); + + crMatrixOrtho(t->currentStack->top, (float)left, (float)right, (float)bottom, (float)top, (float)zNear, (float)zFar); + t->modelViewProjectionValid = 0; + DIRTY(tb->currentMatrix, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateGetClipPlane(GLenum plane, GLdouble *equation) +{ + CRContext *g = GetCurrentContext(); + CRTransformState *t = &g->transform; + unsigned int i; + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glGetClipPlane called in begin/end"); + return; + } + + i = plane - GL_CLIP_PLANE0; + if (i >= g->limits.maxClipPlanes) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "GetClipPlane called with bad enumerant: %d", plane); + return; + } + + equation[0] = t->clipPlane[i].x; + equation[1] = t->clipPlane[i].y; + equation[2] = t->clipPlane[i].z; + equation[3] = t->clipPlane[i].w; +} + +void crStateTransformSwitch( CRTransformBits *t, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx ) +{ + const GLuint maxTextureUnits = toCtx->limits.maxTextureUnits; + CRTransformState *from = &(fromCtx->transform); + CRTransformState *to = &(toCtx->transform); + GLuint i, j; + unsigned int checktex = 0; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + + for (j=0;j<CR_MAX_BITARRAY;j++) + nbitID[j] = ~bitID[j]; + + if (CHECKDIRTY(t->enable, bitID)) + { + glAble able[2]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + if (from->normalize != to->normalize) { + if (to->normalize == GL_TRUE) + diff_api.Enable(GL_NORMALIZE); + else + diff_api.Disable(GL_NORMALIZE); + FILLDIRTY(t->enable); + FILLDIRTY(t->dirty); + } +#ifdef CR_OPENGL_VERSION_1_2 + if (from->rescaleNormals != to->rescaleNormals) + { + able[to->rescaleNormals](GL_RESCALE_NORMAL); + FILLDIRTY(t->enable); + FILLDIRTY(t->dirty); + } +#else + (void) able; +#endif +#ifdef CR_IBM_rasterpos_clip + if (from->rasterPositionUnclipped != to->rasterPositionUnclipped) + { + able[to->rasterPositionUnclipped](GL_RASTER_POSITION_UNCLIPPED_IBM); + FILLDIRTY(t->enable); + FILLDIRTY(t->dirty); + } +#endif + CLEARDIRTY(t->enable, nbitID); + } + + if (CHECKDIRTY(t->clipPlane, bitID)) { + diff_api.MatrixMode(GL_MODELVIEW); + diff_api.PushMatrix(); + diff_api.LoadIdentity(); + for (i=0; i<CR_MAX_CLIP_PLANES; i++) { + if (from->clipPlane[i].x != to->clipPlane[i].x || + from->clipPlane[i].y != to->clipPlane[i].y || + from->clipPlane[i].z != to->clipPlane[i].z || + from->clipPlane[i].w != to->clipPlane[i].w) { + + GLdouble cp[4]; + cp[0] = to->clipPlane[i].x; + cp[1] = to->clipPlane[i].y; + cp[2] = to->clipPlane[i].z; + cp[3] = to->clipPlane[i].w; + + diff_api.ClipPlane(GL_CLIP_PLANE0 + i, (const GLdouble *)(cp)); + + FILLDIRTY(t->clipPlane); + FILLDIRTY(t->dirty); + } + } + diff_api.PopMatrix(); + CLEARDIRTY(t->clipPlane, nbitID); + } + + /* If the matrix stack depths don't match when we're + * updating the context - we can update the wrong matrix + * and get some lovely effects!! + * So we troll each depth list here and Pop & Push the matrix stack + * to bring it right up to date before checking the current + * matrix. + * + * - Alan H. + */ + if ( (from->modelViewStack.depth != to->modelViewStack.depth) || + CHECKDIRTY(t->modelviewMatrix, bitID) ) + { + GLuint td = to->modelViewStack.depth; + GLuint fd = from->modelViewStack.depth; + + if (td != fd || + !crMatrixIsEqual(to->modelViewStack.top, from->modelViewStack.top)) + { + diff_api.MatrixMode(GL_MODELVIEW); + + if (fd > td) + { + for (i = td; i < fd; i++) + { + diff_api.PopMatrix(); + } + fd = td; + } + + for (i = fd; i <= td; i++) + { + LOADMATRIX(to->modelViewStack.stack + i); + FILLDIRTY(t->modelviewMatrix); + FILLDIRTY(t->dirty); + + /* Don't want to push on the current matrix */ + if (i != to->modelViewStack.depth) + diff_api.PushMatrix(); + } + } + CLEARDIRTY(t->modelviewMatrix, nbitID); + } + + /* Projection matrix */ + if ( (from->projectionStack.depth != to->projectionStack.depth) || + CHECKDIRTY(t->projectionMatrix, bitID) ) + { + GLuint td = to->projectionStack.depth; + GLuint fd = from->projectionStack.depth; + + if (td != fd || + !crMatrixIsEqual(to->projectionStack.top, from->projectionStack.top)) { + + diff_api.MatrixMode(GL_PROJECTION); + + if (fd > td) + { + for (i = td; i < fd; i++) + { + diff_api.PopMatrix(); + } + fd = td; + } + + for (i = fd; i <= td; i++) + { + LOADMATRIX(to->projectionStack.stack + i); + FILLDIRTY(t->projectionMatrix); + FILLDIRTY(t->dirty); + + /* Don't want to push on the current matrix */ + if (i != to->projectionStack.depth) + diff_api.PushMatrix(); + } + } + CLEARDIRTY(t->projectionMatrix, nbitID); + } + + /* Texture matrices */ + for (i = 0 ; i < maxTextureUnits ; i++) + if (from->textureStack[i].depth != to->textureStack[i].depth) + checktex = 1; + + if ( checktex || CHECKDIRTY(t->textureMatrix, bitID) ) + { + for (j = 0 ; j < maxTextureUnits ; j++) + { + GLuint td = to->textureStack[j].depth; + GLuint fd = from->textureStack[j].depth; + + if (td != fd || + !crMatrixIsEqual(to->textureStack[j].top, from->textureStack[j].top)) + { + diff_api.MatrixMode(GL_TEXTURE); + + if (fd > td) + { + for (i = td; i < fd; i++) + { + diff_api.PopMatrix(); + } + fd = td; + } + + diff_api.ActiveTextureARB( j + GL_TEXTURE0_ARB ); + for (i = fd; i <= td; i++) + { + LOADMATRIX(to->textureStack[j].stack + i); + FILLDIRTY(t->textureMatrix); + FILLDIRTY(t->dirty); + + /* Don't want to push on the current matrix */ + if (i != to->textureStack[j].depth) + diff_api.PushMatrix(); + } + } + } + /* Since we were mucking with the active texture unit above set it to the + * proper value now. + */ + diff_api.ActiveTextureARB(GL_TEXTURE0_ARB + toCtx->texture.curTextureUnit); + CLEARDIRTY(t->textureMatrix, nbitID); + } + + /* Color matrix */ + if ( (from->colorStack.depth != to->colorStack.depth) || + CHECKDIRTY(t->colorMatrix, bitID) ) + { + GLuint td = to->colorStack.depth; + GLuint fd = from->colorStack.depth; + if (td != fd || !crMatrixIsEqual(to->colorStack.top, from->colorStack.top)) + { + diff_api.MatrixMode(GL_COLOR); + + if (fd > td) + { + for (i = td; i < fd; i++) + { + diff_api.PopMatrix(); + } + fd = td; + } + + for (i = fd; i <= td; i++) + { + LOADMATRIX(to->colorStack.stack + i); + FILLDIRTY(t->colorMatrix); + FILLDIRTY(t->dirty); + + /* Don't want to push on the current matrix */ + if (i != to->colorStack.depth) + diff_api.PushMatrix(); + } + } + CLEARDIRTY(t->colorMatrix, nbitID); + } + + to->modelViewProjectionValid = 0; + CLEARDIRTY(t->dirty, nbitID); + + /* Since we were mucking with the current matrix above + * set it to the proper value now. + */ + diff_api.MatrixMode(to->matrixMode); + + /* sanity tests */ + CRASSERT(from->modelViewStack.top == from->modelViewStack.stack + from->modelViewStack.depth); + CRASSERT(from->projectionStack.top == from->projectionStack.stack + from->projectionStack.depth); + +} + +void +crStateTransformDiff( CRTransformBits *t, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx ) +{ + const GLuint maxTextureUnits = toCtx->limits.maxTextureUnits; + CRTransformState *from = &(fromCtx->transform); + CRTransformState *to = &(toCtx->transform); + CRTextureState *textureFrom = &(fromCtx->texture); + GLuint i, j; + unsigned int checktex = 0; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + + for (j=0;j<CR_MAX_BITARRAY;j++) + nbitID[j] = ~bitID[j]; + + if (CHECKDIRTY(t->enable, bitID)) { + glAble able[2]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + for (i=0; i<CR_MAX_CLIP_PLANES; i++) { + if (from->clip[i] != to->clip[i]) { + if (to->clip[i] == GL_TRUE) + diff_api.Enable(GL_CLIP_PLANE0 + i); + else + diff_api.Disable(GL_CLIP_PLANE0 + i); + from->clip[i] = to->clip[i]; + } + } + if (from->normalize != to->normalize) { + if (to->normalize == GL_TRUE) + diff_api.Enable(GL_NORMALIZE); + else + diff_api.Disable(GL_NORMALIZE); + from->normalize = to->normalize; + } +#ifdef CR_OPENGL_VERSION_1_2 + if (from->rescaleNormals != to->rescaleNormals) { + able[to->rescaleNormals](GL_RESCALE_NORMAL); + from->rescaleNormals = to->rescaleNormals; + } +#else + (void) able; +#endif +#ifdef CR_IBM_rasterpos_clip + if (from->rasterPositionUnclipped != to->rasterPositionUnclipped) { + able[to->rasterPositionUnclipped](GL_RASTER_POSITION_UNCLIPPED_IBM); + from->rasterPositionUnclipped = to->rasterPositionUnclipped; + } +#endif + + CLEARDIRTY(t->enable, nbitID); + } + + if (CHECKDIRTY(t->clipPlane, bitID)) { + if (from->matrixMode != GL_MODELVIEW) { + diff_api.MatrixMode(GL_MODELVIEW); + from->matrixMode = GL_MODELVIEW; + } + diff_api.PushMatrix(); + diff_api.LoadIdentity(); + for (i=0; i<CR_MAX_CLIP_PLANES; i++) { + if (from->clipPlane[i].x != to->clipPlane[i].x || + from->clipPlane[i].y != to->clipPlane[i].y || + from->clipPlane[i].z != to->clipPlane[i].z || + from->clipPlane[i].w != to->clipPlane[i].w) { + + GLdouble cp[4]; + cp[0] = to->clipPlane[i].x; + cp[1] = to->clipPlane[i].y; + cp[2] = to->clipPlane[i].z; + cp[3] = to->clipPlane[i].w; + + diff_api.ClipPlane(GL_CLIP_PLANE0 + i, (const GLdouble *)(cp)); + from->clipPlane[i] = to->clipPlane[i]; + } + } + diff_api.PopMatrix(); + CLEARDIRTY(t->clipPlane, nbitID); + } + + /* If the matrix stack depths don't match when we're + * updating the context - we can update the wrong matrix + * and get some lovely effects!! + * So we troll each depth list here and Pop & Push the matrix stack + * to bring it right up to date before checking the current + * matrix. + * + * - Alan H. + */ + if ( (from->modelViewStack.depth != to->modelViewStack.depth) || + CHECKDIRTY(t->modelviewMatrix, bitID) ) + { + if (from->matrixMode != GL_MODELVIEW) { + diff_api.MatrixMode(GL_MODELVIEW); + from->matrixMode = GL_MODELVIEW; + } + + if (from->modelViewStack.depth > to->modelViewStack.depth) + { + for (i = to->modelViewStack.depth; i < from->modelViewStack.depth; i++) + { + diff_api.PopMatrix(); + } + + from->modelViewStack.depth = to->modelViewStack.depth; + } + + for (i = from->modelViewStack.depth; i <= to->modelViewStack.depth; i++) + { + LOADMATRIX(to->modelViewStack.stack + i); + from->modelViewStack.stack[i] = to->modelViewStack.stack[i]; + + /* Don't want to push on the current matrix */ + if (i != to->modelViewStack.depth) + diff_api.PushMatrix(); + } + from->modelViewStack.depth = to->modelViewStack.depth; + from->modelViewStack.top = from->modelViewStack.stack + from->modelViewStack.depth; + + CLEARDIRTY(t->modelviewMatrix, nbitID); + } + + /* Projection matrix */ + if ( (from->projectionStack.depth != to->projectionStack.depth) || + CHECKDIRTY(t->projectionMatrix, bitID) ) + { + if (from->matrixMode != GL_PROJECTION) { + diff_api.MatrixMode(GL_PROJECTION); + from->matrixMode = GL_PROJECTION; + } + + if (from->projectionStack.depth > to->projectionStack.depth) + { + for (i = to->projectionStack.depth; i < from->projectionStack.depth; i++) + { + diff_api.PopMatrix(); + } + + from->projectionStack.depth = to->projectionStack.depth; + } + + for (i = from->projectionStack.depth; i <= to->projectionStack.depth; i++) + { + LOADMATRIX(to->projectionStack.stack + i); + from->projectionStack.stack[i] = to->projectionStack.stack[i]; + + /* Don't want to push on the current matrix */ + if (i != to->projectionStack.depth) + diff_api.PushMatrix(); + } + from->projectionStack.depth = to->projectionStack.depth; + from->projectionStack.top = from->projectionStack.stack + from->projectionStack.depth; + + CLEARDIRTY(t->projectionMatrix, nbitID); + } + + /* Texture matrices */ + for (i = 0 ; i < maxTextureUnits ; i++) + if (from->textureStack[i].depth != to->textureStack[i].depth) + checktex = 1; + + if (checktex || CHECKDIRTY(t->textureMatrix, bitID)) + { + if (from->matrixMode != GL_TEXTURE) { + diff_api.MatrixMode(GL_TEXTURE); + from->matrixMode = GL_TEXTURE; + } + for (j = 0 ; j < maxTextureUnits; j++) + { + if (from->textureStack[j].depth > to->textureStack[j].depth) + { + if (textureFrom->curTextureUnit != j) { + diff_api.ActiveTextureARB( j + GL_TEXTURE0_ARB ); + textureFrom->curTextureUnit = j; + } + for (i = to->textureStack[j].depth; i < from->textureStack[j].depth; i++) + { + diff_api.PopMatrix(); + } + + from->textureStack[j].depth = to->textureStack[j].depth; + } + + for (i = from->textureStack[j].depth; i <= to->textureStack[j].depth; i++) + { + if (textureFrom->curTextureUnit != j) { + diff_api.ActiveTextureARB( j + GL_TEXTURE0_ARB ); + textureFrom->curTextureUnit = j; + } + LOADMATRIX(to->textureStack[j].stack + i); + from->textureStack[j].stack[i] = to->textureStack[j].stack[i]; + + /* Don't want to push on the current matrix */ + if (i != to->textureStack[j].depth) + diff_api.PushMatrix(); + } + from->textureStack[j].depth = to->textureStack[j].depth; + from->textureStack[j].top = from->textureStack[j].stack + from->textureStack[j].depth; + } + CLEARDIRTY(t->textureMatrix, nbitID); + + /* Restore proper active texture unit */ + diff_api.ActiveTextureARB(GL_TEXTURE0_ARB + toCtx->texture.curTextureUnit); + } + + /* Color matrix */ + if ( (from->colorStack.depth != to->colorStack.depth) || + CHECKDIRTY(t->colorMatrix, bitID) ) + { + if (from->matrixMode != GL_COLOR) { + diff_api.MatrixMode(GL_COLOR); + from->matrixMode = GL_COLOR; + } + + if (from->colorStack.depth > to->colorStack.depth) + { + for (i = to->colorStack.depth; i < from->colorStack.depth; i++) + { + diff_api.PopMatrix(); + } + + from->colorStack.depth = to->colorStack.depth; + } + + for (i = to->colorStack.depth; i <= to->colorStack.depth; i++) + { + LOADMATRIX(to->colorStack.stack + i); + from->colorStack.stack[i] = to->colorStack.stack[i]; + + /* Don't want to push on the current matrix */ + if (i != to->colorStack.depth) + diff_api.PushMatrix(); + } + from->colorStack.depth = to->colorStack.depth; + from->colorStack.top = from->colorStack.stack + from->colorStack.depth; + + CLEARDIRTY(t->colorMatrix, nbitID); + } + + to->modelViewProjectionValid = 0; + CLEARDIRTY(t->dirty, nbitID); + + /* update MatrixMode now */ + if (from->matrixMode != to->matrixMode) { + diff_api.MatrixMode(to->matrixMode); + from->matrixMode = to->matrixMode; + } + + /* sanity tests */ + CRASSERT(from->modelViewStack.top == from->modelViewStack.stack + from->modelViewStack.depth); + CRASSERT(from->projectionStack.top == from->projectionStack.stack + from->projectionStack.depth); +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_viewport.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_viewport.c new file mode 100644 index 00000000..e238f9ae --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_viewport.c @@ -0,0 +1,166 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include <stdio.h> +#include "state.h" +#include "state/cr_statetypes.h" +#include "state_internals.h" + +void crStateViewportInit(CRContext *ctx) +{ + CRViewportState *v = &ctx->viewport; + CRStateBits *sb = GetCurrentBits(); + CRViewportBits *vb = &(sb->viewport); + CRTransformBits *tb = &(sb->transform); + + v->scissorTest = GL_FALSE; + RESET(vb->enable, ctx->bitid); + + v->viewportValid = GL_FALSE; + v->viewportX = 0; + v->viewportY = 0; + /* These are defaults, the tilesort spu overrides when + * the context has been created */ + v->viewportW = 640; + v->viewportH = 480; + RESET(vb->v_dims, ctx->bitid); + + v->scissorValid = GL_FALSE; + v->scissorX = 0; + v->scissorY = 0; + /* These are defaults, the tilesort spu overrides when + * the context has been created */ + v->scissorW = 640; + v->scissorH = 480; + RESET(vb->s_dims, ctx->bitid); + + v->farClip = 1.0; + v->nearClip = 0.0; + RESET(vb->depth, ctx->bitid); + + RESET(vb->dirty, ctx->bitid); + + /* XXX why are these here? */ + RESET(tb->base, ctx->bitid); + RESET(tb->dirty, ctx->bitid); +} + +void crStateViewportApply(CRViewportState *v, GLvectorf *p) +{ + p->x = (p->x+1.0f)*(v->viewportW / 2.0f) + v->viewportX; + p->y = (p->y+1.0f)*(v->viewportH / 2.0f) + v->viewportY; + p->z = (GLfloat) ((p->z+1.0f)*((v->farClip - v->nearClip) / 2.0f) + v->nearClip); +} + +void STATE_APIENTRY crStateViewport(GLint x, GLint y, GLsizei width, + GLsizei height) +{ + CRContext *g = GetCurrentContext(); + CRViewportState *v = &(g->viewport); + CRStateBits *sb = GetCurrentBits(); + CRViewportBits *vb = &(sb->viewport); + CRTransformBits *tb = &(sb->transform); + + if (g->current.inBeginEnd) + { + crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, + "calling glViewport() between glBegin/glEnd" ); + return; + } + + FLUSH(); + + if (width < 0 || height < 0) + { + crStateError( __LINE__, __FILE__, GL_INVALID_VALUE, + "glViewport(bad width or height)" ); + return; + } + + if (x > g->limits.maxViewportDims[0]) x = g->limits.maxViewportDims[0]; + if (x < -g->limits.maxViewportDims[0]) x = -g->limits.maxViewportDims[0]; + if (y > g->limits.maxViewportDims[1]) y = g->limits.maxViewportDims[1]; + if (y < -g->limits.maxViewportDims[1]) y = -g->limits.maxViewportDims[1]; + if (width > g->limits.maxViewportDims[0]) width = g->limits.maxViewportDims[0]; + if (height > g->limits.maxViewportDims[1]) height = g->limits.maxViewportDims[1]; + + v->viewportX = (GLint) (x); + v->viewportY = (GLint) (y); + v->viewportW = (GLint) (width); + v->viewportH = (GLint) (height); + + v->viewportValid = GL_TRUE; + + DIRTY(vb->v_dims, g->neg_bitid); + DIRTY(vb->dirty, g->neg_bitid); + /* XXX why are these here? */ + DIRTY(tb->base, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateDepthRange(GLclampd znear, GLclampd zfar) +{ + CRContext *g = GetCurrentContext(); + CRViewportState *v = &(g->viewport); + CRStateBits *sb = GetCurrentBits(); + CRViewportBits *vb = &(sb->viewport); + CRTransformBits *tb = &(sb->transform); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glDepthRange called in Begin/End"); + return; + } + + FLUSH(); + + v->nearClip = znear; + v->farClip = zfar; + if (v->nearClip < 0.0) v->nearClip = 0.0; + if (v->nearClip > 1.0) v->nearClip = 1.0; + if (v->farClip < 0.0) v->farClip = 0.0; + if (v->farClip > 1.0) v->farClip = 1.0; + + DIRTY(vb->depth, g->neg_bitid); + DIRTY(vb->dirty, g->neg_bitid); + DIRTY(tb->dirty, g->neg_bitid); +} + +void STATE_APIENTRY crStateScissor (GLint x, GLint y, + GLsizei width, GLsizei height) +{ + CRContext *g = GetCurrentContext(); + CRViewportState *v = &(g->viewport); + CRStateBits *sb = GetCurrentBits(); + CRViewportBits *vb = &(sb->viewport); + + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glScissor called in begin/end"); + return; + } + + FLUSH(); + + if (width < 0 || height < 0) + { + crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, + "glScissor called with negative width/height: %d,%d", + width, height); + return; + } + + v->scissorX = (GLint) (x); + v->scissorY = (GLint) (y); + v->scissorW = (GLint) (width); + v->scissorH = (GLint) (height); + + v->scissorValid = GL_TRUE; + + DIRTY(vb->s_dims, g->neg_bitid); + DIRTY(vb->dirty, g->neg_bitid); +} diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_viewport.txt b/src/VBox/GuestHost/OpenGL/state_tracker/state_viewport.txt new file mode 100644 index 00000000..f2857d25 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_viewport.txt @@ -0,0 +1,14 @@ +# Copyright (c) 2001, Stanford University +# All rights reserved. +# +# See the file LICENSE.txt for information on redistributing this software. +:enable:scissorTest:GL_SCISSOR_TEST +:s_dims:scissorX,scissorY,scissorW,scissorH:Scissor +#+scissorTest:s_dims:*CRrecti p; +#+scissorTest:s_dims:scissorX,scissorY,scissorW,scissorH:*diff_api.Scissor(p.x1, p.y1, p.x2-p.x1, p.y2-p.y1); +#-scissorTest:s_dims:scissorX,scissorY,scissorW,scissorH:Scissor +#+:v_dims:*CRrecti p; +#+:v_dims:viewportX,viewportY,viewportW,viewportH:*diff_api.Viewport(p.x1, p.y1, p.x2-p.x1, p.y2-p.y1); +:v_dims:viewportX,viewportY,viewportW,viewportH:Viewport +#-:v_dims:viewportX,viewportY,viewportW,viewportH:Viewport +:depth:nearClip,farClip:DepthRange |