X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=gl_draw.c;h=601413dff7a3467ccffefc55f15416f05fbf8d43;hb=72ee8739858634ef2077ab65276f14656b03f2d9;hp=b80d6fe371a3052b601945c544279ee783b84317;hpb=0fe645c29d3ae9cccbd6e60a391059a99f3fa24f;p=xonotic%2Fdarkplaces.git diff --git a/gl_draw.c b/gl_draw.c index b80d6fe3..601413df 100644 --- a/gl_draw.c +++ b/gl_draw.c @@ -318,6 +318,7 @@ cachepic_t *Draw_CachePic_Flags(const char *path, unsigned int cachepicflags) unsigned char *lmpdata; char lmpname[MAX_QPATH]; int texflags; + int j; texflags = TEXF_ALPHA; if (!(cachepicflags & CACHEPICFLAG_NOCLAMP)) @@ -330,8 +331,12 @@ cachepic_t *Draw_CachePic_Flags(const char *path, unsigned int cachepicflags) hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE; for (pic = cachepichash[hashkey];pic;pic = pic->chain) if (!strcmp (path, pic->name)) - if(pic->texflags == texflags) + if(!((pic->texflags ^ texflags) & ~(TEXF_COMPRESS))) // ignore TEXF_COMPRESS when comparing, because fallback pics remove the flag + { + if(!(cachepicflags & CACHEPICFLAG_NOTPERSISTENT)) + pic->autoload = false; // persist it return pic; + } if (numcachepics == MAX_CACHED_PICS) { @@ -355,6 +360,7 @@ cachepic_t *Draw_CachePic_Flags(const char *path, unsigned int cachepicflags) return pic; } + pic->hasalpha = true; // assume alpha unless we know it has none pic->texflags = texflags; pic->autoload = (cachepicflags & CACHEPICFLAG_NOTPERSISTENT); @@ -364,10 +370,23 @@ cachepic_t *Draw_CachePic_Flags(const char *path, unsigned int cachepicflags) pixels = loadimagepixelsbgra(path+4, false, true, r_texture_convertsRGB_2d.integer, NULL); if (pixels) { + pic->hasalpha = false; + if (pic->texflags & TEXF_ALPHA) + { + for (j = 3;j < image_width * image_height * 4;j += 4) + { + if (pixels[j] < 255) + { + pic->hasalpha = true; + break; + } + } + } + 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, -1, NULL); + pic->tex = R_LoadTexture2D(drawtexturepool, path, image_width, image_height, pixels, TEXTYPE_BGRA, pic->texflags & (pic->hasalpha ? ~0 : ~TEXF_ALPHA), -1, NULL); } else { @@ -438,7 +457,7 @@ cachepic_t *Draw_CachePic_Flags(const char *path, unsigned int cachepicflags) cachepic_t *Draw_CachePic (const char *path) { - return Draw_CachePic_Flags (path, 0); + return Draw_CachePic_Flags (path, 0); // default to persistent! } int draw_frame = 1; @@ -517,7 +536,7 @@ cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, u pic->height = height; if (pic->tex) R_FreeTexture(pic->tex); - pic->tex = R_LoadTexture2D(drawtexturepool, picname, width, height, pixels_bgra, TEXTYPE_BGRA, (alpha ? TEXF_ALPHA : 0) | TEXF_ALLOWUPDATES, -1, NULL); + pic->tex = R_LoadTexture2D(drawtexturepool, picname, width, height, pixels_bgra, TEXTYPE_BGRA, (alpha ? TEXF_ALPHA : 0), -1, NULL); return pic; } @@ -546,7 +565,7 @@ static float snap_to_pixel_x(float x, float roundUpAt); extern int con_linewidth; // to force rewrapping void LoadFont(qboolean override, const char *name, dp_font_t *fnt, float scale, float voffset) { - int i; + int i, ch; float maxwidth; char widthfile[MAX_QPATH]; char *widthbuf; @@ -610,16 +629,16 @@ void LoadFont(qboolean override, const char *name, dp_font_t *fnt, float scale, dpsnprintf(widthfile, sizeof(widthfile), "%s.width", fnt->texpath); // unspecified width == 1 (base width) - for(i = 1; i < 256; ++i) - fnt->width_of[i] = 1; + for(ch = 0; ch < 256; ++ch) + fnt->width_of[ch] = 1; // FIXME load "name.width", if it fails, fill all with 1 if((widthbuf = (char *) FS_LoadFile(widthfile, tempmempool, true, &widthbufsize))) { float extraspacing = 0; const char *p = widthbuf; - int ch = 0; + ch = 0; while(ch < 256) { if(!COM_ParseToken_Simple(&p, false, false)) @@ -641,17 +660,6 @@ void LoadFont(qboolean override, const char *name, dp_font_t *fnt, float scale, case '-': case '.': fnt->width_of[ch] = atof(com_token) + extraspacing; - if (fnt->ft2) - { - for (i = 0; i < MAX_FONT_SIZES; ++i) - { - //Font_MapForIndex(fnt->ft2, i)->width_of[ch] = snap_to_pixel_x(fnt->width_of[ch] * fnt->req_sizes[i], 0.4); - ft2_font_map_t *map = Font_MapForIndex(fnt->ft2, i); - if (!map) - break; - map->width_of[ch] = Font_SnapTo(fnt->width_of[ch], 1/map->size); - } - } ch++; break; default: @@ -680,8 +688,20 @@ void LoadFont(qboolean override, const char *name, dp_font_t *fnt, float scale, Mem_Free(widthbuf); } - maxwidth = fnt->width_of[1]; - for(i = 2; i < 256; ++i) + if(fnt->ft2) + { + for (i = 0; i < MAX_FONT_SIZES; ++i) + { + ft2_font_map_t *map = Font_MapForIndex(fnt->ft2, i); + if (!map) + break; + for(ch = 0; ch < 256; ++ch) + map->width_of[ch] = Font_SnapTo(fnt->width_of[ch], 1/map->size); + } + } + + maxwidth = fnt->width_of[0]; + for(i = 1; i < 256; ++i) maxwidth = max(maxwidth, fnt->width_of[i]); fnt->maxwidth = maxwidth; @@ -956,15 +976,15 @@ void GL_Draw_Init (void) dpsnprintf(FONT_USER(i)->title, sizeof(FONT_USER(i)->title), "user%d", j++); Cmd_AddCommand ("loadfont",LoadFont_f, "loadfont function tganame loads a font; example: loadfont console gfx/veramono; loadfont without arguments lists the available functions"); - R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap); + R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap, NULL, NULL); } -void _DrawQ_Setup(void) +static void _DrawQ_Setup(void) { r_viewport_t viewport; - if (r_refdef.draw2dstage) + if (r_refdef.draw2dstage == 1) return; - r_refdef.draw2dstage = true; + 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_SetViewport(&viewport); @@ -974,36 +994,64 @@ void _DrawQ_Setup(void) GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces R_EntityMatrix(&identitymatrix); - GL_DepthMask(true); GL_DepthRange(0, 1); GL_PolygonOffset(0, 0); GL_DepthTest(false); GL_Color(1,1,1,1); GL_AlphaTest(false); - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } -static void _DrawQ_ProcessDrawFlag(int flags) +qboolean r_draw2d_force = false; +void _DrawQ_SetupAndProcessDrawFlag(int flags, cachepic_t *pic, float alpha) { _DrawQ_Setup(); CHECKGLERROR + if(!r_draw2d.integer && !r_draw2d_force) + return; + DrawQ_ProcessDrawFlag(flags, (alpha < 1) || (pic && pic->hasalpha)); +} +void DrawQ_ProcessDrawFlag(int flags, qboolean alpha) +{ if(flags == DRAWFLAG_ADDITIVE) - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + { + GL_DepthMask(false); + GL_BlendFunc(alpha ? GL_SRC_ALPHA : GL_ONE, GL_ONE); + } else if(flags == DRAWFLAG_MODULATE) + { + GL_DepthMask(false); GL_BlendFunc(GL_DST_COLOR, GL_ZERO); + } else if(flags == DRAWFLAG_2XMODULATE) - GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR); + { + GL_DepthMask(false); + GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); + } else if(flags == DRAWFLAG_SCREEN) - GL_BlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ONE); - else + { + GL_DepthMask(false); + GL_BlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE); + } + else if(alpha) + { + GL_DepthMask(false); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + else + { + GL_DepthMask(true); + GL_BlendFunc(GL_ONE, GL_ZERO); + } } void DrawQ_Pic(float x, float y, cachepic_t *pic, float width, float height, float red, float green, float blue, float alpha, int flags) { float floats[20]; - _DrawQ_ProcessDrawFlag(flags); + _DrawQ_SetupAndProcessDrawFlag(flags, pic, alpha); + if(!r_draw2d.integer && !r_draw2d_force) + return; + GL_Color(red, green, blue, alpha); R_Mesh_VertexPointer(floats, 0, 0); @@ -1058,7 +1106,10 @@ void DrawQ_RotPic(float x, float y, cachepic_t *pic, float width, float height, float sinar = sin(ar); float cosar = cos(ar); - _DrawQ_ProcessDrawFlag(flags); + _DrawQ_SetupAndProcessDrawFlag(flags, pic, alpha); + if(!r_draw2d.integer && !r_draw2d_force) + return; + GL_Color(red, green, blue, alpha); R_Mesh_VertexPointer(floats, 0, 0); @@ -1106,7 +1157,10 @@ void DrawQ_Fill(float x, float y, float width, float height, float red, float gr { float floats[12]; - _DrawQ_ProcessDrawFlag(flags); + _DrawQ_SetupAndProcessDrawFlag(flags, NULL, alpha); + if(!r_draw2d.integer && !r_draw2d_force) + return; + GL_Color(red, green, blue, alpha); R_Mesh_VertexPointer(floats, 0, 0); @@ -1423,7 +1477,9 @@ float DrawQ_String_Scale(float startx, float starty, const char *text, size_t ma if (maxlen < 1) maxlen = 1<<30; - _DrawQ_ProcessDrawFlag(flags); + _DrawQ_SetupAndProcessDrawFlag(flags, NULL, 0); + if(!r_draw2d.integer && !r_draw2d_force) + return startx + DrawQ_TextWidth_UntilWidth_TrackColors_Scale(text, &maxlen, w, h, sw, sh, NULL, ignorecolorcodes, fnt, 1000000000); R_Mesh_ColorPointer(color4f, 0, 0); R_Mesh_ResetTextureState(); @@ -1761,7 +1817,9 @@ void DrawQ_SuperPic(float x, float y, cachepic_t *pic, float width, float height { float floats[36]; - _DrawQ_ProcessDrawFlag(flags); + _DrawQ_SetupAndProcessDrawFlag(flags, pic, a1*a2*a3*a4); + if(!r_draw2d.integer && !r_draw2d_force) + return; R_Mesh_VertexPointer(floats, 0, 0); R_Mesh_ColorPointer(floats + 20, 0, 0); @@ -1795,9 +1853,13 @@ void DrawQ_SuperPic(float x, float y, cachepic_t *pic, float width, float height R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); } -void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags) +void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags, qboolean hasalpha) { - _DrawQ_ProcessDrawFlag(flags); + _DrawQ_Setup(); + CHECKGLERROR + if(!r_draw2d.integer && !r_draw2d_force) + return; + DrawQ_ProcessDrawFlag(flags, hasalpha); R_Mesh_VertexPointer(mesh->data_vertex3f, 0, 0); R_Mesh_ColorPointer(mesh->data_color4f, 0, 0); @@ -1812,7 +1874,9 @@ void DrawQ_LineLoop (drawqueuemesh_t *mesh, int flags) { int num; - _DrawQ_ProcessDrawFlag(flags); + _DrawQ_SetupAndProcessDrawFlag(flags, NULL, 1); + if(!r_draw2d.integer && !r_draw2d_force) + return; GL_Color(1,1,1,1); CHECKGLERROR @@ -1830,7 +1894,9 @@ void DrawQ_LineLoop (drawqueuemesh_t *mesh, int flags) //[515]: this is old, delete void DrawQ_Line (float width, float x1, float y1, float x2, float y2, float r, float g, float b, float alpha, int flags) { - _DrawQ_ProcessDrawFlag(flags); + _DrawQ_SetupAndProcessDrawFlag(flags, NULL, alpha); + if(!r_draw2d.integer && !r_draw2d_force) + return; R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); @@ -1855,8 +1921,8 @@ void DrawQ_SetClipArea(float x, float y, float width, float height) // OGL uses top to bottom ix = (int)(0.5 + x * ((float)vid.width / vid_conwidth.integer)); iy = (int)(0.5 + y * ((float) vid.height / vid_conheight.integer)); - iw = (int)(width * ((float)vid.width / vid_conwidth.integer)); - ih = (int)(height * ((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); GL_ScissorTest(true); @@ -1870,7 +1936,13 @@ void DrawQ_ResetClipArea(void) void DrawQ_Finish(void) { - r_refdef.draw2dstage = false; + r_refdef.draw2dstage = 0; +} + +void DrawQ_RecalcView(void) +{ + if(r_refdef.draw2dstage) + r_refdef.draw2dstage = -1; // next draw call will set viewport etc. again } static float blendvertex3f[9] = {-5000, -5000, 10, 10000, -5000, 10, -5000, 10000, 10};