X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=gl_draw.c;h=86976c858a90ea70221c594a71906397838ce510;hb=2924a0a6e6f62043eb92c77db28434ef76b86461;hp=2e1ce7a65d3c1779cbf2a1ca0c0d5e0547cf35a7;hpb=be26fc71ecb2980b8a33ada15c06545cc5b52784;p=xonotic%2Fdarkplaces.git diff --git a/gl_draw.c b/gl_draw.c index 2e1ce7a6..86976c85 100644 --- a/gl_draw.c +++ b/gl_draw.c @@ -334,8 +334,13 @@ cachepic_t *Draw_CachePic_Flags(const char *path, unsigned int cachepicflags) 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)) { @@ -346,6 +351,8 @@ cachepic_t *Draw_CachePic_Flags(const char *path, unsigned int cachepicflags) } return pic; } + } + } if (numcachepics == MAX_CACHED_PICS) { @@ -354,22 +361,31 @@ cachepic_t *Draw_CachePic_Flags(const char *path, unsigned int cachepicflags) return cachepics; // return the first one } pic = cachepics + (numcachepics++); + memset(pic, 0, sizeof(*pic)); strlcpy (pic->name, path, sizeof(pic->name)); // link into list pic->chain = cachepichash[hashkey]; cachepichash[hashkey] = pic; reload: + // TODO why does this crash? + if(pic->allow_free_tex && pic->tex) + R_PurgeTexture(pic->tex); + // 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->allow_free_tex = false; pic->width = R_TextureWidth(pic->tex); pic->height = R_TextureHeight(pic->tex); // we're done now (early-out) return pic; } + pic->allow_free_tex = true; + pic->hasalpha = true; // assume alpha unless we know it has none pic->texflags = texflags; pic->autoload = (cachepicflags & CACHEPICFLAG_NOTPERSISTENT); @@ -404,9 +420,11 @@ reload: pic->height = image_height; if (!pic->autoload) { - pic->tex = R_LoadTexture2D(drawtexturepool, pic->name, image_width, image_height, pixels, r_texture_sRGB_2d.integer ? TEXTYPE_SRGB_BGRA : 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); +#ifndef USE_GLES2 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); +#endif } } if (!loaded) @@ -431,8 +449,11 @@ reload: 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, pic->name, 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); } @@ -447,16 +468,22 @@ reload: 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, pic->name, 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, pic->name, 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); + } } } @@ -471,6 +498,7 @@ reload: pic->tex = draw_generatepic(pic->name, (cachepicflags & CACHEPICFLAG_QUIET) != 0); pic->width = R_TextureWidth(pic->tex); pic->height = R_TextureHeight(pic->tex); + pic->allow_free_tex = (pic->tex != r_texture_notexture); } return pic; @@ -493,15 +521,19 @@ rtexture_t *Draw_GetPicTexture(cachepic_t *pic) } if (pic->tex == NULL) { - pic->tex = loadtextureimage(drawtexturepool, pic->name, false, pic->texflags, true, r_texture_sRGB_2d.integer != 0); + pic->tex = loadtextureimage(drawtexturepool, pic->name, false, pic->texflags, true, vid.sRGB2D); +#ifndef USE_GLES2 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); +#endif } if (pic->tex == NULL && !strncmp(pic->name, "gfx/", 4)) { - pic->tex = loadtextureimage(drawtexturepool, pic->name+4, false, pic->texflags, true, r_texture_sRGB_2d.integer != 0); + pic->tex = loadtextureimage(drawtexturepool, pic->name+4, false, pic->texflags, true, vid.sRGB2D); +#ifndef USE_GLES2 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); +#endif } if (pic->tex == NULL) pic->tex = draw_generatepic(pic->name, true); @@ -542,7 +574,7 @@ cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, u 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, 0, width, height, 1); return pic; @@ -550,25 +582,24 @@ cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, u } else { - if (pic == NULL) + if (numcachepics == MAX_CACHED_PICS) { - if (numcachepics == MAX_CACHED_PICS) - { - Con_Printf ("Draw_NewPic: numcachepics == MAX_CACHED_PICS\n"); - // FIXME: support NULL in callers? - return cachepics; // return the first one - } - pic = cachepics + (numcachepics++); - strlcpy (pic->name, picname, sizeof(pic->name)); - // link into list - pic->chain = cachepichash[hashkey]; - cachepichash[hashkey] = pic; + Con_Printf ("Draw_NewPic: numcachepics == MAX_CACHED_PICS\n"); + // FIXME: support NULL in callers? + return cachepics; // return the first one } + pic = cachepics + (numcachepics++); + memset(pic, 0, sizeof(*pic)); + strlcpy (pic->name, picname, sizeof(pic->name)); + // link into list + pic->chain = cachepichash[hashkey]; + cachepichash[hashkey] = pic; } + pic->flags = CACHEPICFLAG_NEWPIC; // disable texflags checks in Draw_CachePic pic->width = width; pic->height = height; - if (pic->tex) + if (pic->allow_free_tex && pic->tex) R_FreeTexture(pic->tex); pic->tex = R_LoadTexture2D(drawtexturepool, picname, width, height, pixels_bgra, TEXTYPE_BGRA, (alpha ? TEXF_ALPHA : 0), -1, NULL); return pic; @@ -1123,7 +1154,7 @@ void DrawQ_Pic(float x, float y, cachepic_t *pic, float width, float height, flo 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, (flags & DRAWFLAGS_BLEND) ? false : true, true); #if 0 // AK07: lets be texel correct on the corners @@ -1139,7 +1170,7 @@ void DrawQ_Pic(float x, float y, cachepic_t *pic, float width, float height, flo #endif } else - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true); floats[2] = floats[5] = floats[8] = floats[11] = 0; floats[0] = floats[9] = x; @@ -1172,10 +1203,10 @@ void DrawQ_RotPic(float x, float y, cachepic_t *pic, float width, float height, 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, (flags & DRAWFLAGS_BLEND) ? false : true, true); } else - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true); floats[2] = floats[5] = floats[8] = floats[11] = 0; @@ -1217,7 +1248,7 @@ void DrawQ_Fill(float x, float y, float width, float height, float red, float gr return; // R_Mesh_ResetTextureState(); - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true); floats[2] = floats[5] = floats[8] = floats[11] = 0; floats[0] = floats[9] = x; @@ -1544,7 +1575,7 @@ float DrawQ_String_Scale(float startx, float starty, const char *text, size_t ma // 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, (flags & DRAWFLAGS_BLEND) ? false : true, true); ac = color4f; at = texcoord2f; @@ -1680,7 +1711,7 @@ float DrawQ_String_Scale(float startx, float starty, const char *text, size_t ma at = texcoord2f; av = vertex3f; } - R_SetupShader_Generic(fnt->tex, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(fnt->tex, NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true); map = ft2_oldstyle_map; } } @@ -1749,7 +1780,7 @@ float DrawQ_String_Scale(float startx, float starty, const char *text, size_t ma break; } } - R_SetupShader_Generic(map->pic->tex, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(map->pic->tex, NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true); } mapch = ch - map->start; @@ -1893,10 +1924,10 @@ void DrawQ_SuperPic(float x, float y, cachepic_t *pic, float width, float height 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, (flags & DRAWFLAGS_BLEND) ? false : true, true); } else - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true); floats[2] = floats[5] = floats[8] = floats[11] = 0; floats[0] = floats[9] = x; @@ -1925,7 +1956,7 @@ void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags, qboolean hasalpha) 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, (flags & DRAWFLAGS_BLEND) ? false : true, 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); @@ -1945,6 +1976,7 @@ void DrawQ_LineLoop (drawqueuemesh_t *mesh, int flags) case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GL20: +#ifndef USE_GLES2 CHECKGLERROR qglBegin(GL_LINE_LOOP); for (num = 0;num < mesh->num_vertices;num++) @@ -1955,6 +1987,7 @@ void DrawQ_LineLoop (drawqueuemesh_t *mesh, int flags) } qglEnd(); CHECKGLERROR +#endif break; case RENDERPATH_D3D9: //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); @@ -1982,13 +2015,14 @@ void DrawQ_Line (float width, float x1, float y1, float x2, float y2, float r, f if(!r_draw2d.integer && !r_draw2d_force) return; - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true); switch(vid.renderpath) { case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GL20: +#ifndef USE_GLES2 CHECKGLERROR //qglLineWidth(width);CHECKGLERROR @@ -2000,6 +2034,7 @@ void DrawQ_Line (float width, float x1, float y1, float x2, float y2, float r, f qglVertex2f(x2, y2); qglEnd(); CHECKGLERROR +#endif break; case RENDERPATH_D3D9: //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); @@ -2040,7 +2075,7 @@ void DrawQ_Lines (float width, int numlines, const float *vertex3f, const float case RENDERPATH_GL20: CHECKGLERROR - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true); //qglLineWidth(width);CHECKGLERROR @@ -2145,11 +2180,41 @@ void R_DrawGamma(void) } // 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, 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; @@ -2158,17 +2223,32 @@ void R_DrawGamma(void) } 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; @@ -2180,7 +2260,7 @@ void R_DrawGamma(void) 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); }