/* 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); CRClientState *c = &(g->client); CRTextureObj *tobj; CRTextureLevel *tl; CRStateBits *sb = GetCurrentBits(); CRTextureBits *tb = &(sb->texture); 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; crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl); CRASSERT(tobj); CRASSERT(tl); 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); CRClientState *c = &(g->client); CRTextureObj *tobj = NULL; CRTextureLevel *tl = NULL; CRStateBits *sb = GetCurrentBits(); CRTextureBits *tb = &(sb->texture); const int is_distrib = ((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); CRClientState *c = &(g->client); CRTextureObj *tobj = NULL; CRTextureLevel *tl = NULL; CRStateBits *sb = GetCurrentBits(); CRTextureBits *tb = &(sb->texture); 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); CRClientState *c = &(g->client); CRStateBits *sb = GetCurrentBits(); CRTextureBits *tb = &(sb->texture); CRTextureUnit *unit = t->unit + t->curTextureUnit; CRTextureObj *tobj = unit->currentTexture1D; CRTextureLevel *tl = tobj->level[0] + level; 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(); CRClientState *c = &(g->client); CRStateBits *sb = GetCurrentBits(); CRTextureBits *tb = &(sb->texture); CRTextureObj *tobj; CRTextureLevel *tl; GLubyte *subimg = NULL; GLubyte *img = NULL; #ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE GLubyte *src; int i; #endif 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); CRClientState *c = &(g->client); CRStateBits *sb = GetCurrentBits(); CRTextureBits *tb = &(sb->texture); CRTextureUnit *unit = t->unit + t->curTextureUnit; CRTextureObj *tobj = unit->currentTexture3D; CRTextureLevel *tl = tobj->level[0] + level; GLubyte *subimg = NULL; GLubyte *img = NULL; #ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE GLubyte *src; int i; #endif 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); 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); 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); 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; 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; 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; 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(); CRClientState *c = &(g->client); 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 }