]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_draw.c
Change MAX_TEXTUREUNITS from 16 to 32 - this fixes a memory corruption that was causi...
[xonotic/darkplaces.git] / gl_draw.c
index 47a90f9c48b1115dfad4f04e670e44d9fa57bd18..c61fa3669f8b64745e8e8b789296c61cd38fa4c9 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -105,32 +105,37 @@ cachepic_t *Draw_CachePic_Flags(const char *path, unsigned int cachepicflags)
                if (!strcmp(path, pic->name))
                {
                        // if it was created (or replaced) by Draw_NewPic, just return it
-                       if (pic->flags & CACHEPICFLAG_NEWPIC)
-                       {
-                               if (pic->skinframe)
-                                       R_SkinFrame_MarkUsed(pic->skinframe);
-                               pic->lastusedframe = draw_frame;
-                               return pic;
-                       }
-                       if (!((pic->texflags ^ texflags) & ~(TEXF_COMPRESS | TEXF_MIPMAP))) // ignore TEXF_COMPRESS when comparing, because fallback pics remove the flag, and ignore TEXF_MIPMAP because QC specifies that
+                       if (!(pic->flags & CACHEPICFLAG_NEWPIC))
                        {
+                               // reload the pic if texflags changed in important ways
+                               // ignore TEXF_COMPRESS when comparing, because fallback pics remove the flag, and ignore TEXF_MIPMAP because QC specifies that
+                               if ((pic->texflags ^ texflags) & ~(TEXF_COMPRESS | TEXF_MIPMAP))
+                               {
+                                       Con_DPrintf("Draw_CachePic(\"%s\"): frame %i: reloading pic due to mismatch on flags\n", path, draw_frame);
+                                       goto reload;
+                               }
                                if (!pic->skinframe || !pic->skinframe->base)
+                               {
+                                       Con_DPrintf("Draw_CachePic(\"%s\"): frame %i: reloading pic\n", path, draw_frame);
                                        goto reload;
+                               }
                                if (!(cachepicflags & CACHEPICFLAG_NOTPERSISTENT))
                                        pic->autoload = false; // caller is making this pic persistent
-                               R_SkinFrame_MarkUsed(pic->skinframe);
-                               pic->lastusedframe = draw_frame;
-                               return pic;
                        }
+                       if (pic->skinframe)
+                               R_SkinFrame_MarkUsed(pic->skinframe);
+                       pic->lastusedframe = draw_frame;
+                       return pic;
                }
        }
 
        if (numcachepics == MAX_CACHED_PICS)
        {
-               Con_Printf ("Draw_CachePic: numcachepics == MAX_CACHED_PICS\n");
+               Con_Printf ("Draw_CachePic(\"%s\"): frame %i: numcachepics == MAX_CACHED_PICS\n", path, draw_frame);
                // FIXME: support NULL in callers?
                return cachepics; // return the first one
        }
+       Con_DPrintf("Draw_CachePic(\"%s\"): frame %i: loading pic%s\n", path, draw_frame, (cachepicflags & CACHEPICFLAG_NOTPERSISTENT) ? " notpersist" : "");
        pic = cachepics + (numcachepics++);
        memset(pic, 0, sizeof(*pic));
        strlcpy (pic->name, path, sizeof(pic->name));
@@ -147,8 +152,16 @@ reload:
        pic->autoload = (cachepicflags & CACHEPICFLAG_NOTPERSISTENT) != 0;
        pic->lastusedframe = draw_frame;
 
-       // load high quality image (this falls back to low quality too)
-       pic->skinframe = R_SkinFrame_LoadExternal(pic->name, texflags | TEXF_FORCE_RELOAD, (cachepicflags & CACHEPICFLAG_QUIET) == 0, (cachepicflags & CACHEPICFLAG_FAILONMISSING) == 0);
+       if (pic->skinframe)
+       {
+               // reload image after it was unloaded or texflags changed significantly
+               R_SkinFrame_LoadExternal_SkinFrame(pic->skinframe, pic->name, texflags | TEXF_FORCE_RELOAD, (cachepicflags & CACHEPICFLAG_QUIET) == 0, (cachepicflags & CACHEPICFLAG_FAILONMISSING) == 0);
+       }
+       else
+       {
+               // load high quality image (this falls back to low quality too)
+               pic->skinframe = R_SkinFrame_LoadExternal(pic->name, texflags | TEXF_FORCE_RELOAD, (cachepicflags & CACHEPICFLAG_QUIET) == 0, (cachepicflags & CACHEPICFLAG_FAILONMISSING) == 0);
+       }
 
        // get the dimensions of the image we loaded (if it was successful)
        if (pic->skinframe && pic->skinframe->base)
@@ -194,7 +207,10 @@ qboolean Draw_IsPicLoaded(cachepic_t *pic)
        if (pic == NULL)
                return false;
        if (pic->autoload && (!pic->skinframe || !pic->skinframe->base))
+       {
+               Con_DPrintf("Draw_IsPicLoaded(\"%s\"): Loading external skin\n", pic->name);
                pic->skinframe = R_SkinFrame_LoadExternal(pic->name, pic->texflags | TEXF_FORCE_RELOAD, false, true);
+       }
        // skinframe will only be NULL if the pic was created with CACHEPICFLAG_FAILONMISSING and not found
        return pic->skinframe != NULL && pic->skinframe->base != NULL;
 }
@@ -204,7 +220,10 @@ rtexture_t *Draw_GetPicTexture(cachepic_t *pic)
        if (pic == NULL)
                return NULL;
        if (pic->autoload && (!pic->skinframe || !pic->skinframe->base))
+       {
+               Con_DPrintf("Draw_GetPicTexture(\"%s\"): Loading external skin\n", pic->name);
                pic->skinframe = R_SkinFrame_LoadExternal(pic->name, pic->texflags | TEXF_FORCE_RELOAD, false, true);
+       }
        pic->lastusedframe = draw_frame;
        return pic->skinframe ? pic->skinframe->base : NULL;
 }
@@ -218,8 +237,13 @@ void Draw_Frame(void)
                return;
        nextpurgetime = realtime + 0.05;
        for (i = 0, pic = cachepics;i < numcachepics;i++, pic++)
-               if (pic->autoload && pic->skinframe && pic->skinframe->base && pic->lastusedframe < draw_frame)
+       {
+               if (pic->autoload && pic->skinframe && pic->skinframe->base && pic->lastusedframe < draw_frame - 3)
+               {
+                       Con_DPrintf("Draw_Frame(%i): Unloading \"%s\"\n", draw_frame, pic->name);
                        R_SkinFrame_PurgeSkinFrame(pic->skinframe);
+               }
+       }
        draw_frame++;
 }
 
@@ -238,20 +262,23 @@ cachepic_t *Draw_NewPic(const char *picname, int width, int height, unsigned cha
        {
                if (pic->flags & CACHEPICFLAG_NEWPIC && pic->skinframe && pic->skinframe->base && pic->width == width && pic->height == height)
                {
+                       Con_DPrintf("Draw_NewPic(\"%s\"): frame %i: updating texture\n", picname, draw_frame);
                        R_UpdateTexture(pic->skinframe->base, pixels_bgra, 0, 0, 0, width, height, 1);
                        R_SkinFrame_MarkUsed(pic->skinframe);
                        pic->lastusedframe = draw_frame;
                        return pic;
                }
+               Con_Printf("Draw_NewPic(\"%s\"): frame %i: reloading pic because flags/size changed\n", picname, draw_frame);
        }
        else
        {
                if (numcachepics == MAX_CACHED_PICS)
                {
-                       Con_Printf ("Draw_NewPic: numcachepics == MAX_CACHED_PICS\n");
+                       Con_Printf ("Draw_NewPic(\"%s\"): frame %i: numcachepics == MAX_CACHED_PICS\n", picname, draw_frame);
                        // FIXME: support NULL in callers?
                        return cachepics; // return the first one
                }
+               Con_Printf("Draw_NewPic(\"%s\"): frame %i: creating new cachepic\n", picname, draw_frame);
                pic = cachepics + (numcachepics++);
                memset(pic, 0, sizeof(*pic));
                strlcpy (pic->name, picname, sizeof(pic->name));
@@ -262,6 +289,7 @@ cachepic_t *Draw_NewPic(const char *picname, int width, int height, unsigned cha
 
        R_SkinFrame_PurgeSkinFrame(pic->skinframe);
 
+       pic->autoload = false;
        pic->flags = CACHEPICFLAG_NEWPIC; // disable texflags checks in Draw_CachePic
        pic->flags |= (texflags & TEXF_CLAMP) ? 0 : CACHEPICFLAG_NOCLAMP;
        pic->flags |= (texflags & TEXF_FORCENEAREST) ? CACHEPICFLAG_NEAREST : 0;
@@ -284,9 +312,8 @@ void Draw_FreePic(const char *picname)
        {
                if (!strcmp (picname, pic->name) && pic->skinframe)
                {
+                       Con_DPrintf("Draw_FreePic(\"%s\"): frame %i: freeing pic\n", picname, draw_frame);
                        R_SkinFrame_PurgeSkinFrame(pic->skinframe);
-                       pic->width = 0;
-                       pic->height = 0;
                        return;
                }
        }
@@ -759,6 +786,8 @@ void DrawQ_Pic(float x, float y, cachepic_t *pic, float width, float height, flo
        int e0, e1, e2, e3;
        if (!pic)
                pic = Draw_CachePic("white");
+       // make sure pic is loaded - we don't use the texture here, Mod_Mesh_GetTexture looks up the skinframe by name
+       Draw_GetPicTexture(pic);
        if (width == 0)
                width = pic->width;
        if (height == 0)
@@ -785,6 +814,8 @@ void DrawQ_RotPic(float x, float y, cachepic_t *pic, float width, float height,
        int e0, e1, e2, e3;
        if (!pic)
                pic = Draw_CachePic("white");
+       // make sure pic is loaded - we don't use the texture here, Mod_Mesh_GetTexture looks up the skinframe by name
+       Draw_GetPicTexture(pic);
        if (width == 0)
                width = pic->width;
        if (height == 0)
@@ -1379,6 +1410,8 @@ void DrawQ_SuperPic(float x, float y, cachepic_t *pic, float width, float height
        int e0, e1, e2, e3;
        if (!pic)
                pic = Draw_CachePic("white");
+       // make sure pic is loaded - we don't use the texture here, Mod_Mesh_GetTexture looks up the skinframe by name
+       Draw_GetPicTexture(pic);
        if (width == 0)
                width = pic->width;
        if (height == 0)
@@ -1431,7 +1464,7 @@ void DrawQ_SetClipArea(float x, float y, float width, float height)
        ih = (int)(0.5 + height * ((float)r_refdef.view.height / vid_conheight.integer));
        switch(vid.renderpath)
        {
-       case RENDERPATH_GL20:
+       case RENDERPATH_GL32:
        case RENDERPATH_GLES2:
                GL_Scissor(ix, vid.height - iy - ih, iw, ih);
                break;
@@ -1487,7 +1520,7 @@ void DrawQ_FlushUI(void)
                        GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                else
                        GL_BlendFunc(GL_ONE, GL_ZERO);
-               R_SetupShader_Generic(tex->currentskinframe->base, NULL, GL_MODULATE, 1, (tex->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND) ? false : true, true, false);
+               R_SetupShader_Generic(tex->currentskinframe->base, (tex->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND) ? false : true, true, false);
                R_Mesh_Draw(surf->num_firstvertex, surf->num_vertices, surf->num_firsttriangle, surf->num_triangles, mod->surfmesh.data_element3i, NULL, 0, mod->surfmesh.data_element3s, NULL, 0);
        }