mirror of
https://github.com/UberGames/lilium-voyager.git
synced 2024-12-13 21:51:09 +00:00
OpenGL2: Some tr_image refactoring/cleanup.
This commit is contained in:
parent
8417c184b4
commit
1cfa16674c
1 changed files with 165 additions and 179 deletions
|
@ -1461,7 +1461,7 @@ static qboolean RawImage_ScaleToPower2( byte **data, int *inout_width, int *inou
|
||||||
qboolean picmip = flags & IMGFLAG_PICMIP;
|
qboolean picmip = flags & IMGFLAG_PICMIP;
|
||||||
qboolean mipmap = flags & IMGFLAG_MIPMAP;
|
qboolean mipmap = flags & IMGFLAG_MIPMAP;
|
||||||
qboolean clampToEdge = flags & IMGFLAG_CLAMPTOEDGE;
|
qboolean clampToEdge = flags & IMGFLAG_CLAMPTOEDGE;
|
||||||
qboolean notScaled;
|
qboolean scaled;
|
||||||
|
|
||||||
//
|
//
|
||||||
// convert to exact power of 2 sizes
|
// convert to exact power of 2 sizes
|
||||||
|
@ -1572,7 +1572,7 @@ static qboolean RawImage_ScaleToPower2( byte **data, int *inout_width, int *inou
|
||||||
scaled_width = MAX(1, scaled_width);
|
scaled_width = MAX(1, scaled_width);
|
||||||
scaled_height = MAX(1, scaled_height);
|
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
|
// rescale texture to new size using existing mipmap functions
|
||||||
|
@ -1594,7 +1594,7 @@ static qboolean RawImage_ScaleToPower2( byte **data, int *inout_width, int *inou
|
||||||
*inout_width = width;
|
*inout_width = width;
|
||||||
*inout_height = height;
|
*inout_height = height;
|
||||||
|
|
||||||
return notScaled;
|
return scaled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1628,7 +1628,7 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, GLenum picForm
|
||||||
|
|
||||||
if(normalmap)
|
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)
|
if (!forceNoCompression && glRefConfig.textureCompression & TCR_BPTC)
|
||||||
{
|
{
|
||||||
|
@ -1818,9 +1818,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;
|
byte *compressedData, *p;
|
||||||
|
|
||||||
wBlocks = (width + 3) / 4;
|
wBlocks = (width + 3) / 4;
|
||||||
|
@ -1828,16 +1828,16 @@ static void RawImage_UploadToRgtc2Texture(GLuint texture, byte *data, int width,
|
||||||
size = wBlocks * hBlocks * 16;
|
size = wBlocks * hBlocks * 16;
|
||||||
|
|
||||||
p = compressedData = ri.Hunk_AllocateTempMemory(size);
|
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];
|
byte workingData[16];
|
||||||
int component;
|
int component;
|
||||||
|
|
||||||
int ow = MIN(4, width - x);
|
int ow = MIN(4, width - ix);
|
||||||
|
|
||||||
for (component = 0; component < 2; component++)
|
for (component = 0; component < 2; component++)
|
||||||
{
|
{
|
||||||
|
@ -1845,7 +1845,7 @@ static void RawImage_UploadToRgtc2Texture(GLuint texture, byte *data, int width,
|
||||||
|
|
||||||
for (oy = 0; oy < oh; oy++)
|
for (oy = 0; oy < oh; oy++)
|
||||||
for (ox = 0; ox < ow; ox++)
|
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
|
// dupe data to fill
|
||||||
for (oy = 0; oy < 4; oy++)
|
for (oy = 0; oy < 4; oy++)
|
||||||
|
@ -1858,7 +1858,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);
|
ri.Hunk_FreeTempMemory(compressedData);
|
||||||
}
|
}
|
||||||
|
@ -1903,64 +1904,34 @@ static int CalculateMipSize(int width, int height, GLenum picFormat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 )
|
static GLenum PixelDataFormatFromInternalFormat(GLenum internalFormat)
|
||||||
{
|
{
|
||||||
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;
|
|
||||||
|
|
||||||
switch (internalFormat)
|
switch (internalFormat)
|
||||||
{
|
{
|
||||||
case GL_DEPTH_COMPONENT:
|
case GL_DEPTH_COMPONENT:
|
||||||
case GL_DEPTH_COMPONENT16_ARB:
|
case GL_DEPTH_COMPONENT16_ARB:
|
||||||
case GL_DEPTH_COMPONENT24_ARB:
|
case GL_DEPTH_COMPONENT24_ARB:
|
||||||
case GL_DEPTH_COMPONENT32_ARB:
|
case GL_DEPTH_COMPONENT32_ARB:
|
||||||
dataFormat = GL_DEPTH_COMPONENT;
|
return GL_DEPTH_COMPONENT;
|
||||||
dataType = GL_UNSIGNED_BYTE;
|
|
||||||
break;
|
|
||||||
case GL_RGBA16F_ARB:
|
|
||||||
dataFormat = GL_RGBA;
|
|
||||||
dataType = GL_HALF_FLOAT_ARB;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
dataFormat = GL_RGBA;
|
return GL_RGBA;
|
||||||
dataType = GL_UNSIGNED_BYTE;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!data)
|
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 )
|
||||||
{
|
{
|
||||||
miplevel = 0;
|
GLenum dataFormat, dataType;
|
||||||
do
|
qboolean rgtc = (internalFormat == GL_COMPRESSED_RG_RGTC2);
|
||||||
{
|
qboolean compressed = (!(picFormat == GL_RGBA8) || (picFormat == GL_SRGB8_ALPHA8_EXT));
|
||||||
lastMip = (width == 1 && height == 1) || !mipmap;
|
qboolean mipmap = !!(flags & IMGFLAG_MIPMAP);
|
||||||
qglTextureImage2DEXT(texture, target, miplevel, internalFormat, width, height, 0, dataFormat, dataType, NULL);
|
int size, miplevel;
|
||||||
|
qboolean lastMip = qfalse;
|
||||||
|
|
||||||
width = MAX(1, width >> 1);
|
dataFormat = PixelDataFormatFromInternalFormat(internalFormat);
|
||||||
height = MAX(1, height >> 1);
|
|
||||||
miplevel++;
|
|
||||||
}
|
|
||||||
while (!lastMip);
|
|
||||||
|
|
||||||
return;
|
// 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;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
miplevel = 0;
|
miplevel = 0;
|
||||||
do
|
do
|
||||||
|
@ -1970,10 +1941,7 @@ static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int
|
||||||
|
|
||||||
if (compressed)
|
if (compressed)
|
||||||
{
|
{
|
||||||
if (subtexture)
|
|
||||||
qglCompressedTextureSubImage2DEXT(texture, target, miplevel, x, y, width, height, picFormat, size, data);
|
qglCompressedTextureSubImage2DEXT(texture, target, miplevel, x, y, width, height, picFormat, size, data);
|
||||||
else
|
|
||||||
qglCompressedTextureImage2DEXT(texture, target, miplevel, picFormat, width, height, 0, size, data);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1981,11 +1949,9 @@ static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int
|
||||||
R_BlendOverTexture((byte *)data, width * height, mipBlendColors[miplevel]);
|
R_BlendOverTexture((byte *)data, width * height, mipBlendColors[miplevel]);
|
||||||
|
|
||||||
if (rgtc)
|
if (rgtc)
|
||||||
RawImage_UploadToRgtc2Texture(texture, data, width, height, miplevel);
|
RawImage_UploadToRgtc2Texture(texture, miplevel, x, y, width, height, data);
|
||||||
else if (subtexture)
|
|
||||||
qglTextureSubImage2DEXT(texture, target, miplevel, x, y, width, height, dataFormat, dataType, data);
|
|
||||||
else
|
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)
|
if (!lastMip && numMips < 2)
|
||||||
{
|
{
|
||||||
|
@ -2018,54 +1984,26 @@ 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;
|
int i, c;
|
||||||
byte *scan;
|
byte *scan;
|
||||||
|
|
||||||
imgType_t type = image->type;
|
imgType_t type = image->type;
|
||||||
imgFlags_t flags = image->flags;
|
imgFlags_t flags = image->flags;
|
||||||
GLenum internalFormat = image->internalFormat;
|
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 compressed = (picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT);
|
||||||
qboolean mipmap = !!(flags & IMGFLAG_MIPMAP) && (!compressed || numMips > 1);
|
qboolean mipmap = !!(flags & IMGFLAG_MIPMAP) && (!compressed || numMips > 1);
|
||||||
qboolean cubemap = !!(flags & IMGFLAG_CUBEMAP);
|
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)
|
|
||||||
{
|
|
||||||
for (i = 0; i < depth; i++)
|
|
||||||
{
|
|
||||||
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--)
|
|
||||||
{
|
|
||||||
data += CalculateMipSize(w2, h2, picFormat);
|
|
||||||
w2 = MAX(1, w2 >> 1);
|
|
||||||
h2 = MAX(1, h2 >> 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
notScaled = RawImage_ScaleToPower2(&data, &width, &height, type, flags, &resampledBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
c = width*height;
|
c = width*height;
|
||||||
scan = data;
|
scan = data;
|
||||||
|
|
||||||
|
if (type == IMGTYPE_COLORALPHA)
|
||||||
|
{
|
||||||
if( r_greyscale->integer )
|
if( r_greyscale->integer )
|
||||||
{
|
{
|
||||||
for ( i = 0; i < c; i++ )
|
for ( i = 0; i < c; i++ )
|
||||||
|
@ -2087,66 +2025,35 @@ static void Upload32(byte *data, int x, int y, int width, int height, GLenum pic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glRefConfig.swizzleNormalmap && (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT))
|
// This corresponds to what the OpenGL1 renderer does.
|
||||||
RawImage_SwizzleRA(data, width, height);
|
if (!(flags & IMGFLAG_NOLIGHTSCALE) && (scaled || mipmap))
|
||||||
|
|
||||||
// This corresponds to what the OpenGL1 renderer does
|
|
||||||
if (!(flags & IMGFLAG_NOLIGHTSCALE) && (!notScaled || mipmap))
|
|
||||||
R_LightScaleTexture(data, width, height, !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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RawImage_UploadTexture(image->texnum, data, 0, 0, width, height, uploadTarget, GL_RGBA8, 0, internalFormat, type, flags, qfalse);
|
if (glRefConfig.swizzleNormalmap && (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT))
|
||||||
|
RawImage_SwizzleRA(data, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
if (cubemap)
|
||||||
|
|
||||||
image->uploadWidth = width;
|
|
||||||
image->uploadHeight = height;
|
|
||||||
|
|
||||||
if (mipmap)
|
|
||||||
{
|
{
|
||||||
if (textureFilterAnisotropic && !cubemap)
|
for (i = 0; i < 6; i++)
|
||||||
qglTextureParameteriEXT(image->texnum, textureTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
{
|
||||||
(GLint)Com_Clamp(1, maxAnisotropy, r_ext_max_anisotropy->integer));
|
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);
|
||||||
qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MIN_FILTER, gl_filter_min);
|
for (c = numMips; c; c--)
|
||||||
qglTextureParameterfEXT(image->texnum, textureTarget, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
{
|
||||||
|
data += CalculateMipSize(w2, h2, picFormat);
|
||||||
|
w2 = MAX(1, w2 >> 1);
|
||||||
|
h2 = MAX(1, h2 >> 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (textureFilterAnisotropic && !cubemap)
|
RawImage_UploadTexture(image->texnum, data, x, y, width, height, GL_TEXTURE_2D, picFormat, numMips, internalFormat, type, flags, qfalse);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GL_CheckErrors();
|
GL_CheckErrors();
|
||||||
|
|
||||||
if ( resampledBuffer != NULL )
|
|
||||||
ri.Hunk_FreeTempMemory( resampledBuffer );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2158,10 +2065,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 *R_CreateImage2( const char *name, byte *pic, int width, int height, GLenum picFormat, int numMips, imgType_t type, imgFlags_t flags, int internalFormat ) {
|
||||||
|
byte *resampledBuffer = NULL;
|
||||||
image_t *image;
|
image_t *image;
|
||||||
qboolean isLightmap = qfalse;
|
qboolean isLightmap = qfalse, scaled = qfalse;
|
||||||
long hash;
|
long hash;
|
||||||
int glWrapClampMode;
|
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 ) {
|
if (strlen(name) >= MAX_QPATH ) {
|
||||||
ri.Error (ERR_DROP, "R_CreateImage: \"%s\" is too long", name);
|
ri.Error (ERR_DROP, "R_CreateImage: \"%s\" is too long", name);
|
||||||
|
@ -2195,20 +2110,91 @@ image_t *R_CreateImage2( const char *name, byte *pic, int width, int height, GLe
|
||||||
|
|
||||||
image->internalFormat = internalFormat;
|
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 (image->flags & IMGFLAG_CUBEMAP)
|
if (!cubemap)
|
||||||
{
|
{
|
||||||
qglTextureParameterfEXT(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, glWrapClampMode);
|
if (!compressed)
|
||||||
qglTextureParameterfEXT(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, glWrapClampMode);
|
scaled = RawImage_ScaleToPower2(&pic, &width, &height, type, flags, &resampledBuffer);
|
||||||
qglTextureParameteriEXT(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, glWrapClampMode);
|
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;
|
||||||
|
|
||||||
|
// Allocate texture storage so we don't have to worry about it later.
|
||||||
|
dataFormat = PixelDataFormatFromInternalFormat(internalFormat);
|
||||||
|
mipWidth = width;
|
||||||
|
mipHeight = height;
|
||||||
|
miplevel = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
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
|
else
|
||||||
{
|
{
|
||||||
qglTextureParameterfEXT(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode);
|
qglTextureImage2DEXT(image->texnum, GL_TEXTURE_2D, miplevel, internalFormat, mipWidth, mipHeight, 0, dataFormat, GL_UNSIGNED_BYTE, NULL);
|
||||||
qglTextureParameterfEXT(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mipWidth = MAX(1, mipWidth >> 1);
|
||||||
|
mipHeight = MAX(1, mipHeight >> 1);
|
||||||
|
miplevel++;
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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);
|
hash = generateHashValue(name);
|
||||||
image->next = hashTable[hash];
|
image->next = hashTable[hash];
|
||||||
hashTable[hash] = image;
|
hashTable[hash] = image;
|
||||||
|
@ -2232,7 +2218,7 @@ image_t *R_CreateImage(const char *name, byte *pic, int width, int height, imgTy
|
||||||
|
|
||||||
void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int height )
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===================================================================
|
//===================================================================
|
||||||
|
|
Loading…
Reference in a new issue