From d5892a29c4f1e6954eb59ffc790d29d3f9925fe2 Mon Sep 17 00:00:00 2001 From: black Date: Tue, 27 Nov 2007 22:26:56 +0000 Subject: [PATCH] Rework cl_video to use dyntextures. Add cl_gecko (needs SUPPORT_GECKO to be activated). Fix r_replacemaptexture and make it use matchpattern to replace multiple textures at once. git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@7718 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_dyntexture.c | 35 ++++--- cl_dyntexture.h | 6 +- cl_gecko.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++++ cl_gecko.h | 40 ++++++++ cl_main.c | 4 + cl_video.c | 60 ++++++++---- cl_video.h | 5 +- gl_draw.c | 21 +++-- gl_rmain.c | 32 ++++++- gl_rsurf.c | 8 +- gl_textures.c | 18 +++- host.c | 9 +- r_textures.h | 2 +- render.h | 2 + 14 files changed, 420 insertions(+), 59 deletions(-) create mode 100644 cl_gecko.c create mode 100644 cl_gecko.h diff --git a/cl_dyntexture.c b/cl_dyntexture.c index f2b62451..8ee49464 100644 --- a/cl_dyntexture.c +++ b/cl_dyntexture.c @@ -15,11 +15,16 @@ static unsigned dyntexturecount; #define DEFAULT_DYNTEXTURE r_texture_grey128 -static dyntexture_t * _CL_FindDynTexture( const char *name ) { +static dyntexture_t * cl_finddyntexture( const char *name ) { unsigned i; dyntexture_t *dyntexture = NULL; - // some sanity checks - and make sure its actually a dynamic texture path - if( !name || strncmp( name, DYNAMIC_TEXTURE_PATH_PREFIX, sizeof( DYNAMIC_TEXTURE_PATH_PREFIX ) - 1 ) != 0 ) { + + // 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( developer.integer > 0 ) { + Con_Printf( "cl_finddyntexture: Bad dynamic texture name '%s'\n", name ); + } return NULL; } @@ -41,7 +46,7 @@ static dyntexture_t * _CL_FindDynTexture( const char *name ) { } rtexture_t * CL_GetDynTexture( const char *name ) { - dyntexture_t *dyntexture = _CL_FindDynTexture( name ); + dyntexture_t *dyntexture = cl_finddyntexture( name ); if( dyntexture ) { return dyntexture->texture; } else { @@ -54,26 +59,28 @@ void CL_LinkDynTexture( const char *name, rtexture_t *texture ) { cachepic_t *cachepic; skinframe_t *skinframe; - dyntexture = _CL_FindDynTexture( name ); + dyntexture = cl_finddyntexture( name ); // TODO: assert dyntexture != NULL! if( dyntexture->texture != texture ) { + dyntexture->texture = texture; + cachepic = Draw_CachePic( name, false ); - skinframe = R_SkinFrame_Find( name, 0, 0, 0, 0, false ); - // this is kind of hacky // 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 ); - // TODO: assert skinframe->base = dyntexture->texture - skinframe->base = texture; - // simply reset the compare* attributes of skinframe - skinframe->comparecrc = 0; - skinframe->comparewidth = skinframe->compareheight = 0; - dyntexture->texture = 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 + } } } diff --git a/cl_dyntexture.h b/cl_dyntexture.h index c513ab12..be3f8e14 100644 --- a/cl_dyntexture.h +++ b/cl_dyntexture.h @@ -2,11 +2,13 @@ #ifndef CL_DYNTEXTURE_H #define CL_DYNTEXTURE_H -#define DYNAMIC_TEXTURE_PATH_PREFIX "_dynamic/" +#define CLDYNTEXTUREPREFIX "_dynamic/" #define MAX_DYNAMIC_TEXTURE_COUNT 64 +// 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) -// textureflags will be ignored though for now [11/22/2007 Black] +// 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 diff --git a/cl_gecko.c b/cl_gecko.c new file mode 100644 index 00000000..8c6fafd4 --- /dev/null +++ b/cl_gecko.c @@ -0,0 +1,237 @@ +#ifdef SUPPORT_GECKO + +// includes everything! +#include + +#ifdef _MSC_VER +# pragma comment( lib, "OffscreenGecko" ) +#endif + +#include "quakedef.h" +#include "cl_dyntexture.h" +#include "cl_gecko.h" + +static rtexturepool_t *cl_geckotexturepool; +static OSGK_Embedding *cl_geckoembedding; + +struct clgecko_s { + qboolean active; + char name[ MAX_QPATH + 32 ]; + + OSGK_Browser *browser; + + rtexture_t *texture; +}; + +static clgecko_t cl_geckoinstances[ MAX_GECKO_INSTANCES ]; + +static clgecko_t * cl_gecko_findunusedinstance( void ) { + int i; + for( i = 0 ; i < MAX_GECKO_INSTANCES ; i++ ) { + clgecko_t *instance = &cl_geckoinstances[ i ]; + if( !instance->active ) { + return instance; + } + } + return NULL; +} + +clgecko_t * CL_Gecko_FindBrowser( const char *name ) { + int i; + + if( !name || !*name || strncmp( name, CLGECKOPREFIX, sizeof( CLGECKOPREFIX ) - 1 ) != 0 ) { + if( developer.integer > 0 ) { + Con_Printf( "CL_Gecko_FindBrowser: Bad gecko texture name '%s'!\n", name ); + } + return NULL; + } + + for( i = 0 ; i < MAX_GECKO_INSTANCES ; i++ ) { + clgecko_t *instance = &cl_geckoinstances[ i ]; + if( instance->active && strcmp( instance->name, name ) == 0 ) { + return instance; + } + } + + return NULL; +} + +static void cl_gecko_updatecallback( rtexture_t *texture, clgecko_t *instance ) { + const unsigned char *data; + if( instance->browser ) { + // TODO: OSGK only supports BGRA right now + data = osgk_browser_lock_data( instance->browser, NULL ); + R_UpdateTexture( texture, data, 0, 0, DEFAULT_GECKO_WIDTH, DEFAULT_GECKO_HEIGHT ); + osgk_browser_unlock_data( instance->browser, data ); + } +} + +static void cl_gecko_linktexture( clgecko_t *instance ) { + // TODO: assert that instance->texture == NULL + instance->texture = R_LoadTexture2D( cl_geckotexturepool, instance->name, DEFAULT_GECKO_WIDTH, DEFAULT_GECKO_HEIGHT, NULL, TEXTYPE_RGBA, TEXF_ALPHA, NULL ); + R_MakeTextureDynamic( instance->texture, cl_gecko_updatecallback, instance ); + CL_LinkDynTexture( instance->name, instance->texture ); +} + +static void cl_gecko_unlinktexture( clgecko_t *instance ) { + if( instance->texture ) { + CL_UnlinkDynTexture( instance->name ); + R_FreeTexture( instance->texture ); + instance->texture = NULL; + } +} + +clgecko_t * CL_Gecko_CreateBrowser( const char *name ) { + // TODO: verify that we dont use a name twice + clgecko_t *instance = cl_gecko_findunusedinstance(); + // TODO: assert != NULL + + instance->active = true; + strlcpy( instance->name, name, sizeof( instance->name ) ); + instance->browser = osgk_browser_create( cl_geckoembedding, DEFAULT_GECKO_WIDTH, DEFAULT_GECKO_HEIGHT ); + // TODO: assert != NULL + + cl_gecko_linktexture( instance ); + + return instance; +} + +void CL_Gecko_DestroyBrowser( clgecko_t *instance ) { + if( !instance || !instance->active ) { + return; + } + + instance->active = false; + cl_gecko_unlinktexture( instance ); + + osgk_release( instance->browser ); + instance->browser = NULL; +} + +void CL_Gecko_Frame( void ) { + int i; + for( i = 0 ; i < MAX_GECKO_INSTANCES ; i++ ) { + clgecko_t *instance = &cl_geckoinstances[ i ]; + if( instance->active ) { + if( instance->browser && osgk_browser_query_dirty( instance->browser ) == 1 ) { + R_MarkDirtyTexture( instance->texture ); + } + } + } +} + +static void cl_gecko_start( void ) +{ + int i; + cl_geckotexturepool = R_AllocTexturePool(); + + // recreate textures on module start + for( i = 0 ; i < MAX_GECKO_INSTANCES ; i++ ) { + clgecko_t *instance = &cl_geckoinstances[ i ]; + if( instance->active ) { + cl_gecko_linktexture( instance ); + } + } +} + +static void cl_gecko_shutdown( void ) +{ + int i; + for( i = 0 ; i < MAX_GECKO_INSTANCES ; i++ ) { + clgecko_t *instance = &cl_geckoinstances[ i ]; + if( instance->active ) { + cl_gecko_unlinktexture( instance ); + } + } + R_FreeTexturePool( &cl_geckotexturepool ); +} + +static void cl_gecko_newmap( void ) +{ + // DO NOTHING +} + +void CL_Gecko_Shutdown( void ) { + int i; + for( i = 0 ; i < MAX_GECKO_INSTANCES ; i++ ) { + clgecko_t *instance = &cl_geckoinstances[ i ]; + if( instance->active ) { + cl_gecko_unlinktexture( instance ); + } + } + osgk_release( cl_geckoembedding ); +} + +static void cl_gecko_create_f( void ) { + char name[MAX_QPATH]; + + if (Cmd_Argc() != 2) + { + Con_Print("usage: gecko_create \npcreates a browser (full texture path " CLGECKOPREFIX ")\n"); + return; + } + + // TODO: use snprintf instead + sprintf(name, CLGECKOPREFIX "%s", Cmd_Argv(1)); + CL_Gecko_CreateBrowser( name ); +} + +static void cl_gecko_destroy_f( void ) { + char name[MAX_QPATH]; + + if (Cmd_Argc() != 2) + { + Con_Print("usage: gecko_destroy \ndestroys a browser (full texture path " CLGECKOPREFIX ")\n"); + return; + } + + // TODO: use snprintf instead + sprintf(name, CLGECKOPREFIX "%s", Cmd_Argv(1)); + CL_Gecko_DestroyBrowser( CL_Gecko_FindBrowser( name ) ); +} + +static void cl_gecko_navigate_f( void ) { + char name[MAX_QPATH]; + const char *URI; + + if (Cmd_Argc() != 3) + { + Con_Print("usage: gecko_destroy \nnavigates to a certain URI (full texture path " CLGECKOPREFIX ")\n"); + return; + } + + // TODO: use snprintf instead + sprintf(name, CLGECKOPREFIX "%s", Cmd_Argv(1)); + URI = Cmd_Argv( 2 ); + CL_Gecko_NavigateToURI( CL_Gecko_FindBrowser( name ), URI ); +} + +void CL_Gecko_Init( void ) +{ + OSGK_EmbeddingOptions *options = osgk_embedding_options_create(); + osgk_embedding_options_add_search_path( options, "./xulrunner/" ); + cl_geckoembedding = osgk_embedding_create_with_options( options, NULL ); + osgk_release( options ); + + if( cl_geckoembedding == NULL ) { + Con_Printf( "CL_Gecko_Init: Couldn't retrieve gecko embedding object!\n" ); + } + + Cmd_AddCommand( "gecko_create", cl_gecko_create_f, "Create a gecko browser instance" ); + Cmd_AddCommand( "gecko_destroy", cl_gecko_destroy_f, "Destroy a gecko browser instance" ); + Cmd_AddCommand( "gecko_navigate", cl_gecko_navigate_f, "Navigate a gecko browser to an URI" ); + + R_RegisterModule( "CL_Gecko", cl_gecko_start, cl_gecko_shutdown, cl_gecko_newmap ); +} + +void CL_Gecko_NavigateToURI( clgecko_t *instance, const char *URI ) { + if( instance && instance->active ) { + osgk_browser_navigate( instance->browser, URI ); + } +} + +// TODO: write this function +void CL_Gecko_Event_CursorMove( clgecko_t *instance, float x, float y ); +qboolean CL_Gecko_Event_Key( clgecko_t *instance, int key, clgecko_buttoneventtype_t eventtype ); + +#endif \ No newline at end of file diff --git a/cl_gecko.h b/cl_gecko.h new file mode 100644 index 00000000..d73f7059 --- /dev/null +++ b/cl_gecko.h @@ -0,0 +1,40 @@ +// Andreas Kirsch 07 + +#ifdef SUPPORT_GECKO + +#ifndef CL_GECKO_H +#define CL_GECKO_H + +#define DEFAULT_GECKO_WIDTH 512 +#define DEFAULT_GECKO_HEIGHT DEFAULT_GECKO_WIDTH + +#define CLGECKOPREFIX CLDYNTEXTUREPREFIX "gecko/" +#define MAX_GECKO_INSTANCES 16 + +typedef enum clgecko_buttoneventtype_e { + CLG_BET_DOWN, + CLG_BET_UP, + CLG_BET_DOUBLECLICK, + // use for up + down (but dont use both) + CLG_BET_PRESS +} clgecko_buttoneventtype_t; + +typedef struct clgecko_s clgecko_t; + +void CL_Gecko_Frame( void ); +void CL_Gecko_Init( void ); +void CL_Gecko_Shutdown( void ); + +clgecko_t * CL_Gecko_CreateBrowser( const char *name ); +clgecko_t * CL_Gecko_FindBrowser( const char *name ); +void CL_Gecko_DestroyBrowser( clgecko_t *instance ); + +void CL_Gecko_NavigateToURI( clgecko_t *instance, const char *URI ); +void CL_Gecko_Event_CursorMove( clgecko_t *instance, float x, float y ); + +// returns whether the key/button event was handled or not +qboolean CL_Gecko_Event_Key( clgecko_t *instance, int key, clgecko_buttoneventtype_t eventtype ); + +#endif + +#endif \ No newline at end of file diff --git a/cl_main.c b/cl_main.c index 2f105dbf..2bf63aba 100644 --- a/cl_main.c +++ b/cl_main.c @@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "cl_collision.h" +#include "cl_gecko.h" #include "cl_video.h" #include "image.h" #include "csprogs.h" @@ -2302,6 +2303,9 @@ void CL_Init (void) CL_Screen_Init(); CL_Video_Init(); +#ifdef SUPPORT_GECKO + CL_Gecko_Init(); +#endif } diff --git a/cl_video.c b/cl_video.c index 42c0496d..d1285408 100644 --- a/cl_video.c +++ b/cl_video.c @@ -1,5 +1,6 @@ #include "quakedef.h" +#include "cl_dyntexture.h" #include "cl_video.h" #include "dpvsimpledecode.h" @@ -34,15 +35,31 @@ static qboolean OpenStream( clvideo_t * video ) return true; } +static void VideoUpdateCallback(rtexture_t *rt, clvideo_t *video) { + R_UpdateTexture( video->cpif.tex, (unsigned char *)video->imagedata, 0, 0, video->cpif.width, video->cpif.height ); +} + +static void LinkVideoTexture( clvideo_t *video ) { + video->cpif.tex = R_LoadTexture2D( cl_videotexturepool, video->cpif.name, + video->cpif.width, video->cpif.height, NULL, TEXTYPE_RGBA, TEXF_ALWAYSPRECACHE, NULL ); + R_MakeTextureDynamic( video->cpif.tex, VideoUpdateCallback, video ); + CL_LinkDynTexture( video->cpif.name, video->cpif.tex ); +} + +static void UnlinkVideoTexture( clvideo_t *video ) { + CL_UnlinkDynTexture( video->cpif.name ); + // free the texture + R_FreeTexture( video->cpif.tex ); + // free the image data + Mem_Free( video->imagedata ); +} + static void SuspendVideo( clvideo_t * video ) { if( video->suspended ) return; video->suspended = true; - // free the texture - R_FreeTexture( video->cpif.tex ); - // free the image data - Mem_Free( video->imagedata ); + UnlinkVideoTexture( video ); // if we are in firstframe mode, also close the stream if( video->state == CLVIDEO_FIRSTFRAME ) dpvsimpledecode_close( video->stream ); @@ -61,8 +78,7 @@ static qboolean WakeVideo( clvideo_t * video ) } video->imagedata = Mem_Alloc( cls.permanentmempool, video->cpif.width * video->cpif.height * cl_videobytesperpixel ); - video->cpif.tex = R_LoadTexture2D( cl_videotexturepool, video->cpif.name, - video->cpif.width, video->cpif.height, NULL, TEXTYPE_RGBA, TEXF_ALWAYSPRECACHE, NULL ); + LinkVideoTexture( video ); // update starttime video->starttime += realtime - video->lasttime; @@ -88,10 +104,8 @@ static clvideo_t* OpenVideo( clvideo_t *video, const char *filename, const char video->cpif.width = dpvsimpledecode_getwidth( video->stream ); video->cpif.height = dpvsimpledecode_getheight( video->stream ); - video->cpif.tex = R_LoadTexture2D( cl_videotexturepool, video->cpif.name, - video->cpif.width, video->cpif.height, NULL, TEXTYPE_RGBA, TEXF_ALWAYSPRECACHE, NULL ); - - video->imagedata = Mem_Alloc( cls.permanentmempool, video->cpif.width * video->cpif.height * cl_videobytesperpixel ); + video->imagedata = Mem_Alloc( cls.permanentmempool, video->cpif.width * video->cpif.height * cl_videobytesperpixel ); + LinkVideoTexture( video ); return video; } @@ -99,16 +113,24 @@ static clvideo_t* OpenVideo( clvideo_t *video, const char *filename, const char clvideo_t* CL_OpenVideo( const char *filename, const char *name, int owner ) { clvideo_t *video; + // sanity check + if( !name || !*name || strncmp( name, CLVIDEOPREFIX, sizeof( CLVIDEOPREFIX ) - 1 ) != 0 ) { + if( developer.integer > 0 ) { + Con_Printf( "CL_OpenVideo: Bad video texture name '%s'!\n", name ); + } + return NULL; + } video = FindUnusedVid(); if( !video ) { - Con_Printf( "unable to open video \"%s\" - video limit reached\n", filename ); + Con_Printf( "CL_OpenVideo: unable to open video \"%s\" - video limit reached\n", filename ); return NULL; } video = OpenVideo( video, filename, name, owner ); // expand the active range to include the new entry - if (video) + if (video) { cl_num_videos = max(cl_num_videos, (int)(video - cl_videos) + 1); + } return video; } @@ -175,8 +197,7 @@ void CL_CloseVideo( clvideo_t * video ) if( !video->suspended || video->state != CLVIDEO_FIRSTFRAME ) dpvsimpledecode_close( video->stream ); if( !video->suspended ) { - Mem_Free( video->imagedata ); - R_FreeTexture( video->cpif.tex ); + UnlinkVideoTexture( video ); } video->state = CLVIDEO_UNUSED; @@ -205,11 +226,11 @@ static void VideoFrame( clvideo_t *video ) return; } } while( video->framenum < destframe ); - R_UpdateTexture( video->cpif.tex, (unsigned char *)video->imagedata, 0, 0, video->cpif.width, video->cpif.height ); + R_MarkDirtyTexture( video->cpif.tex ); } } -void CL_VideoFrame( void ) // update all videos +void CL_Video_Frame( void ) // update all videos { int i; clvideo_t *video; @@ -265,7 +286,8 @@ void CL_VideoStart(char *filename) if( cl_videos->state != CLVIDEO_UNUSED ) CL_CloseVideo( cl_videos ); - if( !OpenVideo( cl_videos, filename, va( CLVIDEOPREFIX "%s", filename ), 0 ) ) + // already contains video/ + if( !OpenVideo( cl_videos, filename, va( CLDYNTEXTUREPREFIX "%s", filename ), 0 ) ) return; // expand the active range to include the new entry cl_num_videos = max(cl_num_videos, 1); @@ -323,12 +345,12 @@ static void cl_video_start( void ) for( video = cl_videos, i = 0 ; i < cl_num_videos ; i++, video++ ) if( video->state != CLVIDEO_UNUSED && !video->suspended ) - video->cpif.tex = R_LoadTexture2D( cl_videotexturepool, video->cpif.name, - video->cpif.width, video->cpif.height, NULL, TEXTYPE_RGBA, TEXF_ALWAYSPRECACHE, NULL ); + LinkVideoTexture( video ); } static void cl_video_shutdown( void ) { + // TODO: unlink video textures? R_FreeTexturePool( &cl_videotexturepool ); } diff --git a/cl_video.h b/cl_video.h index cc38798f..d5b1a84f 100644 --- a/cl_video.h +++ b/cl_video.h @@ -3,7 +3,8 @@ #define CL_VIDEO_H #define MAXCLVIDEOS 64 + 1 // 1 video is reserved for the cinematic mode -#define CLVIDEOPREFIX "_video/" +// yields DYNAMIC_TEXTURE_PATH_PREFIX CLVIDEOPREFIX video name for a path +#define CLVIDEOPREFIX CLDYNTEXTUREPREFIX "video/" #define CLTHRESHOLD 2.0 #define MENUOWNER 1 @@ -53,7 +54,7 @@ void CL_RestartVideo( clvideo_t *video ); void CL_CloseVideo( clvideo_t * video ); void CL_PurgeOwner( int owner ); -void CL_VideoFrame( void ); // update all videos +void CL_Video_Frame( void ); // update all videos void CL_Video_Init( void ); void CL_Video_Shutdown( void ); diff --git a/gl_draw.c b/gl_draw.c index b600d6df..28239082 100644 --- a/gl_draw.c +++ b/gl_draw.c @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "wad.h" #include "cl_video.h" +#include "cl_dyntexture.h" cvar_t r_textshadow = {CVAR_SAVE, "r_textshadow", "0", "draws a shadow on all text to improve readability (note: value controls offset, 1 = 1 pixel, 1.5 = 1.5 pixels, etc)"}; cvar_t r_textbrightness = {CVAR_SAVE, "r_textbrightness", "0", "additional brightness for text color codes (0 keeps colors as is, 1 makes them all white)"}; @@ -308,15 +309,7 @@ cachepic_t *Draw_CachePic (const char *path, qboolean persistent) unsigned char *lmpdata; char lmpname[MAX_QPATH]; - if (!strncmp(CLVIDEOPREFIX, path, sizeof(CLVIDEOPREFIX) - 1)) - { - clvideo_t *video; - - video = CL_GetVideoByName(path); - if( video ) - return &video->cpif; - } - + // check whether the picture has already been cached crc = CRC_Block((unsigned char *)path, strlen(path)); hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE; for (pic = cachepichash[hashkey];pic;pic = pic->chain) @@ -335,6 +328,16 @@ cachepic_t *Draw_CachePic (const char *path, qboolean persistent) pic->chain = cachepichash[hashkey]; cachepichash[hashkey] = pic; + // check whether it is an dynamic texture (if so, we can directly use its texture handler) + pic->tex = CL_GetDynTexture( path ); + // if so, set the width/height, too + if( pic->tex ) { + pic->width = R_TextureWidth(pic->tex); + pic->height = R_TextureHeight(pic->tex); + // we're done now (early-out) + return pic; + } + flags = TEXF_ALPHA; if (persistent) flags |= TEXF_PRECACHE; diff --git a/gl_rmain.c b/gl_rmain.c index 29cb7cbd..b36e648f 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -20,6 +20,7 @@ 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" @@ -1494,6 +1495,29 @@ void R_SkinFrame_Purge(void) } } +skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) { + skinframe_t *item; + char basename[MAX_QPATH]; + + Image_StripImageExtension(name, basename, sizeof(basename)); + + if( last == NULL ) { + int hashindex; + hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1); + item = r_skinframe.hash[hashindex]; + } else { + item = last->next; + } + + // linearly search through the hash bucket + for( ; item ; item = item->next ) { + if( !strcmp( item->basename, basename ) ) { + return item; + } + } + return NULL; +} + skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add) { skinframe_t *item; @@ -1508,16 +1532,20 @@ skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewid break; if (!item) { - if (!add) + rtexture_t *dyntexture; + // check whether its a dynamic texture + dyntexture = CL_GetDynTexture( basename ); + if (!add && !dyntexture) return NULL; item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array); memset(item, 0, sizeof(*item)); strlcpy(item->basename, basename, sizeof(item->basename)); item->textureflags = textureflags; + item->base = dyntexture; item->comparewidth = comparewidth; item->compareheight = compareheight; item->comparecrc = comparecrc; - item->next = r_skinframe.hash[hashindex]; + item->next = r_skinframe.hash[hashindex]; r_skinframe.hash[hashindex] = item; } R_SkinFrame_MarkUsed(item); diff --git a/gl_rsurf.c b/gl_rsurf.c index 8ec12e9b..9bfa092d 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -1186,13 +1186,13 @@ void R_ReplaceWorldTexture (void) newt = r; for(i=0,t=m->data_textures;inum_textures;i++,t++) { - if(t->width && !strcasecmp(t->name, r)) + if(/*t->width && !strcasecmp(t->name, r)*/ matchpattern( t->name, r, true ) ) { - if ((skinframe = R_SkinFrame_LoadExternal((char*)newt, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, true))) + if ((skinframe = R_SkinFrame_LoadExternal(newt, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, true))) { - t->skinframes[0] = skinframe; +// t->skinframes[0] = skinframe; + t->currentskinframe = skinframe; Con_Printf("%s replaced with %s\n", r, newt); - return; } else { diff --git a/gl_textures.c b/gl_textures.c index 976946b8..ee927712 100644 --- a/gl_textures.c +++ b/gl_textures.c @@ -218,6 +218,10 @@ static textypeinfo_t *R_GetTexTypeInfo(int textype, int flags) // dynamic texture code [11/22/2007 Black] void R_MarkDirtyTexture(rtexture_t *rt) { gltexture_t *glt = (gltexture_t*) rt; + if( !glt ) { + return; + } + // dont do anything if the texture is already dirty (and make sure this *is* a dynamic texture after all!) if( !glt->dirtytexnum && glt->flags & GLTEXF_DYNAMIC ) { glt->dirtytexnum = glt->texnum; @@ -228,6 +232,10 @@ void R_MarkDirtyTexture(rtexture_t *rt) { void R_MakeTextureDynamic(rtexture_t *rt, updatecallback_t updatecallback, void *data) { gltexture_t *glt = (gltexture_t*) rt; + if( !glt ) { + return; + } + glt->flags |= GLTEXF_DYNAMIC; glt->updatecallback = updatecallback; glt->updatacallback_data = data; @@ -267,10 +275,10 @@ int R_RealGetTexture(rtexture_t *rt) { gltexture_t *glt; glt = (gltexture_t *)rt; - if (glt->flags & GLTEXF_UPLOAD) - R_UploadTexture(glt); if (glt->flags & GLTEXF_DYNAMIC) R_UpdateDynamicTexture(glt); + if (glt->flags & GLTEXF_UPLOAD) + R_UploadTexture(glt); return glt->texnum; } @@ -755,11 +763,11 @@ static void GL_SetupTextureParameters(int flags, int texturetype) CHECKGLERROR } -static void R_Upload(gltexture_t *glt, unsigned char *data, int fragx, int fragy, int fragz, int fragwidth, int fragheight, int fragdepth) +static void R_Upload(gltexture_t *glt, const unsigned char *data, int fragx, int fragy, int fragz, int fragwidth, int fragheight, int fragdepth) { int i, mip, width, height, depth; GLint oldbindtexnum; - unsigned char *prevbuffer; + const unsigned char *prevbuffer; prevbuffer = data; CHECKGLERROR @@ -1087,7 +1095,7 @@ int R_TextureHeight(rtexture_t *rt) return rt ? ((gltexture_t *)rt)->inputheight : 0; } -void R_UpdateTexture(rtexture_t *rt, unsigned char *data, int x, int y, int width, int height) +void R_UpdateTexture(rtexture_t *rt, const unsigned char *data, int x, int y, int width, int height) { gltexture_t *glt; if (rt == NULL) diff --git a/host.c b/host.c index 4638ee8f..694099db 100644 --- a/host.c +++ b/host.c @@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include "libcurl.h" #include "cdaudio.h" +#include "cl_gecko.h" #include "cl_video.h" #include "progsvm.h" #include "csprogs.h" @@ -841,7 +842,10 @@ void Host_Main(void) //ui_update(); - CL_VideoFrame(); + CL_Video_Frame(); +#ifdef SUPPORT_GECKO + CL_Gecko_Frame(); +#endif CL_UpdateScreen(); @@ -1157,6 +1161,9 @@ void Host_Shutdown(void) // AK shutdown PRVM // AK hmm, no PRVM_Shutdown(); yet +#ifdef SUPPORT_GECKO + CL_Gecko_Shutdown(); +#endif CL_Video_Shutdown(); Host_SaveConfig_f(); diff --git a/r_textures.h b/r_textures.h index 4ad5f5e8..f7cb02f9 100644 --- a/r_textures.h +++ b/r_textures.h @@ -77,7 +77,7 @@ void R_FreeTexture(rtexture_t *rt); // update a portion of the image data of a texture, used by lightmap updates // and procedural textures such as video playback. -void R_UpdateTexture(rtexture_t *rt, unsigned char *data, int x, int y, int width, int height); +void R_UpdateTexture(rtexture_t *rt, const unsigned char *data, int x, int y, int width, int height); // returns the renderer dependent texture slot number (call this before each // use, as a texture might not have been precached) diff --git a/render.h b/render.h index a2696fe6..2baf0ea1 100644 --- a/render.h +++ b/render.h @@ -130,6 +130,8 @@ void R_InitSky (unsigned char *src, int bytesperpixel); // called at level load void R_SkinFrame_PrepareForPurge(void); void R_SkinFrame_MarkUsed(skinframe_t *skinframe); 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_LoadInternal(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height, int bitsperpixel, const unsigned int *palette, const unsigned int *alphapalette); -- 2.39.2