@@ -87,16 +87,20 @@ typedef struct
8787
8888typedef struct cachepic_s
8989{
90- char name [MAX_QPATH ];
91- qpic_t pic ;
92- byte padding [32 ]; // for appended glpic
90+ // dynamically-allocated chained cachepic_t
91+ struct cachepic_s * next ;
92+ char name [MAX_QPATH ];
93+ qpic_t pic ;
94+ int picflags ;
95+ byte padding [32 ]; // for appended glpic
9396} cachepic_t ;
9497
95- // TODO : vso : should be dynamically allocated instead ?
96- // On the other hand it takes so little memory that we can push MAX_CACHED_PICS very very high and never touch it again.
97- #define MAX_CACHED_PICS 8192 // vso : from Spike = 512 - increased to avoid csqc issues.
98- static cachepic_t menu_cachepics [MAX_CACHED_PICS ];
99- static int menu_numcachepics ;
98+ // draw_qcvm_mutex also protects q_cachepics / scrap updates
99+ extern SDL_Mutex * draw_qcvm_mutex ;
100+
101+ static cachepic_t * q_cachepics = NULL ;
102+ // Fast lookup pic name => cachepic_t* from q_cachepics.
103+ hash_map_t * q_cachepics_map = NULL ;
100104
101105// scrap allocation
102106// Allocate all the little status bar obejcts into a single texture
@@ -118,7 +122,7 @@ Scrap_AllocBlock
118122returns an index into scrap_texnums[] and the position inside it
119123================
120124*/
121- int Scrap_AllocBlock (int w , int h , int * x , int * y )
125+ static int Scrap_AllocBlock (int w , int h , int * x , int * y )
122126{
123127 int i , j ;
124128 int best , best2 ;
@@ -164,7 +168,7 @@ int Scrap_AllocBlock (int w, int h, int *x, int *y)
164168Scrap_Upload -- johnfitz -- now uses TexMgr
165169================
166170*/
167- void Scrap_Upload (void )
171+ static void Scrap_Upload (void )
168172{
169173 char name [8 ];
170174 int i ;
@@ -185,25 +189,24 @@ void Scrap_Upload (void)
185189Draw_PicFromWad
186190================
187191*/
188- qpic_t * Draw_PicFromWad2 (const char * name , unsigned int texflags )
192+ qpic_t * Draw_PicFromWad2 (const char * name , unsigned int texflags , int picflags )
189193{
190194 int i ;
191- cachepic_t * pic ;
192195 qpic_t * p ;
196+ cachepic_t * pic ;
193197 glpic_t gl ;
194198 src_offset_t offset ; // johnfitz
195199 lumpinfo_t * info ;
196200
197- // Spike -- added cachepic stuff here, to avoid glitches if the function is called multiple times with the same image.
198- for (pic = menu_cachepics , i = 0 ; i < menu_numcachepics ; pic ++ , i ++ )
199- {
200- if (!strncmp (name , pic -> name , countof (pic -> name )))
201- return & pic -> pic ;
202- }
203- if (menu_numcachepics == MAX_CACHED_PICS )
204- Sys_Error ("menu_numcachepics == MAX_CACHED_PICS" );
201+ // Fast lookup:
202+ p = Draw_GetCachedPic (name );
203+
204+ if (p )
205+ return p ;
205206
207+ // not cached, searched for it:
206208 p = (qpic_t * )W_GetLumpName (name , & info );
209+
207210 if (!p )
208211 {
209212 Con_Warning ("W_GetLumpName: %s not found\n" , name );
@@ -266,17 +269,44 @@ qpic_t *Draw_PicFromWad2 (const char *name, unsigned int texflags)
266269 gl .th = 1 ;
267270 }
268271
269- menu_numcachepics ++ ;
272+ // Create a new pic:
273+ pic = Mem_Alloc (sizeof (* pic ));
274+ pic -> picflags = picflags ;
275+
270276 q_strlcpy (pic -> name , name , countof (pic -> name ));
271277 pic -> pic = * p ;
278+
272279 memcpy ((void * )& (pic -> pic .data ), & gl , sizeof (glpic_t ));
273280
281+ // Add to cache:
282+ if (!q_cachepics )
283+ {
284+ q_cachepics = pic ;
285+ }
286+ else
287+ {
288+ cachepic_t * current_pic = q_cachepics ;
289+ cachepic_t * previous_pic = q_cachepics ;
290+
291+ while (current_pic )
292+ {
293+ previous_pic = current_pic ;
294+ current_pic = current_pic -> next ;
295+ }
296+
297+ previous_pic -> next = pic ;
298+ }
299+
300+ // we must downgrade pic->name as a pointer because the hashmap expects a key 8 bytes long (const char*)
301+ const char * pic_name_as_pointer = & pic -> name [0 ];
302+ HashMap_Insert (q_cachepics_map , & pic_name_as_pointer , & pic );
303+
274304 return & pic -> pic ;
275305}
276306
277307qpic_t * Draw_PicFromWad (const char * name )
278308{
279- return Draw_PicFromWad2 (name , TEXPREF_ALPHA | TEXPREF_PAD | TEXPREF_NOPICMIP );
309+ return Draw_PicFromWad2 (name , TEXPREF_ALPHA | TEXPREF_PAD | TEXPREF_NOPICMIP , PICFLAG_AUTO );
280310}
281311#if 0 // vso - unused
282312static qpic_t * Draw_GetCachedPic (const char * path )
@@ -292,24 +322,41 @@ static qpic_t *Draw_GetCachedPic (const char *path)
292322 return NULL ;
293323}
294324#endif
325+ /*
326+ ================
327+ Draw_GetCachedPic : get a pic from cache if already present, or return NULL if not.
328+ ================
329+ */
330+ qpic_t * Draw_GetCachedPic (const char * path )
331+ {
332+ // Fast lookup:
333+ cachepic_t * * pic_ptr = HashMap_Lookup (cachepic_t * , q_cachepics_map , & path );
334+
335+ // found
336+ if (pic_ptr )
337+ {
338+ return & ((* pic_ptr )-> pic );
339+ }
340+
341+ return NULL ;
342+ }
343+
295344/*
296345================
297346Draw_CachePic
298347================
299348*/
300- qpic_t * Draw_TryCachePic (const char * path , unsigned int texflags )
349+ qpic_t * Draw_TryCachePic (const char * path , unsigned int texflags , int picflags )
301350{
351+ qpic_t * p ;
302352 cachepic_t * pic ;
303- int i ;
304353 glpic_t gl ;
305354
306- for (pic = menu_cachepics , i = 0 ; i < menu_numcachepics ; pic ++ , i ++ )
307- {
308- if (!strncmp (path , pic -> name , countof (pic -> name )))
309- return & pic -> pic ;
310- }
311- if (menu_numcachepics == MAX_CACHED_PICS )
312- Sys_Error ("menu_numcachepics == MAX_CACHED_PICS" );
355+ // Fast lookup:
356+ p = Draw_GetCachedPic (path );
357+
358+ if (p )
359+ return p ;
313360
314361 //
315362 // load the pic from disk
@@ -327,9 +374,14 @@ qpic_t *Draw_TryCachePic (const char *path, unsigned int texflags)
327374 pic_data = Image_LoadImage (npath , (int * )& pic_width , (int * )& pic_height , & pic_fmt , 0 );
328375
329376 if (!pic_data )
377+ {
330378 return NULL ;
379+ }
380+
381+ // Create a new pic:
382+ pic = Mem_Alloc (sizeof (* pic ));
383+ pic -> picflags = picflags ;
331384
332- menu_numcachepics ++ ;
333385 q_strlcpy (pic -> name , path , countof (pic -> name ));
334386
335387 pic -> pic .width = pic_width ;
@@ -347,14 +399,36 @@ qpic_t *Draw_TryCachePic (const char *path, unsigned int texflags)
347399
348400 memcpy ((void * )& (pic -> pic .data ), & gl , sizeof (glpic_t ));
349401
402+ // Add to cache:
403+ if (!q_cachepics )
404+ {
405+ q_cachepics = pic ;
406+ }
407+ else
408+ {
409+ cachepic_t * current_pic = q_cachepics ;
410+ cachepic_t * previous_pic = q_cachepics ;
411+
412+ while (current_pic )
413+ {
414+ previous_pic = current_pic ;
415+ current_pic = current_pic -> next ;
416+ }
417+
418+ previous_pic -> next = pic ;
419+ }
420+ // we must downgrade pic->name as a pointer because the hashmap expects a key 8 bytes long (const char*)
421+ const char * pic_name_as_pointer = & pic -> name [0 ];
422+ HashMap_Insert (q_cachepics_map , & pic_name_as_pointer , & pic );
423+
350424 Mem_Free (pic_data );
351425
352426 return & pic -> pic ;
353427}
354428
355429qpic_t * Draw_CachePic (const char * path )
356430{
357- qpic_t * pic = Draw_TryCachePic (path , TEXPREF_ALPHA | TEXPREF_PAD | TEXPREF_NOPICMIP );
431+ qpic_t * pic = Draw_TryCachePic (path , TEXPREF_ALPHA | TEXPREF_PAD | TEXPREF_NOPICMIP , PICFLAG_AUTO );
358432 if (!pic )
359433 Sys_Error ("Draw_CachePic: failed to load %s" , path );
360434 return pic ;
@@ -421,26 +495,35 @@ Draw_NewGame -- johnfitz
421495*/
422496void Draw_NewGame (void )
423497{
424- cachepic_t * pic ;
425- int i ;
498+ SDL_LockMutex (draw_qcvm_mutex );
426499
427500 // empty scrap and reallocate gltextures
428501 memset (scrap_allocated , 0 , sizeof (scrap_allocated ));
429502 memset (scrap_texels , 255 , sizeof (scrap_texels ));
430503
431504 Scrap_Upload (); // creates 2 empty gltextures
432505
433- // empty lmp cache
434- for (pic = menu_cachepics , i = 0 ; i < menu_numcachepics ; pic ++ , i ++ )
435- pic -> name [0 ] = 0 ;
436- menu_numcachepics = 0 ;
506+ // empty pic cache :
507+ cachepic_t * cached_pic = q_cachepics ;
508+ cachepic_t * next_cached_pic ;
509+
510+ while (cached_pic )
511+ {
512+ next_cached_pic = cached_pic -> next ;
513+ Mem_Free (cached_pic );
514+ cached_pic = next_cached_pic ;
515+ }
516+ q_cachepics = NULL ;
517+
518+ HashMap_Clear (q_cachepics_map );
437519
438520 // reload wad pics
439521 W_LoadWadFile (); // johnfitz -- filename is now hard-coded for honesty
440522 Draw_LoadPics ();
441523 SCR_LoadPics ();
442524 Sbar_LoadPics ();
443- PR_ReloadPics (false);
525+
526+ SDL_UnlockMutex (draw_qcvm_mutex );
444527}
445528
446529/*
@@ -450,6 +533,8 @@ Draw_Init -- johnfitz -- rewritten
450533*/
451534void Draw_Init (void )
452535{
536+ q_cachepics_map = HashMap_Create (const char * , cachepic_t * , & HashStr , & HashStrCmp );
537+
453538 Cvar_RegisterVariable (& scr_conalpha );
454539
455540 // clear scrap and allocate gltextures
0 commit comments