static cachepic_t cachepics[MAX_CACHED_PICS];
static int numcachepics;
-static rtexturepool_t *drawtexturepool;
+rtexturepool_t *drawtexturepool;
static const unsigned char concharimage[FONT_FILESIZE] =
{
return r_texture_notexture;
}
+int draw_frame = 1;
/*
================
cachepic_t *Draw_CachePic_Flags(const char *path, unsigned int cachepicflags)
{
int crc, hashkey;
- unsigned char *pixels;
+ unsigned char *pixels = NULL;
cachepic_t *pic;
fs_offset_t lmpsize;
unsigned char *lmpdata;
char lmpname[MAX_QPATH];
int texflags;
int j;
+ qboolean ddshasalpha;
+ float ddsavgcolor[4];
+ qboolean loaded = false;
texflags = TEXF_ALPHA;
if (!(cachepicflags & CACHEPICFLAG_NOCLAMP))
texflags |= TEXF_CLAMP;
- if (!(cachepicflags & CACHEPICFLAG_NOCOMPRESSION) && gl_texturecompression_2d.integer)
+ if (!(cachepicflags & CACHEPICFLAG_NOCOMPRESSION) && gl_texturecompression_2d.integer && gl_texturecompression.integer)
texflags |= TEXF_COMPRESS;
// check whether the picture has already been cached
crc = CRC_Block((unsigned char *)path, strlen(path));
hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
for (pic = cachepichash[hashkey];pic;pic = pic->chain)
+ {
if (!strcmp (path, pic->name))
- if(!((pic->texflags ^ texflags) & ~(TEXF_COMPRESS))) // ignore TEXF_COMPRESS when comparing, because fallback pics remove the flag
+ {
+ // if it was created (or replaced) by Draw_NewPic, just return it
+ if(pic->flags & CACHEPICFLAG_NEWPIC)
+ return pic;
+ if (!((pic->texflags ^ texflags) & ~(TEXF_COMPRESS))) // ignore TEXF_COMPRESS when comparing, because fallback pics remove the flag
{
if(!(cachepicflags & CACHEPICFLAG_NOTPERSISTENT))
{
}
return pic;
}
+ }
+ }
if (numcachepics == MAX_CACHED_PICS)
{
reload:
// check whether it is an dynamic texture (if so, we can directly use its texture handler)
+ pic->flags = cachepicflags;
pic->tex = CL_GetDynTexture( path );
// if so, set the width/height, too
if( pic->tex ) {
pic->hasalpha = true; // assume alpha unless we know it has none
pic->texflags = texflags;
pic->autoload = (cachepicflags & CACHEPICFLAG_NOTPERSISTENT);
+ pic->lastusedframe = draw_frame;
// load a high quality image from disk if possible
- pixels = loadimagepixelsbgra(path, false, true, r_texture_convertsRGB_2d.integer != 0, NULL);
- if (pixels == NULL && !strncmp(path, "gfx/", 4))
- pixels = loadimagepixelsbgra(path+4, false, true, r_texture_convertsRGB_2d.integer != 0, NULL);
- if (pixels)
+ if (!loaded && r_texture_dds_load.integer != 0 && (pic->tex = R_LoadTextureDDSFile(drawtexturepool, va("dds/%s.dds", pic->name), pic->texflags, &ddshasalpha, ddsavgcolor, 0)))
{
+ // note this loads even if autoload is true, otherwise we can't get the width/height
+ loaded = true;
+ pic->hasalpha = ddshasalpha;
+ pic->width = R_TextureWidth(pic->tex);
+ pic->height = R_TextureHeight(pic->tex);
+ }
+ if (!loaded && ((pixels = loadimagepixelsbgra(pic->name, false, true, false, NULL)) || (!strncmp(pic->name, "gfx/", 4) && (pixels = loadimagepixelsbgra(pic->name+4, false, true, false, NULL)))))
+ {
+ loaded = true;
pic->hasalpha = false;
if (pic->texflags & TEXF_ALPHA)
{
pic->width = image_width;
pic->height = image_height;
if (!pic->autoload)
- pic->tex = R_LoadTexture2D(drawtexturepool, path, image_width, image_height, pixels, TEXTYPE_BGRA, pic->texflags & (pic->hasalpha ? ~0 : ~TEXF_ALPHA), -1, NULL);
+ {
+ pic->tex = R_LoadTexture2D(drawtexturepool, pic->name, image_width, image_height, pixels, vid.sRGB2D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, pic->texflags & (pic->hasalpha ? ~0 : ~TEXF_ALPHA), -1, NULL);
+ if (r_texture_dds_save.integer && qglGetCompressedTexImageARB && pic->tex)
+ R_SaveTextureDDSFile(pic->tex, va("dds/%s.dds", pic->name), r_texture_dds_save.integer < 2, pic->hasalpha);
+ }
}
- else
+ if (!loaded)
{
pic->autoload = false;
// never compress the fallback images
// size from that even if we don't upload the texture, this way the pics
// show up the right size in the menu even if they were replaced with
// higher or lower resolution versions
- dpsnprintf(lmpname, sizeof(lmpname), "%s.lmp", path);
- if (!strncmp(path, "gfx/", 4) && (lmpdata = FS_LoadFile(lmpname, tempmempool, false, &lmpsize)))
+ dpsnprintf(lmpname, sizeof(lmpname), "%s.lmp", pic->name);
+ if (!strncmp(pic->name, "gfx/", 4) && (lmpdata = FS_LoadFile(lmpname, tempmempool, false, &lmpsize)))
{
if (developer_loading.integer)
- Con_Printf("loading lump \"%s\"\n", path);
+ Con_Printf("loading lump \"%s\"\n", pic->name);
if (lmpsize >= 9)
{
pic->width = lmpdata[0] + lmpdata[1] * 256 + lmpdata[2] * 65536 + lmpdata[3] * 16777216;
pic->height = lmpdata[4] + lmpdata[5] * 256 + lmpdata[6] * 65536 + lmpdata[7] * 16777216;
// if no high quality replacement image was found, upload the original low quality texture
- if (!pixels)
- pic->tex = R_LoadTexture2D(drawtexturepool, path, pic->width, pic->height, lmpdata + 8, TEXTYPE_PALETTE, pic->texflags, -1, palette_bgra_transparent);
+ if (!loaded)
+ {
+ loaded = true;
+ pic->tex = R_LoadTexture2D(drawtexturepool, pic->name, pic->width, pic->height, lmpdata + 8, vid.sRGB2D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, pic->texflags, -1, palette_bgra_transparent);
+ }
}
Mem_Free(lmpdata);
}
- else if ((lmpdata = W_GetLumpName (path + 4)))
+ else if ((lmpdata = W_GetLumpName (pic->name + 4)))
{
if (developer_loading.integer)
- Con_Printf("loading gfx.wad lump \"%s\"\n", path + 4);
+ Con_Printf("loading gfx.wad lump \"%s\"\n", pic->name + 4);
- if (!strcmp(path, "gfx/conchars"))
+ if (!strcmp(pic->name, "gfx/conchars"))
{
// conchars is a raw image and with color 0 as transparent instead of 255
pic->width = 128;
pic->height = 128;
// if no high quality replacement image was found, upload the original low quality texture
- if (!pixels)
- pic->tex = R_LoadTexture2D(drawtexturepool, path, 128, 128, lmpdata, TEXTYPE_PALETTE, pic->texflags, -1, palette_bgra_font);
+ if (!loaded)
+ {
+ loaded = true;
+ pic->tex = R_LoadTexture2D(drawtexturepool, pic->name, 128, 128, lmpdata, vid.sRGB2D != 0 ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, pic->texflags, -1, palette_bgra_font);
+ }
}
else
{
pic->width = lmpdata[0] + lmpdata[1] * 256 + lmpdata[2] * 65536 + lmpdata[3] * 16777216;
pic->height = lmpdata[4] + lmpdata[5] * 256 + lmpdata[6] * 65536 + lmpdata[7] * 16777216;
// if no high quality replacement image was found, upload the original low quality texture
- if (!pixels)
- pic->tex = R_LoadTexture2D(drawtexturepool, path, pic->width, pic->height, lmpdata + 8, TEXTYPE_PALETTE, pic->texflags, -1, palette_bgra_transparent);
+ if (!loaded)
+ {
+ loaded = true;
+ pic->tex = R_LoadTexture2D(drawtexturepool, pic->name, pic->width, pic->height, lmpdata + 8, vid.sRGB2D != 0 ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, pic->texflags, -1, palette_bgra_transparent);
+ }
}
}
Mem_Free(pixels);
pixels = NULL;
}
- else if (pic->tex == NULL)
+ if (!loaded)
{
// if it's not found on disk, generate an image
- pic->tex = draw_generatepic(path, (cachepicflags & CACHEPICFLAG_QUIET) != 0);
+ pic->tex = draw_generatepic(pic->name, (cachepicflags & CACHEPICFLAG_QUIET) != 0);
pic->width = R_TextureWidth(pic->tex);
pic->height = R_TextureHeight(pic->tex);
}
return Draw_CachePic_Flags (path, 0); // default to persistent!
}
-int draw_frame = 1;
-
rtexture_t *Draw_GetPicTexture(cachepic_t *pic)
{
if (pic->autoload && !pic->tex)
{
- pic->tex = loadtextureimage(drawtexturepool, pic->name, false, pic->texflags, true, r_texture_convertsRGB_2d.integer != 0);
+ if (pic->tex == NULL && r_texture_dds_load.integer != 0)
+ {
+ qboolean ddshasalpha;
+ float ddsavgcolor[4];
+ pic->tex = R_LoadTextureDDSFile(drawtexturepool, va("dds/%s.dds", pic->name), pic->texflags, &ddshasalpha, ddsavgcolor, 0);
+ }
+ if (pic->tex == NULL)
+ {
+ pic->tex = loadtextureimage(drawtexturepool, pic->name, false, pic->texflags, true, vid.sRGB2D);
+ if (r_texture_dds_save.integer && qglGetCompressedTexImageARB && pic->tex)
+ R_SaveTextureDDSFile(pic->tex, va("dds/%s.dds", pic->name), r_texture_dds_save.integer < 2, pic->hasalpha);
+ }
if (pic->tex == NULL && !strncmp(pic->name, "gfx/", 4))
- pic->tex = loadtextureimage(drawtexturepool, pic->name+4, false, pic->texflags, true, r_texture_convertsRGB_2d.integer != 0);
+ {
+ pic->tex = loadtextureimage(drawtexturepool, pic->name+4, false, pic->texflags, true, vid.sRGB2D);
+ if (r_texture_dds_save.integer && qglGetCompressedTexImageARB && pic->tex)
+ R_SaveTextureDDSFile(pic->tex, va("dds/%s.dds", pic->name), r_texture_dds_save.integer < 2, pic->hasalpha);
+ }
if (pic->tex == NULL)
pic->tex = draw_generatepic(pic->name, true);
}
if (pic)
{
- if (pic->tex && pic->width == width && pic->height == height)
+ if (pic->flags == CACHEPICFLAG_NEWPIC && pic->tex && pic->width == width && pic->height == height)
{
- R_UpdateTexture(pic->tex, pixels_bgra, 0, 0, width, height);
+ R_UpdateTexture(pic->tex, pixels_bgra, 0, 0, 0, width, height, 1);
return pic;
}
}
}
}
+ pic->flags = CACHEPICFLAG_NEWPIC; // disable texflags checks in Draw_CachePic
pic->width = width;
pic->height = height;
if (pic->tex)
r_refdef.draw2dstage = 1;
CHECKGLERROR
R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.y - r_refdef.view.height, r_refdef.view.width, r_refdef.view.height, 0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100, NULL);
+ R_Mesh_ResetRenderTargets();
R_SetViewport(&viewport);
GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
GL_DepthFunc(GL_LEQUAL);
width = pic->width;
if (height == 0)
height = pic->height;
- R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1);
+ R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1, true);
#if 0
// AK07: lets be texel correct on the corners
#endif
}
else
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
floats[2] = floats[5] = floats[8] = floats[11] = 0;
floats[0] = floats[9] = x;
width = pic->width;
if (height == 0)
height = pic->height;
- R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1);
+ R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1, true);
}
else
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
floats[2] = floats[5] = floats[8] = floats[11] = 0;
return;
// R_Mesh_ResetTextureState();
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
floats[2] = floats[5] = floats[8] = floats[11] = 0;
floats[0] = floats[9] = x;
// R_Mesh_ResetTextureState();
if (!fontmap)
R_Mesh_TexBind(0, fnt->tex);
- R_SetupShader_Generic(fnt->tex, NULL, GL_MODULATE, 1);
+ R_SetupShader_Generic(fnt->tex, NULL, GL_MODULATE, 1, true);
ac = color4f;
at = texcoord2f;
at = texcoord2f;
av = vertex3f;
}
- R_SetupShader_Generic(fnt->tex, NULL, GL_MODULATE, 1);
+ R_SetupShader_Generic(fnt->tex, NULL, GL_MODULATE, 1, true);
map = ft2_oldstyle_map;
}
}
break;
}
}
- R_SetupShader_Generic(map->texture, NULL, GL_MODULATE, 1);
+ R_SetupShader_Generic(map->pic->tex, NULL, GL_MODULATE, 1, true);
}
mapch = ch - map->start;
width = pic->width;
if (height == 0)
height = pic->height;
- R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1);
+ R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1, true);
}
else
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
floats[2] = floats[5] = floats[8] = floats[11] = 0;
floats[0] = floats[9] = x;
DrawQ_ProcessDrawFlag(flags, hasalpha);
// R_Mesh_ResetTextureState();
- R_SetupShader_Generic(mesh->texture, NULL, GL_MODULATE, 1);
+ R_SetupShader_Generic(mesh->texture, NULL, GL_MODULATE, 1, true);
R_Mesh_PrepareVertices_Generic_Arrays(mesh->num_vertices, mesh->data_vertex3f, mesh->data_color4f, mesh->data_texcoord2f);
R_Mesh_Draw(0, mesh->num_vertices, 0, mesh->num_triangles, mesh->data_element3i, NULL, 0, mesh->data_element3s, NULL, 0);
case RENDERPATH_GL11:
case RENDERPATH_GL13:
case RENDERPATH_GL20:
- case RENDERPATH_CGGL:
CHECKGLERROR
qglBegin(GL_LINE_LOOP);
for (num = 0;num < mesh->num_vertices;num++)
case RENDERPATH_SOFT:
//Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
break;
+ case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
//Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
return;
if(!r_draw2d.integer && !r_draw2d_force)
return;
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
switch(vid.renderpath)
{
case RENDERPATH_GL11:
case RENDERPATH_GL13:
case RENDERPATH_GL20:
- case RENDERPATH_CGGL:
CHECKGLERROR
//qglLineWidth(width);CHECKGLERROR
case RENDERPATH_SOFT:
//Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
break;
+ case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
//Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
return;
case RENDERPATH_GL11:
case RENDERPATH_GL13:
case RENDERPATH_GL20:
- case RENDERPATH_CGGL:
CHECKGLERROR
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
//qglLineWidth(width);CHECKGLERROR
case RENDERPATH_SOFT:
//Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
break;
+ case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
//Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
return;
iy = (int)(0.5 + y * ((float) vid.height / vid_conheight.integer));
iw = (int)(0.5 + (x+width) * ((float)vid.width / vid_conwidth.integer)) - ix;
ih = (int)(0.5 + (y+height) * ((float) vid.height / vid_conheight.integer)) - iy;
- GL_Scissor(ix, vid.height - iy - ih, iw, ih);
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
+ case RENDERPATH_SOFT:
+ GL_Scissor(ix, vid.height - iy - ih, iw, ih);
+ break;
+ case RENDERPATH_D3D9:
+ GL_Scissor(ix, iy, iw, ih);
+ break;
+ case RENDERPATH_D3D10:
+ Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+ break;
+ case RENDERPATH_D3D11:
+ Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+ break;
+ }
GL_ScissorTest(true);
}
switch(vid.renderpath)
{
case RENDERPATH_GL20:
- case RENDERPATH_CGGL:
case RENDERPATH_D3D9:
case RENDERPATH_D3D10:
case RENDERPATH_D3D11:
if (vid_usinghwgamma || v_glslgamma.integer)
return;
break;
- case RENDERPATH_GL13:
case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
if (vid_usinghwgamma)
return;
break;
+ case RENDERPATH_GLES1:
case RENDERPATH_SOFT:
return;
}
// all the blends ignore depth
// R_Mesh_ResetTextureState();
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
GL_DepthMask(true);
GL_DepthRange(0, 1);
GL_PolygonOffset(0, 0);
GL_DepthTest(false);
+
+ // interpretation of brightness and contrast:
+ // color range := brightness .. (brightness + contrast)
+ // i.e. "c *= contrast; c += brightness"
+ // plausible values for brightness thus range from -contrast to 1
+
+ // apply pre-brightness (subtractive brightness, for where contrast was >= 1)
+ if (vid.support.ext_blend_subtract)
+ {
+ if (v_color_enable.integer)
+ {
+ c[0] = -v_color_black_r.value / v_color_white_r.value;
+ c[1] = -v_color_black_g.value / v_color_white_g.value;
+ c[2] = -v_color_black_b.value / v_color_white_b.value;
+ }
+ else
+ c[0] = c[1] = c[2] = -v_brightness.value / v_contrast.value;
+ if (c[0] >= 0.01f || c[1] >= 0.01f || c[2] >= 0.01f)
+ {
+ // need SUBTRACTIVE blending to do this!
+ GL_BlendEquationSubtract(true);
+ GL_BlendFunc(GL_ONE, GL_ONE);
+ GL_Color(c[0], c[1], c[2], 1);
+ R_Mesh_PrepareVertices_Generic_Arrays(3, blendvertex3f, NULL, NULL);
+ R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
+ GL_BlendEquationSubtract(false);
+ }
+ }
+
+ // apply contrast
if (v_color_enable.integer)
{
c[0] = v_color_white_r.value;
}
else
c[0] = c[1] = c[2] = v_contrast.value;
- if (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
+ if (c[0] >= 1.003f || c[1] >= 1.003f || c[2] >= 1.003f)
{
GL_BlendFunc(GL_DST_COLOR, GL_ONE);
- while (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
+ while (c[0] >= 1.003f || c[1] >= 1.003f || c[2] >= 1.003f)
{
- GL_Color(c[0] - 1, c[1] - 1, c[2] - 1, 1);
+ float cc[4];
+ cc[0] = bound(0, c[0] - 1, 1);
+ cc[1] = bound(0, c[1] - 1, 1);
+ cc[2] = bound(0, c[2] - 1, 1);
+ GL_Color(cc[0], cc[1], cc[2], 1);
R_Mesh_PrepareVertices_Generic_Arrays(3, blendvertex3f, NULL, NULL);
R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
- VectorScale(c, 0.5, c);
+ c[0] /= 1 + cc[0];
+ c[1] /= 1 + cc[1];
+ c[2] /= 1 + cc[2];
}
}
+ if (c[0] <= 0.997f || c[1] <= 0.997f || c[2] <= 0.997f)
+ {
+ GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
+ GL_Color(c[0], c[1], c[2], 1);
+ R_Mesh_PrepareVertices_Generic_Arrays(3, blendvertex3f, NULL, NULL);
+ R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
+ }
+
+ // apply post-brightness (additive brightness, for where contrast was <= 1)
if (v_color_enable.integer)
{
c[0] = v_color_black_r.value;
if (c[0] >= 0.01f || c[1] >= 0.01f || c[2] >= 0.01f)
{
GL_BlendFunc(GL_ONE, GL_ONE);
- GL_Color(c[0] - 1, c[1] - 1, c[2] - 1, 1);
+ GL_Color(c[0], c[1], c[2], 1);
R_Mesh_PrepareVertices_Generic_Arrays(3, blendvertex3f, NULL, NULL);
R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
}