static textypeinfo_t textype_bgra_alpha = {TEXTYPE_BGRA , 4, 4, 4.0f, GL_BGRA , 4, GL_UNSIGNED_BYTE};
static textypeinfo_t textype_bgra_compress = {TEXTYPE_BGRA , 4, 4, 0.5f, GL_BGRA , GL_COMPRESSED_RGB_ARB, GL_UNSIGNED_BYTE};
static textypeinfo_t textype_bgra_alpha_compress = {TEXTYPE_BGRA , 4, 4, 1.0f, GL_BGRA , GL_COMPRESSED_RGBA_ARB, GL_UNSIGNED_BYTE};
-static textypeinfo_t textype_shadowmap = {TEXTYPE_SHADOWMAP,4,4, 4.0f, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT24_ARB, GL_UNSIGNED_INT};
-static textypeinfo_t textype_projection = {TEXTYPE_PROJECTION,4,4,4.0f, GL_LUMINANCE_ALPHA, GL_LUMINANCE16_ALPHA16, GL_UNSIGNED_SHORT};
+static textypeinfo_t textype_shadowmap16 = {TEXTYPE_SHADOWMAP,2,2, 2.0f, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT16_ARB, GL_UNSIGNED_SHORT};
+static textypeinfo_t textype_shadowmap24 = {TEXTYPE_SHADOWMAP,4,4, 4.0f, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT24_ARB, GL_UNSIGNED_INT};
typedef enum gltexturetype_e
{
- GLTEXTURETYPE_1D,
GLTEXTURETYPE_2D,
GLTEXTURETYPE_3D,
GLTEXTURETYPE_CUBEMAP,
}
gltexturetype_t;
-static int gltexturetypeenums[GLTEXTURETYPE_TOTAL] = {GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_RECTANGLE_ARB};
-static int gltexturetypebindingenums[GLTEXTURETYPE_TOTAL] = {GL_TEXTURE_BINDING_1D, GL_TEXTURE_BINDING_2D, GL_TEXTURE_BINDING_3D, GL_TEXTURE_BINDING_CUBE_MAP_ARB, GL_TEXTURE_BINDING_RECTANGLE_ARB};
-static int gltexturetypedimensions[GLTEXTURETYPE_TOTAL] = {1, 2, 3, 2, 2};
+static int gltexturetypeenums[GLTEXTURETYPE_TOTAL] = {GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_RECTANGLE_ARB};
+static int gltexturetypebindingenums[GLTEXTURETYPE_TOTAL] = {GL_TEXTURE_BINDING_2D, GL_TEXTURE_BINDING_3D, GL_TEXTURE_BINDING_CUBE_MAP_ARB, GL_TEXTURE_BINDING_RECTANGLE_ARB};
+static int gltexturetypedimensions[GLTEXTURETYPE_TOTAL] = {2, 3, 2, 2};
static int cubemapside[6] =
{
GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
// palette if the texture is TEXTYPE_PALETTE
const unsigned int *palette;
// actual stored texture size after gl_picmip and gl_max_size are applied
- // (power of 2 if gl_support_arb_texture_non_power_of_two is not supported)
+ // (power of 2 if vid.support.arb_texture_non_power_of_two is not supported)
int tilewidth, tileheight, tiledepth;
// 1 or 6 depending on texturetype
int sides;
static textypeinfo_t *R_GetTexTypeInfo(textype_t textype, int flags)
{
- if ((flags & TEXF_COMPRESS) && gl_texturecompression.integer >= 1 && gl_support_texture_compression)
+ if ((flags & TEXF_COMPRESS) && gl_texturecompression.integer >= 1 && vid.support.arb_texture_compression)
{
if (flags & TEXF_ALPHA)
{
case TEXTYPE_BGRA:
return &textype_bgra;
case TEXTYPE_SHADOWMAP:
- return &textype_shadowmap;
- case TEXTYPE_PROJECTION:
- return &textype_projection;
+ return (flags & TEXF_LOWPRECISION) ? &textype_shadowmap16 : &textype_shadowmap24;
default:
Host_Error("R_GetTexTypeInfo: unknown texture format");
return NULL;
}
}
-static void R_UploadTexture(gltexture_t *t);
-
-static void R_PrecacheTexture(gltexture_t *glt)
-{
- int precache;
- precache = false;
- if (glt->flags & TEXF_ALWAYSPRECACHE)
- precache = true;
- else if (r_precachetextures.integer >= 2)
- precache = true;
- else if (r_precachetextures.integer >= 1)
- if (glt->flags & TEXF_PRECACHE)
- precache = true;
-
- if (precache)
- R_UploadTexture(glt);
-}
-
-int R_RealGetTexture(rtexture_t *rt)
-{
- if (rt)
- {
- gltexture_t *glt;
- glt = (gltexture_t *)rt;
- if (glt->flags & GLTEXF_DYNAMIC)
- R_UpdateDynamicTexture(glt);
- if (glt->flags & GLTEXF_UPLOAD)
- R_UploadTexture(glt);
-
- return glt->texnum;
- }
- else
- return 0;
-}
-
void R_PurgeTexture(rtexture_t *rt)
{
if(rt && !(((gltexture_t*) rt)->flags & TEXF_PERSISTENT)) {
{
int picmip = 0, maxsize = 0, width2 = 1, height2 = 1, depth2 = 1;
- if (gl_max_size.integer > gl_max_texture_size)
- Cvar_SetValue("gl_max_size", gl_max_texture_size);
+ if (gl_max_size.integer > (int)vid.maxtexturesize_2d)
+ Cvar_SetValue("gl_max_size", vid.maxtexturesize_2d);
switch (texturetype)
{
default:
- case GLTEXTURETYPE_1D:
case GLTEXTURETYPE_2D:
- maxsize = gl_max_texture_size;
+ maxsize = vid.maxtexturesize_2d;
break;
case GLTEXTURETYPE_3D:
- maxsize = gl_max_3d_texture_size;
+ maxsize = vid.maxtexturesize_3d;
break;
case GLTEXTURETYPE_CUBEMAP:
- maxsize = gl_max_cube_map_texture_size;
+ maxsize = vid.maxtexturesize_cubemap;
break;
}
if (outwidth)
{
- if (gl_support_arb_texture_non_power_of_two)
+ if (vid.support.arb_texture_non_power_of_two)
width2 = min(inwidth >> picmip, maxsize);
else
{
}
if (outheight)
{
- if (gl_support_arb_texture_non_power_of_two)
+ if (vid.support.arb_texture_non_power_of_two)
height2 = min(inheight >> picmip, maxsize);
else
{
}
if (outdepth)
{
- if (gl_support_arb_texture_non_power_of_two)
+ if (vid.support.arb_texture_non_power_of_two)
depth2 = min(indepth >> picmip, maxsize);
else
{
gltexturepool_t *pool;
GLint oldbindtexnum;
- old_aniso = bound(1, gl_texture_anisotropy.integer, gl_max_anisotropy);
+ old_aniso = bound(1, gl_texture_anisotropy.integer, (int)vid.max_anisotropy);
Cvar_SetValueQuick(&gl_texture_anisotropy, old_aniso);
static void GL_SetupTextureParameters(int flags, textype_t textype, int texturetype)
{
int textureenum = gltexturetypeenums[texturetype];
- int wrapmode = ((flags & TEXF_CLAMP) && gl_support_clamptoedge) ? GL_CLAMP_TO_EDGE : GL_REPEAT;
+ int wrapmode = (flags & TEXF_CLAMP) ? GL_CLAMP_TO_EDGE : GL_REPEAT;
CHECKGLERROR
- if (gl_support_anisotropy && (flags & TEXF_MIPMAP))
+ if (vid.support.ext_texture_filter_anisotropic && (flags & TEXF_MIPMAP))
{
- int aniso = bound(1, gl_texture_anisotropy.integer, gl_max_anisotropy);
+ int aniso = bound(1, gl_texture_anisotropy.integer, (int)vid.max_anisotropy);
if (gl_texture_anisotropy.integer != aniso)
Cvar_SetValueQuick(&gl_texture_anisotropy, aniso);
qglTexParameteri(textureenum, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);CHECKGLERROR
if (textype == TEXTYPE_SHADOWMAP)
{
- if (flags & TEXF_COMPARE)
- {
- qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);CHECKGLERROR
- }
- else
+ if (vid.support.arb_shadow)
{
- qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);CHECKGLERROR
+ if (flags & TEXF_COMPARE)
+ {
+ qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);CHECKGLERROR
+ }
+ else
+ {
+ qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);CHECKGLERROR
+ }
+ qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);CHECKGLERROR
}
- qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);CHECKGLERROR
qglTexParameteri(textureenum, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);CHECKGLERROR
}
qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
// these are rounded up versions of the size to do better resampling
- if (gl_support_arb_texture_non_power_of_two || glt->texturetype == GLTEXTURETYPE_RECTANGLE)
+ if (vid.support.arb_texture_non_power_of_two || glt->texturetype == GLTEXTURETYPE_RECTANGLE)
{
width = glt->inputwidth;
height = glt->inputheight;
// update a portion of the image
switch(glt->texturetype)
{
- case GLTEXTURETYPE_1D:
- qglTexSubImage1D(GL_TEXTURE_1D, 0, fragx, fragwidth, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
- break;
case GLTEXTURETYPE_2D:
qglTexSubImage2D(GL_TEXTURE_2D, 0, fragx, fragy, fragwidth, fragheight, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
break;
qglTexSubImage3D(GL_TEXTURE_3D, 0, fragx, fragy, fragz, fragwidth, fragheight, fragdepth, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
break;
default:
- Host_Error("R_Upload: partial update of type other than 1D, 2D, or 3D");
+ Host_Error("R_Upload: partial update of type other than 2D");
break;
}
}
}
}
mip = 0;
- if (gl_support_texture_compression)
+ if (vid.support.arb_texture_compression)
{
if (gl_texturecompression.integer >= 2)
qglHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_NICEST);
}
switch(glt->texturetype)
{
- case GLTEXTURETYPE_1D:
- qglTexImage1D(GL_TEXTURE_1D, mip++, glt->glinternalformat, width, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
- if (glt->flags & TEXF_MIPMAP)
- {
- while (width > 1 || height > 1 || depth > 1)
- {
- Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
- prevbuffer = resizebuffer;
- qglTexImage1D(GL_TEXTURE_1D, mip++, glt->glinternalformat, width, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
- }
- }
- break;
case GLTEXTURETYPE_2D:
qglTexImage2D(GL_TEXTURE_2D, mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
if (glt->flags & TEXF_MIPMAP)
qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
}
-static void R_UploadTexture (gltexture_t *glt)
+int R_RealGetTexture(rtexture_t *rt)
{
- if (!(glt->flags & GLTEXF_UPLOAD))
- return;
-
- CHECKGLERROR
- qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
- R_Upload(glt, glt->inputtexels, 0, 0, 0, glt->inputwidth, glt->inputheight, glt->inputdepth);
- if (glt->inputtexels)
+ if (rt)
{
- Mem_Free(glt->inputtexels);
- glt->inputtexels = NULL;
- glt->flags |= GLTEXF_DESTROYED;
+ gltexture_t *glt;
+ glt = (gltexture_t *)rt;
+ if (glt->flags & GLTEXF_DYNAMIC)
+ R_UpdateDynamicTexture(glt);
+ if (glt->flags & GLTEXF_UPLOAD)
+ {
+ CHECKGLERROR
+ qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
+ R_Upload(glt, glt->inputtexels, 0, 0, 0, glt->inputwidth, glt->inputheight, glt->inputdepth);
+ if (glt->inputtexels)
+ {
+ Mem_Free(glt->inputtexels);
+ glt->inputtexels = NULL;
+ glt->flags |= GLTEXF_DESTROYED;
+ }
+ else if (glt->flags & GLTEXF_DESTROYED)
+ Con_Printf("R_GetTexture: Texture %s already uploaded and destroyed. Can not upload original image again. Uploaded blank texture.\n", glt->identifier);
+ }
+
+ return glt->texnum;
}
- else if (glt->flags & GLTEXF_DESTROYED)
- Con_Printf("R_UploadTexture: Texture %s already uploaded and destroyed. Can not upload original image again. Uploaded blank texture.\n", glt->identifier);
+ else
+ return 0;
}
static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int depth, int sides, int flags, textype_t textype, int texturetype, const unsigned char *data, const unsigned int *palette)
gltexture_t *glt;
gltexturepool_t *pool = (gltexturepool_t *)rtexturepool;
textypeinfo_t *texinfo;
+ int precache;
if (cls.state == ca_dedicated)
return NULL;
- if (texturetype == GLTEXTURETYPE_RECTANGLE && !gl_texturerectangle)
+ if (texturetype == GLTEXTURETYPE_RECTANGLE && !vid.support.arb_texture_rectangle)
{
Con_Printf ("R_LoadTexture: rectangle texture not supported by driver\n");
return NULL;
}
- if (texturetype == GLTEXTURETYPE_CUBEMAP && !gl_texturecubemap)
+ if (texturetype == GLTEXTURETYPE_CUBEMAP && !vid.support.arb_texture_cube_map)
{
Con_Printf ("R_LoadTexture: cubemap texture not supported by driver\n");
return NULL;
}
- if (texturetype == GLTEXTURETYPE_3D && !gl_texture3d)
+ if (texturetype == GLTEXTURETYPE_3D && !vid.support.ext_texture_3d)
{
Con_Printf ("R_LoadTexture: 3d texture not supported by driver\n");
return NULL;
}
break;
case TEXTYPE_SHADOWMAP:
- case TEXTYPE_PROJECTION:
break;
default:
Host_Error("R_LoadTexture: unknown texture type");
glt->updatecallback = NULL;
glt->updatacallback_data = NULL;
- if (data)
+ GL_Texture_CalcImageSize(glt->texturetype, glt->flags, glt->inputwidth, glt->inputheight, glt->inputdepth, &glt->tilewidth, &glt->tileheight, &glt->tiledepth);
+
+ precache = false;
+ if (glt->flags & TEXF_ALWAYSPRECACHE)
+ precache = true;
+ else if (r_precachetextures.integer >= 2)
+ precache = true;
+ else if (r_precachetextures.integer >= 1)
+ if (glt->flags & TEXF_PRECACHE)
+ precache = true;
+
+ if (precache)
{
- glt->inputtexels = (unsigned char *)Mem_Alloc(texturemempool, size);
- memcpy(glt->inputtexels, data, size);
+ // immediate upload (most common case)
+ // data may be NULL (blank texture for dynamic rendering)
+ CHECKGLERROR
+ qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
+ R_Upload(glt, data, 0, 0, 0, glt->inputwidth, glt->inputheight, glt->inputdepth);
+ }
+ else if (data)
+ {
+ // deferred texture upload (menu graphics)
+ // optimize first if possible
+ if ((textype == TEXTYPE_BGRA || textype == TEXTYPE_RGBA) && glt->inputwidth * glt->inputheight * glt->inputdepth > glt->tilewidth * glt->tileheight * glt->tiledepth)
+ {
+ glt->inputtexels = (unsigned char *)Mem_Alloc(texturemempool, glt->tilewidth*glt->tileheight*glt->tiledepth*glt->sides*glt->bytesperpixel);
+ Image_Resample32(data, glt->inputwidth, glt->inputheight, glt->inputdepth, glt->inputtexels, glt->tilewidth, glt->tileheight, glt->tiledepth, r_lerpimages.integer);
+ // change texture size accordingly
+ glt->inputwidth = glt->tilewidth;
+ glt->inputheight = glt->tileheight;
+ glt->inputdepth = glt->tiledepth;
+ GL_Texture_CalcImageSize(glt->texturetype, glt->flags, glt->inputwidth, glt->inputheight, glt->inputdepth, &glt->tilewidth, &glt->tileheight, &glt->tiledepth);
+ }
+ else
+ {
+ glt->inputtexels = (unsigned char *)Mem_Alloc(texturemempool, size);
+ memcpy(glt->inputtexels, data, size);
+ }
}
- else
- glt->inputtexels = NULL;
-
- GL_Texture_CalcImageSize(glt->texturetype, glt->flags, glt->inputwidth, glt->inputheight, glt->inputdepth, &glt->tilewidth, &glt->tileheight, &glt->tiledepth);
- R_PrecacheTexture(glt);
// texture converting and uploading can take a while, so make sure we're sending keepalives
CL_KeepaliveMessage(false);
return (rtexture_t *)glt;
}
-rtexture_t *R_LoadTexture1D(rtexturepool_t *rtexturepool, const char *identifier, int width, const unsigned char *data, textype_t textype, int flags, const unsigned int *palette)
-{
- return R_SetupTexture(rtexturepool, identifier, width, 1, 1, 1, flags, textype, GLTEXTURETYPE_1D, data, palette);
-}
-
rtexture_t *R_LoadTexture2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, const unsigned char *data, textype_t textype, int flags, const unsigned int *palette)
{
return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, flags, textype, GLTEXTURETYPE_2D, data, palette);
return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, flags, textype, GLTEXTURETYPE_CUBEMAP, data, palette);
}
-rtexture_t *R_LoadTextureShadowMapRectangle(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, qboolean filter)
+static int R_ShadowMapTextureFlags(int precision, qboolean filter)
{
- return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, TEXF_ALWAYSPRECACHE | TEXF_CLAMP | (filter ? TEXF_FORCELINEAR | TEXF_COMPARE : TEXF_FORCENEAREST), TEXTYPE_SHADOWMAP, GLTEXTURETYPE_RECTANGLE, NULL, NULL);
+ int flags = TEXF_ALWAYSPRECACHE | TEXF_CLAMP;
+ if (filter)
+ flags |= TEXF_FORCELINEAR | TEXF_COMPARE;
+ else
+ flags |= TEXF_FORCENEAREST;
+ if (precision <= 16)
+ flags |= TEXF_LOWPRECISION;
+ return flags;
}
-rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, qboolean filter)
+rtexture_t *R_LoadTextureShadowMapRectangle(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int precision, qboolean filter)
{
- return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, TEXF_ALWAYSPRECACHE | TEXF_CLAMP | (filter ? TEXF_FORCELINEAR | TEXF_COMPARE : TEXF_FORCENEAREST), TEXTYPE_SHADOWMAP, GLTEXTURETYPE_2D, NULL, NULL);
+ return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, R_ShadowMapTextureFlags(precision, filter), TEXTYPE_SHADOWMAP, GLTEXTURETYPE_RECTANGLE, NULL, NULL);
}
-rtexture_t *R_LoadTextureShadowMapCube(rtexturepool_t *rtexturepool, const char *identifier, int width, qboolean filter)
+rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int precision, qboolean filter)
{
- return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, TEXF_ALWAYSPRECACHE | TEXF_CLAMP | (filter ? TEXF_FORCELINEAR | TEXF_COMPARE : TEXF_FORCENEAREST), TEXTYPE_SHADOWMAP, GLTEXTURETYPE_CUBEMAP, NULL, NULL);
+ return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, R_ShadowMapTextureFlags(precision, filter), TEXTYPE_SHADOWMAP, GLTEXTURETYPE_2D, NULL, NULL);
}
-rtexture_t *R_LoadTextureCubeProjection(rtexturepool_t *rtexturepool, const char *identifier, int size, int border)
+rtexture_t *R_LoadTextureShadowMapCube(rtexturepool_t *rtexturepool, const char *identifier, int width, int precision, qboolean filter)
{
- // maps to a 2x3 texture rectangle with normalized coordinates (must be scaled by size after lookup)
- // +-
- // XX
- // YY
- // ZZ
- rtexture_t *projection;
- unsigned short *data, *texel;
- unsigned int sizebits = 0, stepbits = 0, res, i, j, k;
- while ((1 << sizebits) < size) sizebits++;
- while ((1 << stepbits) <= border) stepbits++;
- stepbits = min(stepbits, sizebits);
- res = size>>stepbits;
- stepbits += 16 - sizebits - 1;
- data = (unsigned short *)Mem_Alloc(texturemempool, 2*sizeof(unsigned short)*res*res*6);
- texel = data;
- for (i = 0;i < 6;i++)
- {
- unsigned int x = (i%2)<<16, y = (i/2)<<16;
- for (j = 0;j < res;j++)
- {
- for (k = 0;k < res;k++)
- {
- *texel++ = (x + ((2*k + 1)<<stepbits))/2;
- *texel++ = (y + ((2*j + 1)<<stepbits))/3;
- }
- }
- }
- projection = R_SetupTexture(rtexturepool, identifier, res, res, 1, 6, TEXF_ALWAYSPRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, TEXTYPE_PROJECTION, GLTEXTURETYPE_CUBEMAP, (unsigned char *)data, NULL);
- Mem_Free(data);
- return projection;
-}
-
-int R_TextureHasAlpha(rtexture_t *rt)
-{
- return rt ? (((gltexture_t *)rt)->flags & TEXF_ALPHA) != 0 : false;
+ return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, R_ShadowMapTextureFlags(precision, filter), TEXTYPE_SHADOWMAP, GLTEXTURETYPE_CUBEMAP, NULL, NULL);
}
int R_TextureWidth(rtexture_t *rt)
void R_UpdateTexture(rtexture_t *rt, const unsigned char *data, int x, int y, int width, int height)
{
- gltexture_t *glt;
- if (rt == NULL)
- Host_Error("R_UpdateTexture: no texture supplied");
+ gltexture_t *glt = (gltexture_t *)rt;
if (data == NULL)
Host_Error("R_UpdateTexture: no data supplied");
- glt = (gltexture_t *)rt;
-
- // we need it to be uploaded before we can update a part of it
- if (glt->flags & GLTEXF_UPLOAD)
- R_UploadTexture(glt);
-
+ if (glt == NULL)
+ Host_Error("R_UpdateTexture: no texture supplied");
+ if (!glt->texnum)
+ Host_Error("R_UpdateTexture: texture has not been uploaded yet");
// update part of the texture
R_Upload(glt, data, x, y, 0, width, height, 1);
}