summaryrefslogtreecommitdiffstats
path: root/src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
commitf8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch)
tree26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c
parentInitial commit. (diff)
downloadvirtualbox-upstream.tar.xz
virtualbox-upstream.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/state_teximage.c')
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c1762
1 files changed, 1762 insertions, 0 deletions
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
+}