]> git.rm.cloudns.org Git - xonotic/darkplaces.git/commitdiff
Rework cl_video to use dyntextures.
authorblack <black@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 27 Nov 2007 22:26:56 +0000 (22:26 +0000)
committerblack <black@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 27 Nov 2007 22:26:56 +0000 (22:26 +0000)
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

14 files changed:
cl_dyntexture.c
cl_dyntexture.h
cl_gecko.c [new file with mode: 0644]
cl_gecko.h [new file with mode: 0644]
cl_main.c
cl_video.c
cl_video.h
gl_draw.c
gl_rmain.c
gl_rsurf.c
gl_textures.c
host.c
r_textures.h
render.h

index f2b6245113245ab2eecc3f9fe577fe6109f99f9d..8ee494640e73c355db0801e22f066e518642e27b 100644 (file)
@@ -15,11 +15,16 @@ static unsigned dyntexturecount;
 \r
 #define DEFAULT_DYNTEXTURE r_texture_grey128\r
 \r
-static dyntexture_t * _CL_FindDynTexture( const char *name ) {\r
+static dyntexture_t * cl_finddyntexture( const char *name ) {\r
        unsigned i;\r
        dyntexture_t *dyntexture = NULL;\r
-       // some sanity checks - and make sure its actually a dynamic texture path\r
-       if( !name || strncmp( name, DYNAMIC_TEXTURE_PATH_PREFIX, sizeof( DYNAMIC_TEXTURE_PATH_PREFIX ) - 1 ) != 0 ) {\r
+\r
+       // sanity checks - make sure its actually a dynamic texture path\r
+       if( !name || !*name || strncmp( name, CLDYNTEXTUREPREFIX, sizeof( CLDYNTEXTUREPREFIX ) - 1 ) != 0 ) {\r
+               // TODO: print a warning or something\r
+               if( developer.integer > 0 ) {\r
+                       Con_Printf( "cl_finddyntexture: Bad dynamic texture name '%s'\n", name );\r
+               }\r
                return NULL;\r
        }\r
 \r
@@ -41,7 +46,7 @@ static dyntexture_t * _CL_FindDynTexture( const char *name ) {
 }\r
 \r
 rtexture_t * CL_GetDynTexture( const char *name ) {\r
-       dyntexture_t *dyntexture = _CL_FindDynTexture( name );\r
+       dyntexture_t *dyntexture = cl_finddyntexture( name );\r
        if( dyntexture ) {\r
                return dyntexture->texture;\r
        } else {\r
@@ -54,26 +59,28 @@ void CL_LinkDynTexture( const char *name, rtexture_t *texture ) {
        cachepic_t *cachepic;\r
        skinframe_t *skinframe;\r
 \r
-       dyntexture = _CL_FindDynTexture( name );\r
+       dyntexture = cl_finddyntexture( name );\r
        // TODO: assert dyntexture != NULL!\r
        if( dyntexture->texture != texture ) {\r
+               dyntexture->texture = texture;\r
+\r
                cachepic = Draw_CachePic( name, false );\r
-               skinframe = R_SkinFrame_Find( name, 0, 0, 0, 0, false );\r
-               // this is kind of hacky\r
                // TODO: assert cachepic and skinframe should be valid pointers...\r
-\r
                // TODO: assert cachepic->tex = dyntexture->texture\r
                cachepic->tex = texture;\r
                // update cachepic's size, too\r
                cachepic->width = R_TextureWidth( texture );\r
                cachepic->height = R_TextureHeight( texture );\r
-               // TODO: assert skinframe->base = dyntexture->texture\r
-               skinframe->base = texture;\r
-               // simply reset the compare* attributes of skinframe\r
-               skinframe->comparecrc = 0;\r
-               skinframe->comparewidth = skinframe->compareheight = 0;\r
 \r
-               dyntexture->texture = texture;\r
+               // update skinframes\r
+               skinframe = NULL;\r
+               while( (skinframe = R_SkinFrame_FindNextByName( skinframe, name )) != NULL ) {\r
+                       skinframe->base = texture;\r
+                       // simply reset the compare* attributes of skinframe\r
+                       skinframe->comparecrc = 0;\r
+                       skinframe->comparewidth = skinframe->compareheight = 0;\r
+                       // this is kind of hacky\r
+               }\r
        }\r
 }\r
 \r
index c513ab1262036ca2995d23752e3a92eb31141737..be3f8e141b9a0297b7e9bbdffc7394bdfc2d791c 100644 (file)
@@ -2,11 +2,13 @@
 #ifndef CL_DYNTEXTURE_H\r
 #define CL_DYNTEXTURE_H\r
 \r
-#define DYNAMIC_TEXTURE_PATH_PREFIX                    "_dynamic/"\r
+#define CLDYNTEXTUREPREFIX                     "_dynamic/"\r
 #define MAX_DYNAMIC_TEXTURE_COUNT                      64\r
 \r
+// always path fully specified names to the dynamic texture functions! (ie. with the _dynamic/ prefix, etc.!)\r
+\r
 // return a valid texture handle for a dynamic texture (might be filler texture if it hasnt been initialized yet)\r
-// textureflags will be ignored though for now [11/22/2007 Black]\r
+// or NULL if its not a valid dynamic texture name\r
 rtexture_t * CL_GetDynTexture( const char *name );\r
 \r
 // link a texture handle as dynamic texture and update texture handles in the renderer and draw_* accordingly\r
diff --git a/cl_gecko.c b/cl_gecko.c
new file mode 100644 (file)
index 0000000..8c6fafd
--- /dev/null
@@ -0,0 +1,237 @@
+#ifdef SUPPORT_GECKO\r
+\r
+// includes everything!\r
+#include <OffscreenGecko/browser.h>\r
+\r
+#ifdef _MSC_VER\r
+#      pragma comment( lib, "OffscreenGecko" )\r
+#endif\r
+\r
+#include "quakedef.h"\r
+#include "cl_dyntexture.h"\r
+#include "cl_gecko.h"\r
+\r
+static rtexturepool_t *cl_geckotexturepool;\r
+static OSGK_Embedding *cl_geckoembedding;\r
+\r
+struct clgecko_s {\r
+       qboolean active;\r
+       char name[ MAX_QPATH + 32 ];\r
+\r
+       OSGK_Browser *browser;\r
+       \r
+       rtexture_t *texture;\r
+};\r
+\r
+static clgecko_t cl_geckoinstances[ MAX_GECKO_INSTANCES ];\r
+\r
+static clgecko_t * cl_gecko_findunusedinstance( void ) {\r
+       int i;\r
+       for( i = 0 ; i < MAX_GECKO_INSTANCES ; i++ ) {\r
+               clgecko_t *instance = &cl_geckoinstances[ i ];\r
+               if( !instance->active ) {\r
+                       return instance;\r
+               }\r
+       }\r
+       return NULL;\r
+}\r
+\r
+clgecko_t * CL_Gecko_FindBrowser( const char *name ) {\r
+       int i;\r
+\r
+       if( !name || !*name || strncmp( name, CLGECKOPREFIX, sizeof( CLGECKOPREFIX ) - 1 ) != 0 ) {\r
+               if( developer.integer > 0 ) {\r
+                       Con_Printf( "CL_Gecko_FindBrowser: Bad gecko texture name '%s'!\n", name );\r
+               }\r
+               return NULL;\r
+       }\r
+\r
+       for( i = 0 ; i < MAX_GECKO_INSTANCES ; i++ ) {\r
+               clgecko_t *instance = &cl_geckoinstances[ i ];\r
+               if( instance->active && strcmp( instance->name, name ) == 0 ) {\r
+                       return instance;\r
+               }\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+static void cl_gecko_updatecallback( rtexture_t *texture, clgecko_t *instance ) {\r
+       const unsigned char *data;\r
+       if( instance->browser ) {\r
+               // TODO: OSGK only supports BGRA right now\r
+               data = osgk_browser_lock_data( instance->browser, NULL );\r
+               R_UpdateTexture( texture, data, 0, 0, DEFAULT_GECKO_WIDTH, DEFAULT_GECKO_HEIGHT );\r
+               osgk_browser_unlock_data( instance->browser, data );\r
+       }\r
+}\r
+\r
+static void cl_gecko_linktexture( clgecko_t *instance ) {\r
+       // TODO: assert that instance->texture == NULL\r
+       instance->texture = R_LoadTexture2D( cl_geckotexturepool, instance->name, DEFAULT_GECKO_WIDTH, DEFAULT_GECKO_HEIGHT, NULL, TEXTYPE_RGBA, TEXF_ALPHA, NULL );\r
+       R_MakeTextureDynamic( instance->texture, cl_gecko_updatecallback, instance );\r
+       CL_LinkDynTexture( instance->name, instance->texture );\r
+}\r
+\r
+static void cl_gecko_unlinktexture( clgecko_t *instance ) {\r
+       if( instance->texture ) {\r
+               CL_UnlinkDynTexture( instance->name );\r
+               R_FreeTexture( instance->texture );\r
+               instance->texture = NULL;\r
+       }\r
+}\r
+\r
+clgecko_t * CL_Gecko_CreateBrowser( const char *name ) {\r
+       // TODO: verify that we dont use a name twice\r
+       clgecko_t *instance = cl_gecko_findunusedinstance();\r
+       // TODO: assert != NULL\r
+       \r
+       instance->active = true;\r
+       strlcpy( instance->name, name, sizeof( instance->name ) );\r
+       instance->browser = osgk_browser_create( cl_geckoembedding, DEFAULT_GECKO_WIDTH, DEFAULT_GECKO_HEIGHT );\r
+       // TODO: assert != NULL\r
+\r
+       cl_gecko_linktexture( instance );\r
+\r
+       return instance;\r
+}\r
+\r
+void CL_Gecko_DestroyBrowser( clgecko_t *instance ) {\r
+   if( !instance || !instance->active ) {\r
+               return;\r
+       }\r
+\r
+       instance->active = false;\r
+       cl_gecko_unlinktexture( instance );\r
+\r
+       osgk_release( instance->browser );\r
+       instance->browser = NULL;\r
+}\r
+\r
+void CL_Gecko_Frame( void ) {\r
+       int i;\r
+       for( i = 0 ; i < MAX_GECKO_INSTANCES ; i++ ) {\r
+               clgecko_t *instance = &cl_geckoinstances[ i ];\r
+               if( instance->active ) {\r
+                       if( instance->browser && osgk_browser_query_dirty( instance->browser ) == 1 ) {\r
+                               R_MarkDirtyTexture( instance->texture );\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+static void cl_gecko_start( void )\r
+{\r
+       int i;\r
+       cl_geckotexturepool = R_AllocTexturePool();\r
+\r
+       // recreate textures on module start\r
+       for( i = 0 ; i < MAX_GECKO_INSTANCES ; i++ ) {\r
+               clgecko_t *instance = &cl_geckoinstances[ i ];\r
+               if( instance->active ) {\r
+                       cl_gecko_linktexture( instance );\r
+               }\r
+       }\r
+}\r
+\r
+static void cl_gecko_shutdown( void )\r
+{\r
+       int i;\r
+       for( i = 0 ; i < MAX_GECKO_INSTANCES ; i++ ) {\r
+               clgecko_t *instance = &cl_geckoinstances[ i ];\r
+               if( instance->active ) {\r
+                       cl_gecko_unlinktexture( instance );\r
+               }\r
+       }\r
+       R_FreeTexturePool( &cl_geckotexturepool );\r
+}\r
+\r
+static void cl_gecko_newmap( void )\r
+{\r
+       // DO NOTHING\r
+}\r
+\r
+void CL_Gecko_Shutdown( void ) {\r
+       int i;\r
+       for( i = 0 ; i < MAX_GECKO_INSTANCES ; i++ ) {\r
+               clgecko_t *instance = &cl_geckoinstances[ i ];\r
+               if( instance->active ) {\r
+                       cl_gecko_unlinktexture( instance );\r
+               }               \r
+       }\r
+       osgk_release( cl_geckoembedding );\r
+}\r
+\r
+static void cl_gecko_create_f( void ) {\r
+       char name[MAX_QPATH];\r
+\r
+       if (Cmd_Argc() != 2)\r
+       {\r
+               Con_Print("usage: gecko_create <name>\npcreates a browser (full texture path " CLGECKOPREFIX "<name>)\n");\r
+               return;\r
+       }\r
+\r
+       // TODO: use snprintf instead\r
+       sprintf(name, CLGECKOPREFIX "%s", Cmd_Argv(1));\r
+       CL_Gecko_CreateBrowser( name );\r
+}\r
+\r
+static void cl_gecko_destroy_f( void ) {\r
+       char name[MAX_QPATH];\r
+\r
+       if (Cmd_Argc() != 2)\r
+       {\r
+               Con_Print("usage: gecko_destroy <name>\ndestroys a browser (full texture path " CLGECKOPREFIX "<name>)\n");\r
+               return;\r
+       }\r
+\r
+       // TODO: use snprintf instead\r
+       sprintf(name, CLGECKOPREFIX "%s", Cmd_Argv(1));\r
+       CL_Gecko_DestroyBrowser( CL_Gecko_FindBrowser( name ) );\r
+}\r
+\r
+static void cl_gecko_navigate_f( void ) {\r
+       char name[MAX_QPATH];\r
+       const char *URI;\r
+\r
+       if (Cmd_Argc() != 3)\r
+       {\r
+               Con_Print("usage: gecko_destroy <name> <URI>\nnavigates to a certain URI (full texture path " CLGECKOPREFIX "<name>)\n");\r
+               return;\r
+       }\r
+\r
+       // TODO: use snprintf instead\r
+       sprintf(name, CLGECKOPREFIX "%s", Cmd_Argv(1));\r
+       URI = Cmd_Argv( 2 );\r
+       CL_Gecko_NavigateToURI( CL_Gecko_FindBrowser( name ), URI );\r
+}\r
+\r
+void CL_Gecko_Init( void )\r
+{\r
+       OSGK_EmbeddingOptions *options = osgk_embedding_options_create();\r
+       osgk_embedding_options_add_search_path( options, "./xulrunner/" );\r
+   cl_geckoembedding = osgk_embedding_create_with_options( options, NULL );\r
+       osgk_release( options );\r
+       \r
+       if( cl_geckoembedding == NULL ) {\r
+               Con_Printf( "CL_Gecko_Init: Couldn't retrieve gecko embedding object!\n" );\r
+       }\r
+       \r
+       Cmd_AddCommand( "gecko_create", cl_gecko_create_f, "Create a gecko browser instance" );\r
+       Cmd_AddCommand( "gecko_destroy", cl_gecko_destroy_f, "Destroy a gecko browser instance" );\r
+       Cmd_AddCommand( "gecko_navigate", cl_gecko_navigate_f, "Navigate a gecko browser to an URI" );\r
+\r
+       R_RegisterModule( "CL_Gecko", cl_gecko_start, cl_gecko_shutdown, cl_gecko_newmap );\r
+}\r
+\r
+void CL_Gecko_NavigateToURI( clgecko_t *instance, const char *URI ) {\r
+       if( instance && instance->active ) {\r
+               osgk_browser_navigate( instance->browser, URI );\r
+       }\r
+}\r
+\r
+// TODO: write this function\r
+void CL_Gecko_Event_CursorMove( clgecko_t *instance, float x, float y );\r
+qboolean CL_Gecko_Event_Key( clgecko_t *instance, int key, clgecko_buttoneventtype_t eventtype );\r
+\r
+#endif
\ No newline at end of file
diff --git a/cl_gecko.h b/cl_gecko.h
new file mode 100644 (file)
index 0000000..d73f705
--- /dev/null
@@ -0,0 +1,40 @@
+// Andreas Kirsch 07\r
+\r
+#ifdef SUPPORT_GECKO\r
+\r
+#ifndef CL_GECKO_H\r
+#define CL_GECKO_H\r
+\r
+#define DEFAULT_GECKO_WIDTH    512\r
+#define DEFAULT_GECKO_HEIGHT   DEFAULT_GECKO_WIDTH\r
+\r
+#define CLGECKOPREFIX                  CLDYNTEXTUREPREFIX "gecko/"\r
+#define MAX_GECKO_INSTANCES    16\r
+\r
+typedef enum clgecko_buttoneventtype_e {\r
+       CLG_BET_DOWN,\r
+       CLG_BET_UP,\r
+       CLG_BET_DOUBLECLICK,\r
+       // use for up + down (but dont use both)\r
+       CLG_BET_PRESS\r
+} clgecko_buttoneventtype_t;\r
+\r
+typedef struct clgecko_s clgecko_t;\r
+\r
+void CL_Gecko_Frame( void );\r
+void CL_Gecko_Init( void );\r
+void CL_Gecko_Shutdown( void );\r
+\r
+clgecko_t * CL_Gecko_CreateBrowser( const char *name );\r
+clgecko_t * CL_Gecko_FindBrowser( const char *name );\r
+void CL_Gecko_DestroyBrowser( clgecko_t *instance );\r
+\r
+void CL_Gecko_NavigateToURI( clgecko_t *instance, const char *URI );\r
+void CL_Gecko_Event_CursorMove( clgecko_t *instance, float x, float y );\r
+\r
+// returns whether the key/button event was handled or not\r
+qboolean CL_Gecko_Event_Key( clgecko_t *instance, int key, clgecko_buttoneventtype_t eventtype );\r
+\r
+#endif\r
+\r
+#endif
\ No newline at end of file
index 2f105dbff54b8cf70ed5d7e38e545c368ac9061e..2bf63abaaa6c5cdbc87eae58dda01cbea9b45821 100644 (file)
--- 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
 }
 
 
index 42c0496d679026ff9e5229329b32cd27bd6321cc..d12854086f2deaf4fd790a1fbd53b3acdf8d2820 100644 (file)
@@ -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 );
 }
 
index cc38798f0c435413ebc7c089ce5bea351ef88b49..d5b1a84faabeeb6560596914f9233fbde5a40e06 100644 (file)
@@ -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 );
 
index b600d6df5df49df6b6a0dfb1573c7f0013c87a85..28239082f0326f669eac7dba03c4d5410f73da9b 100644 (file)
--- 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;
index 29cb7cbd1a64258c1e4283dda0f6745e6f4159a9..b36e648fe6461b3ef84d4d40ddb2da694d69b877 100644 (file)
@@ -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);
index 8ec12e9b65af8c30eee9ec487028bb3fe3e67fbf..9bfa092dbba913f2623d85883ae093283d179f1e 100644 (file)
@@ -1186,13 +1186,13 @@ void R_ReplaceWorldTexture (void)
                newt = r;
        for(i=0,t=m->data_textures;i<m->num_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
                        {
index 976946b88508c90fb79d0b70c3cd35f30f0626cf..ee9277129d297824150d3481d489141c7c3ce179 100644 (file)
@@ -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 4638ee8fae2226dbf3fb2cf3952e5bf783030193..694099db66800df24f5676cef282d54c5f52b4ca 100644 (file)
--- a/host.c
+++ b/host.c
@@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include <time.h>
 #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();
index 4ad5f5e8d2ce9650e6a17241faaeb8d87f1d0404..f7cb02f9b7322df22c632bae5fa30f79291bc3e5 100644 (file)
@@ -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)
index a2696fe61845dac9613027125f88a71d9cb4cb32..2baf0ea16cb29d2ee230d7072be368ea5e752db5 100644 (file)
--- 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);