[iortcw] 125/152: All: Rend2: Some tr_image refactoring/cleanup
Simon McVittie
smcv at debian.org
Fri Sep 8 10:40:23 UTC 2017
This is an automated email from the git hooks/post-receive script.
smcv pushed a commit to annotated tag 1.5a
in repository iortcw.
commit 16c7a9981583b437c58204c2d1c9b15b84f8cfec
Author: MAN-AT-ARMS <M4N4T4RMS at gmail.com>
Date: Sun Sep 25 06:03:23 2016 -0400
All: Rend2: Some tr_image refactoring/cleanup
---
MP/code/rend2/tr_image.c | 382 +++++++++++++++++++++++-----------------------
SP/code/rend2/tr_image.c | 385 +++++++++++++++++++++++------------------------
2 files changed, 375 insertions(+), 392 deletions(-)
diff --git a/MP/code/rend2/tr_image.c b/MP/code/rend2/tr_image.c
index 122e436..4e8b56f 100644
--- a/MP/code/rend2/tr_image.c
+++ b/MP/code/rend2/tr_image.c
@@ -1507,6 +1507,7 @@ static void R_MipMapNormalHeight (const byte *in, byte *out, int width, int heig
R_RMSE
================
*/
+#if 0 // FIXME
static float R_RMSE( byte *in, int width, int height ) {
int i, j;
float out, rmse, rtemp;
@@ -1546,6 +1547,7 @@ static float R_RMSE( byte *in, int width, int height ) {
rmse = sqrt( rmse / ( height * width * 4 ) );
return rmse;
}
+#endif
/*
@@ -1621,7 +1623,23 @@ static qboolean RawImage_ScaleToPower2( byte **data, int *inout_width, int *inou
qboolean picmip = flags & IMGFLAG_PICMIP;
qboolean mipmap = flags & IMGFLAG_MIPMAP;
qboolean clampToEdge = flags & IMGFLAG_CLAMPTOEDGE;
- qboolean notScaled;
+ qboolean scaled;
+#if 0
+ static int rmse_saved = 0;
+
+ // do the root mean square error stuff first
+ if ( r_rmse->value ) {
+ while ( R_RMSE( *data, width, height ) < r_rmse->value ) {
+ rmse_saved += ( height * width * 4 ) - ( ( width >> 1 ) * ( height >> 1 ) * 4 );
+ *resampledBuffer = ri.Hunk_AllocateTempMemory( ( width >> 1 ) * ( height >> 1 ) * 4 );
+ ResampleTexture( *data, width, height, *resampledBuffer, width >> 1, height >> 1 );
+ *data = *resampledBuffer;
+ width = width >> 1;
+ height = height >> 1;
+ ri.Printf( PRINT_ALL, "r_rmse of %f has saved %dkb\n", r_rmse->value, ( rmse_saved / 1024 ) );
+ }
+ }
+#endif
//
// convert to exact power of 2 sizes
@@ -1688,7 +1706,6 @@ static qboolean RawImage_ScaleToPower2( byte **data, int *inout_width, int *inou
else if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT)
FillInNormalizedZ(*resampledBuffer, *resampledBuffer, scaled_width, scaled_height);
-
//endTime = ri.Milliseconds();
//ri.Printf(PRINT_ALL, "upsampled %dx%d to %dx%d in %dms\n", width, height, scaled_width, scaled_height, endTime - startTime);
@@ -1733,7 +1750,7 @@ static qboolean RawImage_ScaleToPower2( byte **data, int *inout_width, int *inou
scaled_width = MAX(1, scaled_width);
scaled_height = MAX(1, scaled_height);
- notScaled = (width == scaled_width) && (height == scaled_height);
+ scaled = (width != scaled_width) || (height != scaled_height);
//
// rescale texture to new size using existing mipmap functions
@@ -1755,7 +1772,7 @@ static qboolean RawImage_ScaleToPower2( byte **data, int *inout_width, int *inou
*inout_width = width;
*inout_height = height;
- return notScaled;
+ return scaled;
}
@@ -1789,7 +1806,7 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, GLenum picForm
if(normalmap)
{
- if ((type == IMGTYPE_NORMALHEIGHT) && RawImage_HasAlpha(data, numPixels))
+ if ((type == IMGTYPE_NORMALHEIGHT) && RawImage_HasAlpha(data, numPixels) && r_parallaxMapping->integer)
{
if (!forceNoCompression && glRefConfig.textureCompression & TCR_BPTC)
{
@@ -1979,9 +1996,9 @@ static void CompressMonoBlock(byte outdata[8], const byte indata[16])
}
}
-static void RawImage_UploadToRgtc2Texture(GLuint texture, byte *data, int width, int height, int mip)
+static void RawImage_UploadToRgtc2Texture(GLuint texture, int miplevel, int x, int y, int width, int height, byte *data)
{
- int wBlocks, hBlocks, y, x, size;
+ int wBlocks, hBlocks, iy, ix, size;
byte *compressedData, *p;
wBlocks = (width + 3) / 4;
@@ -1989,16 +2006,16 @@ static void RawImage_UploadToRgtc2Texture(GLuint texture, byte *data, int width,
size = wBlocks * hBlocks * 16;
p = compressedData = ri.Hunk_AllocateTempMemory(size);
- for (y = 0; y < height; y += 4)
+ for (iy = 0; iy < height; iy += 4)
{
- int oh = MIN(4, height - y);
+ int oh = MIN(4, height - iy);
- for (x = 0; x < width; x += 4)
+ for (ix = 0; ix < width; ix += 4)
{
byte workingData[16];
int component;
- int ow = MIN(4, width - x);
+ int ow = MIN(4, width - ix);
for (component = 0; component < 2; component++)
{
@@ -2006,7 +2023,7 @@ static void RawImage_UploadToRgtc2Texture(GLuint texture, byte *data, int width,
for (oy = 0; oy < oh; oy++)
for (ox = 0; ox < ow; ox++)
- workingData[oy * 4 + ox] = data[((y + oy) * width + x + ox) * 4 + component];
+ workingData[oy * 4 + ox] = data[((iy + oy) * width + ix + ox) * 4 + component];
// dupe data to fill
for (oy = 0; oy < 4; oy++)
@@ -2019,7 +2036,8 @@ static void RawImage_UploadToRgtc2Texture(GLuint texture, byte *data, int width,
}
}
- qglCompressedTextureImage2DEXT(texture, GL_TEXTURE_2D, mip, GL_COMPRESSED_RG_RGTC2, width, height, 0, size, compressedData);
+ // FIXME: Won't work for x/y that aren't multiples of 4.
+ qglCompressedTextureSubImage2DEXT(texture, GL_TEXTURE_2D, miplevel, x, y, width, height, GL_COMPRESSED_RG_RGTC2, size, compressedData);
ri.Hunk_FreeTempMemory(compressedData);
}
@@ -2063,64 +2081,35 @@ static int CalculateMipSize(int width, int height, GLenum picFormat)
return 0;
}
-static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int width, int height, GLenum target, GLenum picFormat, int numMips, GLenum internalFormat, imgType_t type, imgFlags_t flags, qboolean subtexture )
-{
- int dataFormat, dataType;
- qboolean rgtc = (internalFormat == GL_COMPRESSED_RG_RGTC2);
- qboolean compressed = (!(picFormat == GL_RGBA8) || (picFormat == GL_SRGB8_ALPHA8_EXT));
- qboolean mipmap = !!(flags & IMGFLAG_MIPMAP);
- qboolean picmip = !!(flags & IMGFLAG_PICMIP);
- int size, miplevel;
- qboolean lastMip = qfalse;
+static GLenum PixelDataFormatFromInternalFormat(GLenum internalFormat)
+{
switch (internalFormat)
{
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16_ARB:
case GL_DEPTH_COMPONENT24_ARB:
case GL_DEPTH_COMPONENT32_ARB:
- dataFormat = GL_DEPTH_COMPONENT;
- dataType = GL_UNSIGNED_BYTE;
- break;
- case GL_RGBA16F_ARB:
- dataFormat = GL_RGBA;
- dataType = GL_HALF_FLOAT_ARB;
- break;
+ return GL_DEPTH_COMPONENT;
default:
- dataFormat = GL_RGBA;
- dataType = GL_UNSIGNED_BYTE;
+ return GL_RGBA;
break;
}
+}
- if (!data)
- {
- miplevel = 0;
- do
- {
- lastMip = (width == 1 && height == 1) || !mipmap;
- qglTextureImage2DEXT(texture, target, miplevel, internalFormat, width, height, 0, dataFormat, dataType, NULL);
+static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int width, int height, GLenum target, GLenum picFormat, int numMips, GLenum internalFormat, imgType_t type, imgFlags_t flags, qboolean subtexture )
+{
+ GLenum dataFormat, dataType;
+ qboolean rgtc = (internalFormat == GL_COMPRESSED_RG_RGTC2);
+ qboolean compressed = (!(picFormat == GL_RGBA8) || (picFormat == GL_SRGB8_ALPHA8_EXT));
+ qboolean mipmap = !!(flags & IMGFLAG_MIPMAP);
+ int size, miplevel;
+ qboolean lastMip = qfalse;
- width = MAX(1, width >> 1);
- height = MAX(1, height >> 1);
- miplevel++;
- }
- while (!lastMip);
+ dataFormat = PixelDataFormatFromInternalFormat(internalFormat);
- return;
- }
-
- if (compressed && picmip)
- {
- for (miplevel = r_picmip->integer; miplevel > 0 && numMips > 1; miplevel--, numMips--)
- {
- size = CalculateMipSize(width, height, picFormat);
- x >>= 1;
- y >>= 1;
- width = MAX(1, width >> 1);
- height = MAX(1, height >> 1);
- data += size;
- }
- }
+ // FIXME: This is an old hack to use half floats with lightmaps, use picFormat to determine this instead.
+ dataType = (internalFormat == GL_RGBA16F_ARB) ? GL_HALF_FLOAT_ARB : GL_UNSIGNED_BYTE;
miplevel = 0;
do
@@ -2130,10 +2119,7 @@ static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int
if (compressed)
{
- if (subtexture)
- qglCompressedTextureSubImage2DEXT(texture, target, miplevel, x, y, width, height, picFormat, size, data);
- else
- qglCompressedTextureImage2DEXT(texture, target, miplevel, picFormat, width, height, 0, size, data);
+ qglCompressedTextureSubImage2DEXT(texture, target, miplevel, x, y, width, height, picFormat, size, data);
}
else
{
@@ -2141,11 +2127,9 @@ static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int
R_BlendOverTexture((byte *)data, width * height, mipBlendColors[miplevel]);
if (rgtc)
- RawImage_UploadToRgtc2Texture(texture, data, width, height, miplevel);
- else if (subtexture)
- qglTextureSubImage2DEXT(texture, target, miplevel, x, y, width, height, dataFormat, dataType, data);
+ RawImage_UploadToRgtc2Texture(texture, miplevel, x, y, width, height, data);
else
- qglTextureImage2DEXT(texture, target, miplevel, internalFormat, width, height, 0, dataFormat, dataType, data);
+ qglTextureSubImage2DEXT(texture, target, miplevel, x, y, width, height, dataFormat, dataType, data);
if (!lastMip && numMips < 2)
{
@@ -2171,157 +2155,86 @@ static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int
while (!lastMip);
}
+
/*
===============
Upload32
===============
*/
-static void Upload32(byte *data, int x, int y, int width, int height, GLenum picFormat, int numMips, image_t *image)
+static void Upload32(byte *data, int x, int y, int width, int height, GLenum picFormat, int numMips, image_t *image, qboolean scaled)
{
- byte *resampledBuffer = NULL;
int i, c;
byte *scan;
- static int rmse_saved = 0;
-
- // do the root mean square error stuff first
- if ( r_rmse->value ) {
- while ( R_RMSE( (byte *)data, width, height ) < r_rmse->value ) {
- rmse_saved += ( height * width * 4 ) - ( ( width >> 1 ) * ( height >> 1 ) * 4 );
- resampledBuffer = ri.Hunk_AllocateTempMemory( ( width >> 1 ) * ( height >> 1 ) * 4 );
- ResampleTexture( data, width, height, resampledBuffer, width >> 1, height >> 1 );
- data = resampledBuffer;
- width = width >> 1;
- height = height >> 1;
- ri.Printf( PRINT_ALL, "r_rmse of %f has saved %dkb\n", r_rmse->value, ( rmse_saved / 1024 ) );
- }
- }
imgType_t type = image->type;
imgFlags_t flags = image->flags;
GLenum internalFormat = image->internalFormat;
- qboolean subtexture = (x != 0) || (y != 0) || (width != image->width) || (height != image->height);
- qboolean notScaled = qtrue;
qboolean compressed = (picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT);
qboolean mipmap = !!(flags & IMGFLAG_MIPMAP) && (!compressed || numMips > 1);
qboolean cubemap = !!(flags & IMGFLAG_CUBEMAP);
- GLenum uploadTarget = cubemap ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : GL_TEXTURE_2D;
- GLenum textureTarget = cubemap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
- int depth = cubemap ? 6 : 1;
- if (!data)
+ // These operations cannot be performed on pre-compressed images.
+ if (!compressed && !cubemap)
{
- RawImage_ScaleToPower2(NULL, &width, &height, type, flags, NULL);
- for (i = 0; i < depth; i++)
- RawImage_UploadTexture(image->texnum, NULL, 0, 0, width, height, uploadTarget + i, GL_RGBA8, 0, internalFormat, type, flags, qfalse);
- goto done;
- }
- else if (!subtexture)
- {
- if (compressed || cubemap)
+ c = width*height;
+ scan = data;
+
+ if (type == IMGTYPE_COLORALPHA)
{
- for (i = 0; i < depth; i++)
+ if( r_greyscale->integer )
{
- int w2 = width, h2 = height;
- RawImage_UploadTexture(image->texnum, data, 0, 0, width, height, uploadTarget + i, picFormat, numMips, internalFormat, type, flags, qfalse);
- for (c = numMips; c; c--)
+ for ( i = 0; i < c; i++ )
{
- data += CalculateMipSize(w2, h2, picFormat);
- w2 = MAX(1, w2 >> 1);
- h2 = MAX(1, h2 >> 1);
+ byte luma = LUMA(scan[i*4], scan[i*4 + 1], scan[i*4 + 2]);
+ scan[i*4] = luma;
+ scan[i*4 + 1] = luma;
+ scan[i*4 + 2] = luma;
+ }
+ }
+ else if( r_greyscale->value )
+ {
+ for ( i = 0; i < c; i++ )
+ {
+ float luma = LUMA(scan[i*4], scan[i*4 + 1], scan[i*4 + 2]);
+ scan[i*4] = LERP(scan[i*4], luma, r_greyscale->value);
+ scan[i*4 + 1] = LERP(scan[i*4 + 1], luma, r_greyscale->value);
+ scan[i*4 + 2] = LERP(scan[i*4 + 2], luma, r_greyscale->value);
}
}
- goto done;
- }
- notScaled = RawImage_ScaleToPower2(&data, &width, &height, type, flags, &resampledBuffer);
- }
- c = width*height;
- scan = data;
-
- if( r_greyscale->integer )
- {
- for ( i = 0; i < c; i++ )
- {
- byte luma = LUMA(scan[i*4], scan[i*4 + 1], scan[i*4 + 2]);
- scan[i*4] = luma;
- scan[i*4 + 1] = luma;
- scan[i*4 + 2] = luma;
- }
- }
- else if( r_greyscale->value )
- {
- for ( i = 0; i < c; i++ )
- {
- float luma = LUMA(scan[i*4], scan[i*4 + 1], scan[i*4 + 2]);
- scan[i*4] = LERP(scan[i*4], luma, r_greyscale->value);
- scan[i*4 + 1] = LERP(scan[i*4 + 1], luma, r_greyscale->value);
- scan[i*4 + 2] = LERP(scan[i*4 + 2], luma, r_greyscale->value);
+ // This corresponds to what the OpenGL1 renderer does.
+ if (!(flags & IMGFLAG_NOLIGHTSCALE) && (scaled || mipmap))
+ R_LightScaleTexture(data, width, height, !mipmap);
}
- }
-
- if (glRefConfig.swizzleNormalmap && (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT))
- RawImage_SwizzleRA(data, width, height);
-
- // This corresponds to what the OpenGL1 renderer does
- if (!(flags & IMGFLAG_NOLIGHTSCALE) && (!notScaled || mipmap))
- R_LightScaleTexture(data, width, height, !mipmap);
- if (subtexture)
- {
- // FIXME: Incorrect if original texture was not a power of 2 texture or picmipped
- RawImage_UploadTexture(image->texnum, data, x, y, width, height, uploadTarget, GL_RGBA8, 0, internalFormat, type, flags, qtrue);
- GL_CheckErrors();
- return;
+ if (glRefConfig.swizzleNormalmap && (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT))
+ RawImage_SwizzleRA(data, width, height);
}
- RawImage_UploadTexture(image->texnum, data, 0, 0, width, height, uploadTarget, GL_RGBA8, 0, internalFormat, type, flags, qfalse);
-
-done:
-
- image->uploadWidth = width;
- image->uploadHeight = height;
-
- if (mipmap)
+ if (cubemap)
{
- if (textureFilterAnisotropic && !cubemap)
- qglTextureParameteriEXT(image->texnum, textureTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT,
- (GLint)Com_Clamp(1, maxAnisotropy, r_ext_max_anisotropy->integer));
-
- qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MIN_FILTER, gl_filter_min);
- qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+ for (i = 0; i < 6; i++)
+ {
+ int w2 = width, h2 = height;
+ RawImage_UploadTexture(image->texnum, data, x, y, width, height, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, picFormat, numMips, internalFormat, type, flags, qfalse);
+ for (c = numMips; c; c--)
+ {
+ data += CalculateMipSize(w2, h2, picFormat);
+ w2 = MAX(1, w2 >> 1);
+ h2 = MAX(1, h2 >> 1);
+ }
+ }
}
else
{
- if (textureFilterAnisotropic && !cubemap)
- qglTextureParameteriEXT(image->texnum, textureTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
-
- qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- }
-
- // Fix for sampling depth buffer on old nVidia cards
- // from http://www.idevgames.com/forums/thread-4141-post-34844.html#pid34844
- switch(internalFormat)
- {
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_COMPONENT16_ARB:
- case GL_DEPTH_COMPONENT24_ARB:
- case GL_DEPTH_COMPONENT32_ARB:
- qglTextureParameterfEXT(image->texnum, textureTarget, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
- qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- break;
- default:
- break;
+ RawImage_UploadTexture(image->texnum, data, x, y, width, height, GL_TEXTURE_2D, picFormat, numMips, internalFormat, type, flags, qfalse);
}
GL_CheckErrors();
-
- if ( resampledBuffer != NULL )
- ri.Hunk_FreeTempMemory( resampledBuffer );
}
+
/*
================
R_CreateImage2
@@ -2330,10 +2243,18 @@ This is the only way any image_t are created
================
*/
image_t *R_CreateImage2( const char *name, byte *pic, int width, int height, GLenum picFormat, int numMips, imgType_t type, imgFlags_t flags, int internalFormat ) {
- image_t *image;
- qboolean isLightmap = qfalse;
- long hash;
- int glWrapClampMode;
+ byte *resampledBuffer = NULL;
+ image_t *image;
+ qboolean isLightmap = qfalse, scaled = qfalse;
+ long hash;
+ int glWrapClampMode, mipWidth, mipHeight, miplevel;
+ qboolean compressed = (!(picFormat == GL_RGBA8) || (picFormat == GL_SRGB8_ALPHA8_EXT));
+ qboolean mipmap = !!(flags & IMGFLAG_MIPMAP);
+ qboolean cubemap = !!(flags & IMGFLAG_CUBEMAP);
+ qboolean picmip = !!(flags & IMGFLAG_PICMIP);
+ qboolean lastMip;
+ GLenum textureTarget = cubemap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
+ GLenum dataFormat;
if ( strlen( name ) >= MAX_QPATH ) {
ri.Error( ERR_DROP, "R_CreateImage: \"%s\" is too long", name );
@@ -2367,20 +2288,91 @@ image_t *R_CreateImage2( const char *name, byte *pic, int width, int height, GLe
image->internalFormat = internalFormat;
- Upload32(pic, 0, 0, image->width, image->height, picFormat, numMips, image);
+ // Possibly scale image before uploading.
+ // if compressed and uploading an image, skip picmips.
+ if (!cubemap)
+ {
+ if (!compressed)
+ scaled = RawImage_ScaleToPower2(&pic, &width, &height, type, flags, &resampledBuffer);
+ else if (pic && picmip)
+ {
+ for (miplevel = r_picmip->integer; miplevel > 0 && numMips > 1; miplevel--, numMips--)
+ {
+ int size = CalculateMipSize(width, height, picFormat);
+ width = MAX(1, width >> 1);
+ height = MAX(1, height >> 1);
+ pic += size;
+ }
+ }
+ }
+
+ image->uploadWidth = width;
+ image->uploadHeight = height;
- if (image->flags & IMGFLAG_CUBEMAP)
+ // Allocate texture storage so we don't have to worry about it later.
+ dataFormat = PixelDataFormatFromInternalFormat(internalFormat);
+ mipWidth = width;
+ mipHeight = height;
+ miplevel = 0;
+ do
{
- qglTextureParameterfEXT(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, glWrapClampMode);
- qglTextureParameterfEXT(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, glWrapClampMode);
- qglTextureParameteriEXT(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, glWrapClampMode);
+ lastMip = !mipmap || (mipWidth == 1 && mipHeight == 1);
+ if (cubemap)
+ {
+ int i;
+
+ for (i = 0; i < 6; i++)
+ qglTextureImage2DEXT(image->texnum, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, miplevel, internalFormat, mipWidth, mipHeight, 0, dataFormat, GL_UNSIGNED_BYTE, NULL);
+ }
+ else
+ {
+ qglTextureImage2DEXT(image->texnum, GL_TEXTURE_2D, miplevel, internalFormat, mipWidth, mipHeight, 0, dataFormat, GL_UNSIGNED_BYTE, NULL);
+ }
+
+ mipWidth = MAX(1, mipWidth >> 1);
+ mipHeight = MAX(1, mipHeight >> 1);
+ miplevel++;
}
- else
+ while (!lastMip);
+
+ // Upload data.
+ if (pic)
+ Upload32(pic, 0, 0, width, height, picFormat, numMips, image, scaled);
+
+ if (resampledBuffer != NULL)
+ ri.Hunk_FreeTempMemory(resampledBuffer);
+
+ // Set all necessary texture parameters.
+ qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_WRAP_S, glWrapClampMode);
+ qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_WRAP_T, glWrapClampMode);
+
+ if (cubemap)
+ qglTextureParameteriEXT(image->texnum, textureTarget, GL_TEXTURE_WRAP_R, glWrapClampMode);
+
+ if (textureFilterAnisotropic && !cubemap)
+ qglTextureParameteriEXT(image->texnum, textureTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT,
+ mipmap ? (GLint)Com_Clamp(1, maxAnisotropy, r_ext_max_anisotropy->integer) : 1);
+
+ switch(internalFormat)
{
- qglTextureParameterfEXT(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode);
- qglTextureParameterfEXT(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode);
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT16_ARB:
+ case GL_DEPTH_COMPONENT24_ARB:
+ case GL_DEPTH_COMPONENT32_ARB:
+ // Fix for sampling depth buffer on old nVidia cards.
+ // from http://www.idevgames.com/forums/thread-4141-post-34844.html#pid34844
+ qglTextureParameterfEXT(image->texnum, textureTarget, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
+ qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ break;
+ default:
+ qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MIN_FILTER, mipmap ? gl_filter_min : GL_LINEAR);
+ qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MAG_FILTER, mipmap ? gl_filter_max : GL_LINEAR);
+ break;
}
+ GL_CheckErrors();
+
hash = generateHashValue( name );
image->next = hashTable[hash];
hashTable[hash] = image;
@@ -2391,6 +2383,7 @@ image_t *R_CreateImage2( const char *name, byte *pic, int width, int height, GLe
return image;
}
+
/*
================
R_CreateImage
@@ -2403,9 +2396,10 @@ image_t *R_CreateImage(const char *name, byte *pic, int width, int height, imgTy
return R_CreateImage2(name, pic, width, height, GL_RGBA8, 0, type, flags, internalFormat);
}
+
void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int height )
{
- Upload32(pic, x, y, width, height, GL_RGBA8, 0, image);
+ Upload32(pic, x, y, width, height, GL_RGBA8, 0, image, qfalse);
}
//===================================================================
@@ -2433,7 +2427,6 @@ static imageExtToLoaderMap_t imageLoaders[ ] =
static int numImageLoaders = ARRAY_LEN( imageLoaders );
-
/*
=================
R_LoadImage
@@ -2533,6 +2526,7 @@ void R_LoadImage( const char *name, byte **pic, int *width, int *height, GLenum
}
}
+
/*
===============
R_FindImageFile
diff --git a/SP/code/rend2/tr_image.c b/SP/code/rend2/tr_image.c
index e6b3b80..428ffc8 100644
--- a/SP/code/rend2/tr_image.c
+++ b/SP/code/rend2/tr_image.c
@@ -46,7 +46,6 @@ int gl_filter_max = GL_LINEAR;
#define FILE_HASH_SIZE 4096
static image_t* hashTable[FILE_HASH_SIZE];
-
/*
** R_GammaCorrect
*/
@@ -1503,6 +1502,7 @@ static void R_MipMapNormalHeight (const byte *in, byte *out, int width, int heig
R_RMSE
================
*/
+#if 0 // FIXME
static float R_RMSE( byte *in, int width, int height ) {
int i, j;
float out, rmse, rtemp;
@@ -1542,6 +1542,8 @@ static float R_RMSE( byte *in, int width, int height ) {
rmse = sqrt( rmse / ( height * width * 4 ) );
return rmse;
}
+#endif
+
/*
==================
@@ -1616,7 +1618,23 @@ static qboolean RawImage_ScaleToPower2( byte **data, int *inout_width, int *inou
qboolean picmip = flags & IMGFLAG_PICMIP;
qboolean mipmap = flags & IMGFLAG_MIPMAP;
qboolean clampToEdge = flags & IMGFLAG_CLAMPTOEDGE;
- qboolean notScaled;
+ qboolean scaled;
+#if 0
+ static int rmse_saved = 0;
+
+ // do the root mean square error stuff first
+ if ( r_rmse->value ) {
+ while ( R_RMSE( *data, width, height ) < r_rmse->value ) {
+ rmse_saved += ( height * width * 4 ) - ( ( width >> 1 ) * ( height >> 1 ) * 4 );
+ *resampledBuffer = ri.Hunk_AllocateTempMemory( ( width >> 1 ) * ( height >> 1 ) * 4 );
+ ResampleTexture( *data, width, height, *resampledBuffer, width >> 1, height >> 1 );
+ *data = *resampledBuffer;
+ width = width >> 1;
+ height = height >> 1;
+ ri.Printf( PRINT_ALL, "r_rmse of %f has saved %dkb\n", r_rmse->value, ( rmse_saved / 1024 ) );
+ }
+ }
+#endif
//
// convert to exact power of 2 sizes
@@ -1683,7 +1701,6 @@ static qboolean RawImage_ScaleToPower2( byte **data, int *inout_width, int *inou
else if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT)
FillInNormalizedZ(*resampledBuffer, *resampledBuffer, scaled_width, scaled_height);
-
//endTime = ri.Milliseconds();
//ri.Printf(PRINT_ALL, "upsampled %dx%d to %dx%d in %dms\n", width, height, scaled_width, scaled_height, endTime - startTime);
@@ -1728,7 +1745,7 @@ static qboolean RawImage_ScaleToPower2( byte **data, int *inout_width, int *inou
scaled_width = MAX(1, scaled_width);
scaled_height = MAX(1, scaled_height);
- notScaled = (width == scaled_width) && (height == scaled_height);
+ scaled = (width != scaled_width) || (height != scaled_height);
//
// rescale texture to new size using existing mipmap functions
@@ -1750,7 +1767,7 @@ static qboolean RawImage_ScaleToPower2( byte **data, int *inout_width, int *inou
*inout_width = width;
*inout_height = height;
- return notScaled;
+ return scaled;
}
@@ -1784,7 +1801,7 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, GLenum picForm
if(normalmap)
{
- if ((type == IMGTYPE_NORMALHEIGHT) && RawImage_HasAlpha(data, numPixels))
+ if ((type == IMGTYPE_NORMALHEIGHT) && RawImage_HasAlpha(data, numPixels) && r_parallaxMapping->integer)
{
if (!forceNoCompression && glRefConfig.textureCompression & TCR_BPTC)
{
@@ -1974,9 +1991,9 @@ static void CompressMonoBlock(byte outdata[8], const byte indata[16])
}
}
-static void RawImage_UploadToRgtc2Texture(GLuint texture, byte *data, int width, int height, int mip)
+static void RawImage_UploadToRgtc2Texture(GLuint texture, int miplevel, int x, int y, int width, int height, byte *data)
{
- int wBlocks, hBlocks, y, x, size;
+ int wBlocks, hBlocks, iy, ix, size;
byte *compressedData, *p;
wBlocks = (width + 3) / 4;
@@ -1984,16 +2001,16 @@ static void RawImage_UploadToRgtc2Texture(GLuint texture, byte *data, int width,
size = wBlocks * hBlocks * 16;
p = compressedData = ri.Hunk_AllocateTempMemory(size);
- for (y = 0; y < height; y += 4)
+ for (iy = 0; iy < height; iy += 4)
{
- int oh = MIN(4, height - y);
+ int oh = MIN(4, height - iy);
- for (x = 0; x < width; x += 4)
+ for (ix = 0; ix < width; ix += 4)
{
byte workingData[16];
int component;
- int ow = MIN(4, width - x);
+ int ow = MIN(4, width - ix);
for (component = 0; component < 2; component++)
{
@@ -2001,7 +2018,7 @@ static void RawImage_UploadToRgtc2Texture(GLuint texture, byte *data, int width,
for (oy = 0; oy < oh; oy++)
for (ox = 0; ox < ow; ox++)
- workingData[oy * 4 + ox] = data[((y + oy) * width + x + ox) * 4 + component];
+ workingData[oy * 4 + ox] = data[((iy + oy) * width + ix + ox) * 4 + component];
// dupe data to fill
for (oy = 0; oy < 4; oy++)
@@ -2014,7 +2031,8 @@ static void RawImage_UploadToRgtc2Texture(GLuint texture, byte *data, int width,
}
}
- qglCompressedTextureImage2DEXT(texture, GL_TEXTURE_2D, mip, GL_COMPRESSED_RG_RGTC2, width, height, 0, size, compressedData);
+ // FIXME: Won't work for x/y that aren't multiples of 4.
+ qglCompressedTextureSubImage2DEXT(texture, GL_TEXTURE_2D, miplevel, x, y, width, height, GL_COMPRESSED_RG_RGTC2, size, compressedData);
ri.Hunk_FreeTempMemory(compressedData);
}
@@ -2058,64 +2076,35 @@ static int CalculateMipSize(int width, int height, GLenum picFormat)
return 0;
}
-static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int width, int height, GLenum target, GLenum picFormat, int numMips, GLenum internalFormat, imgType_t type, imgFlags_t flags, qboolean subtexture )
-{
- int dataFormat, dataType;
- qboolean rgtc = (internalFormat == GL_COMPRESSED_RG_RGTC2);
- qboolean compressed = (!(picFormat == GL_RGBA8) || (picFormat == GL_SRGB8_ALPHA8_EXT));
- qboolean mipmap = !!(flags & IMGFLAG_MIPMAP);
- qboolean picmip = !!(flags & IMGFLAG_PICMIP);
- int size, miplevel;
- qboolean lastMip = qfalse;
+static GLenum PixelDataFormatFromInternalFormat(GLenum internalFormat)
+{
switch (internalFormat)
{
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16_ARB:
case GL_DEPTH_COMPONENT24_ARB:
case GL_DEPTH_COMPONENT32_ARB:
- dataFormat = GL_DEPTH_COMPONENT;
- dataType = GL_UNSIGNED_BYTE;
- break;
- case GL_RGBA16F_ARB:
- dataFormat = GL_RGBA;
- dataType = GL_HALF_FLOAT_ARB;
- break;
+ return GL_DEPTH_COMPONENT;
default:
- dataFormat = GL_RGBA;
- dataType = GL_UNSIGNED_BYTE;
+ return GL_RGBA;
break;
}
+}
- if (!data)
- {
- miplevel = 0;
- do
- {
- lastMip = (width == 1 && height == 1) || !mipmap;
- qglTextureImage2DEXT(texture, target, miplevel, internalFormat, width, height, 0, dataFormat, dataType, NULL);
-
- width = MAX(1, width >> 1);
- height = MAX(1, height >> 1);
- miplevel++;
- }
- while (!lastMip);
+static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int width, int height, GLenum target, GLenum picFormat, int numMips, GLenum internalFormat, imgType_t type, imgFlags_t flags, qboolean subtexture )
+{
+ GLenum dataFormat, dataType;
+ qboolean rgtc = (internalFormat == GL_COMPRESSED_RG_RGTC2);
+ qboolean compressed = (!(picFormat == GL_RGBA8) || (picFormat == GL_SRGB8_ALPHA8_EXT));
+ qboolean mipmap = !!(flags & IMGFLAG_MIPMAP);
+ int size, miplevel;
+ qboolean lastMip = qfalse;
- return;
- }
+ dataFormat = PixelDataFormatFromInternalFormat(internalFormat);
- if (compressed && picmip)
- {
- for (miplevel = r_picmip->integer; miplevel > 0 && numMips > 1; miplevel--, numMips--)
- {
- size = CalculateMipSize(width, height, picFormat);
- x >>= 1;
- y >>= 1;
- width = MAX(1, width >> 1);
- height = MAX(1, height >> 1);
- data += size;
- }
- }
+ // FIXME: This is an old hack to use half floats with lightmaps, use picFormat to determine this instead.
+ dataType = (internalFormat == GL_RGBA16F_ARB) ? GL_HALF_FLOAT_ARB : GL_UNSIGNED_BYTE;
miplevel = 0;
do
@@ -2125,10 +2114,7 @@ static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int
if (compressed)
{
- if (subtexture)
- qglCompressedTextureSubImage2DEXT(texture, target, miplevel, x, y, width, height, picFormat, size, data);
- else
- qglCompressedTextureImage2DEXT(texture, target, miplevel, picFormat, width, height, 0, size, data);
+ qglCompressedTextureSubImage2DEXT(texture, target, miplevel, x, y, width, height, picFormat, size, data);
}
else
{
@@ -2136,11 +2122,9 @@ static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int
R_BlendOverTexture((byte *)data, width * height, mipBlendColors[miplevel]);
if (rgtc)
- RawImage_UploadToRgtc2Texture(texture, data, width, height, miplevel);
- else if (subtexture)
- qglTextureSubImage2DEXT(texture, target, miplevel, x, y, width, height, dataFormat, dataType, data);
+ RawImage_UploadToRgtc2Texture(texture, miplevel, x, y, width, height, data);
else
- qglTextureImage2DEXT(texture, target, miplevel, internalFormat, width, height, 0, dataFormat, dataType, data);
+ qglTextureSubImage2DEXT(texture, target, miplevel, x, y, width, height, dataFormat, dataType, data);
if (!lastMip && numMips < 2)
{
@@ -2166,160 +2150,87 @@ static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int
while (!lastMip);
}
+
/*
===============
Upload32
===============
*/
-static void Upload32(byte *data, int x, int y, int width, int height, GLenum picFormat, int numMips, image_t *image)
+static void Upload32(byte *data, int x, int y, int width, int height, GLenum picFormat, int numMips, image_t *image, qboolean scaled)
{
- byte *resampledBuffer = NULL;
int i, c;
byte *scan;
- static int rmse_saved = 0;
-
- // do the root mean square error stuff first
- if ( r_rmse->value ) {
- while ( R_RMSE( (byte *)data, width, height ) < r_rmse->value ) {
- rmse_saved += ( height * width * 4 ) - ( ( width >> 1 ) * ( height >> 1 ) * 4 );
- resampledBuffer = ri.Hunk_AllocateTempMemory( ( width >> 1 ) * ( height >> 1 ) * 4 );
- ResampleTexture( data, width, height, resampledBuffer, width >> 1, height >> 1 );
- data = resampledBuffer;
- width = width >> 1;
- height = height >> 1;
- ri.Printf( PRINT_ALL, "r_rmse of %f has saved %dkb\n", r_rmse->value, ( rmse_saved / 1024 ) );
- }
- }
imgType_t type = image->type;
imgFlags_t flags = image->flags;
GLenum internalFormat = image->internalFormat;
- qboolean subtexture = (x != 0) || (y != 0) || (width != image->width) || (height != image->height);
- qboolean notScaled = qtrue;
qboolean compressed = (picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT);
qboolean mipmap = !!(flags & IMGFLAG_MIPMAP) && (!compressed || numMips > 1);
qboolean cubemap = !!(flags & IMGFLAG_CUBEMAP);
- GLenum uploadTarget = cubemap ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : GL_TEXTURE_2D;
- GLenum textureTarget = cubemap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
- int depth = cubemap ? 6 : 1;
- if (!data)
- {
- RawImage_ScaleToPower2(NULL, &width, &height, type, flags, NULL);
- for (i = 0; i < depth; i++)
- RawImage_UploadTexture(image->texnum, NULL, 0, 0, width, height, uploadTarget + i, GL_RGBA8, 0, internalFormat, type, flags, qfalse);
- goto done;
- }
- else if (!subtexture)
+ // These operations cannot be performed on pre-compressed images.
+ if (!compressed && !cubemap)
{
- if (compressed || cubemap)
+ c = width*height;
+ scan = data;
+
+ if (type == IMGTYPE_COLORALPHA)
{
- for (i = 0; i < depth; i++)
+ if( r_greyscale->integer )
{
- int w2 = width, h2 = height;
- RawImage_UploadTexture(image->texnum, data, 0, 0, width, height, uploadTarget + i, picFormat, numMips, internalFormat, type, flags, qfalse);
- for (c = numMips; c; c--)
+ for ( i = 0; i < c; i++ )
{
- data += CalculateMipSize(w2, h2, picFormat);
- w2 = MAX(1, w2 >> 1);
- h2 = MAX(1, h2 >> 1);
+ byte luma = LUMA(scan[i*4], scan[i*4 + 1], scan[i*4 + 2]);
+ scan[i*4] = luma;
+ scan[i*4 + 1] = luma;
+ scan[i*4 + 2] = luma;
+ }
+ }
+ else if( r_greyscale->value )
+ {
+ for ( i = 0; i < c; i++ )
+ {
+ float luma = LUMA(scan[i*4], scan[i*4 + 1], scan[i*4 + 2]);
+ scan[i*4] = LERP(scan[i*4], luma, r_greyscale->value);
+ scan[i*4 + 1] = LERP(scan[i*4 + 1], luma, r_greyscale->value);
+ scan[i*4 + 2] = LERP(scan[i*4 + 2], luma, r_greyscale->value);
}
}
- goto done;
- }
- notScaled = RawImage_ScaleToPower2(&data, &width, &height, type, flags, &resampledBuffer);
- }
- c = width*height;
- scan = data;
-
- if( r_greyscale->integer )
- {
- for ( i = 0; i < c; i++ )
- {
- byte luma = LUMA(scan[i*4], scan[i*4 + 1], scan[i*4 + 2]);
- scan[i*4] = luma;
- scan[i*4 + 1] = luma;
- scan[i*4 + 2] = luma;
- }
- }
- else if( r_greyscale->value )
- {
- for ( i = 0; i < c; i++ )
- {
- float luma = LUMA(scan[i*4], scan[i*4 + 1], scan[i*4 + 2]);
- scan[i*4] = LERP(scan[i*4], luma, r_greyscale->value);
- scan[i*4 + 1] = LERP(scan[i*4 + 1], luma, r_greyscale->value);
- scan[i*4 + 2] = LERP(scan[i*4 + 2], luma, r_greyscale->value);
+ // This corresponds to what the OpenGL1 renderer does.
+ if (!(flags & IMGFLAG_NOLIGHTSCALE) && (scaled || mipmap))
+ R_LightScaleTexture(data, width, height, !mipmap);
}
- }
-
- if (glRefConfig.swizzleNormalmap && (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT))
- RawImage_SwizzleRA(data, width, height);
- // This corresponds to what the OpenGL1 renderer does
- if (!(flags & IMGFLAG_NOLIGHTSCALE) && (!notScaled || mipmap))
- R_LightScaleTexture(data, width, height, !mipmap);
-
- if (subtexture)
- {
- // FIXME: Incorrect if original texture was not a power of 2 texture or picmipped
- RawImage_UploadTexture(image->texnum, data, x, y, width, height, uploadTarget, GL_RGBA8, 0, internalFormat, type, flags, qtrue);
- GL_CheckErrors();
- return;
+ if (glRefConfig.swizzleNormalmap && (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT))
+ RawImage_SwizzleRA(data, width, height);
}
- RawImage_UploadTexture(image->texnum, data, 0, 0, width, height, uploadTarget, GL_RGBA8, 0, internalFormat, type, flags, qfalse);
-
-done:
-
- image->uploadWidth = width;
- image->uploadHeight = height;
-
- if (mipmap)
+ if (cubemap)
{
- if (textureFilterAnisotropic && !cubemap)
- qglTextureParameteriEXT(image->texnum, textureTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT,
- (GLint)Com_Clamp(1, maxAnisotropy, r_ext_max_anisotropy->integer));
-
- qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MIN_FILTER, gl_filter_min);
- qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+ for (i = 0; i < 6; i++)
+ {
+ int w2 = width, h2 = height;
+ RawImage_UploadTexture(image->texnum, data, x, y, width, height, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, picFormat, numMips, internalFormat, type, flags, qfalse);
+ for (c = numMips; c; c--)
+ {
+ data += CalculateMipSize(w2, h2, picFormat);
+ w2 = MAX(1, w2 >> 1);
+ h2 = MAX(1, h2 >> 1);
+ }
+ }
}
else
{
- if (textureFilterAnisotropic && !cubemap)
- qglTextureParameteriEXT(image->texnum, textureTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
-
- qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- }
-
- // Fix for sampling depth buffer on old nVidia cards
- // from http://www.idevgames.com/forums/thread-4141-post-34844.html#pid34844
- switch(internalFormat)
- {
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_COMPONENT16_ARB:
- case GL_DEPTH_COMPONENT24_ARB:
- case GL_DEPTH_COMPONENT32_ARB:
- qglTextureParameterfEXT(image->texnum, textureTarget, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
- qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- break;
- default:
- break;
+ RawImage_UploadTexture(image->texnum, data, x, y, width, height, GL_TEXTURE_2D, picFormat, numMips, internalFormat, type, flags, qfalse);
}
GL_CheckErrors();
-
- if ( resampledBuffer != NULL )
- ri.Hunk_FreeTempMemory( resampledBuffer );
}
//----(SA) modified
-
/*
================
R_CreateImageExt2
@@ -2328,10 +2239,18 @@ This is the only way any image_t are created
================
*/
image_t *R_CreateImageExt2( const char *name, byte *pic, int width, int height, GLenum picFormat, int numMips, imgType_t type, imgFlags_t flags, int internalFormat, qboolean characterMip ) {
- image_t *image;
- qboolean isLightmap = qfalse;
- int glWrapClampMode;
- long hash;
+ byte *resampledBuffer = NULL;
+ image_t *image;
+ qboolean isLightmap = qfalse, scaled = qfalse;
+ long hash;
+ int glWrapClampMode, mipWidth, mipHeight, miplevel;
+ qboolean compressed = (!(picFormat == GL_RGBA8) || (picFormat == GL_SRGB8_ALPHA8_EXT));
+ qboolean mipmap = !!(flags & IMGFLAG_MIPMAP);
+ qboolean cubemap = !!(flags & IMGFLAG_CUBEMAP);
+ qboolean picmip = !!(flags & IMGFLAG_PICMIP);
+ qboolean lastMip;
+ GLenum textureTarget = cubemap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
+ GLenum dataFormat;
if ( strlen( name ) >= MAX_QPATH ) {
ri.Error( ERR_DROP, "R_CreateImage: \"%s\" is too long", name );
@@ -2365,20 +2284,91 @@ image_t *R_CreateImageExt2( const char *name, byte *pic, int width, int height,
image->internalFormat = internalFormat;
- Upload32(pic, 0, 0, image->width, image->height, picFormat, numMips, image);
+ // Possibly scale image before uploading.
+ // if compressed and uploading an image, skip picmips.
+ if (!cubemap)
+ {
+ if (!compressed)
+ scaled = RawImage_ScaleToPower2(&pic, &width, &height, type, flags, &resampledBuffer);
+ else if (pic && picmip)
+ {
+ for (miplevel = r_picmip->integer; miplevel > 0 && numMips > 1; miplevel--, numMips--)
+ {
+ int size = CalculateMipSize(width, height, picFormat);
+ width = MAX(1, width >> 1);
+ height = MAX(1, height >> 1);
+ pic += size;
+ }
+ }
+ }
+
+ image->uploadWidth = width;
+ image->uploadHeight = height;
- if (image->flags & IMGFLAG_CUBEMAP)
+ // Allocate texture storage so we don't have to worry about it later.
+ dataFormat = PixelDataFormatFromInternalFormat(internalFormat);
+ mipWidth = width;
+ mipHeight = height;
+ miplevel = 0;
+ do
{
- qglTextureParameterfEXT(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, glWrapClampMode);
- qglTextureParameterfEXT(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, glWrapClampMode);
- qglTextureParameteriEXT(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, glWrapClampMode);
+ lastMip = !mipmap || (mipWidth == 1 && mipHeight == 1);
+ if (cubemap)
+ {
+ int i;
+
+ for (i = 0; i < 6; i++)
+ qglTextureImage2DEXT(image->texnum, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, miplevel, internalFormat, mipWidth, mipHeight, 0, dataFormat, GL_UNSIGNED_BYTE, NULL);
+ }
+ else
+ {
+ qglTextureImage2DEXT(image->texnum, GL_TEXTURE_2D, miplevel, internalFormat, mipWidth, mipHeight, 0, dataFormat, GL_UNSIGNED_BYTE, NULL);
+ }
+
+ mipWidth = MAX(1, mipWidth >> 1);
+ mipHeight = MAX(1, mipHeight >> 1);
+ miplevel++;
}
- else
+ while (!lastMip);
+
+ // Upload data.
+ if (pic)
+ Upload32(pic, 0, 0, width, height, picFormat, numMips, image, scaled);
+
+ if (resampledBuffer != NULL)
+ ri.Hunk_FreeTempMemory(resampledBuffer);
+
+ // Set all necessary texture parameters.
+ qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_WRAP_S, glWrapClampMode);
+ qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_WRAP_T, glWrapClampMode);
+
+ if (cubemap)
+ qglTextureParameteriEXT(image->texnum, textureTarget, GL_TEXTURE_WRAP_R, glWrapClampMode);
+
+ if (textureFilterAnisotropic && !cubemap)
+ qglTextureParameteriEXT(image->texnum, textureTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT,
+ mipmap ? (GLint)Com_Clamp(1, maxAnisotropy, r_ext_max_anisotropy->integer) : 1);
+
+ switch(internalFormat)
{
- qglTextureParameterfEXT(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode);
- qglTextureParameterfEXT(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode);
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT16_ARB:
+ case GL_DEPTH_COMPONENT24_ARB:
+ case GL_DEPTH_COMPONENT32_ARB:
+ // Fix for sampling depth buffer on old nVidia cards.
+ // from http://www.idevgames.com/forums/thread-4141-post-34844.html#pid34844
+ qglTextureParameterfEXT(image->texnum, textureTarget, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
+ qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ break;
+ default:
+ qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MIN_FILTER, mipmap ? gl_filter_min : GL_LINEAR);
+ qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MAG_FILTER, mipmap ? gl_filter_max : GL_LINEAR);
+ break;
}
+ GL_CheckErrors();
+
hash = generateHashValue( name );
image->next = hashTable[hash];
hashTable[hash] = image;
@@ -2389,6 +2379,7 @@ image_t *R_CreateImageExt2( const char *name, byte *pic, int width, int height,
return image;
}
+
/*
================
R_CreateImage
@@ -2399,12 +2390,11 @@ Wrapper for R_CreateImageExt2(), for the old parameters.
image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgType_t type, imgFlags_t flags, int internalFormat ) {
return R_CreateImageExt2(name, pic, width, height, GL_RGBA8, 0, type, flags, internalFormat, qfalse);
}
-
//----(SA) end
void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int height )
{
- Upload32(pic, x, y, width, height, GL_RGBA8, 0, image);
+ Upload32(pic, x, y, width, height, GL_RGBA8, 0, image, qfalse);
}
//===================================================================
@@ -2429,9 +2419,8 @@ static imageExtToLoaderMap_t imageLoaders[ ] =
{ "pcx", R_LoadPCX },
{ "bmp", R_LoadBMP }
};
-
-static int numImageLoaders = ARRAY_LEN( imageLoaders );
+static int numImageLoaders = ARRAY_LEN( imageLoaders );
/*
=================
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/iortcw.git
More information about the Pkg-games-commits
mailing list