Added Draw_GetPicWidth, Draw_GetPicHeight, Draw_IsPicLoaded functions and moved cache...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 11 Apr 2018 05:28:24 +0000 (05:28 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 11 Apr 2018 05:28:24 +0000 (05:28 +0000)
Changed Draw_CachePic to use the R_SkinFrame_LoadExternal system, and reworked font loading to use Draw_CachePic rather than keeping track of textures itself.  R_SkinFrame_LoadExternal can now load gfx.wad lumps and gfx/*.lmp files, and the embedded images have been moved to image.c as they are now returned as raw images, suitable for R_SkinFrame_LoadExternal to use.

Reworked cl_video code to not need the cl_dyntexture system (which has been removed); it still uses dynamic texture callbacks (which is a feature of rtexture_t).

Changed the parameters to Mod_LoadCustomMaterial and a few other model_shared.c functions to not assume loadmodel is the owner of memory and textures; this was necessary for Draw_CachePic to be able to use R_SkinFrame_LoadExternal.

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12385 d7cf8633-e32d-0410-b094-e92efae38249

32 files changed:
cl_dyntexture.c
cl_dyntexture.h
cl_particles.c
cl_screen.c
cl_video.c
cl_video.h
clvm_cmds.c
console.c
darkplaces-dedicated-vs2017.vcxproj
darkplaces-sdl2-vs2017.vcxproj
darkplaces-wgl-vs2017.vcxproj
draw.h
ft2.c
gl_draw.c
gl_rmain.c
gl_rsurf.c
gl_textures.c
image.c
image.h
libcurl.c
menu.c
model_alias.c
model_brush.c
model_shared.c
model_shared.h
model_sprite.c
prvm_cmds.c
r_lightning.c
render.h
sbar.c
wad.c
wad.h

index fb378de..e69de29 100644 (file)
@@ -1,93 +0,0 @@
-// Andreas Kirsch 07
-
-#include "quakedef.h"
-#include "cl_dyntexture.h"
-
-typedef struct dyntexture_s {
-       // everything after DYNAMIC_TEXTURE_PATH_PREFIX
-       char name[ MAX_QPATH + 32 ];
-       // texture pointer (points to r_texture_white at first)
-       rtexture_t *texture;
-} dyntexture_t;
-
-static dyntexture_t dyntextures[ MAX_DYNAMIC_TEXTURE_COUNT ];
-static unsigned dyntexturecount;
-
-#define DEFAULT_DYNTEXTURE r_texture_grey128
-
-static dyntexture_t * cl_finddyntexture( const char *name, qboolean warnonfailure ) {
-       unsigned i;
-       dyntexture_t *dyntexture = NULL;
-
-       // sanity checks - make sure its actually a dynamic texture path
-       if( !name || !*name || strncmp( name, CLDYNTEXTUREPREFIX, sizeof( CLDYNTEXTUREPREFIX ) - 1 ) != 0 ) {
-               // TODO: print a warning or something
-               if (warnonfailure)
-                       Con_Printf( "cl_finddyntexture: Bad dynamic texture name '%s'\n", name );
-               return NULL;
-       }
-
-       for( i = 0 ; i < dyntexturecount ; i++ ) {
-               dyntexture = &dyntextures[ i ];
-               if( dyntexture->name && strcmp( dyntexture->name, name ) == 0 ) {
-                       return dyntexture;
-               }
-       }
-
-       if( dyntexturecount == MAX_DYNAMIC_TEXTURE_COUNT ) {
-               // TODO: warn or expand the array, etc.
-               return NULL;
-       }
-       dyntexture = &dyntextures[ dyntexturecount++ ];
-       strlcpy( dyntexture->name, name, sizeof( dyntexture->name ) );
-       dyntexture->texture = DEFAULT_DYNTEXTURE;
-       return dyntexture;
-}
-
-rtexture_t * CL_GetDynTexture( const char *name ) {
-       dyntexture_t *dyntexture = cl_finddyntexture( name, false );
-       if( dyntexture ) {
-               return dyntexture->texture;
-       } else {
-               return NULL;
-       }
-}
-
-void CL_LinkDynTexture( const char *name, rtexture_t *texture ) {
-       dyntexture_t *dyntexture;
-       cachepic_t *cachepic;
-       skinframe_t *skinframe;
-
-       dyntexture = cl_finddyntexture( name, true );
-       if( !dyntexture ) {
-               Con_Printf( "CL_LinkDynTexture: internal error in cl_finddyntexture!\n" );
-               return;
-       }
-       // TODO: assert dyntexture != NULL!
-       if( dyntexture->texture != texture ) {
-               dyntexture->texture = texture;
-
-               cachepic = Draw_CachePic_Flags( name, CACHEPICFLAG_NOTPERSISTENT );
-               // TODO: assert cachepic and skinframe should be valid pointers...
-               // TODO: assert cachepic->tex = dyntexture->texture
-               cachepic->tex = texture;
-               // update cachepic's size, too
-               cachepic->width = R_TextureWidth( texture );
-               cachepic->height = R_TextureHeight( texture );
-
-               // update skinframes
-               skinframe = NULL;
-               while( (skinframe = R_SkinFrame_FindNextByName( skinframe, name )) != NULL ) {
-                       skinframe->base = texture;
-                       // simply reset the compare* attributes of skinframe
-                       skinframe->comparecrc = 0;
-                       skinframe->comparewidth = skinframe->compareheight = 0;
-                       // this is kind of hacky
-               }
-       }
-}
-
-void CL_UnlinkDynTexture( const char *name ) {
-       CL_LinkDynTexture( name, DEFAULT_DYNTEXTURE );
-}
-
index 130dc16..e69de29 100644 (file)
@@ -1,20 +0,0 @@
-// Andreas 'Black' Kirsch 07
-#ifndef CL_DYNTEXTURE_H
-#define CL_DYNTEXTURE_H
-
-#define CLDYNTEXTUREPREFIX                     "_dynamic/"
-
-// always path fully specified names to the dynamic texture functions! (ie. with the _dynamic/ prefix, etc.!)
-
-// return a valid texture handle for a dynamic texture (might be filler texture if it hasnt been initialized yet)
-// or NULL if its not a valid dynamic texture name
-rtexture_t * CL_GetDynTexture( const char *name );
-
-// link a texture handle as dynamic texture and update texture handles in the renderer and draw_* accordingly
-void CL_LinkDynTexture( const char *name, rtexture_t *texture );
-
-// unlink a texture handle from its name
-void CL_UnlinkDynTexture( const char *name );
-
-#endif
-
index 9d64080..b159698 100644 (file)
@@ -2180,7 +2180,7 @@ static void R_InitParticleTexture (void)
        // we invert it again during the blendfunc to make it work...
 
 #ifndef DUMPPARTICLEFONT
-       decalskinframe = R_SkinFrame_LoadExternal("particles/particlefont.tga", TEXF_ALPHA | TEXF_FORCELINEAR | TEXF_RGBMULTIPLYBYALPHA, false);
+       decalskinframe = R_SkinFrame_LoadExternal("particles/particlefont.tga", TEXF_ALPHA | TEXF_FORCELINEAR | TEXF_RGBMULTIPLYBYALPHA, false, false);
        if (decalskinframe)
        {
                particlefonttexture = decalskinframe->base;
@@ -2427,12 +2427,7 @@ static void R_InitParticleTexture (void)
                                Con_Printf("particles/particlefont.txt: texnum %i outside valid range (0 to %i)\n", i, MAX_PARTICLETEXTURES);
                                continue;
                        }
-                       sf = R_SkinFrame_LoadExternal(texturename, TEXF_ALPHA | TEXF_FORCELINEAR | TEXF_RGBMULTIPLYBYALPHA, true); // note: this loads as sRGB if sRGB is active!
-                       if(!sf)
-                       {
-                               // R_SkinFrame_LoadExternal already complained
-                               continue;
-                       }
+                       sf = R_SkinFrame_LoadExternal(texturename, TEXF_ALPHA | TEXF_FORCELINEAR | TEXF_RGBMULTIPLYBYALPHA, true, true); // note: this loads as sRGB if sRGB is active!
                        particletexture[i].texture = sf->base;
                        particletexture[i].s1 = s1;
                        particletexture[i].t1 = t1;
index abde749..ece99e9 100644 (file)
@@ -457,7 +457,7 @@ static void SCR_DrawPause (void)
                return;
 
        pic = Draw_CachePic ("gfx/pause");
-       DrawQ_Pic ((vid_conwidth.integer - pic->width)/2, (vid_conheight.integer - pic->height)/2, pic, 0, 0, 1, 1, 1, 1, 0);
+       DrawQ_Pic ((vid_conwidth.integer - Draw_GetPicWidth(pic))/2, (vid_conheight.integer - Draw_GetPicHeight(pic))/2, pic, 0, 0, 1, 1, 1, 1, 0);
 }
 
 /*
@@ -479,26 +479,26 @@ static void SCR_DrawBrand (void)
        {
        case 1: // bottom left
                x = 0;
-               y = vid_conheight.integer - pic->height;
+               y = vid_conheight.integer - Draw_GetPicHeight(pic);
                break;
        case 2: // bottom centre
-               x = (vid_conwidth.integer - pic->width) / 2;
-               y = vid_conheight.integer - pic->height;
+               x = (vid_conwidth.integer - Draw_GetPicWidth(pic)) / 2;
+               y = vid_conheight.integer - Draw_GetPicHeight(pic);
                break;
        case 3: // bottom right
-               x = vid_conwidth.integer - pic->width;
-               y = vid_conheight.integer - pic->height;
+               x = vid_conwidth.integer - Draw_GetPicWidth(pic);
+               y = vid_conheight.integer - Draw_GetPicHeight(pic);
                break;
        case 4: // centre right
-               x = vid_conwidth.integer - pic->width;
-               y = (vid_conheight.integer - pic->height) / 2;
+               x = vid_conwidth.integer - Draw_GetPicWidth(pic);
+               y = (vid_conheight.integer - Draw_GetPicHeight(pic)) / 2;
                break;
        case 5: // top right
-               x = vid_conwidth.integer - pic->width;
+               x = vid_conwidth.integer - Draw_GetPicWidth(pic);
                y = 0;
                break;
        case 6: // top centre
-               x = (vid_conwidth.integer - pic->width) / 2;
+               x = (vid_conwidth.integer - Draw_GetPicWidth(pic)) / 2;
                y = 0;
                break;
        case 7: // top left
@@ -507,7 +507,7 @@ static void SCR_DrawBrand (void)
                break;
        case 8: // centre left
                x = 0;
-               y = (vid_conheight.integer - pic->height) / 2;
+               y = (vid_conheight.integer - Draw_GetPicHeight(pic)) / 2;
                break;
        default:
                return;
@@ -2070,9 +2070,9 @@ static void SCR_DrawTouchscreenOverlay(void)
                        DrawQ_Fill(a->rect[0] +              1, a->rect[1] + a->rect[3] - 2, a->rect[2] - 2,          1    , 1, 1, 1, vid_touchscreen_outlinealpha.value * (0.5f + 0.5f * a->active), 0);
                        DrawQ_Fill(a->rect[0] +              2, a->rect[1] + a->rect[3] - 1, a->rect[2] - 4,          1    , 1, 1, 1, vid_touchscreen_outlinealpha.value * (0.5f + 0.5f * a->active), 0);
                }
-               pic = a->pic ? Draw_CachePic(a->pic) : NULL;
-               if (pic && pic->tex != r_texture_notexture)
-                       DrawQ_Pic(a->rect[0], a->rect[1], Draw_CachePic(a->pic), a->rect[2], a->rect[3], 1, 1, 1, vid_touchscreen_overlayalpha.value * (0.5f + 0.5f * a->active), 0);
+               pic = a->pic ? Draw_CachePic_Flags(a->pic, CACHEPICFLAG_FAILONMISSING) : NULL;
+               if (Draw_IsPicLoaded(pic))
+                       DrawQ_Pic(a->rect[0], a->rect[1], pic, a->rect[2], a->rect[3], 1, 1, 1, vid_touchscreen_overlayalpha.value * (0.5f + 0.5f * a->active), 0);
                if (a->text && a->text[0])
                {
                        int textwidth = DrawQ_TextWidth(a->text, 0, a->textheight, a->textheight, false, FONT_CHAT);
@@ -2499,8 +2499,8 @@ static void SCR_DrawLoadingScreen_SharedSetup (qboolean clear)
        // draw the loading plaque
        loadingscreenpic = Draw_CachePic_Flags (loadingscreenpic_number ? va(vabuf, sizeof(vabuf), "%s%d", scr_loadingscreen_picture.string, loadingscreenpic_number+1) : scr_loadingscreen_picture.string, loadingscreenpic_number ? CACHEPICFLAG_NOTPERSISTENT : 0);
 
-       w = loadingscreenpic->width;
-       h = loadingscreenpic->height;
+       w = Draw_GetPicWidth(loadingscreenpic);
+       h = Draw_GetPicHeight(loadingscreenpic);
 
        // apply scale
        w *= scr_loadingscreen_scale.value;
index bcaa85b..7543c30 100644 (file)
@@ -1,6 +1,5 @@
 
 #include "quakedef.h"
-#include "cl_dyntexture.h"
 #include "cl_video.h"
 
 // cvars
@@ -72,22 +71,20 @@ static qboolean OpenStream( clvideo_t * video )
 static void VideoUpdateCallback(rtexture_t *rt, void *data)
 {
        clvideo_t *video = (clvideo_t *) data;
-       R_UpdateTexture( video->cpif.tex, (unsigned char *)video->imagedata, 0, 0, 0, video->cpif.width, video->cpif.height, 1 );
+       Draw_NewPic(video->name, video->width, video->height, (unsigned char *)video->imagedata, TEXTYPE_BGRA, TEXF_CLAMP);
 }
 
 static void LinkVideoTexture( clvideo_t *video )
 {
-       video->cpif.tex = R_LoadTexture2D( cl_videotexturepool, video->cpif.name, video->cpif.width, video->cpif.height, NULL, TEXTYPE_BGRA, TEXF_PERSISTENT | TEXF_CLAMP, -1, NULL );
-       R_MakeTextureDynamic( video->cpif.tex, VideoUpdateCallback, video );
-       CL_LinkDynTexture( video->cpif.name, video->cpif.tex );
+       video->cachepic = Draw_NewPic(video->name, video->width, video->height, NULL, TEXTYPE_BGRA, TEXF_CLAMP);
+       // make R_GetTexture() call our VideoUpdateCallback
+       R_MakeTextureDynamic(Draw_GetPicTexture(video->cachepic), VideoUpdateCallback, video);
 }
 
 static void UnlinkVideoTexture( clvideo_t *video )
 {
-       CL_UnlinkDynTexture( video->cpif.name );
-       // free the texture
-       R_FreeTexture( video->cpif.tex );
-       video->cpif.tex = NULL;
+       // free the texture (this does not destroy the cachepic_t, which is eternal)
+       Draw_FreePic(video->name);
        // free the image data
        Mem_Free( video->imagedata );
 }
@@ -119,7 +116,7 @@ static qboolean WakeVideo( clvideo_t * video )
                        return false;
                }
 
-       video->imagedata = Mem_Alloc( cls.permanentmempool, video->cpif.width * video->cpif.height * cl_videobytesperpixel );
+       video->imagedata = Mem_Alloc( cls.permanentmempool, video->width * video->height * cl_videobytesperpixel );
        LinkVideoTexture( video );
 
        // update starttime
@@ -217,11 +214,12 @@ static void LoadSubtitles( clvideo_t *video, const char *subtitlesfile )
 
 static clvideo_t* OpenVideo( clvideo_t *video, const char *filename, const char *name, int owner, const char *subtitlesfile )
 {
-       strlcpy( video->filename, filename, sizeof(video->filename) );
+       strlcpy(video->filename, filename, sizeof(video->filename));
+       dpsnprintf(video->name, sizeof(video->name), CLVIDEOPREFIX "%s", name);
        video->ownertag = owner;
        if( strncmp( name, CLVIDEOPREFIX, sizeof( CLVIDEOPREFIX ) - 1 ) )
                return NULL;
-       strlcpy( video->cpif.name, name, sizeof(video->cpif.name) );
+       video->cachepic = Draw_CachePic_Flags(name, CACHEPICFLAG_NOTPERSISTENT | CACHEPICFLAG_QUIET);
 
        if( !OpenStream( video ) )
                return NULL;
@@ -232,9 +230,9 @@ static clvideo_t* OpenVideo( clvideo_t *video, const char *filename, const char
        video->lasttime = realtime;
        video->subtitles = 0;
 
-       video->cpif.width = video->getwidth( video->stream );
-       video->cpif.height = video->getheight( video->stream );
-       video->imagedata = Mem_Alloc( cls.permanentmempool, video->cpif.width * video->cpif.height * cl_videobytesperpixel );
+       video->width = video->getwidth( video->stream );
+       video->height = video->getheight( video->stream );
+       video->imagedata = Mem_Alloc( cls.permanentmempool, video->width * video->height * cl_videobytesperpixel );
        LinkVideoTexture( video );
 
        // VorteX: load simple subtitle_text file
@@ -289,7 +287,7 @@ clvideo_t *CL_GetVideoByName( const char *name )
 
        for( i = 0 ; i < cl_num_videos ; i++ )
                if( cl_videos[ i ].state != CLVIDEO_UNUSED
-                       &&      !strcmp( cl_videos[ i ].cpif.name , name ) )
+                       &&      !strcmp( cl_videos[ i ].name , name ) )
                        break;
        if( i != cl_num_videos )
                return CL_GetVideoBySlot( i );
@@ -387,7 +385,7 @@ void CL_Video_Frame(void)
                        {
                                do {
                                        video->framenum++;
-                                       if (video->decodeframe(video->stream, video->imagedata, cl_videormask, cl_videogmask, cl_videobmask, cl_videobytesperpixel, cl_videobytesperpixel * video->cpif.width))
+                                       if (video->decodeframe(video->stream, video->imagedata, cl_videormask, cl_videogmask, cl_videobmask, cl_videobytesperpixel, cl_videobytesperpixel * video->width))
                                        { 
                                                // finished?
                                                CL_RestartVideo(video);
@@ -396,7 +394,7 @@ void CL_Video_Frame(void)
                                                return;
                                        }
                                } while(video->framenum < destframe);
-                               R_MarkDirtyTexture(video->cpif.tex);
+                               R_MarkDirtyTexture(Draw_GetPicTexture(video->cachepic));
                        }
                }
        }
@@ -557,12 +555,12 @@ void CL_DrawVideo(void)
 
        // draw video
        if (v_glslgamma_video.value >= 1)
-               DrawQ_SuperPic(px, py, &video->cpif, sx, sy, st[0], st[1], b, b, b, 1, st[2], st[3], b, b, b, 1, st[4], st[5], b, b, b, 1, st[6], st[7], b, b, b, 1, 0);
+               DrawQ_SuperPic(px, py, video->cachepic, sx, sy, st[0], st[1], b, b, b, 1, st[2], st[3], b, b, b, 1, st[4], st[5], b, b, b, 1, st[6], st[7], b, b, b, 1, 0);
        else
        {
-               DrawQ_SuperPic(px, py, &video->cpif, sx, sy, st[0], st[1], b, b, b, 1, st[2], st[3], b, b, b, 1, st[4], st[5], b, b, b, 1, st[6], st[7], b, b, b, 1, DRAWFLAG_NOGAMMA);
+               DrawQ_SuperPic(px, py, video->cachepic, sx, sy, st[0], st[1], b, b, b, 1, st[2], st[3], b, b, b, 1, st[4], st[5], b, b, b, 1, st[6], st[7], b, b, b, 1, DRAWFLAG_NOGAMMA);
                if (v_glslgamma_video.value > 0.0)
-                       DrawQ_SuperPic(px, py, &video->cpif, sx, sy, st[0], st[1], b, b, b, v_glslgamma_video.value, st[2], st[3], b, b, b, v_glslgamma_video.value, st[4], st[5], b, b, b, v_glslgamma_video.value, st[6], st[7], b, b, b, v_glslgamma_video.value, 0);
+                       DrawQ_SuperPic(px, py, video->cachepic, sx, sy, st[0], st[1], b, b, b, v_glslgamma_video.value, st[2], st[3], b, b, b, v_glslgamma_video.value, st[4], st[5], b, b, b, v_glslgamma_video.value, st[6], st[7], b, b, b, v_glslgamma_video.value, 0);
        }
 
 #ifndef USE_GLES2
@@ -600,13 +598,12 @@ void CL_DrawVideo(void)
 
 void CL_VideoStart(char *filename, const char *subtitlesfile)
 {
-       char vabuf[1024];
        Host_StartVideo();
 
        if( cl_videos->state != CLVIDEO_UNUSED )
                CL_CloseVideo( cl_videos );
        // already contains video/
-       if( !OpenVideo( cl_videos, filename, va(vabuf, sizeof(vabuf),  CLDYNTEXTUREPREFIX "%s", filename ), 0, subtitlesfile ) )
+       if( !OpenVideo( cl_videos, filename, filename, 0, subtitlesfile ) )
                return;
        // expand the active range to include the new entry
        cl_num_videos = max(cl_num_videos, 1);
index 97960b8..e96e2a4 100644 (file)
@@ -2,10 +2,7 @@
 #ifndef CL_VIDEO_H
 #define CL_VIDEO_H
 
-#include "cl_dyntexture.h"
-
-// yields DYNAMIC_TEXTURE_PATH_PREFIX CLVIDEOPREFIX video name for a path
-#define CLVIDEOPREFIX  CLDYNTEXTUREPREFIX "video/"
+#define CLVIDEOPREFIX  "video/"
 #define CLTHRESHOLD            2.0
 
 #define MENUOWNER              1
@@ -46,7 +43,11 @@ typedef struct clvideo_s
 
        void    *imagedata;
 
-       cachepic_t cpif;
+       // cachepic holds the relevant texture_t and we simply update the texture as needed
+       cachepic_t *cachepic;
+       char    name[MAX_QPATH]; // name of this video UI element (not the filename)
+       int             width;
+       int             height;
 
        // VorteX: subtitles array
        int             subtitles;
index 54848d8..27d247f 100644 (file)
@@ -1714,13 +1714,11 @@ static void VM_CL_ReadPicture (prvm_prog_t *prog)
        // if yes, it is used and the data is discarded
        // if not, the (low quality) data is used to build a new texture, whose name will get returned
 
-       pic = Draw_CachePic_Flags (name, CACHEPICFLAG_NOTPERSISTENT);
+       pic = Draw_CachePic_Flags(name, CACHEPICFLAG_NOTPERSISTENT | CACHEPICFLAG_FAILONMISSING);
 
        if(size)
        {
-               if(pic->tex == r_texture_notexture)
-                       pic->tex = NULL; // don't overwrite the notexture by Draw_NewPic
-               if(pic->tex && !cl_readpicture_force.integer)
+               if (Draw_IsPicLoaded(pic) && !cl_readpicture_force.integer)
                {
                        // texture found and loaded
                        // skip over the jpeg as we don't need it
@@ -1735,7 +1733,7 @@ static void VM_CL_ReadPicture (prvm_prog_t *prog)
                        MSG_ReadBytes(&cl_message, size, buf);
                        data = JPEG_LoadImage_BGRA(buf, size, NULL);
                        Mem_Free(buf);
-                       Draw_NewPic(name, image_width, image_height, false, data);
+                       Draw_NewPic(name, image_width, image_height, data, TEXTYPE_BGRA, TEXF_CLAMP);
                        Mem_Free(data);
                }
        }
@@ -3479,7 +3477,7 @@ static void VM_CL_R_PolygonBegin (prvm_prog_t *prog)
                while(sf && sf->textureflags != tf);
 
                if(!sf || !sf->base)
-                       sf = R_SkinFrame_LoadExternal(picname, tf, true);
+                       sf = R_SkinFrame_LoadExternal(picname, tf, true, true);
 
                if(sf)
                        R_SkinFrame_MarkUsed(sf);
index 51a1a12..6eac13e 100644 (file)
--- a/console.c
+++ b/console.c
@@ -1975,7 +1975,7 @@ void Con_DrawConsole (int lines)
                conbackpic = scr_conbrightness.value >= 0.01f ? Draw_CachePic_Flags("gfx/conback", (sx != 0 || sy != 0) ? CACHEPICFLAG_NOCLAMP : 0) : NULL;
                sx *= realtime; sy *= realtime;
                sx -= floor(sx); sy -= floor(sy);
-               if (conbackpic && conbackpic->tex != r_texture_notexture)
+               if (Draw_IsPicLoaded(conbackpic))
                        DrawQ_SuperPic(0, lines - vid_conheight.integer, conbackpic, vid_conwidth.integer, vid_conheight.integer,
                                        0 + sx, 0 + sy, scr_conbrightness.value, scr_conbrightness.value, scr_conbrightness.value, alpha,
                                        1 + sx, 0 + sy, scr_conbrightness.value, scr_conbrightness.value, scr_conbrightness.value, alpha,
@@ -1992,7 +1992,7 @@ void Con_DrawConsole (int lines)
                conbackpic = Draw_CachePic_Flags("gfx/conback2", (sx != 0 || sy != 0) ? CACHEPICFLAG_NOCLAMP : 0);
                sx *= realtime; sy *= realtime;
                sx -= floor(sx); sy -= floor(sy);
-               if(conbackpic && conbackpic->tex != r_texture_notexture)
+               if(Draw_IsPicLoaded(conbackpic))
                        DrawQ_SuperPic(0, lines - vid_conheight.integer, conbackpic, vid_conwidth.integer, vid_conheight.integer,
                                        0 + sx, 0 + sy, scr_conbrightness.value, scr_conbrightness.value, scr_conbrightness.value, alpha,
                                        1 + sx, 0 + sy, scr_conbrightness.value, scr_conbrightness.value, scr_conbrightness.value, alpha,
@@ -2007,7 +2007,7 @@ void Con_DrawConsole (int lines)
                conbackpic = Draw_CachePic_Flags("gfx/conback3", (sx != 0 || sy != 0) ? CACHEPICFLAG_NOCLAMP : 0);
                sx *= realtime; sy *= realtime;
                sx -= floor(sx); sy -= floor(sy);
-               if(conbackpic && conbackpic->tex != r_texture_notexture)
+               if(Draw_IsPicLoaded(conbackpic))
                        DrawQ_SuperPic(0, lines - vid_conheight.integer, conbackpic, vid_conwidth.integer, vid_conheight.integer,
                                        0 + sx, 0 + sy, scr_conbrightness.value, scr_conbrightness.value, scr_conbrightness.value, alpha,
                                        1 + sx, 0 + sy, scr_conbrightness.value, scr_conbrightness.value, scr_conbrightness.value, alpha,
index fd982c9..9e422ea 100644 (file)
     <ClCompile Include="cd_shared.c" />\r
     <ClCompile Include="cl_collision.c" />\r
     <ClCompile Include="cl_demo.c" />\r
-    <ClCompile Include="cl_dyntexture.c" />\r
     <ClCompile Include="cl_input.c" />\r
     <ClCompile Include="cl_main.c" />\r
     <ClCompile Include="cl_parse.c" />\r
     <ClInclude Include="cap_ogg.h" />\r
     <ClInclude Include="cdaudio.h" />\r
     <ClInclude Include="cl_collision.h" />\r
-    <ClInclude Include="cl_dyntexture.h" />\r
     <ClInclude Include="cl_gecko.h" />\r
     <ClInclude Include="cl_screen.h" />\r
     <ClInclude Include="cl_video.h" />\r
index 12b5f8a..77b60e1 100644 (file)
     <ClCompile Include="cd_shared.c" />\r
     <ClCompile Include="cl_collision.c" />\r
     <ClCompile Include="cl_demo.c" />\r
-    <ClCompile Include="cl_dyntexture.c" />\r
     <ClCompile Include="cl_input.c" />\r
     <ClCompile Include="cl_main.c" />\r
     <ClCompile Include="cl_parse.c" />\r
     <ClInclude Include="cap_ogg.h" />\r
     <ClInclude Include="cdaudio.h" />\r
     <ClInclude Include="cl_collision.h" />\r
-    <ClInclude Include="cl_dyntexture.h" />\r
     <ClInclude Include="cl_gecko.h" />\r
     <ClInclude Include="cl_screen.h" />\r
     <ClInclude Include="cl_video.h" />\r
index 631a2b2..67ead0d 100644 (file)
     <ClCompile Include="cd_win.c" />\r
     <ClCompile Include="cl_collision.c" />\r
     <ClCompile Include="cl_demo.c" />\r
-    <ClCompile Include="cl_dyntexture.c" />\r
     <ClCompile Include="cl_input.c" />\r
     <ClCompile Include="cl_main.c" />\r
     <ClCompile Include="cl_parse.c" />\r
     <ClInclude Include="cap_ogg.h" />\r
     <ClInclude Include="cdaudio.h" />\r
     <ClInclude Include="cl_collision.h" />\r
-    <ClInclude Include="cl_dyntexture.h" />\r
     <ClInclude Include="cl_gecko.h" />\r
     <ClInclude Include="cl_screen.h" />\r
     <ClInclude Include="cl_video.h" />\r
diff --git a/draw.h b/draw.h
index 6ac5c39..59470b6 100644 (file)
--- a/draw.h
+++ b/draw.h
@@ -24,31 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #ifndef DRAW_H
 #define DRAW_H
 
-// FIXME: move this stuff to cl_screen
-typedef struct cachepic_s
-{
-       // size of pic
-       int width, height;
-       // this flag indicates that it should be loaded and unloaded on demand
-       int autoload;
-       // texture flags to upload with
-       int texflags;
-       // texture may be freed after a while
-       int lastusedframe;
-       // renderer texture to use
-       rtexture_t *tex;
-       // used for hash lookups
-       struct cachepic_s *chain;
-       // flags - CACHEPICFLAG_NEWPIC for example
-       unsigned int flags;
-       // has alpha?
-       qboolean hasalpha;
-       // name of pic
-       char name[MAX_QPATH];
-       // allow to override/free the texture
-       qboolean allow_free_tex;
-}
-cachepic_t;
+typedef struct cachepic_s cachepic_t;
 
 typedef enum cachepicflags_e
 {
@@ -58,7 +34,8 @@ typedef enum cachepicflags_e
        CACHEPICFLAG_NOCLAMP = 8,
        CACHEPICFLAG_NEWPIC = 16, // disables matching texflags check, because a pic created with Draw_NewPic should not be subject to that
        CACHEPICFLAG_MIPMAP = 32,
-       CACHEPICFLAG_NEAREST = 64 // force nearest filtering instead of linear
+       CACHEPICFLAG_NEAREST = 64, // force nearest filtering instead of linear
+       CACHEPICFLAG_FAILONMISSING = 128 // return NULL if the pic has no texture
 }
 cachepicflags_t;
 
@@ -67,8 +44,8 @@ void Draw_Frame (void);
 cachepic_t *Draw_CachePic_Flags (const char *path, unsigned int cachepicflags);
 cachepic_t *Draw_CachePic (const char *path); // standard function with no options, used throughout engine
 // create or update a pic's image
-cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, unsigned char *pixels);
-// free the texture memory used by a pic
+cachepic_t *Draw_NewPic(const char *picname, int width, int height, unsigned char *pixels, textype_t textype, int texflags);
+// free the texture memory used by a pic (the cachepic_t itself is eternal)
 void Draw_FreePic(const char *picname);
 
 // a triangle mesh..
@@ -113,7 +90,7 @@ typedef struct ft2_settings_s
 #define MAX_FONT_FALLBACKS 3
 typedef struct dp_font_s
 {
-       rtexture_t *tex;
+       cachepic_t *pic;
        float width_of[256]; // width_of[0] == max width of any char; 1.0f is base width (1/16 of texture width); therefore, all widths have to be <= 1 (does not include scale)
        float maxwidth; // precalculated max width of the font (includes scale)
        char texpath[MAX_QPATH];
@@ -197,6 +174,11 @@ void DrawQ_Finish(void);
 void DrawQ_ProcessDrawFlag(int flags, qboolean alpha); // sets GL_DepthMask and GL_BlendFunc
 void DrawQ_RecalcView(void); // use this when changing r_refdef.view.* from e.g. csqc
 
+
+const char *Draw_GetPicName(cachepic_t *pic);
+int Draw_GetPicWidth(cachepic_t *pic);
+int Draw_GetPicHeight(cachepic_t *pic);
+qboolean Draw_IsPicLoaded(cachepic_t *pic);
 rtexture_t *Draw_GetPicTexture(cachepic_t *pic);
 
 extern rtexturepool_t *drawtexturepool; // used by ft2.c
diff --git a/ft2.c b/ft2.c
index e30c22e..6ae0979 100644 (file)
--- a/ft2.c
+++ b/ft2.c
@@ -1332,7 +1332,7 @@ static qboolean Font_LoadMap(ft2_font_t *font, ft2_font_map_t *mapstart, Uchar _
        map->pic = Draw_CachePic_Flags(map_identifier, CACHEPICFLAG_QUIET);
        if (developer_font.integer)
        {
-               if (map->pic->tex == r_texture_notexture)
+               if (!Draw_IsPicLoaded(map->pic))
                        Con_Printf("Generating font map %s (size: %.1f MB)\n", map_identifier, mapstart->glyphSize * (256 * 4 / 1048576.0) * mapstart->glyphSize);
                else
                        Con_Printf("Using cached font map %s (size: %.1f MB)\n", map_identifier, mapstart->glyphSize * (256 * 4 / 1048576.0) * mapstart->glyphSize);
@@ -1348,7 +1348,7 @@ static qboolean Font_LoadMap(ft2_font_t *font, ft2_font_map_t *mapstart, Uchar _
        map->sfy = mapstart->sfy;
 
        pitch = map->glyphSize * FONT_CHARS_PER_LINE * bytesPerPixel;
-       if (map->pic->tex == r_texture_notexture)
+       if (!Draw_IsPicLoaded(map->pic))
        {
                data = (unsigned char *)Mem_Alloc(font_mempool, (FONT_CHAR_LINES * map->glyphSize) * pitch);
                if (!data)
@@ -1624,16 +1624,12 @@ static qboolean Font_LoadMap(ft2_font_t *font, ft2_font_map_t *mapstart, Uchar _
                map->glyphs[mapch].image = false;
        }
 
-       if (map->pic->tex == r_texture_notexture)
+       if (!Draw_IsPicLoaded(map->pic))
        {
                int w = map->glyphSize * FONT_CHARS_PER_LINE;
                int h = map->glyphSize * FONT_CHAR_LINES;
-               rtexture_t *tex;
-               // abuse the Draw_CachePic system to keep track of this texture
-               tex = R_LoadTexture2D(drawtexturepool, map_identifier, w, h, data, r_font_use_alpha_textures.integer ? TEXTYPE_ALPHA : TEXTYPE_RGBA, TEXF_ALPHA | (r_font_compress.integer > 0 ? TEXF_COMPRESS : 0), -1, NULL);
-               // if tex is NULL for any reason, the pic->tex will remain set to r_texture_notexture
-               if (tex)
-                       map->pic->tex = tex;
+               // update the pic returned by Draw_CachePic_Flags earlier to contain our texture
+               Draw_NewPic(map_identifier, w, h, data, r_font_use_alpha_textures.integer ? TEXTYPE_ALPHA : TEXTYPE_RGBA, TEXF_ALPHA | (r_font_compress.integer > 0 ? TEXF_COMPRESS : 0));
 
                if (r_font_diskcache.integer >= 1)
                {
@@ -1649,8 +1645,8 @@ static qboolean Font_LoadMap(ft2_font_t *font, ft2_font_map_t *mapstart, Uchar _
                        }
                        Image_WriteTGABGRA(va(vabuf, sizeof(vabuf), "%s.tga", map_identifier), w, h, data);
 #ifndef USE_GLES2
-                       if (r_font_compress.integer && qglGetCompressedTexImageARB && tex)
-                               R_SaveTextureDDSFile(tex, va(vabuf, sizeof(vabuf), "dds/%s.dds", map_identifier), r_texture_dds_save.integer < 2, true);
+                       if (r_font_compress.integer && qglGetCompressedTexImageARB && Draw_IsPicLoaded(map->pic))
+                               R_SaveTextureDDSFile(Draw_GetPicTexture(map->pic), va(vabuf, sizeof(vabuf), "dds/%s.dds", map_identifier), r_texture_dds_save.integer < 2, true);
 #endif
                }
        }
@@ -1658,7 +1654,7 @@ static qboolean Font_LoadMap(ft2_font_t *font, ft2_font_map_t *mapstart, Uchar _
        if(data)
                Mem_Free(data);
 
-       if (map->pic->tex == r_texture_notexture)
+       if (!Draw_IsPicLoaded(map->pic))
        {
                // if the first try isn't successful, keep it with a broken texture
                // otherwise we retry to load it every single frame where ft2 rendering is used
index 77c873c..4e0bfd6 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -23,11 +23,30 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "wad.h"
 
 #include "cl_video.h"
-#include "cl_dyntexture.h"
 
 #include "ft2.h"
 #include "ft2_fontdefs.h"
 
+struct cachepic_s
+{
+       // size of pic
+       int width, height;
+       // this flag indicates that it should be loaded and unloaded on demand
+       int autoload;
+       // texture flags to upload with
+       int texflags;
+       // texture may be freed after a while
+       int lastusedframe;
+       // renderable texture
+       skinframe_t *skinframe;
+       // used for hash lookups
+       struct cachepic_s *chain;
+       // flags - CACHEPICFLAG_NEWPIC for example
+       unsigned int flags;
+       // name of pic
+       char name[MAX_QPATH];
+};
+
 dp_fonts_t dp_fonts;
 static mempool_t *fonts_mempool = NULL;
 
@@ -48,260 +67,12 @@ cvar_t r_nearest_conchars = {CVAR_SAVE, "r_nearest_conchars", "0", "use nearest
 //=============================================================================
 /* Support Routines */
 
-#define FONT_FILESIZE 13468
 static cachepic_t *cachepichash[CACHEPICHASHSIZE];
 static cachepic_t cachepics[MAX_CACHED_PICS];
 static int numcachepics;
 
 rtexturepool_t *drawtexturepool;
 
-static const unsigned char concharimage[FONT_FILESIZE] =
-{
-#include "lhfont.h"
-};
-
-static rtexture_t *draw_generateconchars(void)
-{
-       int i;
-       unsigned char *data;
-       double random;
-       rtexture_t *tex;
-
-       data = LoadTGA_BGRA (concharimage, FONT_FILESIZE, NULL);
-// Gold numbers
-       for (i = 0;i < 8192;i++)
-       {
-               random = lhrandom (0.0,1.0);
-               data[i*4+3] = data[i*4+0];
-               data[i*4+2] = 83 + (unsigned char)(random * 64);
-               data[i*4+1] = 71 + (unsigned char)(random * 32);
-               data[i*4+0] = 23 + (unsigned char)(random * 16);
-       }
-// White chars
-       for (i = 8192;i < 32768;i++)
-       {
-               random = lhrandom (0.0,1.0);
-               data[i*4+3] = data[i*4+0];
-               data[i*4+2] = 95 + (unsigned char)(random * 64);
-               data[i*4+1] = 95 + (unsigned char)(random * 64);
-               data[i*4+0] = 95 + (unsigned char)(random * 64);
-       }
-// Gold numbers
-       for (i = 32768;i < 40960;i++)
-       {
-               random = lhrandom (0.0,1.0);
-               data[i*4+3] = data[i*4+0];
-               data[i*4+2] = 83 + (unsigned char)(random * 64);
-               data[i*4+1] = 71 + (unsigned char)(random * 32);
-               data[i*4+0] = 23 + (unsigned char)(random * 16);
-       }
-// Red chars
-       for (i = 40960;i < 65536;i++)
-       {
-               random = lhrandom (0.0,1.0);
-               data[i*4+3] = data[i*4+0];
-               data[i*4+2] = 96 + (unsigned char)(random * 64);
-               data[i*4+1] = 43 + (unsigned char)(random * 32);
-               data[i*4+0] = 27 + (unsigned char)(random * 32);
-       }
-
-#if 0
-       Image_WriteTGABGRA ("gfx/generated_conchars.tga", 256, 256, data);
-#endif
-
-       tex = R_LoadTexture2D(drawtexturepool, "conchars", 256, 256, data, TEXTYPE_BGRA, TEXF_ALPHA | (r_nearest_conchars.integer ? TEXF_FORCENEAREST : 0), -1, NULL);
-       Mem_Free(data);
-       return tex;
-}
-
-static rtexture_t *draw_generateditherpattern(void)
-{
-       int x, y;
-       unsigned char pixels[8][8];
-       for (y = 0;y < 8;y++)
-               for (x = 0;x < 8;x++)
-                       pixels[y][x] = ((x^y) & 4) ? 254 : 0;
-       return R_LoadTexture2D(drawtexturepool, "ditherpattern", 8, 8, pixels[0], TEXTYPE_PALETTE, TEXF_FORCENEAREST, -1, palette_bgra_transparent);
-}
-
-typedef struct embeddedpic_s
-{
-       const char *name;
-       int width;
-       int height;
-       const char *pixels;
-}
-embeddedpic_t;
-
-static const embeddedpic_t embeddedpics[] =
-{
-       {
-       "gfx/prydoncursor001", 16, 16,
-       "477777774......."
-       "77.....6........"
-       "7.....6........."
-       "7....6.........."
-       "7.....6........."
-       "7..6...6........"
-       "7.6.6...6......."
-       "76...6...6......"
-       "4.....6.6......."
-       ".......6........"
-       "................"
-       "................"
-       "................"
-       "................"
-       "................"
-       "................"
-       },
-       {
-       "ui/mousepointer", 16, 16,
-       "477777774......."
-       "77.....6........"
-       "7.....6........."
-       "7....6.........."
-       "7.....6........."
-       "7..6...6........"
-       "7.6.6...6......."
-       "76...6...6......"
-       "4.....6.6......."
-       ".......6........"
-       "................"
-       "................"
-       "................"
-       "................"
-       "................"
-       "................"
-       },
-       {
-       "gfx/crosshair1", 16, 16,
-       "................"
-       "................"
-       "................"
-       "...33......33..."
-       "...355....553..."
-       "....577..775...."
-       ".....77..77....."
-       "................"
-       "................"
-       ".....77..77....."
-       "....577..775...."
-       "...355....553..."
-       "...33......33..."
-       "................"
-       "................"
-       "................"
-       },
-       {
-       "gfx/crosshair2", 16, 16,
-       "................"
-       "................"
-       "................"
-       "...3........3..."
-       "....5......5...."
-       ".....7....7....."
-       "......7..7......"
-       "................"
-       "................"
-       "......7..7......"
-       ".....7....7....."
-       "....5......5...."
-       "...3........3..."
-       "................"
-       "................"
-       "................"
-       },
-       {
-       "gfx/crosshair3", 16, 16,
-       "................"
-       ".......77......."
-       ".......77......."
-       "................"
-       "................"
-       ".......44......."
-       ".......44......."
-       ".77..44..44..77."
-       ".77..44..44..77."
-       ".......44......."
-       ".......44......."
-       "................"
-       "................"
-       ".......77......."
-       ".......77......."
-       "................"
-       },
-       {
-       "gfx/crosshair4", 16, 16,
-       "................"
-       "................"
-       "................"
-       "................"
-       "................"
-       "................"
-       "................"
-       "................"
-       "........7777777."
-       "........752....."
-       "........72......"
-       "........7......."
-       "........7......."
-       "........7......."
-       "........7......."
-       "................"
-       },
-       {
-       "gfx/crosshair5", 8, 8,
-       "........"
-       "........"
-       "....7..."
-       "........"
-       "..7.7.7."
-       "........"
-       "....7..."
-       "........"
-       },
-       {
-       "gfx/crosshair6", 2, 2,
-       "77"
-       "77"
-       },
-       {
-       "gfx/crosshair7", 16, 16,
-       "................"
-       ".3............3."
-       "..5...2332...5.."
-       "...7.3....3.7..."
-       "....7......7...."
-       "...3.7....7.3..."
-       "..2...7..7...2.."
-       "..3..........3.."
-       "..3..........3.."
-       "..2...7..7...2.."
-       "...3.7....7.3..."
-       "....7......7...."
-       "...7.3....3.7..."
-       "..5...2332...5.."
-       ".3............3."
-       "................"
-       },
-       {NULL, 0, 0, NULL}
-};
-
-static rtexture_t *draw_generatepic(const char *name, qboolean quiet)
-{
-       const embeddedpic_t *p;
-       for (p = embeddedpics;p->name;p++)
-               if (!strcmp(name, p->name))
-                       return R_LoadTexture2D(drawtexturepool, p->name, p->width, p->height, (const unsigned char *)p->pixels, TEXTYPE_PALETTE, TEXF_ALPHA, -1, palette_bgra_embeddedpic);
-       if (!strcmp(name, "gfx/conchars"))
-               return draw_generateconchars();
-       if (!strcmp(name, "gfx/colorcontrol/ditherpattern"))
-               return draw_generateditherpattern();
-       if (!quiet)
-               Con_DPrintf("Draw_CachePic: failed to load %s\n", name);
-       return r_texture_notexture;
-}
-
 int draw_frame = 1;
 
 /*
@@ -313,17 +84,8 @@ Draw_CachePic
 cachepic_t *Draw_CachePic_Flags(const char *path, unsigned int cachepicflags)
 {
        int crc, hashkey;
-       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;
-       char vabuf[1024];
 
        texflags = TEXF_ALPHA;
        if (!(cachepicflags & CACHEPICFLAG_NOCLAMP))
@@ -340,20 +102,24 @@ 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 (!strcmp(path, pic->name))
                {
                        // if it was created (or replaced) by Draw_NewPic, just return it
-                       if(pic->flags & CACHEPICFLAG_NEWPIC)
+                       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(!(cachepicflags & CACHEPICFLAG_NOTPERSISTENT))
-                               {
-                                       if(pic->tex)
-                                               pic->autoload = false; // persist it
-                                       else
-                                               goto reload; // load it below, and then persist
-                               }
+                               if (!pic->skinframe || !pic->skinframe->base)
+                                       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;
                        }
                }
@@ -373,138 +139,26 @@ cachepic_t *Draw_CachePic_Flags(const char *path, unsigned int cachepicflags)
        cachepichash[hashkey] = pic;
 
 reload:
-       // TODO why does this crash?
-       if(pic->allow_free_tex && pic->tex)
-               R_PurgeTexture(pic->tex);
+       if (pic->skinframe)
+               R_SkinFrame_PurgeSkinFrame(pic->skinframe);
 
-       // 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);
+       pic->autoload = (cachepicflags & CACHEPICFLAG_NOTPERSISTENT) != 0;
        pic->lastusedframe = draw_frame;
 
-       // load a high quality image from disk if possible
-       if (!loaded && r_texture_dds_load.integer != 0 && (pic->tex = R_LoadTextureDDSFile(drawtexturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", pic->name), vid.sRGB2D, pic->texflags, &ddshasalpha, ddsavgcolor, 0, false)))
-       {
-               // 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)
-               {
-                       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, 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(vabuf, sizeof(vabuf), "dds/%s.dds", pic->name), r_texture_dds_save.integer < 2, pic->hasalpha);
-#endif
-               }
-       }
-       if (!loaded)
-       {
-               pic->autoload = false;
-               // never compress the fallback images
-               pic->texflags &= ~TEXF_COMPRESS;
-       }
-
-       // now read the low quality version (wad or lmp file), and take the pic
-       // 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", pic->name);
-       if ((!strncmp(pic->name, "gfx/", 4) || (gamemode == GAME_BLOODOMNICIDE && !strncmp(pic->name, "locale/", 6))) && (lmpdata = FS_LoadFile(lmpname, tempmempool, false, &lmpsize)))
-       {
-               if (developer_loading.integer)
-                       Con_Printf("loading lump \"%s\"\n", pic->name);
+       // load high quality image (this falls back to low quality too)
+       pic->skinframe = R_SkinFrame_LoadExternal(pic->name, texflags, (cachepicflags & CACHEPICFLAG_QUIET) == 0, (cachepicflags & CACHEPICFLAG_FAILONMISSING) == 0);
 
-               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 (!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 (pic->name + 4)))
+       // get the dimensions of the image we loaded (if it was successful)
+       if (pic->skinframe && pic->skinframe->base)
        {
-               if (developer_loading.integer)
-                       Con_Printf("loading gfx.wad lump \"%s\"\n", pic->name + 4);
-
-               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 (!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 (!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);
-                       }
-               }
+               pic->width = R_TextureWidth(pic->skinframe->base);
+               pic->height = R_TextureHeight(pic->skinframe->base);
        }
 
-       if (pixels)
-       {
-               Mem_Free(pixels);
-               pixels = NULL;
-       }
-       if (!loaded)
-       {
-               // if it's not found on disk, generate an image
-               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);
-       }
+       // check for a low quality version of the pic and use its size if possible, to match the stock hud
+       Image_GetStockPicSize(pic->name, &pic->width, &pic->height);
 
        return pic;
 }
@@ -514,38 +168,45 @@ cachepic_t *Draw_CachePic (const char *path)
        return Draw_CachePic_Flags (path, 0); // default to persistent!
 }
 
+const char *Draw_GetPicName(cachepic_t *pic)
+{
+       if (pic == NULL)
+               return "";
+       return pic->name;
+}
+
+int Draw_GetPicWidth(cachepic_t *pic)
+{
+       if (pic == NULL)
+               return 0;
+       return pic->width;
+}
+
+int Draw_GetPicHeight(cachepic_t *pic)
+{
+       if (pic == NULL)
+               return 0;
+       return pic->height;
+}
+
+qboolean Draw_IsPicLoaded(cachepic_t *pic)
+{
+       if (pic == NULL)
+               return false;
+       if (pic->autoload && (!pic->skinframe || !pic->skinframe->base))
+               pic->skinframe = R_SkinFrame_LoadExternal(pic->name, pic->texflags, 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;
+}
+
 rtexture_t *Draw_GetPicTexture(cachepic_t *pic)
 {
-       char vabuf[1024];
-       if (pic->autoload && !pic->tex)
-       {
-               if (pic->tex == NULL && r_texture_dds_load.integer != 0)
-               {
-                       qboolean ddshasalpha;
-                       float ddsavgcolor[4];
-                       pic->tex = R_LoadTextureDDSFile(drawtexturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", pic->name), vid.sRGB2D, pic->texflags, &ddshasalpha, ddsavgcolor, 0, false);
-               }
-               if (pic->tex == NULL)
-               {
-                       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(vabuf, sizeof(vabuf), "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, vid.sRGB2D);
-#ifndef USE_GLES2
-                       if (r_texture_dds_save.integer && qglGetCompressedTexImageARB && pic->tex)
-                               R_SaveTextureDDSFile(pic->tex, va(vabuf, sizeof(vabuf), "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);
-       }
+       if (pic == NULL)
+               return NULL;
+       if (pic->autoload && (!pic->skinframe || !pic->skinframe->base))
+               pic->skinframe = R_SkinFrame_LoadExternal(pic->name, pic->texflags, false, true);
        pic->lastusedframe = draw_frame;
-       return pic->tex;
+       return pic->skinframe ? pic->skinframe->base : NULL;
 }
 
 void Draw_Frame(void)
@@ -557,17 +218,12 @@ void Draw_Frame(void)
                return;
        nextpurgetime = realtime + 0.05;
        for (i = 0, pic = cachepics;i < numcachepics;i++, pic++)
-       {
-               if (pic->autoload && pic->tex && pic->lastusedframe < draw_frame)
-               {
-                       R_FreeTexture(pic->tex);
-                       pic->tex = NULL;
-               }
-       }
+               if (pic->autoload && pic->skinframe && pic->skinframe->base && pic->lastusedframe < draw_frame)
+                       R_SkinFrame_PurgeSkinFrame(pic->skinframe);
        draw_frame++;
 }
 
-cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, unsigned char *pixels_bgra)
+cachepic_t *Draw_NewPic(const char *picname, int width, int height, unsigned char *pixels_bgra, textype_t textype, int texflags)
 {
        int crc, hashkey;
        cachepic_t *pic;
@@ -580,9 +236,11 @@ cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, u
 
        if (pic)
        {
-               if (pic->flags == CACHEPICFLAG_NEWPIC && pic->tex && pic->width == width && pic->height == height)
+               if (pic->flags & CACHEPICFLAG_NEWPIC && pic->skinframe && pic->skinframe->base && pic->width == width && pic->height == height)
                {
-                       R_UpdateTexture(pic->tex, pixels_bgra, 0, 0, 0, width, height, 1);
+                       R_UpdateTexture(pic->skinframe->base, pixels_bgra, 0, 0, 0, width, height, 1);
+                       R_SkinFrame_MarkUsed(pic->skinframe);
+                       pic->lastusedframe = draw_frame;
                        return pic;
                }
        }
@@ -602,12 +260,15 @@ cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, u
                cachepichash[hashkey] = pic;
        }
 
+       R_SkinFrame_PurgeSkinFrame(pic->skinframe);
+
        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;
        pic->width = width;
        pic->height = height;
-       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);
+       pic->skinframe = R_SkinFrame_LoadInternalBGRA(picname, texflags, pixels_bgra, width, height, vid.sRGB2D);
+       pic->lastusedframe = draw_frame;
        return pic;
 }
 
@@ -616,15 +277,14 @@ void Draw_FreePic(const char *picname)
        int crc;
        int hashkey;
        cachepic_t *pic;
-       // this doesn't really free the pic, but does free it's texture
+       // this doesn't really free the pic, but does free its texture
        crc = CRC_Block((unsigned char *)picname, strlen(picname));
        hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
        for (pic = cachepichash[hashkey];pic;pic = pic->chain)
        {
-               if (!strcmp (picname, pic->name) && pic->tex)
+               if (!strcmp (picname, pic->name) && pic->skinframe)
                {
-                       R_FreeTexture(pic->tex);
-                       pic->tex = NULL;
+                       R_SkinFrame_PurgeSkinFrame(pic->skinframe);
                        pic->width = 0;
                        pic->height = 0;
                        return;
@@ -677,20 +337,20 @@ void LoadFont(qboolean override, const char *name, dp_font_t *fnt, float scale,
                        Con_DPrintf("Failed to load font-file for '%s', it will not support as many characters.\n", fnt->texpath);
        }
 
-       fnt->tex = Draw_CachePic_Flags(fnt->texpath, CACHEPICFLAG_QUIET | CACHEPICFLAG_NOCOMPRESSION | (r_nearest_conchars.integer ? CACHEPICFLAG_NEAREST : 0))->tex;
-       if(fnt->tex == r_texture_notexture)
+       fnt->pic = Draw_CachePic_Flags(fnt->texpath, CACHEPICFLAG_QUIET | CACHEPICFLAG_NOCOMPRESSION | (r_nearest_conchars.integer ? CACHEPICFLAG_NEAREST : 0) | CACHEPICFLAG_FAILONMISSING);
+       if(!Draw_IsPicLoaded(fnt->pic))
        {
                for (i = 0; i < MAX_FONT_FALLBACKS; ++i)
                {
                        if (!fnt->fallbacks[i][0])
                                break;
-                       fnt->tex = Draw_CachePic_Flags(fnt->fallbacks[i], CACHEPICFLAG_QUIET | CACHEPICFLAG_NOCOMPRESSION | (r_nearest_conchars.integer ? CACHEPICFLAG_NEAREST : 0))->tex;
-                       if(fnt->tex != r_texture_notexture)
+                       fnt->pic = Draw_CachePic_Flags(fnt->fallbacks[i], CACHEPICFLAG_QUIET | CACHEPICFLAG_NOCOMPRESSION | (r_nearest_conchars.integer ? CACHEPICFLAG_NEAREST : 0) | CACHEPICFLAG_FAILONMISSING);
+                       if(Draw_IsPicLoaded(fnt->pic))
                                break;
                }
-               if(fnt->tex == r_texture_notexture)
+               if(!Draw_IsPicLoaded(fnt->pic))
                {
-                       fnt->tex = Draw_CachePic_Flags("gfx/conchars", CACHEPICFLAG_NOCOMPRESSION | (r_nearest_conchars.integer ? CACHEPICFLAG_NEAREST : 0))->tex;
+                       fnt->pic = Draw_CachePic_Flags("gfx/conchars", CACHEPICFLAG_NOCOMPRESSION | (r_nearest_conchars.integer ? CACHEPICFLAG_NEAREST : 0));
                        strlcpy(widthfile, "gfx/conchars.width", sizeof(widthfile));
                }
                else
@@ -1031,7 +691,16 @@ static void gl_draw_shutdown(void)
 
 static void gl_draw_newmap(void)
 {
+       int i;
        font_newmap();
+
+       // mark all of the persistent pics so they are not purged...
+       for (i = 0; i < numcachepics; i++)
+       {
+               cachepic_t *pic = cachepics + i;
+               if (!pic->autoload && pic->skinframe)
+                       R_SkinFrame_MarkUsed(pic->skinframe);
+       }
 }
 
 void GL_Draw_Init (void)
@@ -1090,7 +759,7 @@ static void _DrawQ_SetupAndProcessDrawFlag(int flags, cachepic_t *pic, float alp
        _DrawQ_Setup();
        if(!r_draw2d.integer && !r_draw2d_force)
                return;
-       DrawQ_ProcessDrawFlag(flags, (alpha < 1) || (pic && pic->hasalpha));
+       DrawQ_ProcessDrawFlag(flags, (alpha < 1) || (pic && pic->skinframe && pic->skinframe->hasalpha));
 }
 void DrawQ_ProcessDrawFlag(int flags, qboolean alpha)
 {
@@ -1532,8 +1201,8 @@ float DrawQ_String_Scale(float startx, float starty, const char *text, size_t ma
        const float *width_of;
 
        int tw, th;
-       tw = R_TextureWidth(fnt->tex);
-       th = R_TextureHeight(fnt->tex);
+       tw = Draw_GetPicWidth(fnt->pic);
+       th = Draw_GetPicHeight(fnt->pic);
 
        if (!h) h = w;
        if (!h) {
@@ -1570,8 +1239,8 @@ 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, (flags & DRAWFLAGS_BLEND) ? false : true, true, false);
+               R_Mesh_TexBind(0, Draw_GetPicTexture(fnt->pic));
+       R_SetupShader_Generic(Draw_GetPicTexture(fnt->pic), NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true, false);
 
        ac = color4f;
        at = texcoord2f;
@@ -1707,7 +1376,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, (flags & DRAWFLAGS_BLEND) ? false : true, true, false);
+                                               R_SetupShader_Generic(Draw_GetPicTexture(fnt->pic), NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true, false);
                                                map = ft2_oldstyle_map;
                                        }
                                }
@@ -1786,7 +1455,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, (flags & DRAWFLAGS_BLEND) ? false : true, true, false);
+                                       R_SetupShader_Generic(Draw_GetPicTexture(map->pic), NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true, false);
                                }
 
                                mapch = ch - map->start;
@@ -2108,7 +1777,7 @@ void DrawQ_SetClipArea(float x, float y, float width, float height)
        _DrawQ_Setup();
 
        // We have to convert the con coords into real coords
-       // OGL uses top to bottom
+       // OGL uses bottom to top (origin is in bottom left)
        ix = (int)(0.5 + x * ((float)r_refdef.view.width / vid_conwidth.integer)) + r_refdef.view.x;
        iy = (int)(0.5 + y * ((float)r_refdef.view.height / vid_conheight.integer)) + r_refdef.view.y;
        iw = (int)(0.5 + width * ((float)r_refdef.view.width / vid_conwidth.integer));
index 4e35c2e..36a45b0 100644 (file)
@@ -20,7 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 // r_main.c
 
 #include "quakedef.h"
-#include "cl_dyntexture.h"
 #include "r_shadow.h"
 #include "polygon.h"
 #include "image.h"
@@ -3195,16 +3194,13 @@ skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewid
                if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
                        break;
 
-       if (!item) {
-               rtexture_t *dyntexture;
-               // check whether its a dynamic texture
-               dyntexture = CL_GetDynTexture( basename );
-               if (!add && !dyntexture)
+       if (!item)
+       {
+               if (!add)
                        return NULL;
                item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
                memset(item, 0, sizeof(*item));
                strlcpy(item->basename, basename, sizeof(item->basename));
-               item->base = dyntexture; // either NULL or dyntexture handle
                item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
                item->comparewidth = comparewidth;
                item->compareheight = compareheight;
@@ -3214,21 +3210,10 @@ skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewid
        }
        else if (textureflags & TEXF_FORCE_RELOAD)
        {
-               rtexture_t *dyntexture;
-               // check whether its a dynamic texture
-               dyntexture = CL_GetDynTexture( basename );
-               if (!add && !dyntexture)
+               if (!add)
                        return NULL;
                R_SkinFrame_PurgeSkinFrame(item);
        }
-       else if( item->base == NULL )
-       {
-               rtexture_t *dyntexture;
-               // check whether its a dynamic texture
-               // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
-               dyntexture = CL_GetDynTexture( basename );
-               item->base = dyntexture; // either NULL or dyntexture handle
-       }
 
        R_SkinFrame_MarkUsed(item);
        return item;
@@ -3270,7 +3255,7 @@ skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewid
        }
 
 extern cvar_t gl_picmip;
-skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
+skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
 {
        int j;
        unsigned char *pixels;
@@ -3304,6 +3289,8 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole
        if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
        {
                basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
+               if (basepixels == NULL && fallbacknotexture)
+                       basepixels = Image_GenerateNoTexture();
                if (basepixels == NULL)
                        return NULL;
        }
@@ -3729,7 +3716,7 @@ skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, co
                Con_Printf("loading embedded 8bit image \"%s\"\n", name);
 
        skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
-       if (textureflags & TEXF_ALPHA)
+       if ((textureflags & TEXF_ALPHA) && alphapalette)
        {
                for (i = 0;i < width * height;i++)
                {
@@ -3777,6 +3764,73 @@ skinframe_t *R_SkinFrame_LoadMissing(void)
        return skinframe;
 }
 
+skinframe_t *R_SkinFrame_LoadNoTexture(void)
+{
+       int x, y;
+       static unsigned char pix[16][16][4];
+
+       if (cls.state == ca_dedicated)
+               return NULL;
+
+       // this makes a light grey/dark grey checkerboard texture
+       if (!pix[0][0][3])
+       {
+               for (y = 0; y < 16; y++)
+               {
+                       for (x = 0; x < 16; x++)
+                       {
+                               if ((y < 8) ^ (x < 8))
+                               {
+                                       pix[y][x][0] = 128;
+                                       pix[y][x][1] = 128;
+                                       pix[y][x][2] = 128;
+                                       pix[y][x][3] = 255;
+                               }
+                               else
+                               {
+                                       pix[y][x][0] = 64;
+                                       pix[y][x][1] = 64;
+                                       pix[y][x][2] = 64;
+                                       pix[y][x][3] = 255;
+                               }
+                       }
+               }
+       }
+
+       return R_SkinFrame_LoadInternalBGRA("notexture", TEXF_FORCENEAREST, pix[0][0], 16, 16, false);
+}
+
+skinframe_t *R_SkinFrame_LoadInternalUsingTexture(const char *name, int textureflags, rtexture_t *tex, int width, int height, qboolean sRGB)
+{
+       skinframe_t *skinframe;
+       if (cls.state == ca_dedicated)
+               return NULL;
+       // if already loaded just return it, otherwise make a new skinframe
+       skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : 0, true);
+       if (skinframe->base)
+               return skinframe;
+       textureflags &= ~TEXF_FORCE_RELOAD;
+       skinframe->stain = NULL;
+       skinframe->merged = NULL;
+       skinframe->base = NULL;
+       skinframe->pants = NULL;
+       skinframe->shirt = NULL;
+       skinframe->nmap = NULL;
+       skinframe->gloss = NULL;
+       skinframe->glow = NULL;
+       skinframe->fog = NULL;
+       skinframe->reflect = NULL;
+       skinframe->hasalpha = (textureflags & TEXF_ALPHA) != 0;
+       // if no data was provided, then clearly the caller wanted to get a blank skinframe
+       if (!tex)
+               return NULL;
+       if (developer_loading.integer)
+               Con_Printf("loading 32bit skin \"%s\"\n", name);
+       skinframe->base = skinframe->merged = tex;
+       Vector4Set(skinframe->avgcolor, 1, 1, 1, 1); // bogus placeholder
+       return skinframe;
+}
+
 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
 typedef struct suffixinfo_s
 {
index 0bec0bd..130e745 100644 (file)
@@ -1577,7 +1577,7 @@ static void R_ReplaceWorldTexture (void)
        {
                if(/*t->width && !strcasecmp(t->name, r)*/ matchpattern( t->name, r, true ) )
                {
-                       if ((skinframe = R_SkinFrame_LoadExternal(newt, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PICMIP, true)))
+                       if ((skinframe = R_SkinFrame_LoadExternal(newt, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PICMIP, true, false)))
                        {
 //                             t->skinframes[0] = skinframe;
                                t->currentskinframe = skinframe;
index 29d325e..0637365 100644 (file)
@@ -324,7 +324,7 @@ static textypeinfo_t *R_GetTexTypeInfo(textype_t textype, int flags)
        case TEXTYPE_SRGB_BGRA: return ((flags & TEXF_COMPRESS) && vid.support.ext_texture_compression_s3tc) ? ((flags & TEXF_ALPHA) ? &textype_sRGB_bgra_alpha_compress : &textype_sRGB_bgra_compress) : ((flags & TEXF_ALPHA) ? &textype_sRGB_bgra_alpha : &textype_sRGB_bgra);
 #endif
        default:
-               Host_Error("R_GetTexTypeInfo: unknown texture format");
+               Host_Error("R_GetTexTypeInfo: unknown texture format %i with flags %x", (int)textype, flags);
                break;
        }
        return NULL;
diff --git a/image.c b/image.c
index 1f15a2f..9e3f0fd 100644 (file)
--- a/image.c
+++ b/image.c
@@ -4,10 +4,13 @@
 #include "jpeg.h"
 #include "image_png.h"
 #include "r_shadow.h"
+#include "wad.h"
 
 int            image_width;
 int            image_height;
 
+static unsigned char *Image_GetEmbeddedPicBGRA(const char *name);
+
 static void Image_CopyAlphaFromBlueBGRA(unsigned char *outpixels, const unsigned char *inpixels, int w, int h)
 {
        int i, n;
@@ -834,6 +837,78 @@ qboolean LoadWAL_GetMetadata(const unsigned char *f, int filesize, int *retwidth
        return true;
 }
 
+// gfx/* wad lumps and gfx/*.lmp files are simply width and height and paletted pixels, with color 255 as transparent
+static unsigned char* LoadLMP_BGRA(const unsigned char *f, int filesize, int *miplevel)
+{
+       unsigned char *image_buffer;
+       int i;
+
+       if (filesize < 9)
+       {
+               Con_Print("Bad lmp file\n");
+               return NULL;
+       }
+
+       image_width = f[0] + f[1] * 0x100 + f[2] * 0x10000 + f[3] * 0x1000000;
+       image_height = f[4] + f[5] * 0x100 + f[6] * 0x10000 + f[7] * 0x1000000;
+
+       if (image_width > 32768 || image_height > 32768 || image_width <= 0 || image_height <= 0 || image_width * image_height > filesize - 8)
+       {
+               Con_Print("Bad lmp file\n");
+               return NULL;
+       }
+
+       image_buffer = (unsigned char *)Mem_Alloc(tempmempool, image_width*image_height * 4);
+       if (!image_buffer)
+       {
+               Con_Printf("LoadLMP: not enough memory for %i by %i image\n", image_width, image_height);
+               return NULL;
+       }
+
+       for (i = 0; i < image_width * image_height; i++)
+       {
+               const unsigned char *p = (const unsigned char *)palette_bgra_transparent + 4 * f[8 + i];
+               image_buffer[i * 4 + 0] = p[0];
+               image_buffer[i * 4 + 1] = p[1];
+               image_buffer[i * 4 + 2] = p[2];
+               image_buffer[i * 4 + 3] = p[3];
+       }
+
+       return image_buffer;
+}
+
+// gfx/conchars is a raw 128x128 image with 0 as transparent color rather than 255
+unsigned char *LoadConChars_BGRA(const unsigned char *f, int filesize, int *miplevel)
+{
+       unsigned char *image_buffer;
+       int i;
+
+       image_width = 128;
+       image_height = 128;
+       if (image_width * image_height > filesize)
+       {
+               Con_Print("Bad lmp file\n");
+               return NULL;
+       }
+
+       image_buffer = (unsigned char *)Mem_Alloc(tempmempool, image_width*image_height * 4);
+       if (!image_buffer)
+       {
+               Con_Printf("LoadConChars: not enough memory for %i by %i image\n", image_width, image_height);
+               return NULL;
+       }
+
+       for (i = 0; i < image_width * image_height; i++)
+       {
+               const unsigned char *p = (const unsigned char *)palette_bgra_font + 4 * f[i];
+               image_buffer[i * 4 + 0] = p[0];
+               image_buffer[i * 4 + 1] = p[1];
+               image_buffer[i * 4 + 2] = p[2];
+               image_buffer[i * 4 + 3] = p[3];
+       }
+
+       return image_buffer;
+}
 
 void Image_StripImageExtension (const char *in, char *out, size_t size_out)
 {
@@ -950,6 +1025,7 @@ imageformat_t imageformats_gfx[] =
        {"%s.png", PNG_LoadImage_BGRA},
        {"%s.jpg", JPEG_LoadImage_BGRA},
        {"%s.pcx", LoadPCX_BGRA},
+       {"%s.lmp", LoadLMP_BGRA},
        {NULL, NULL}
 };
 
@@ -959,6 +1035,7 @@ imageformat_t imageformats_other[] =
        {"%s.png", PNG_LoadImage_BGRA},
        {"%s.jpg", JPEG_LoadImage_BGRA},
        {"%s.pcx", LoadPCX_BGRA},
+       {"%s.lmp", LoadLMP_BGRA},
        {NULL, NULL}
 };
 
@@ -968,7 +1045,7 @@ unsigned char *loadimagepixelsbgra (const char *filename, qboolean complain, qbo
        fs_offset_t filesize;
        imageformat_t *firstformat, *format;
        unsigned char *f, *data = NULL, *data2 = NULL;
-       char basename[MAX_QPATH], name[MAX_QPATH], name2[MAX_QPATH], *c;
+       char basename[MAX_QPATH], name[MAX_QPATH], name2[MAX_QPATH], path[MAX_QPATH], afterpath[MAX_QPATH], *c;
        char vabuf[1024];
        //if (developer_memorydebug.integer)
        //      Mem_CheckSentinelsGlobal();
@@ -979,23 +1056,26 @@ unsigned char *loadimagepixelsbgra (const char *filename, qboolean complain, qbo
        for (c = basename;*c;c++)
                if (*c == '*')
                        *c = '#';
+       path[0] = 0;
        name[0] = 0;
+       strlcpy(afterpath, basename, sizeof(afterpath));
        if (strchr(basename, '/'))
        {
                int i;
-               for (i = 0;i < (int)sizeof(name)-1 && basename[i] != '/';i++)
-                       name[i] = basename[i];
-               name[i] = 0;
+               for (i = 0;i < (int)sizeof(path)-1 && basename[i] != '/' && basename[i];i++)
+                       path[i] = basename[i];
+               path[i] = 0;
+               strlcpy(afterpath, basename + i + 1, sizeof(afterpath));
        }
        if (gamemode == GAME_TENEBRAE)
                firstformat = imageformats_tenebrae;
        else if (gamemode == GAME_DELUXEQUAKE)
                firstformat = imageformats_dq;
-       else if (!strcasecmp(name, "textures"))
+       else if (!strcasecmp(path, "textures"))
                firstformat = imageformats_textures;
-       else if (!strcasecmp(name, "gfx"))
+       else if (!strcasecmp(path, "gfx") || !strcasecmp(path, "locale")) // locale/ is used in GAME_BLOODOMNICIDE
                firstformat = imageformats_gfx;
-       else if (!strchr(basename, '/'))
+       else if (!path[0])
                firstformat = imageformats_nopath;
        else
                firstformat = imageformats_other;
@@ -1064,6 +1144,33 @@ unsigned char *loadimagepixelsbgra (const char *filename, qboolean complain, qbo
                                Con_DPrintf("Error loading image %s (file loaded but decode failed)\n", name);
                }
        }
+       if (!strcasecmp(path, "gfx"))
+       {
+               unsigned char *lmpdata;
+               if ((lmpdata = W_GetLumpName(afterpath, &filesize)))
+               {
+                       if (developer_loading.integer)
+                               Con_Printf("loading gfx.wad lump \"%s\"\n", afterpath);
+
+                       int mymiplevel = miplevel ? *miplevel : 0;
+                       if (!strcmp(afterpath, "conchars"))
+                       {
+                               // conchars is a raw image and with color 0 as transparent instead of 255
+                               data = LoadConChars_BGRA(lmpdata, filesize, &mymiplevel);
+                       }
+                       else
+                               data = LoadLMP_BGRA(lmpdata, filesize, &mymiplevel);
+                       // no cleanup after looking up a wad lump - the whole gfx.wad is loaded at once
+                       if (data)
+                               return data;
+                       Con_DPrintf("Error loading image %s (file loaded but decode failed)\n", name);
+               }
+       }
+
+       // check if the image name exists as an embedded pic
+       if ((data = Image_GetEmbeddedPicBGRA(basename)))
+               return data;
+
        if (complain)
        {
                Con_Printf("Couldn't load %s using ", filename);
@@ -1079,9 +1186,58 @@ unsigned char *loadimagepixelsbgra (const char *filename, qboolean complain, qbo
 
        //if (developer_memorydebug.integer)
        //      Mem_CheckSentinelsGlobal();
+
        return NULL;
 }
 
+qboolean Image_GetStockPicSize(const char *filename, int *returnwidth, int *returnheight)
+{
+       unsigned char *data;
+       fs_offset_t filesize;
+       char lmppath[MAX_QPATH];
+       if (!strcasecmp(filename, "gfx/conchars"))
+       {
+               *returnwidth = 128;
+               *returnheight = 128;
+               return true;
+       }
+
+       dpsnprintf(lmppath, sizeof(lmppath), "%s.lmp", filename);
+       data = FS_LoadFile(lmppath, tempmempool, true, &filesize);
+       if (data)
+       {
+               if (filesize > 8)
+               {
+                       int w = data[0] + data[1] * 0x100 + data[2] * 0x10000 + data[3] * 0x1000000;
+                       int h = data[4] + data[5] * 0x100 + data[6] * 0x10000 + data[7] * 0x1000000;
+                       if (w >= 1 && w <= 32768 && h >= 1 && h <= 32768)
+                       {
+                               *returnwidth = w;
+                               *returnheight = h;
+                               Mem_Free(data);
+                               return true;
+                       }
+               }
+               Mem_Free(data);
+       }
+       if (!strncasecmp(filename, "gfx/", 4))
+       {
+               data = W_GetLumpName(filename + 4, &filesize);
+               if (data && filesize > 8)
+               {
+                       int w = data[0] + data[1] * 0x100 + data[2] * 0x10000 + data[3] * 0x1000000;
+                       int h = data[4] + data[5] * 0x100 + data[6] * 0x10000 + data[7] * 0x1000000;
+                       if (w >= 1 && w <= 32768 && h >= 1 && h <= 32768)
+                       {
+                               *returnwidth = w;
+                               *returnheight = h;
+                               return true;
+                       }
+               }
+       }
+       return false;
+}
+
 extern cvar_t gl_picmip;
 rtexture_t *loadtextureimage (rtexturepool_t *pool, const char *filename, qboolean complain, int flags, qboolean allowFixtrans, qboolean sRGB)
 {
@@ -1647,3 +1803,302 @@ void Image_HeightmapToNormalmap_BGRA(const unsigned char *inpixels, unsigned cha
                }
        }
 }
+
+static const unsigned char concharimage[] =
+{
+#include "lhfont.h"
+};
+
+static unsigned char *Image_GenerateConChars(void)
+{
+       int i;
+       unsigned char *data;
+       double random;
+
+       image_width = 256;
+       image_height = 256;
+
+       data = LoadTGA_BGRA(concharimage, sizeof(concharimage), NULL);
+       // Gold numbers
+       for (i = 0; i < 8192; i++)
+       {
+               random = lhrandom(0.0, 1.0);
+               data[i * 4 + 3] = data[i * 4 + 0];
+               data[i * 4 + 2] = 83 + (unsigned char)(random * 64);
+               data[i * 4 + 1] = 71 + (unsigned char)(random * 32);
+               data[i * 4 + 0] = 23 + (unsigned char)(random * 16);
+       }
+       // White chars
+       for (i = 8192; i < 32768; i++)
+       {
+               random = lhrandom(0.0, 1.0);
+               data[i * 4 + 3] = data[i * 4 + 0];
+               data[i * 4 + 2] = 95 + (unsigned char)(random * 64);
+               data[i * 4 + 1] = 95 + (unsigned char)(random * 64);
+               data[i * 4 + 0] = 95 + (unsigned char)(random * 64);
+       }
+       // Gold numbers
+       for (i = 32768; i < 40960; i++)
+       {
+               random = lhrandom(0.0, 1.0);
+               data[i * 4 + 3] = data[i * 4 + 0];
+               data[i * 4 + 2] = 83 + (unsigned char)(random * 64);
+               data[i * 4 + 1] = 71 + (unsigned char)(random * 32);
+               data[i * 4 + 0] = 23 + (unsigned char)(random * 16);
+       }
+       // Red chars
+       for (i = 40960; i < 65536; i++)
+       {
+               random = lhrandom(0.0, 1.0);
+               data[i * 4 + 3] = data[i * 4 + 0];
+               data[i * 4 + 2] = 96 + (unsigned char)(random * 64);
+               data[i * 4 + 1] = 43 + (unsigned char)(random * 32);
+               data[i * 4 + 0] = 27 + (unsigned char)(random * 32);
+       }
+
+#if 0
+       Image_WriteTGABGRA("gfx/generated_conchars.tga", 256, 256, data);
+#endif
+
+       return data;
+}
+
+static unsigned char *Image_GenerateDitherPattern(void)
+{
+       int x, y;
+       unsigned char *data = (unsigned char *)Mem_Alloc(tempmempool, 8 * 8 * 4);
+       image_width = 8;
+       image_height = 8;
+       for (y = 0; y < 8; y++)
+       {
+               for (x = 0; x < 8; x++)
+               {
+                       data[(y * 8 + x) * 4 + 0] = ((x^y) & 4) ? 255 : 0;
+                       data[(y * 8 + x) * 4 + 1] = ((x^y) & 4) ? 255 : 0;
+                       data[(y * 8 + x) * 4 + 2] = ((x^y) & 4) ? 255 : 0;
+                       data[(y * 8 + x) * 4 + 3] = 255;
+               }
+       }
+       return data;
+}
+
+// also used in R_SkinFrame code
+unsigned char *Image_GenerateNoTexture(void)
+{
+       int x, y;
+       unsigned char *data = (unsigned char *)Mem_Alloc(tempmempool, 16 * 16 * 4);
+       image_width = 16;
+       image_height = 16;
+       // this makes a light grey/dark grey checkerboard texture
+       for (y = 0; y < 16; y++)
+       {
+               for (x = 0; x < 16; x++)
+               {
+                       data[(y * 8 + x) * 4 + 0] =
+                               data[(y * 8 + x) * 4 + 1] =
+                               data[(y * 8 + x) * 4 + 2] = (y < 8) ^ (x < 8) ? 128 : 64;
+                       data[(y * 8 + x) * 4 + 3] = 255;
+               }
+       }
+       return data;
+}
+
+static unsigned char *Image_GenerateWhite(void)
+{
+       unsigned char *data = (unsigned char *)Mem_Alloc(tempmempool, 1 * 1 * 4);
+       image_width = 1;
+       image_height = 1;
+       data[0] = data[1] = data[2] = data[3] = 255;
+       return data;
+}
+
+typedef struct embeddedpic_s
+{
+const char *name;
+int width;
+int height;
+const char *pixels;
+}
+embeddedpic_t;
+
+static const embeddedpic_t embeddedpics[] =
+{
+       {
+               "gfx/prydoncursor001", 16, 16,
+               "477777774......."
+               "77.....6........"
+               "7.....6........."
+               "7....6.........."
+               "7.....6........."
+               "7..6...6........"
+               "7.6.6...6......."
+               "76...6...6......"
+               "4.....6.6......."
+               ".......6........"
+               "................"
+               "................"
+               "................"
+               "................"
+               "................"
+               "................"
+       },
+       {
+               "ui/mousepointer", 16, 16,
+               "477777774......."
+               "77.....6........"
+               "7.....6........."
+               "7....6.........."
+               "7.....6........."
+               "7..6...6........"
+               "7.6.6...6......."
+               "76...6...6......"
+               "4.....6.6......."
+               ".......6........"
+               "................"
+               "................"
+               "................"
+               "................"
+               "................"
+               "................"
+       },
+       {
+               "gfx/crosshair1", 16, 16,
+               "................"
+               "................"
+               "................"
+               "...33......33..."
+               "...355....553..."
+               "....577..775...."
+               ".....77..77....."
+               "................"
+               "................"
+               ".....77..77....."
+               "....577..775...."
+               "...355....553..."
+               "...33......33..."
+               "................"
+               "................"
+               "................"
+       },
+       {
+               "gfx/crosshair2", 16, 16,
+               "................"
+               "................"
+               "................"
+               "...3........3..."
+               "....5......5...."
+               ".....7....7....."
+               "......7..7......"
+               "................"
+               "................"
+               "......7..7......"
+               ".....7....7....."
+               "....5......5...."
+               "...3........3..."
+               "................"
+               "................"
+               "................"
+       },
+       {
+               "gfx/crosshair3", 16, 16,
+               "................"
+               ".......77......."
+               ".......77......."
+               "................"
+               "................"
+               ".......44......."
+               ".......44......."
+               ".77..44..44..77."
+               ".77..44..44..77."
+               ".......44......."
+               ".......44......."
+               "................"
+               "................"
+               ".......77......."
+               ".......77......."
+               "................"
+       },
+       {
+               "gfx/crosshair4", 16, 16,
+               "................"
+               "................"
+               "................"
+               "................"
+               "................"
+               "................"
+               "................"
+               "................"
+               "........7777777."
+               "........752....."
+               "........72......"
+               "........7......."
+               "........7......."
+               "........7......."
+               "........7......."
+               "................"
+       },
+       {
+               "gfx/crosshair5", 8, 8,
+               "........"
+               "........"
+               "....7..."
+               "........"
+               "..7.7.7."
+               "........"
+               "....7..."
+               "........"
+       },
+       {
+               "gfx/crosshair6", 2, 2,
+               "77"
+               "77"
+       },
+       {
+               "gfx/crosshair7", 16, 16,
+               "................"
+               ".3............3."
+               "..5...2332...5.."
+               "...7.3....3.7..."
+               "....7......7...."
+               "...3.7....7.3..."
+               "..2...7..7...2.."
+               "..3..........3.."
+               "..3..........3.."
+               "..2...7..7...2.."
+               "...3.7....7.3..."
+               "....7......7...."
+               "...7.3....3.7..."
+               "..5...2332...5.."
+               ".3............3."
+               "................"
+       },
+       { NULL, 0, 0, NULL }
+};
+
+unsigned char *Image_GetEmbeddedPicBGRA(const char *name)
+{
+       const embeddedpic_t *p;
+       for (p = embeddedpics; p->name; p++)
+       {
+               if (!strcmp(name, p->name))
+               {
+                       int i;
+                       unsigned char *data = (unsigned char *)Mem_Alloc(tempmempool, p->width * p->height * 4);
+                       image_width = p->width;
+                       image_height = p->height;
+                       for (i = 0; i < p->width * p->height; i++)
+                       {
+                               const unsigned char *c = (const unsigned char *)palette_bgra_embeddedpic + 4 * p->pixels[i];
+                               Vector4Copy(c, data + 4 * i);
+                       }
+                       return data;
+               }
+       }
+       if (!strcmp(name, "white"))
+               return Image_GenerateWhite();
+       if (!strcmp(name, "gfx/conchars"))
+               return Image_GenerateConChars();
+       if (!strcmp(name, "gfx/colorcontrol/ditherpattern"))
+               return Image_GenerateDitherPattern();
+       return NULL;
+}
diff --git a/image.h b/image.h
index dd555a8..21dc012 100644 (file)
--- a/image.h
+++ b/image.h
@@ -4,6 +4,7 @@
 
 extern int image_width, image_height;
 
+unsigned char *Image_GenerateNoTexture(void);
 
 // swizzle components (even converting number of components) and flip images
 // (warning: input must be different than output due to non-linear read/write)
@@ -25,6 +26,9 @@ unsigned char *LoadTGA_BGRA (const unsigned char *f, int filesize, int *miplevel
 // loads a texture, as pixel data
 unsigned char *loadimagepixelsbgra (const char *filename, qboolean complain, qboolean allowFixtrans, qboolean convertsRGB, int *miplevel);
 
+// searches for lmp and wad pics of the provided name and returns true and their dimensions if found
+qboolean Image_GetStockPicSize(const char *filename, int *returnwidth, int *returnheight);
+
 // loads an 8bit pcx image into a 296x194x8bit buffer, with cropping as needed
 qboolean LoadPCX_QWSkin(const unsigned char *f, int filesize, unsigned char *pixels, int outwidth, int outheight);
 
index 72ec15d..a1b5690 100644 (file)
--- a/libcurl.c
+++ b/libcurl.c
@@ -598,7 +598,7 @@ static void Curl_EndDownload(downloadinfo *di, CurlStatus status, CURLcode error
 
                pixels = decode_image(di, content_type);
                if(pixels)
-                       Draw_NewPic(p, image_width, image_height, true, pixels);
+                       Draw_NewPic(p, image_width, image_height, pixels, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP);
                else
                        CLEAR_AND_RETRY();
        }
diff --git a/menu.c b/menu.c
index 5ad0755..aa6fb7b 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -414,7 +414,7 @@ void M_Menu_Main_f (void)
                MAIN_ITEMS = 5;
 
        // check if the game data is missing and use a different main menu if so
-       m_missingdata = !forceqmenu.integer && Draw_CachePic (s)->tex == r_texture_notexture;
+       m_missingdata = !forceqmenu.integer && !Draw_IsPicLoaded(Draw_CachePic(s));
        if (m_missingdata)
                MAIN_ITEMS = 2;
 
@@ -458,7 +458,7 @@ static void M_Main_Draw (void)
                int y1, y2, y3;
                M_Background(640, 480);
                p = Draw_CachePic ("gfx/menu/tb-transfusion");
-               M_DrawPic (640/2 - p->width/2, 40, "gfx/menu/tb-transfusion");
+               M_DrawPic (640/2 - Draw_GetPicWidth(p)/2, 40, "gfx/menu/tb-transfusion");
                y2 = 120;
                // 8 rather than MAIN_ITEMS to skip a number and not miss the last option
                for (y1 = 1; y1 <= 8; y1++)
@@ -479,7 +479,7 @@ static void M_Main_Draw (void)
        M_Background(320, 200);
        M_DrawPic (16, 4, "gfx/qplaque");
        p = Draw_CachePic ("gfx/ttl_main");
-       M_DrawPic ( (320-p->width)/2, 4, "gfx/ttl_main");
+       M_DrawPic ( (320-Draw_GetPicWidth(p))/2, 4, "gfx/ttl_main");
 // Nehahra
        if (gamemode == GAME_NEHAHRA)
        {
@@ -758,7 +758,7 @@ static void M_SinglePlayer_Draw (void)
        // Some mods don't have a single player mode
        if (gamemode == GAME_GOODVSBAD2 || gamemode == GAME_BATTLEMECH)
        {
-               M_DrawPic ((320 - p->width) / 2, 4, "gfx/ttl_sgl");
+               M_DrawPic ((320 - Draw_GetPicWidth(p)) / 2, 4, "gfx/ttl_sgl");
 
                M_DrawTextBox (60, 8 * 8, 23, 4);
                if (gamemode == GAME_GOODVSBAD2)
@@ -771,7 +771,7 @@ static void M_SinglePlayer_Draw (void)
        {
                int             f;
 
-               M_DrawPic ( (320-p->width)/2, 4, "gfx/ttl_sgl");
+               M_DrawPic ( (320-Draw_GetPicWidth(p))/2, 4, "gfx/ttl_sgl");
                M_DrawPic (72, 32, "gfx/sp_menu");
 
                f = (int)(realtime * 10)%6;
@@ -925,7 +925,7 @@ static void M_Load_Draw (void)
        M_Background(320, 200);
 
        p = Draw_CachePic ("gfx/p_load");
-       M_DrawPic ( (320-p->width)/2, 4, "gfx/p_load" );
+       M_DrawPic ( (320-Draw_GetPicWidth(p))/2, 4, "gfx/p_load" );
 
        for (i=0 ; i< MAX_SAVEGAMES; i++)
                M_Print(16, 32 + 8*i, m_filenames[i]);
@@ -943,7 +943,7 @@ static void M_Save_Draw (void)
        M_Background(320, 200);
 
        p = Draw_CachePic ("gfx/p_save");
-       M_DrawPic ( (320-p->width)/2, 4, "gfx/p_save");
+       M_DrawPic ( (320-Draw_GetPicWidth(p))/2, 4, "gfx/p_save");
 
        for (i=0 ; i<MAX_SAVEGAMES ; i++)
                M_Print(16, 32 + 8*i, m_filenames[i]);
@@ -1052,7 +1052,7 @@ static void M_Transfusion_Episode_Draw (void)
        M_Background(640, 480);
 
        p = Draw_CachePic ("gfx/menu/tb-episodes");
-       M_DrawPic (640/2 - p->width/2, 40, "gfx/menu/tb-episodes");
+       M_DrawPic (640/2 - Draw_GetPicWidth(p)/2, 40, "gfx/menu/tb-episodes");
        for (y = 0; y < EPISODE_ITEMS; y++){
                M_DrawPic (0, 160 + y * 40, va(vabuf, sizeof(vabuf), "gfx/menu/episode%i", y+1));
        }
@@ -1110,7 +1110,7 @@ static void M_Transfusion_Skill_Draw (void)
        M_Background(640, 480);
 
        p = Draw_CachePic ("gfx/menu/tb-difficulty");
-       M_DrawPic(640/2 - p->width/2, 40, "gfx/menu/tb-difficulty");
+       M_DrawPic(640/2 - Draw_GetPicWidth(p)/2, 40, "gfx/menu/tb-difficulty");
 
        for (y = 0; y < SKILL_ITEMS; y++)
        {
@@ -1215,7 +1215,7 @@ static void M_MultiPlayer_Draw (void)
        {
                M_Background(640, 480);
                p = Draw_CachePic ("gfx/menu/tb-online");
-               M_DrawPic (640/2 - p->width/2, 140, "gfx/menu/tb-online");
+               M_DrawPic (640/2 - Draw_GetPicWidth(p)/2, 140, "gfx/menu/tb-online");
                for (f = 1; f <= MULTIPLAYER_ITEMS; f++)
                        M_DrawPic (0, 180 + f*40, va(vabuf, sizeof(vabuf), "gfx/menu/online%i", f));
                M_DrawPic (0, 220 + m_multiplayer_cursor * 40, va(vabuf, sizeof(vabuf), "gfx/menu/online%iselected", m_multiplayer_cursor + 1));
@@ -1225,7 +1225,7 @@ static void M_MultiPlayer_Draw (void)
 
        M_DrawPic (16, 4, "gfx/qplaque");
        p = Draw_CachePic ("gfx/p_multi");
-       M_DrawPic ( (320-p->width)/2, 4, "gfx/p_multi");
+       M_DrawPic ( (320-Draw_GetPicWidth(p))/2, 4, "gfx/p_multi");
        M_DrawPic (72, 32, "gfx/mp_menu");
 
        f = (int)(realtime * 10)%6;
@@ -1344,7 +1344,7 @@ static void M_Setup_Draw (void)
 
        M_DrawPic (16, 4, "gfx/qplaque");
        p = Draw_CachePic ("gfx/p_multi");
-       M_DrawPic ( (320-p->width)/2, 4, "gfx/p_multi");
+       M_DrawPic ( (320-Draw_GetPicWidth(p))/2, 4, "gfx/p_multi");
 
        M_Print(64, 40, "Your name");
        M_DrawTextBox (160, 32, 16, 1);
@@ -1415,7 +1415,7 @@ static void M_Setup_Draw (void)
                                }
                                menuplyr_translated[i] = palette_bgra_transparent[j];
                        }
-                       Draw_NewPic("gfx/menuplyr", menuplyr_width, menuplyr_height, true, (unsigned char *)menuplyr_translated);
+                       Draw_NewPic("gfx/menuplyr", menuplyr_width, menuplyr_height, (unsigned char *)menuplyr_translated, TEXTYPE_BGRA, TEXF_CLAMP);
                }
                M_DrawPic(160, 48, "gfx/bigbox");
                M_DrawPic(172, 56, "gfx/menuplyr");
@@ -1680,7 +1680,7 @@ static void M_Options_Draw (void)
 
        M_DrawPic(16, 4, "gfx/qplaque");
        p = Draw_CachePic ("gfx/p_option");
-       M_DrawPic((320-p->width)/2, 4, "gfx/p_option");
+       M_DrawPic((320-Draw_GetPicWidth(p))/2, 4, "gfx/p_option");
 
        m_optnum = 0;
        m_optcursor = options_cursor;
@@ -1889,7 +1889,7 @@ static void M_Options_Effects_Draw (void)
 
        M_DrawPic(16, 4, "gfx/qplaque");
        p = Draw_CachePic ("gfx/p_option");
-       M_DrawPic((320-p->width)/2, 4, "gfx/p_option");
+       M_DrawPic((320-Draw_GetPicWidth(p))/2, 4, "gfx/p_option");
 
        m_optcursor = options_effects_cursor;
        m_optnum = 0;
@@ -2036,7 +2036,7 @@ static void M_Options_Graphics_Draw (void)
 
        M_DrawPic(16, 4, "gfx/qplaque");
        p = Draw_CachePic ("gfx/p_option");
-       M_DrawPic((320-p->width)/2, 4, "gfx/p_option");
+       M_DrawPic((320-Draw_GetPicWidth(p))/2, 4, "gfx/p_option");
 
        m_optcursor = options_graphics_cursor;
        m_optnum = 0;
@@ -2226,7 +2226,7 @@ static void M_Options_ColorControl_Draw (void)
 
        M_DrawPic(16, 4, "gfx/qplaque");
        p = Draw_CachePic ("gfx/p_option");
-       M_DrawPic((320-p->width)/2, 4, "gfx/p_option");
+       M_DrawPic((320-Draw_GetPicWidth(p))/2, 4, "gfx/p_option");
 
        m_optcursor = options_colorcontrol_cursor;
        m_optnum = 0;
@@ -2617,7 +2617,7 @@ static void M_Keys_Draw (void)
        M_Background(320, 48 + 8 * numcommands);
 
        p = Draw_CachePic ("gfx/ttl_cstm");
-       M_DrawPic ( (320-p->width)/2, 4, "gfx/ttl_cstm");
+       M_DrawPic ( (320-Draw_GetPicWidth(p))/2, 4, "gfx/ttl_cstm");
 
        if (bind_grab)
                M_Print(12, 32, "Press a key or button for this action");
@@ -2928,7 +2928,7 @@ static void M_Video_Draw (void)
 
        M_DrawPic(16, 4, "gfx/qplaque");
        p = Draw_CachePic ("gfx/vidmodes");
-       M_DrawPic((320-p->width)/2, 4, "gfx/vidmodes");
+       M_DrawPic((320-Draw_GetPicWidth(p))/2, 4, "gfx/vidmodes");
 
        t = 0;
 
@@ -3370,7 +3370,7 @@ static void M_LanConfig_Draw (void)
 
        M_DrawPic (16, 4, "gfx/qplaque");
        p = Draw_CachePic ("gfx/p_multi");
-       basex = (320-p->width)/2;
+       basex = (320-Draw_GetPicWidth(p))/2;
        M_DrawPic (basex, 4, "gfx/p_multi");
 
        if (StartingGame)
@@ -3994,7 +3994,7 @@ void M_GameOptions_Draw (void)
 
        M_DrawPic (16, 4, "gfx/qplaque");
        p = Draw_CachePic ("gfx/p_multi");
-       M_DrawPic ( (320-p->width)/2, 4, "gfx/p_multi");
+       M_DrawPic ( (320-Draw_GetPicWidth(p))/2, 4, "gfx/p_multi");
 
        M_DrawTextBox (152, 32, 10, 1);
        M_Print(160, 40, "begin game");
@@ -4435,7 +4435,7 @@ static void M_ServerList_Draw (void)
        end = min(start + visible, serverlist_viewcount);
 
        p = Draw_CachePic ("gfx/p_multi");
-       M_DrawPic((640 - p->width) / 2, 4, "gfx/p_multi");
+       M_DrawPic((640 - Draw_GetPicWidth(p)) / 2, 4, "gfx/p_multi");
        if (end > start)
        {
                for (n = start;n < end;n++)
@@ -4671,7 +4671,7 @@ static void M_ModList_Draw (void)
        end = min(start + visible, modlist_count);
 
        p = Draw_CachePic ("gfx/p_option");
-       M_DrawPic((640 - p->width) / 2, 4, "gfx/p_option");
+       M_DrawPic((640 - Draw_GetPicWidth(p)) / 2, 4, "gfx/p_option");
        if (end > start)
        {
                for (n = start;n < end;n++)
@@ -4889,7 +4889,7 @@ void M_Draw (void)
                        drop1 = Draw_CachePic ("gfx/menu/blooddrop1");
                        drop2 = Draw_CachePic ("gfx/menu/blooddrop2");
                        drop3 = Draw_CachePic ("gfx/menu/blooddrop3");
-                       for (scale_x = 0; scale_x <= vid_conwidth.integer; scale_x += p->width) {
+                       for (scale_x = 0; scale_x <= vid_conwidth.integer; scale_x += Draw_GetPicWidth(p)) {
                                for (scale_y = -scale_y_repeat; scale_y <= vid_conheight.integer; scale_y += scale_y_repeat) {
                                        DrawQ_Pic (scale_x + 21, scale_y_repeat * .5 + scale_y + scale_y_rate * scale_y_repeat, drop3, 0, 0, 1, 1, 1, 1, 0);
                                        DrawQ_Pic (scale_x +  116, scale_y_repeat + scale_y + scale_y_rate * scale_y_repeat, drop1, 0, 0, 1, 1, 1, 1, 0);
index e319582..9fdc080 100644 (file)
@@ -922,45 +922,6 @@ static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *ve
        }
 }
 
-static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
-{
-       if (cls.state == ca_dedicated)
-               return;
-       // hack
-       if (!skinframe)
-               skinframe = R_SkinFrame_LoadMissing();
-       memset(texture, 0, sizeof(*texture));
-       texture->currentframe = texture;
-       //texture->animated = false;
-       texture->materialshaderpass = texture->shaderpasses[0] = Mod_CreateShaderPass(skinframe);
-       texture->currentskinframe = skinframe;
-       //texture->backgroundnumskinframes = 0;
-       //texture->customblendfunc[0] = 0;
-       //texture->customblendfunc[1] = 0;
-       //texture->surfaceflags = 0;
-       //texture->supercontents = 0;
-       //texture->surfaceparms = 0;
-       //texture->textureflags = 0;
-
-       texture->basematerialflags = MATERIALFLAG_WALL;
-       texture->basealpha = 1.0f;
-       if (texture->currentskinframe->hasalpha)
-               texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
-       texture->currentmaterialflags = texture->basematerialflags;
-       texture->offsetmapping = OFFSETMAPPING_DEFAULT;
-       texture->offsetscale = 1;
-       texture->offsetbias = 0;
-       texture->specularscalemod = 1;
-       texture->specularpowermod = 1;
-       texture->surfaceflags = 0;
-       texture->supercontents = SUPERCONTENTS_SOLID;
-       if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
-               texture->supercontents |= SUPERCONTENTS_OPAQUE;
-       texture->transparentsort = TRANSPARENTSORT_DISTANCE;
-       // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
-       // JUST GREP FOR "specularscalemod = 1".
-}
-
 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
 {
        int i;
@@ -983,14 +944,14 @@ void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, con
                                        Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
                                        if(developer_extra.integer)
                                                Con_DPrintf("--> got %s from skin file\n", stripbuf);
-                                       Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
+                                       Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
                                        break;
                                }
                        }
                        if (!skinfileitem)
                        {
                                // don't render unmentioned meshes
-                               Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
+                               Mod_LoadCustomMaterial(loadmodel->mempool, skin, meshname, SUPERCONTENTS_SOLID, MATERIALFLAG_WALL, R_SkinFrame_LoadMissing());
                                if(developer_extra.integer)
                                        Con_DPrintf("--> skipping\n");
                                skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
@@ -1002,7 +963,7 @@ void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, con
                if(developer_extra.integer)
                        Con_DPrintf("--> using default\n");
                Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
-               Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
+               Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
        }
 }
 
@@ -1030,7 +991,6 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
        float *vertst;
        int *vertonseam, *vertremap;
        skinfile_t *skinfiles;
-       char vabuf[1024];
 
        datapointer = (unsigned char *)buffer;
        pinmodel = (mdl_t *)datapointer;
@@ -1299,8 +1259,8 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
                                        dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
                                else
                                        dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
-                               if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS))
-                                       Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight));
+                               if (!Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, false, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS))
+                                       Mod_LoadCustomMaterial(loadmodel->mempool, loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, SUPERCONTENTS_SOLID, MATERIALFLAG_WALL, R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight));
                                datapointer += skinwidth * skinheight;
                                totalskins++;
                        }
@@ -1308,8 +1268,12 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
                // check for skins that don't exist in the model, but do exist as external images
                // (this was added because yummyluv kept pestering me about support for it)
                // TODO: support shaders here?
-               while ((tempskinframe = R_SkinFrame_LoadExternal(va(vabuf, sizeof(vabuf), "%s_%i", loadmodel->name, loadmodel->numskins), (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false)))
+               for (;;)
                {
+                       dpsnprintf(name, sizeof(name), "%s_%i", loadmodel->name, loadmodel->numskins);
+                       tempskinframe = R_SkinFrame_LoadExternal(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false, false);
+                       if (!tempskinframe)
+                               break;
                        // expand the arrays to make room
                        tempskinscenes = loadmodel->skinscenes;
                        loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
@@ -1322,7 +1286,7 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
                        Mem_Free(tempaliasskins);
 
                        // store the info about the new skin
-                       Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
+                       Mod_LoadCustomMaterial(loadmodel->mempool, loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, SUPERCONTENTS_SOLID, MATERIALFLAG_WALL, tempskinframe);
                        strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
                        loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
                        loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
@@ -1487,7 +1451,7 @@ void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
                loadmodel->num_texturesperskin = loadmodel->num_surfaces;
                loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
                for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
-                       Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
+                       Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
        }
        else
        {
@@ -1496,7 +1460,7 @@ void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
                loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
                loadmodel->num_texturesperskin = loadmodel->num_surfaces;
                loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
-               Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
+               Mod_LoadCustomMaterial(loadmodel->mempool, loadmodel->data_textures, loadmodel->name, SUPERCONTENTS_SOLID, MATERIALFLAG_WALL, R_SkinFrame_LoadMissing());
        }
 
        loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
index e981a59..e6451a0 100644 (file)
@@ -1725,7 +1725,7 @@ static void Mod_Q1BSP_LoadTextures(sizebuf_t *sb)
                tx->width = 16;
                tx->height = 16;
                tx->basealpha = 1.0f;
-               tx->materialshaderpass = tx->shaderpasses[0] = Mod_CreateShaderPass(skinframemissing);
+               tx->materialshaderpass = tx->shaderpasses[0] = Mod_CreateShaderPass(loadmodel->mempool, skinframemissing);
                tx->materialshaderpass->skinframes[0] = skinframemissing;
                tx->currentskinframe = skinframemissing;
                tx->basematerialflags = MATERIALFLAG_WALL;
@@ -1826,7 +1826,7 @@ static void Mod_Q1BSP_LoadTextures(sizebuf_t *sb)
 
                // LordHavoc: backup the texture_t because q3 shader loading overwrites it
                backuptex = loadmodel->data_textures[i];
-               if (name[0] && Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i, name, false, false, 0))
+               if (name[0] && Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, loadmodel->data_textures + i, name, false, false, 0))
                        continue;
                loadmodel->data_textures[i] = backuptex;
 
@@ -1889,9 +1889,9 @@ static void Mod_Q1BSP_LoadTextures(sizebuf_t *sb)
                        }
                        else
                        {
-                               skinframe_t *skinframe = R_SkinFrame_LoadExternal(gamemode == GAME_TENEBRAE ? tx->name : va(vabuf, sizeof(vabuf), "textures/%s/%s", mapname, tx->name), TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS, false);
+                               skinframe_t *skinframe = R_SkinFrame_LoadExternal(gamemode == GAME_TENEBRAE ? tx->name : va(vabuf, sizeof(vabuf), "textures/%s/%s", mapname, tx->name), TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS, false, false);
                                if (!skinframe)
-                                       skinframe = R_SkinFrame_LoadExternal(gamemode == GAME_TENEBRAE ? tx->name : va(vabuf, sizeof(vabuf), "textures/%s", tx->name), TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS, false);
+                                       skinframe = R_SkinFrame_LoadExternal(gamemode == GAME_TENEBRAE ? tx->name : va(vabuf, sizeof(vabuf), "textures/%s", tx->name), TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS, false, false);
                                if (skinframe)
                                        tx->offsetmapping = OFFSETMAPPING_DEFAULT; // allow offsetmapping on external textures without a q3 shader
                                if (!skinframe)
@@ -4439,7 +4439,7 @@ static void Mod_Q2BSP_LoadTexinfo(sizebuf_t *sb)
                                int q2flags = out->q2flags;
                                unsigned char *walfile = NULL;
                                fs_offset_t walfilesize = 0;
-                               Mod_LoadTextureFromQ3Shader(tx, filename, true, true, TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS);
+                               Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, tx, filename, true, true, TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS);
                                // now read the .wal file to get metadata (even if a .tga was overriding it, we still need the wal data)
                                walfile = FS_LoadFile(filename, tempmempool, true, &walfilesize);
                                if (walfile)
@@ -5309,7 +5309,7 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l)
        {
                out[i].surfaceflags = LittleLong(in[i].surfaceflags);
                out[i].supercontents = Mod_Q3BSP_SuperContentsFromNativeContents(LittleLong(in[i].contents));
-               Mod_LoadTextureFromQ3Shader(out + i, in[i].name, true, true, TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS);
+               Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, out + i, in[i].name, true, true, TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS);
                // restore the surfaceflags and supercontents
                out[i].surfaceflags = LittleLong(in[i].surfaceflags);
                out[i].supercontents = Mod_Q3BSP_SuperContentsFromNativeContents(LittleLong(in[i].contents));
index eaa7134..9d7d449 100644 (file)
@@ -2412,9 +2412,9 @@ q3shaderinfo_t *Mod_LookupQ3Shader(const char *name)
        return NULL;
 }
 
-texture_shaderpass_t *Mod_CreateShaderPass(skinframe_t *skinframe)
+texture_shaderpass_t *Mod_CreateShaderPass(mempool_t *mempool, skinframe_t *skinframe)
 {
-       texture_shaderpass_t *shaderpass = (texture_shaderpass_t *)Mem_Alloc(loadmodel->mempool, sizeof(*shaderpass));
+       texture_shaderpass_t *shaderpass = (texture_shaderpass_t *)Mem_Alloc(mempool, sizeof(*shaderpass));
        shaderpass->framerate = 0.0f;
        shaderpass->numframes = 1;
        shaderpass->blendfunc[0] = GL_ONE;
@@ -2427,10 +2427,10 @@ texture_shaderpass_t *Mod_CreateShaderPass(skinframe_t *skinframe)
        return shaderpass;
 }
 
-texture_shaderpass_t *Mod_CreateShaderPassFromQ3ShaderLayer(q3shaderinfo_layer_t *layer, int layerindex, int texflags, const char *texturename)
+texture_shaderpass_t *Mod_CreateShaderPassFromQ3ShaderLayer(mempool_t *mempool, const char *modelname, q3shaderinfo_layer_t *layer, int layerindex, int texflags, const char *texturename)
 {
        int j;
-       texture_shaderpass_t *shaderpass = (texture_shaderpass_t *)Mem_Alloc(loadmodel->mempool, sizeof(*shaderpass));
+       texture_shaderpass_t *shaderpass = (texture_shaderpass_t *)Mem_Alloc(mempool, sizeof(*shaderpass));
        shaderpass->alphatest = layer->alphatest != 0;
        shaderpass->framerate = layer->framerate;
        shaderpass->numframes = layer->numframes;
@@ -2442,21 +2442,11 @@ texture_shaderpass_t *Mod_CreateShaderPassFromQ3ShaderLayer(q3shaderinfo_layer_t
        for (j = 0; j < Q3MAXTCMODS && layer->tcmods[j].tcmod != Q3TCMOD_NONE; j++)
                shaderpass->tcmods[j] = layer->tcmods[j];
        for (j = 0; j < layer->numframes; j++)
-       {
-               if (cls.state == ca_dedicated)
-               {
-                       shaderpass->skinframes[j] = NULL;
-               }
-               else if (!(shaderpass->skinframes[j] = R_SkinFrame_LoadExternal(layer->texturename[j], texflags, false)))
-               {
-                       Con_Printf("^1%s:^7 could not load texture ^3\"%s\"^7 (frame %i) for layer %i of shader ^2\"%s\"\n", loadmodel->name, layer->texturename[j], j, layerindex, texturename);
-                       shaderpass->skinframes[j] = R_SkinFrame_LoadMissing();
-               }
-       }
+               shaderpass->skinframes[j] = R_SkinFrame_LoadExternal(layer->texturename[j], texflags, false, true);
        return shaderpass;
 }
 
-qboolean Mod_LoadTextureFromQ3Shader(texture_t *texture, const char *name, qboolean warnmissing, qboolean fallback, int defaulttexflags)
+qboolean Mod_LoadTextureFromQ3Shader(mempool_t *mempool, const char *modelname, texture_t *texture, const char *name, qboolean warnmissing, qboolean fallback, int defaulttexflags)
 {
        int texflagsmask, texflagsor;
        qboolean success = true;
@@ -2492,12 +2482,12 @@ qboolean Mod_LoadTextureFromQ3Shader(texture_t *texture, const char *name, qbool
        if (shader)
        {
                if (developer_loading.integer)
-                       Con_Printf("%s: loaded shader for %s\n", loadmodel->name, name);
+                       Con_Printf("%s: loaded shader for %s\n", modelname, name);
 
                if (shader->surfaceparms & Q3SURFACEPARM_SKY)
                {
                        texture->basematerialflags = MATERIALFLAG_SKY;
-                       if (shader->skyboxname[0])
+                       if (shader->skyboxname[0] && loadmodel)
                        {
                                // quake3 seems to append a _ to the skybox name, so this must do so as well
                                dpsnprintf(loadmodel->brush.skybox, sizeof(loadmodel->brush.skybox), "%s_", shader->skyboxname);
@@ -2644,19 +2634,19 @@ nothing                GL_ZERO GL_ONE
                        // convert the main material layer
                        // FIXME: if alphagenspecularlayer is used, we should pass a specular texture name to R_SkinFrame_LoadExternal and have it load that texture instead of the assumed name for _gloss texture
                        if (materiallayer >= 0)
-                               texture->materialshaderpass = texture->shaderpasses[shaderpassindex++] = Mod_CreateShaderPassFromQ3ShaderLayer(&shader->layers[materiallayer], materiallayer, (shader->layers[materiallayer].dptexflags & texflagsmask) | texflagsor, texture->name);
+                               texture->materialshaderpass = texture->shaderpasses[shaderpassindex++] = Mod_CreateShaderPassFromQ3ShaderLayer(mempool, modelname, &shader->layers[materiallayer], materiallayer, (shader->layers[materiallayer].dptexflags & texflagsmask) | texflagsor, texture->name);
                        // convert the terrain background blend layer (if any)
                        if (terrainbackgroundlayer >= 0)
-                               texture->backgroundshaderpass = texture->shaderpasses[shaderpassindex++] = Mod_CreateShaderPassFromQ3ShaderLayer(&shader->layers[terrainbackgroundlayer], terrainbackgroundlayer, (shader->layers[terrainbackgroundlayer].dptexflags & texflagsmask) | texflagsor, texture->name);
+                               texture->backgroundshaderpass = texture->shaderpasses[shaderpassindex++] = Mod_CreateShaderPassFromQ3ShaderLayer(mempool, modelname, &shader->layers[terrainbackgroundlayer], terrainbackgroundlayer, (shader->layers[terrainbackgroundlayer].dptexflags & texflagsmask) | texflagsor, texture->name);
                        // convert the prepass layers (if any)
                        texture->startpreshaderpass = shaderpassindex;
                        for (i = 0; i < endofprelayers; i++)
-                               texture->shaderpasses[shaderpassindex++] = Mod_CreateShaderPassFromQ3ShaderLayer(&shader->layers[i], i, (shader->layers[i].dptexflags & texflagsmask) | texflagsor, texture->name);
+                               texture->shaderpasses[shaderpassindex++] = Mod_CreateShaderPassFromQ3ShaderLayer(mempool, modelname, &shader->layers[i], i, (shader->layers[i].dptexflags & texflagsmask) | texflagsor, texture->name);
                        texture->endpreshaderpass = shaderpassindex;
                        texture->startpostshaderpass = shaderpassindex;
                        // convert the postpass layers (if any)
                        for (i = firstpostlayer; i < shader->numlayers; i++)
-                               texture->shaderpasses[shaderpassindex++] = Mod_CreateShaderPassFromQ3ShaderLayer(&shader->layers[i], i, (shader->layers[i].dptexflags & texflagsmask) | texflagsor, texture->name);
+                               texture->shaderpasses[shaderpassindex++] = Mod_CreateShaderPassFromQ3ShaderLayer(mempool, modelname, &shader->layers[i], i, (shader->layers[i].dptexflags & texflagsmask) | texflagsor, texture->name);
                        texture->startpostshaderpass = shaderpassindex;
                }
 
@@ -2766,25 +2756,25 @@ nothing                GL_ZERO GL_ONE
                if (shader->dpmeshcollisions)
                        texture->basematerialflags |= MATERIALFLAG_MESHCOLLISIONS;
                if (shader->dpshaderkill && developer_extra.integer)
-                       Con_DPrintf("^1%s:^7 killing shader ^3\"%s\" because of cvar\n", loadmodel->name, name);
+                       Con_DPrintf("^1%s:^7 killing shader ^3\"%s\" because of cvar\n", modelname, name);
        }
        else if (!strcmp(texture->name, "noshader") || !texture->name[0])
        {
                if (developer_extra.integer)
-                       Con_DPrintf("^1%s:^7 using fallback noshader material for ^3\"%s\"\n", loadmodel->name, name);
+                       Con_DPrintf("^1%s:^7 using fallback noshader material for ^3\"%s\"\n", modelname, name);
                texture->supercontents = SUPERCONTENTS_SOLID | SUPERCONTENTS_OPAQUE;
        }
        else if (!strcmp(texture->name, "common/nodraw") || !strcmp(texture->name, "textures/common/nodraw"))
        {
                if (developer_extra.integer)
-                       Con_DPrintf("^1%s:^7 using fallback nodraw material for ^3\"%s\"\n", loadmodel->name, name);
+                       Con_DPrintf("^1%s:^7 using fallback nodraw material for ^3\"%s\"\n", modelname, name);
                texture->basematerialflags = MATERIALFLAG_NODRAW | MATERIALFLAG_NOSHADOW;
                texture->supercontents = SUPERCONTENTS_SOLID;
        }
        else
        {
                if (developer_extra.integer)
-                       Con_DPrintf("^1%s:^7 No shader found for texture ^3\"%s\"\n", loadmodel->name, texture->name);
+                       Con_DPrintf("^1%s:^7 No shader found for texture ^3\"%s\"\n", modelname, texture->name);
                if (texture->surfaceflags & Q3SURFACEFLAG_NODRAW)
                {
                        texture->basematerialflags |= MATERIALFLAG_NODRAW | MATERIALFLAG_NOSHADOW;
@@ -2809,27 +2799,23 @@ nothing                GL_ZERO GL_ONE
                {
                        if (fallback)
                        {
-                               texture->materialshaderpass = texture->shaderpasses[0] = Mod_CreateShaderPass(R_SkinFrame_LoadExternal(texture->name, defaulttexflags, false));
-                               if (texture->materialshaderpass->skinframes[0])
-                               {
-                                       if (texture->materialshaderpass->skinframes[0]->hasalpha)
-                                               texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
-                                       if (texture->q2contents)
-                                               texture->supercontents = Mod_Q2BSP_SuperContentsFromNativeContents(texture->q2contents);
-                               }
-                               else
-                                       success = false;
+                               texture->materialshaderpass = texture->shaderpasses[0] = Mod_CreateShaderPass(mempool, R_SkinFrame_LoadExternal(texture->name, defaulttexflags, false, true));
+                               if (texture->materialshaderpass->skinframes[0]->hasalpha)
+                                       texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
+                               if (texture->q2contents)
+                                       texture->supercontents = Mod_Q2BSP_SuperContentsFromNativeContents(texture->q2contents);
                        }
                        else
                                success = false;
                        if (!success && warnmissing)
-                               Con_Printf("^1%s:^7 could not load texture ^3\"%s\"\n", loadmodel->name, texture->name);
+                               Con_Printf("^1%s:^7 could not load texture ^3\"%s\"\n", modelname, texture->name);
                }
        }
        // init the animation variables
        texture->currentframe = texture;
+       texture->currentmaterialflags = texture->basematerialflags;
        if (!texture->materialshaderpass)
-               texture->materialshaderpass = texture->shaderpasses[0] = Mod_CreateShaderPass(R_SkinFrame_LoadMissing());
+               texture->materialshaderpass = texture->shaderpasses[0] = Mod_CreateShaderPass(mempool, R_SkinFrame_LoadMissing());
        if (!texture->materialshaderpass->skinframes[0])
                texture->materialshaderpass->skinframes[0] = R_SkinFrame_LoadMissing();
        texture->currentskinframe = texture->materialshaderpass ? texture->materialshaderpass->skinframes[0] : NULL;
@@ -2837,13 +2823,14 @@ nothing                GL_ZERO GL_ONE
        return success;
 }
 
-void Mod_LoadCustomMaterial(texture_t *texture, const char *name, int supercontents, int materialflags, skinframe_t *skinframe)
+void Mod_LoadCustomMaterial(mempool_t *mempool, texture_t *texture, const char *name, int supercontents, int materialflags, skinframe_t *skinframe)
 {
        if (!(materialflags & (MATERIALFLAG_WALL | MATERIALFLAG_SKY)))
-               Con_DPrintf("^1%s:^7 Custom texture ^3\"%s\" does not have MATERIALFLAG_WALL set\n", loadmodel->name, texture->name);
+               Con_DPrintf("^1Custom texture ^3\"%s\" does not have MATERIALFLAG_WALL set\n", texture->name);
+
        strlcpy(texture->name, name, sizeof(texture->name));
        texture->basealpha = 1.0f;
-       texture->basematerialflags = texture->currentmaterialflags = materialflags;
+       texture->basematerialflags = materialflags;
        texture->supercontents = supercontents;
 
        texture->offsetmapping = (mod_noshader_default_offsetmapping.value) ? OFFSETMAPPING_DEFAULT : OFFSETMAPPING_OFF;
@@ -2857,17 +2844,35 @@ void Mod_LoadCustomMaterial(texture_t *texture, const char *name, int superconte
        // JUST GREP FOR "specularscalemod = 1".
 
        if (developer_extra.integer)
-               Con_DPrintf("^1%s:^7 Custom texture ^3\"%s\"\n", loadmodel->name, texture->name);
-       texture->materialshaderpass = texture->shaderpasses[0] = Mod_CreateShaderPass(skinframe);
+               Con_DPrintf("^1Custom texture ^3\"%s\"\n", texture->name);
+       if (skinframe)
+               texture->materialshaderpass = texture->shaderpasses[0] = Mod_CreateShaderPass(mempool, skinframe);
 
        // init the animation variables
+       texture->currentmaterialflags = texture->basematerialflags;
        texture->currentframe = texture;
-       if (!texture->materialshaderpass)
-               texture->materialshaderpass = texture->shaderpasses[0] = Mod_CreateShaderPass(R_SkinFrame_LoadMissing());
-       if (!texture->materialshaderpass->skinframes[0])
-               texture->materialshaderpass->skinframes[0] = R_SkinFrame_LoadMissing();
-       texture->currentskinframe = texture->materialshaderpass ? texture->materialshaderpass->skinframes[0] : NULL;
-       texture->backgroundcurrentskinframe = texture->backgroundshaderpass ? texture->backgroundshaderpass->skinframes[0] : NULL;
+       texture->currentskinframe = skinframe;
+       texture->backgroundcurrentskinframe = NULL;
+}
+
+void Mod_UnloadCustomMaterial(texture_t *texture, qboolean purgeskins)
+{
+       int i, j;
+       for (i = 0; i < sizeof(texture->shaderpasses) / sizeof(texture->shaderpasses[0]); i++)
+       {
+               if (texture->shaderpasses[i])
+               {
+                       if (purgeskins)
+                               for (j = 0; j < sizeof(texture->shaderpasses[i]->skinframes) / sizeof(skinframe_t *);j++)
+                                       if (texture->shaderpasses[i]->skinframes[j] && texture->shaderpasses[i]->skinframes[j]->base)
+                                               R_SkinFrame_PurgeSkinFrame(texture->shaderpasses[i]->skinframes[j]);
+                       Mem_Free(texture->shaderpasses[i]);
+                       texture->shaderpasses[i] = NULL;
+               }
+       }
+       texture->materialshaderpass = NULL;
+       texture->currentskinframe = NULL;
+       texture->backgroundcurrentskinframe = NULL;
 }
 
 skinfile_t *Mod_LoadSkinFiles(void)
@@ -4609,7 +4614,7 @@ void Mod_Mesh_Reset(dp_model_t *mod)
        mod->DrawAddWaterPlanes = NULL; // will be set if a texture needs it
 }
 
-texture_t *Mod_Mesh_GetTexture(dp_model_t *mod, const char *name)
+texture_t *Mod_Mesh_GetTexture(dp_model_t *mod, const char *name, int defaultdrawflags, int defaulttexflags, int addmaterialflags)
 {
        int i;
        texture_t *t;
@@ -4626,35 +4631,62 @@ texture_t *Mod_Mesh_GetTexture(dp_model_t *mod, const char *name)
                        mod->data_surfaces[i].texture = mod->data_textures + (mod->data_surfaces[i].texture - oldtextures);
        }
        t = &mod->data_textures[mod->num_textures++];
-       Mod_LoadTextureFromQ3Shader(t, name, false, true, 0);
+       Mod_LoadTextureFromQ3Shader(mod->mempool, mod->name, t, name, false, true, defaulttexflags);
+       t->basematerialflags |= addmaterialflags;
+       switch (defaultdrawflags & DRAWFLAG_MASK)
+       {
+       case DRAWFLAG_ADDITIVE:
+               t->basematerialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED;
+               t->currentmaterialflags = t->basematerialflags;
+               break;
+       case DRAWFLAG_MODULATE:
+               t->basematerialflags |= MATERIALFLAG_CUSTOMBLEND | MATERIALFLAG_BLENDED;
+               t->currentmaterialflags = t->basematerialflags;
+               t->customblendfunc[0] = GL_DST_COLOR;
+               t->customblendfunc[1] = GL_ZERO;
+               break;
+       case DRAWFLAG_2XMODULATE:
+               t->basematerialflags |= MATERIALFLAG_CUSTOMBLEND | MATERIALFLAG_BLENDED;
+               t->currentmaterialflags = t->basematerialflags;
+               t->customblendfunc[0] = GL_DST_COLOR;
+               t->customblendfunc[1] = GL_SRC_COLOR;
+               break;
+       case DRAWFLAG_SCREEN:
+               t->basematerialflags |= MATERIALFLAG_CUSTOMBLEND | MATERIALFLAG_BLENDED;
+               t->currentmaterialflags = t->basematerialflags;
+               t->customblendfunc[0] = GL_ONE_MINUS_DST_COLOR;
+               t->customblendfunc[1] = GL_ONE;
+               break;
+       default:
+               break;
+       }
        return t;
 }
 
-msurface_t *Mod_Mesh_AddSurface(dp_model_t *mod, texture_t *tex)
+msurface_t *Mod_Mesh_AddSurface(dp_model_t *mod, texture_t *tex, qboolean batchwithprevioussurface)
 {
        msurface_t *surf;
-       // check if the proposed surface matches the last one we created
-       if (mod->num_surfaces == 0 || mod->data_surfaces[mod->num_surfaces - 1].texture != tex)
+       // batch if possible; primarily useful for UI rendering where bounding boxes don't matter
+       if (batchwithprevioussurface && mod->num_surfaces > 0 && mod->data_surfaces[mod->num_surfaces - 1].texture == tex)
+               return mod->data_surfaces + mod->num_surfaces - 1;
+       // create new surface
+       if (mod->max_surfaces == mod->num_surfaces)
        {
-               if (mod->max_surfaces == mod->num_surfaces)
-               {
-                       mod->max_surfaces = 2 * max(mod->num_surfaces, 64);
-                       mod->data_surfaces = (msurface_t *)Mem_Realloc(mod->mempool, mod->data_surfaces, mod->max_surfaces * sizeof(*mod->data_surfaces));
-                       mod->sortedmodelsurfaces = (int *)Mem_Realloc(mod->mempool, mod->sortedmodelsurfaces, mod->max_surfaces * sizeof(*mod->sortedmodelsurfaces));
-               }
-               surf = mod->data_surfaces + mod->num_surfaces;
-               mod->num_surfaces++;
-               memset(surf, 0, sizeof(*surf));
-               surf->texture = tex;
-               surf->num_firsttriangle = mod->surfmesh.num_triangles;
-               surf->num_firstvertex = mod->surfmesh.num_vertices;
-               if (tex->basematerialflags & (MATERIALFLAG_SKY))
-                       mod->DrawSky = R_Q1BSP_DrawSky;
-               if (tex->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
-                       mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
-               return surf;
+               mod->max_surfaces = 2 * max(mod->num_surfaces, 64);
+               mod->data_surfaces = (msurface_t *)Mem_Realloc(mod->mempool, mod->data_surfaces, mod->max_surfaces * sizeof(*mod->data_surfaces));
+               mod->sortedmodelsurfaces = (int *)Mem_Realloc(mod->mempool, mod->sortedmodelsurfaces, mod->max_surfaces * sizeof(*mod->sortedmodelsurfaces));
        }
-       return mod->data_surfaces + mod->num_surfaces - 1;
+       surf = mod->data_surfaces + mod->num_surfaces;
+       mod->num_surfaces++;
+       memset(surf, 0, sizeof(*surf));
+       surf->texture = tex;
+       surf->num_firsttriangle = mod->surfmesh.num_triangles;
+       surf->num_firstvertex = mod->surfmesh.num_vertices;
+       if (tex->basematerialflags & (MATERIALFLAG_SKY))
+               mod->DrawSky = R_Q1BSP_DrawSky;
+       if (tex->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
+               mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
+       return surf;
 }
 
 int Mod_Mesh_IndexForVertex(dp_model_t *mod, msurface_t *surf, float x, float y, float z, float nx, float ny, float nz, float s, float t, float u, float v, float r, float g, float b, float a)
index f913e4b..0d3914e 100644 (file)
@@ -1183,11 +1183,13 @@ void Mod_CreateCollisionMesh(dp_model_t *mod);
 void Mod_FreeQ3Shaders(void);
 void Mod_LoadQ3Shaders(void);
 q3shaderinfo_t *Mod_LookupQ3Shader(const char *name);
-qboolean Mod_LoadTextureFromQ3Shader(texture_t *texture, const char *name, qboolean warnmissing, qboolean fallback, int defaulttexflags);
-texture_shaderpass_t *Mod_CreateShaderPass(skinframe_t *skinframe);
-texture_shaderpass_t *Mod_CreateShaderPassFromQ3ShaderLayer(q3shaderinfo_layer_t *layer, int layerindex, int texflags, const char *texturename);
+qboolean Mod_LoadTextureFromQ3Shader(mempool_t *mempool, const char *modelname, texture_t *texture, const char *name, qboolean warnmissing, qboolean fallback, int defaulttexflags);
+texture_shaderpass_t *Mod_CreateShaderPass(mempool_t *mempool, skinframe_t *skinframe);
+texture_shaderpass_t *Mod_CreateShaderPassFromQ3ShaderLayer(mempool_t *mempool, const char *modelname, q3shaderinfo_layer_t *layer, int layerindex, int texflags, const char *texturename);
 /// Sets up a material to render the provided skinframe.  See also R_SkinFrame_LoadInternalBGRA.
-void Mod_LoadCustomMaterial(texture_t *texture, const char *name, int supercontents, int materialflags, skinframe_t *skinframe);
+void Mod_LoadCustomMaterial(mempool_t *mempool, texture_t *texture, const char *name, int supercontents, int materialflags, skinframe_t *skinframe);
+/// Removes all shaderpasses from material, and optionally deletes the textures in the skinframes.
+void Mod_UnloadCustomMaterial(texture_t *texture, qboolean purgeskins);
 
 extern cvar_t r_mipskins;
 extern cvar_t r_mipnormalmaps;
@@ -1265,8 +1267,8 @@ void R_Q1BSP_DrawLight(struct entity_render_s *ent, int numsurfaces, const int *
 void Mod_Mesh_Create(dp_model_t *mod, const char *name);
 void Mod_Mesh_Destroy(dp_model_t *mod);
 void Mod_Mesh_Reset(dp_model_t *mod);
-texture_t *Mod_Mesh_GetTexture(dp_model_t *mod, const char *name);
-msurface_t *Mod_Mesh_AddSurface(dp_model_t *mod, texture_t *tex);
+texture_t *Mod_Mesh_GetTexture(dp_model_t *mod, const char *name, int defaultdrawflags, int defaulttexflags, int addmaterialflags);
+msurface_t *Mod_Mesh_AddSurface(dp_model_t *mod, texture_t *tex, qboolean batchwithprevioussurface);
 int Mod_Mesh_IndexForVertex(dp_model_t *mod, msurface_t *surf, float x, float y, float z, float nx, float ny, float nz, float s, float t, float u, float v, float r, float g, float b, float a);
 void Mod_Mesh_AddTriangle(dp_model_t *mod, msurface_t *surf, int e0, int e1, int e2);
 void Mod_Mesh_Finalize(dp_model_t *mod);
index 2dd7469..12819e4 100644 (file)
@@ -75,7 +75,7 @@ static void Mod_SpriteSetupTexture(texture_t *texture, skinframe_t *skinframe, q
        else if (skinframe->hasalpha)
                texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
        texture->currentmaterialflags = texture->basematerialflags;
-       texture->materialshaderpass = texture->shaderpasses[0] = Mod_CreateShaderPass(skinframe);
+       texture->materialshaderpass = texture->shaderpasses[0] = Mod_CreateShaderPass(loadmodel->mempool, skinframe);
        texture->currentskinframe = skinframe;
        texture->surfaceflags = 0;
        texture->supercontents = SUPERCONTENTS_SOLID;
@@ -220,7 +220,7 @@ static void Mod_Sprite_SharedSetup(const unsigned char *datapointer, int version
                                                dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
                                                dpsnprintf (fogname, sizeof(fogname), "%s_%ifog", loadmodel->name, i);
                                        }
-                                       if (!(skinframe = R_SkinFrame_LoadExternal(name, texflags | TEXF_COMPRESS, false)))
+                                       if (!(skinframe = R_SkinFrame_LoadExternal(name, texflags | TEXF_COMPRESS, false, false)))
                                        {
                                                unsigned char *pixels = (unsigned char *) Mem_Alloc(loadmodel->mempool, width*height*4);
                                                if (version == SPRITE32_VERSION)
@@ -464,7 +464,7 @@ void Mod_IDS2_Load(dp_model_t *mod, void *buffer, void *bufferend)
                {
                        const dsprite2frame_t *pinframe;
                        pinframe = &pinqsprite->frames[i];
-                       if (!(skinframe = R_SkinFrame_LoadExternal(pinframe->name, texflags, false)))
+                       if (!(skinframe = R_SkinFrame_LoadExternal(pinframe->name, texflags, false, false)))
                        {
                                Con_Printf("Mod_IDS2_Load: failed to load %s", pinframe->name);
                                skinframe = R_SkinFrame_LoadMissing();
index e2b023e..af6d27b 100644 (file)
@@ -3292,8 +3292,7 @@ void VM_precache_pic(prvm_prog_t *prog)
                        flags |= CACHEPICFLAG_MIPMAP;
        }
 
-       // AK Draw_CachePic is supposed to always return a valid pointer
-       if( Draw_CachePic_Flags(s, flags)->tex == r_texture_notexture )
+       if( !Draw_IsPicLoaded(Draw_CachePic_Flags(s, flags)) )
                PRVM_G_INT(OFS_RETURN) = OFS_NULL;
 }
 
@@ -3951,15 +3950,15 @@ void VM_getimagesize(prvm_prog_t *prog)
        VM_CheckEmptyString(prog, p);
 
        pic = Draw_CachePic_Flags (p, CACHEPICFLAG_NOTPERSISTENT);
-       if( pic->tex == r_texture_notexture )
+       if (!Draw_IsPicLoaded(pic))
        {
                PRVM_G_VECTOR(OFS_RETURN)[0] = 0;
                PRVM_G_VECTOR(OFS_RETURN)[1] = 0;
        }
        else
        {
-               PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
-               PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
+               PRVM_G_VECTOR(OFS_RETURN)[0] = Draw_GetPicWidth(pic);
+               PRVM_G_VECTOR(OFS_RETURN)[1] = Draw_GetPicHeight(pic);
        }
        PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
 }
index addcece..5373e63 100644 (file)
@@ -21,7 +21,7 @@ static void r_lightningbeams_start(void)
 
 static void CL_Beams_SetupExternalTexture(void)
 {
-       if (Mod_LoadTextureFromQ3Shader(&cl_beams_externaltexture, "textures/particles/lightning", false, false, TEXF_ALPHA | TEXF_FORCELINEAR))
+       if (Mod_LoadTextureFromQ3Shader(r_main_mempool, "r_lightning.c", &cl_beams_externaltexture, "textures/particles/lightning", false, false, TEXF_ALPHA | TEXF_FORCELINEAR))
                cl_beams_externaltexture.basematerialflags = cl_beams_externaltexture.currentmaterialflags = MATERIALFLAG_WALL | MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOCULLFACE;
        else
                Cvar_SetValueQuick(&r_lightningbeam_qmbtexture, false);
@@ -77,7 +77,7 @@ static void CL_Beams_SetupBuiltinTexture(void)
        }
 
        skinframe = R_SkinFrame_LoadInternalBGRA("lightningbeam", TEXF_FORCELINEAR, data, texwidth, texheight, false);
-       Mod_LoadCustomMaterial(&cl_beams_builtintexture, "cl_beams_builtintexture", 0, MATERIALFLAG_WALL | MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOCULLFACE, skinframe);
+       Mod_LoadCustomMaterial(r_main_mempool, &cl_beams_builtintexture, "cl_beams_builtintexture", 0, MATERIALFLAG_WALL | MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOCULLFACE, skinframe);
        Mem_Free(data);
 }
 
@@ -183,7 +183,7 @@ void CL_Beam_AddPolygons(const beam_t *b)
        //  the viewer)
 
        mod = &cl_meshentitymodels[MESH_PARTICLES];
-       surf = Mod_Mesh_AddSurface(mod, r_lightningbeam_qmbtexture.integer ? &cl_beams_externaltexture : &cl_beams_builtintexture);
+       surf = Mod_Mesh_AddSurface(mod, r_lightningbeam_qmbtexture.integer ? &cl_beams_externaltexture : &cl_beams_builtintexture, false);
        // polygon 1
        VectorM(r_lightningbeam_thickness.value, right, offset);
        CL_Beam_AddQuad(mod, surf, start, end, offset, t1, t2);
index 8f38710..3663834 100644 (file)
--- a/render.h
+++ b/render.h
@@ -146,11 +146,13 @@ void R_SkinFrame_Purge(void);
 // set last to NULL to start from the beginning
 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name );
 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add);
-skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain);
+skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture);
 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB);
 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height);
 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette);
 skinframe_t *R_SkinFrame_LoadMissing(void);
+skinframe_t *R_SkinFrame_LoadNoTexture(void);
+skinframe_t *R_SkinFrame_LoadInternalUsingTexture(const char *name, int textureflags, rtexture_t *tex, int width, int height, qboolean sRGB);
 
 rtexture_t *R_GetCubemap(const char *basename);
 
@@ -459,7 +461,6 @@ void RSurf_SetupDepthAndCulling(void);
 void R_Mesh_ResizeArrays(int newvertices);
 
 texture_t *R_GetCurrentTexture(texture_t *t);
-void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass);
 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass);
 void R_AddWaterPlanes(entity_render_t *ent);
 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass);
diff --git a/sbar.c b/sbar.c
index 14d69ce..5028909 100644 (file)
--- a/sbar.c
+++ b/sbar.c
@@ -161,7 +161,7 @@ static void sbar_start(void)
                for (i = 0;i < 10;i++)
                        sb_nums[0][i] = Draw_CachePic_Flags (va(vabuf, sizeof(vabuf), "gfx/num_%i",i), CACHEPICFLAG_QUIET);
                sb_nums[0][10] = Draw_CachePic_Flags ("gfx/num_minus", CACHEPICFLAG_QUIET);
-               sb_colon = Draw_CachePic_Flags ("gfx/num_colon", CACHEPICFLAG_QUIET);
+               sb_colon = Draw_CachePic_Flags ("gfx/num_colon", CACHEPICFLAG_QUIET | CACHEPICFLAG_FAILONMISSING);
 
                sb_ammo[0] = Draw_CachePic_Flags ("gfx/sb_shells", CACHEPICFLAG_QUIET);
                sb_ammo[1] = Draw_CachePic_Flags ("gfx/sb_bullets", CACHEPICFLAG_QUIET);
@@ -219,7 +219,7 @@ static void sbar_start(void)
                sb_nums[0][10] = Draw_CachePic_Flags ("gfx/num_minus", CACHEPICFLAG_QUIET);
                sb_nums[1][10] = Draw_CachePic_Flags ("gfx/anum_minus", CACHEPICFLAG_QUIET);
 
-               sb_colon = Draw_CachePic_Flags ("gfx/num_colon", CACHEPICFLAG_QUIET);
+               sb_colon = Draw_CachePic_Flags ("gfx/num_colon", CACHEPICFLAG_QUIET | CACHEPICFLAG_FAILONMISSING);
                sb_slash = Draw_CachePic_Flags ("gfx/num_slash", CACHEPICFLAG_QUIET);
 
                sb_weapons[0][0] = Draw_CachePic_Flags ("gfx/inv_shotgun", CACHEPICFLAG_QUIET);
@@ -1774,7 +1774,7 @@ void Sbar_Draw (void)
        if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && !cl.intermission && !r_letterbox.value)
        {
                pic = Draw_CachePic (va(vabuf, sizeof(vabuf), "gfx/crosshair%i", crosshair.integer));
-               DrawQ_Pic((vid_conwidth.integer - pic->width * crosshair_size.value) * 0.5f, (vid_conheight.integer - pic->height * crosshair_size.value) * 0.5f, pic, pic->width * crosshair_size.value, pic->height * crosshair_size.value, crosshair_color_red.value, crosshair_color_green.value, crosshair_color_blue.value, crosshair_color_alpha.value, 0);
+               DrawQ_Pic((vid_conwidth.integer - Draw_GetPicWidth(pic) * crosshair_size.value) * 0.5f, (vid_conheight.integer - Draw_GetPicHeight(pic) * crosshair_size.value) * 0.5f, pic, Draw_GetPicWidth(pic) * crosshair_size.value, Draw_GetPicHeight(pic) * crosshair_size.value, crosshair_color_red.value, crosshair_color_green.value, crosshair_color_blue.value, crosshair_color_alpha.value, 0);
        }
 
        if (cl_prydoncursor.integer > 0)
@@ -1914,7 +1914,7 @@ void Sbar_DeathmatchOverlay (void)
        if(IS_OLDNEXUIZ_DERIVED(gamemode))
                DrawQ_Pic (xmin - 8, ymin - 8, 0, xmax-xmin+1 + 2*8, ymax-ymin+1 + 2*8, 0, 0, 0, sbar_alpha_bg.value, 0);
 
-       DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
+       DrawQ_Pic ((vid_conwidth.integer - Draw_GetPicWidth(sb_ranking))/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
 
        // draw the text
        y = 40;
@@ -2162,14 +2162,14 @@ void Sbar_Score (int margin)
                if (minutes >= 5)
                {
                        Sbar_DrawXNum(-12*6, 32, minutes,  3, 12, 1, 1, 1, 1, 0);
-                       if(sb_colon && sb_colon->tex != r_texture_notexture)
+                       if (Draw_IsPicLoaded(sb_colon))
                                DrawQ_Pic(sbar_x + -12*3, sbar_y + 32, sb_colon, 12, 12, 1, 1, 1, sbar_alpha_fg.value, 0);
                        Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
                }
                else if (minutes >= 1)
                {
                        Sbar_DrawXNum(-12*6, 32, minutes,  3, 12, 1, 1, 0, 1, 0);
-                       if(sb_colon && sb_colon->tex != r_texture_notexture)
+                       if (Draw_IsPicLoaded(sb_colon))
                                DrawQ_Pic(sbar_x + -12*3, sbar_y + 32, sb_colon, 12, 12, 1, 1, 0, sbar_alpha_fg.value, 0);
                        Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 0, 1, 0);
                }
@@ -2183,7 +2183,7 @@ void Sbar_Score (int margin)
                minutes = (int)floor(cl.time / 60);
                seconds = (int)(floor(cl.time) - minutes * 60);
                Sbar_DrawXNum(-12*6, 32, minutes,  3, 12, 1, 1, 1, 1, 0);
-               if(sb_colon && sb_colon->tex != r_texture_notexture)
+               if (Draw_IsPicLoaded(sb_colon))
                        DrawQ_Pic(sbar_x + -12*3, sbar_y + 32, sb_colon, 12, 12, 1, 1, 1, sbar_alpha_fg.value, 0);
                Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
        }
@@ -2258,6 +2258,6 @@ Sbar_FinaleOverlay
 */
 void Sbar_FinaleOverlay (void)
 {
-       DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
+       DrawQ_Pic((vid_conwidth.integer - Draw_GetPicWidth(sb_finale))/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
 }
 
diff --git a/wad.c b/wad.c
index 4e714b0..fabffc3 100644 (file)
--- a/wad.c
+++ b/wad.c
@@ -111,7 +111,7 @@ void W_UnloadAll(void)
        memset(&wad, 0, sizeof(wad));
 }
 
-unsigned char *W_GetLumpName(const char *name)
+unsigned char *W_GetLumpName(const char *name, fs_offset_t *returnfilesize)
 {
        int i;
        fs_offset_t filesize;
@@ -146,8 +146,14 @@ unsigned char *W_GetLumpName(const char *name)
        }
 
        for (lump = wad.gfx.lumps, i = 0;i < wad.gfx.numlumps;i++, lump++)
+       {
                if (!strcmp(clean, lump->name))
+               {
+                       if (returnfilesize)
+                               *returnfilesize = lump->size;
                        return (wad.gfx_base + lump->filepos);
+               }
+       }
        return NULL;
 }
 
diff --git a/wad.h b/wad.h
index 3c4297d..ac08589 100644 (file)
--- a/wad.h
+++ b/wad.h
@@ -66,7 +66,7 @@ typedef struct lumpinfo_s
 } lumpinfo_t;
 
 void W_UnloadAll(void);
-unsigned char *W_GetLumpName(const char *name);
+unsigned char *W_GetLumpName(const char *name, fs_offset_t *returnfilesize);
 
 // halflife texture wads
 void W_LoadTextureWadFile(char *filename, int complain);