From 43eb06dd283d90d8467c4c44e8c66b3e6d02a385 Mon Sep 17 00:00:00 2001 From: mcmartin Date: Thu, 11 Jan 2007 00:45:48 +0000 Subject: [PATCH] Major rewrite of SwapBuffers routines. This rewrite abstracts out all screen compositing code into sdl_common.c and treats pure and OpenGL modes as backends. This should make fixing compositor bugs easier in the future, as well as providing alternate rendering forms for weaker cards if necessary. git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2653 8092fc87-c524-0410-9efc-e669fe64eaf9 --- sc2/ChangeLog | 4 + sc2/src/sc2code/libs/graphics/sdl/opengl.c | 369 ++++++++++-------- sc2/src/sc2code/libs/graphics/sdl/opengl.h | 2 - sc2/src/sc2code/libs/graphics/sdl/pure.c | 233 ++++++----- sc2/src/sc2code/libs/graphics/sdl/pure.h | 1 - .../sc2code/libs/graphics/sdl/sdl_common.c | 61 ++- .../sc2code/libs/graphics/sdl/sdl_common.h | 10 + 7 files changed, 390 insertions(+), 290 deletions(-) diff --git a/sc2/ChangeLog b/sc2/ChangeLog index 192daaa11..f1aa46714 100644 --- a/sc2/ChangeLog +++ b/sc2/ChangeLog @@ -1,4 +1,8 @@ Changes towards version 0.7: +- Major rewrite of the SwapBuffers commands -- screen compositing logic + has all been abstracted out into sdl_common.c instead of being + nearly-duplicated in opengl.c and pure.c - Michael +- --- 0.6.1 maintenance release occurred at this point --- - The Unicode Private Use Area is no longer considered printable. This is a stopgap to handle unusual behavior with text entry under OS X. See bug #942 for more details - Michael diff --git a/sc2/src/sc2code/libs/graphics/sdl/opengl.c b/sc2/src/sc2code/libs/graphics/sdl/opengl.c index 1bdf5316e..bea2d80f4 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/opengl.c +++ b/sc2/src/sc2code/libs/graphics/sdl/opengl.c @@ -23,15 +23,19 @@ #include "scalers.h" #include "libs/log.h" -static SDL_Surface *scaled_display = NULL; -static SDL_Surface *scaled_transition = NULL; +typedef struct _gl_screeninfo { + SDL_Surface *scaled; + GLuint texture; + BOOLEAN dirty, active; + SDL_Rect updated; +} TFB_GL_SCREENINFO; + +static TFB_GL_SCREENINFO GL_Screens[TFB_GFX_NUMSCREENS]; static int ScreenFilterMode; -static GLuint DisplayTexture; -static GLuint TransitionTexture; -static BOOLEAN upload_transitiontexture = FALSE; static TFB_ScaleFunc scaler = NULL; +static BOOLEAN first_init = TRUE; #if SDL_BYTEORDER == SDL_BIG_ENDIAN #define R_MASK 0xff000000 @@ -45,6 +49,24 @@ static TFB_ScaleFunc scaler = NULL; #define A_MASK 0xff000000 #endif +static void TFB_GL_Preprocess (int force_full_redraw, int transition_amount, int fade_amount); +static void TFB_GL_Postprocess (void); +static void TFB_GL_Scaled_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect); +static void TFB_GL_Unscaled_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect); +static void TFB_GL_ColorLayer (Uint8 r, Uint8 g, Uint8 b, Uint8 a, SDL_Rect *rect); + +static TFB_GRAPHICS_BACKEND opengl_scaled_backend = { + TFB_GL_Preprocess, + TFB_GL_Postprocess, + TFB_GL_Scaled_ScreenLayer, + TFB_GL_ColorLayer }; + +static TFB_GRAPHICS_BACKEND opengl_unscaled_backend = { + TFB_GL_Preprocess, + TFB_GL_Postprocess, + TFB_GL_Unscaled_ScreenLayer, + TFB_GL_ColorLayer }; + static SDL_Surface * Create_Screen (SDL_Surface *template, int w, int h) @@ -173,20 +195,34 @@ TFB_GL_ConfigureVideo (int driver, int flags, int width, int height) SDL_Screen = SDL_Screens[0]; TransitionScreen = SDL_Screens[2]; + if (first_init) + { + for (i = 0; i < TFB_GFX_NUMSCREENS; i++) + { + GL_Screens[i].scaled = NULL; + GL_Screens[i].dirty = TRUE; + GL_Screens[i].active = TRUE; + } + GL_Screens[1].active = FALSE; + first_init = FALSE; + } + if (GfxFlags & TFB_GFXFLAGS_SCALE_SOFT_ONLY) { - if (0 != ReInit_Screen (&scaled_display, format_conv_surf, - ScreenWidth * 2, ScreenHeight * 2)) - return -1; - - if (0 != ReInit_Screen (&scaled_transition, format_conv_surf, - ScreenWidth * 2, ScreenHeight * 2)) + for (i = 0; i < TFB_GFX_NUMSCREENS; i++) + { + if (!GL_Screens[i].active) + continue; + if (0 != ReInit_Screen (&GL_Screens[i].scaled, format_conv_surf, + ScreenWidth * 2, ScreenHeight * 2)) return -1; + } texture_width = 1024; texture_height = 512; scaler = Scale_PrepPlatform (flags, SDL_Screen->format); + graphics_backend = &opengl_scaled_backend; } else { @@ -194,6 +230,7 @@ TFB_GL_ConfigureVideo (int driver, int flags, int width, int height) texture_height = 256; scaler = NULL; + graphics_backend = &opengl_unscaled_backend; } if (GfxFlags & TFB_GFXFLAGS_SCALE_ANY) @@ -209,21 +246,18 @@ TFB_GL_ConfigureVideo (int driver, int flags, int width, int height) glDisable (GL_DITHER); glDepthMask(GL_FALSE); - glGenTextures (1, &DisplayTexture); - glBindTexture (GL_TEXTURE_2D, DisplayTexture); - glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, texture_width, texture_height, - 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - - glGenTextures (1, &TransitionTexture); - glBindTexture (GL_TEXTURE_2D, TransitionTexture); - glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, texture_width, texture_height, - 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + for (i = 0; i < TFB_GFX_NUMSCREENS; i++) + { + if (!GL_Screens[i].active) + continue; + glGenTextures (1, &GL_Screens[i].texture); + glBindTexture (GL_TEXTURE_2D, GL_Screens[i].texture); + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, texture_width, texture_height, + 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + } return 0; } @@ -258,7 +292,11 @@ TFB_GL_InitGraphics (int driver, int flags, int width, int height) void TFB_GL_UploadTransitionScreen (void) { - upload_transitiontexture = TRUE; + GL_Screens[TFB_SCREEN_TRANSITION].updated.x = 0; + GL_Screens[TFB_SCREEN_TRANSITION].updated.y = 0; + GL_Screens[TFB_SCREEN_TRANSITION].updated.w = ScreenWidth; + GL_Screens[TFB_SCREEN_TRANSITION].updated.h = ScreenHeight; + GL_Screens[TFB_SCREEN_TRANSITION].dirty = TRUE; } void @@ -289,9 +327,22 @@ TFB_GL_ScanLines (void) } } -void -TFB_GL_DrawQuad (void) +static void +TFB_GL_DrawQuad (SDL_Rect *r) { + if (r != NULL) + { + float scale_x = (ScreenWidthActual / (float)ScreenWidth); + float scale_y = (ScreenHeightActual / (float)ScreenHeight); + + glScissor ( + (GLint) (r->x * scale_x), + (GLint) ((ScreenHeight - (r->y + r->h)) * scale_y), + (GLsizei) (r->w * scale_x), + (GLsizei) (r->h * scale_y) + ); + glEnable (GL_SCISSOR_TEST); + } glBegin (GL_TRIANGLE_FAN); glTexCoord2f (0, 0); glVertex2i (0, 0); @@ -302,161 +353,157 @@ TFB_GL_DrawQuad (void) glTexCoord2f (0, ScreenHeight / 256.0f); glVertex2i (0, ScreenHeightActual); glEnd (); + if (r != NULL) + { + glDisable (GL_SCISSOR_TEST); + } } -void -TFB_GL_SwapBuffers (int force_full_redraw) +static void +TFB_GL_Preprocess (int force_full_redraw, int transition_amount, int fade_amount) { - int fade_amount = FadeAmount; - int transition_amount = TransitionAmount; - - if (!force_full_redraw && !TFB_BBox.valid && - fade_amount == 255 && transition_amount == 255) - return; - glMatrixMode (GL_PROJECTION); glLoadIdentity (); glOrtho (0,ScreenWidthActual,ScreenHeightActual, 0, -1, 1); glMatrixMode (GL_MODELVIEW); - glLoadIdentity (); - glBindTexture (GL_TEXTURE_2D, DisplayTexture); + glLoadIdentity (); + (void) force_full_redraw; + (void) transition_amount; + (void) fade_amount; + if (TFB_BBox.valid) + { + GL_Screens[TFB_SCREEN_MAIN].updated.x = TFB_BBox.region.corner.x; + GL_Screens[TFB_SCREEN_MAIN].updated.y = TFB_BBox.region.corner.y; + GL_Screens[TFB_SCREEN_MAIN].updated.w = TFB_BBox.region.extent.width; + GL_Screens[TFB_SCREEN_MAIN].updated.h = TFB_BBox.region.extent.height; + GL_Screens[TFB_SCREEN_MAIN].dirty = TRUE; + } +} + +static void +TFB_GL_Unscaled_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect) +{ + glBindTexture (GL_TEXTURE_2D, GL_Screens[screen].texture); glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + if (GL_Screens[screen].dirty) + { + glPixelStorei (GL_UNPACK_ROW_LENGTH, ScreenWidth); + /* Matrox OpenGL drivers do not handle GL_UNPACK_SKIP_* + correctly */ + glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); + SDL_LockSurface (SDL_Screens[screen]); + glTexSubImage2D (GL_TEXTURE_2D, 0, GL_Screens[screen].updated.x, + GL_Screens[screen].updated.y, + GL_Screens[screen].updated.w, + GL_Screens[screen].updated.h, + GL_RGBA, GL_UNSIGNED_BYTE, + (Uint32 *)SDL_Screens[screen]->pixels + + (GL_Screens[screen].updated.y * ScreenWidth + + GL_Screens[screen].updated.x)); + SDL_UnlockSurface (SDL_Screens[screen]); + GL_Screens[screen].dirty = FALSE; + } + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, ScreenFilterMode); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, ScreenFilterMode); glEnable (GL_TEXTURE_2D); - glDisable (GL_BLEND); - glColor4f (1, 1, 1, 1); - if (TFB_BBox.valid) + if (a == 255) { - SDL_Rect updated; - - updated.x = TFB_BBox.region.corner.x; - updated.y = TFB_BBox.region.corner.y; - updated.w = TFB_BBox.region.extent.width; - updated.h = TFB_BBox.region.extent.height; - - if (scaler) - { - scaler (SDL_Screen, scaled_display, &updated); - - glPixelStorei (GL_UNPACK_ROW_LENGTH, ScreenWidth * 2); - /* Matrox OpenGL drivers do not handle GL_UNPACK_SKIP_* - correctly */ - glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); - glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); - SDL_LockSurface (scaled_display); - glTexSubImage2D (GL_TEXTURE_2D, 0, updated.x * 2, updated.y * 2, - updated.w * 2, updated.h * 2, GL_RGBA, GL_UNSIGNED_BYTE, - (Uint32*)scaled_display->pixels + - (updated.y * 4 * ScreenWidth + updated.x * 2)); - SDL_UnlockSurface (scaled_display); - } - else - { - glPixelStorei (GL_UNPACK_ROW_LENGTH, ScreenWidth); - /* Matrox OpenGL drivers do not handle GL_UNPACK_SKIP_* - correctly */ - glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); - glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); - SDL_LockSurface (SDL_Screen); - glTexSubImage2D (GL_TEXTURE_2D, 0, updated.x, updated.y, - updated.w, updated.h, GL_RGBA, GL_UNSIGNED_BYTE, - (Uint32*)SDL_Screen->pixels + - (updated.y * ScreenWidth + updated.x)); - SDL_UnlockSurface (SDL_Screen); - } + glDisable (GL_BLEND); + glColor4f (1, 1, 1, 1); } - - TFB_GL_DrawQuad (); - - if (transition_amount != 255) + else { - float scale_x = (ScreenWidthActual / (float)ScreenWidth); - float scale_y = (ScreenHeightActual / (float)ScreenHeight); - - glBindTexture(GL_TEXTURE_2D, TransitionTexture); - - if (upload_transitiontexture) - { - if (scaler) - { - SDL_Rect r; - r.x = r.y = 0; - r.w = ScreenWidth; - r.h = ScreenHeight; - - scaler (TransitionScreen, scaled_transition, &r); - - glPixelStorei (GL_UNPACK_ROW_LENGTH, ScreenWidth * 2); - glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); - glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); - SDL_LockSurface (scaled_transition); - glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, ScreenWidth * 2, - ScreenHeight * 2, GL_RGBA, GL_UNSIGNED_BYTE, - scaled_transition->pixels); - SDL_UnlockSurface (scaled_transition); - } - else - { - glPixelStorei (GL_UNPACK_ROW_LENGTH, ScreenWidth); - glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); - glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); - SDL_LockSurface (TransitionScreen); - glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, ScreenWidth, - ScreenHeight, GL_RGBA, GL_UNSIGNED_BYTE, - TransitionScreen->pixels); - SDL_UnlockSurface (TransitionScreen); - } - - upload_transitiontexture = FALSE; - } - - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - ScreenFilterMode); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - ScreenFilterMode); - glEnable (GL_BLEND); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4f (1, 1, 1, (255 - transition_amount) / 255.0f); - glScissor ( - (GLint) (TransitionClipRect.x * scale_x), - (GLint) ((ScreenHeight - (TransitionClipRect.y + - TransitionClipRect.h)) * scale_y), - (GLsizei) (TransitionClipRect.w * scale_x), - (GLsizei) (TransitionClipRect.h * scale_y) - ); - glEnable (GL_SCISSOR_TEST); - TFB_GL_DrawQuad (); - glDisable (GL_SCISSOR_TEST); - } - - if (fade_amount != 255) - { - float c; - - if (fade_amount < 255) - { - c = (255 - fade_amount) / 255.0f; - glColor4f (0, 0, 0, c); - } - else - { - c = (fade_amount - 255) / 255.0f; - glColor4f (1, 1, 1, c); - } - - glDisable (GL_TEXTURE_2D); + float a_f = a / 255.0f; glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable (GL_BLEND); + glColor4f (1, 1, 1, a_f); + } + + TFB_GL_DrawQuad (rect); +} - TFB_GL_DrawQuad (); +static void +TFB_GL_Scaled_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect) +{ + glBindTexture (GL_TEXTURE_2D, GL_Screens[screen].texture); + glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + if (GL_Screens[screen].dirty) + { + scaler (SDL_Screens[screen], GL_Screens[screen].scaled, &GL_Screens[screen].updated); + glPixelStorei (GL_UNPACK_ROW_LENGTH, ScreenWidth * 2); + + /* Matrox OpenGL drivers do not handle GL_UNPACK_SKIP_* + correctly */ + glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); + SDL_LockSurface (GL_Screens[screen].scaled); + glTexSubImage2D (GL_TEXTURE_2D, 0, GL_Screens[screen].updated.x * 2, + GL_Screens[screen].updated.y * 2, + GL_Screens[screen].updated.w * 2, + GL_Screens[screen].updated.h * 2, + GL_RGBA, GL_UNSIGNED_BYTE, + (Uint32 *)GL_Screens[screen].scaled->pixels + + (GL_Screens[screen].updated.y * 4 * ScreenWidth + + GL_Screens[screen].updated.x * 2)); + SDL_UnlockSurface (GL_Screens[screen].scaled); + GL_Screens[screen].dirty = FALSE; } + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, ScreenFilterMode); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, ScreenFilterMode); + glEnable (GL_TEXTURE_2D); + + if (a == 255) + { + glDisable (GL_BLEND); + glColor4f (1, 1, 1, 1); + } + else + { + float a_f = a / 255.0f; + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable (GL_BLEND); + glColor4f (1, 1, 1, a_f); + } + + TFB_GL_DrawQuad (rect); +} + +static void +TFB_GL_ColorLayer (Uint8 r, Uint8 g, Uint8 b, Uint8 a, SDL_Rect *rect) +{ + float r_f = r / 255.0f; + float g_f = g / 255.0f; + float b_f = b / 255.0f; + float a_f = a / 255.0f; + glColor4f(r_f, g_f, b_f, a_f); + + glDisable (GL_TEXTURE_2D); + if (a != 255) + { + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable (GL_BLEND); + } + else + { + glDisable (GL_BLEND); + } + + TFB_GL_DrawQuad (rect); +} + +static void +TFB_GL_Postprocess (void) +{ if (GfxFlags & TFB_GFXFLAGS_SCANLINES) TFB_GL_ScanLines (); SDL_GL_SwapBuffers (); -} +} #endif diff --git a/sc2/src/sc2code/libs/graphics/sdl/opengl.h b/sc2/src/sc2code/libs/graphics/sdl/opengl.h index 629645682..90ab5f461 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/opengl.h +++ b/sc2/src/sc2code/libs/graphics/sdl/opengl.h @@ -24,8 +24,6 @@ int TFB_GL_InitGraphics (int driver, int flags, int width, int height); int TFB_GL_ConfigureVideo (int driver, int flags, int width, int height); void TFB_GL_UploadTransitionScreen (void); -void TFB_GL_SwapBuffers (int force_full_redraw); - #ifdef HAVE_OPENGL #ifdef WIN32 diff --git a/sc2/src/sc2code/libs/graphics/sdl/pure.c b/sc2/src/sc2code/libs/graphics/sdl/pure.c index 21e16097b..9faf7d758 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/pure.c +++ b/sc2/src/sc2code/libs/graphics/sdl/pure.c @@ -22,13 +22,33 @@ #include "scalers.h" #include "libs/log.h" -static SDL_Surface *fade_black = NULL; -static SDL_Surface *fade_white = NULL; +static SDL_Surface *fade_color_surface = NULL; static SDL_Surface *fade_temp = NULL; static SDL_Surface *scaled_display = NULL; static TFB_ScaleFunc scaler = NULL; +static Uint32 fade_color; + +static void TFB_Pure_Scaled_Preprocess (int force_full_redraw, int transition_amount, int fade_amount); +static void TFB_Pure_Scaled_Postprocess (void); +static void TFB_Pure_Unscaled_Preprocess (int force_full_redraw, int transition_amount, int fade_amount); +static void TFB_Pure_Unscaled_Postprocess (void); +static void TFB_Pure_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect); +static void TFB_Pure_ColorLayer (Uint8 r, Uint8 g, Uint8 b, Uint8 a, SDL_Rect *rect); + +static TFB_GRAPHICS_BACKEND pure_scaled_backend = { + TFB_Pure_Scaled_Preprocess, + TFB_Pure_Scaled_Postprocess, + TFB_Pure_ScreenLayer, + TFB_Pure_ColorLayer }; + +static TFB_GRAPHICS_BACKEND pure_unscaled_backend = { + TFB_Pure_Unscaled_Preprocess, + TFB_Pure_Unscaled_Postprocess, + TFB_Pure_ScreenLayer, + TFB_Pure_ColorLayer }; + static SDL_Surface * Create_Screen (SDL_Surface *template, int w, int h) { @@ -68,12 +88,14 @@ TFB_Pure_ConfigureVideo (int driver, int flags, int width, int height) videomode_flags = SDL_SWSURFACE; ScreenWidthActual = 320; ScreenHeightActual = 240; + graphics_backend = &pure_unscaled_backend; } else { videomode_flags = SDL_SWSURFACE; ScreenWidthActual = 640; ScreenHeightActual = 480; + graphics_backend = &pure_scaled_backend; if (width != 640 || height != 480) log_add (log_Error, "Screen resolution of %dx%d not supported " @@ -142,17 +164,11 @@ TFB_Pure_ConfigureVideo (int driver, int flags, int width, int height) SDL_Screen = SDL_Screens[0]; TransitionScreen = SDL_Screens[2]; - if (0 != ReInit_Screen (&fade_white, format_conv_surf, + if (0 != ReInit_Screen (&fade_color_surface, format_conv_surf, ScreenWidth, ScreenHeight)) return -1; - SDL_FillRect (fade_white, NULL, - SDL_MapRGB (fade_white->format, 255, 255, 255)); - - if (0 != ReInit_Screen (&fade_black, format_conv_surf, - ScreenWidth, ScreenHeight)) - return -1; - SDL_FillRect (fade_black, NULL, - SDL_MapRGB (fade_black->format, 0, 0, 0)); + fade_color = SDL_MapRGB (fade_color_surface->format, 0, 0, 0); + SDL_FillRect (fade_color_surface, NULL, fade_color); if (0 != ReInit_Screen (&fade_temp, format_conv_surf, ScreenWidth, ScreenHeight)) @@ -233,17 +249,13 @@ ScanLines (SDL_Surface *dst, SDL_Rect *r) } } -void -TFB_Pure_SwapBuffers (int force_full_redraw) -{ - static int last_fade_amount = 255, last_transition_amount = 255; - int fade_amount = FadeAmount; - int transition_amount = TransitionAmount; - SDL_Rect updated; +static SDL_Surface *backbuffer = NULL, *scalebuffer = NULL; +static SDL_Rect updated; - if (force_full_redraw || - fade_amount != 255 || transition_amount != 255 || - last_fade_amount != 255 || last_transition_amount != 255) +static void +TFB_Pure_Scaled_Preprocess (int force_full_redraw, int transition_amount, int fade_amount) +{ + if (force_full_redraw) { updated.x = updated.y = 0; updated.w = ScreenWidth; @@ -251,113 +263,100 @@ TFB_Pure_SwapBuffers (int force_full_redraw) } else { - if (!TFB_BBox.valid) - return; updated.x = TFB_BBox.region.corner.x; updated.y = TFB_BBox.region.corner.y; updated.w = TFB_BBox.region.extent.width; updated.h = TFB_BBox.region.extent.height; } - last_fade_amount = fade_amount; - last_transition_amount = transition_amount; - - if (ScreenWidthActual == ScreenWidth * 2 && - ScreenHeightActual == ScreenHeight * 2) + if (transition_amount == 255 && fade_amount == 255) + backbuffer = SDL_Screens[TFB_SCREEN_MAIN]; + else + backbuffer = fade_temp; + + // we can scale directly onto SDL_Video if video is compatible + if (SDL_Video->format->BitsPerPixel == + SDL_Screen->format->BitsPerPixel) + scalebuffer = SDL_Video; + else + scalebuffer = scaled_display; + +} + +static void +TFB_Pure_Unscaled_Preprocess (int force_full_redraw, int transition_amount, int fade_amount) +{ + if (force_full_redraw) { - // scales 320x240 backbuffer to 640x480 - - SDL_Surface *backbuffer = SDL_Screen; - SDL_Surface *scalebuffer = scaled_display; - - // we can scale directly onto SDL_Video if video is compatible - if (SDL_Video->format->BitsPerPixel == - SDL_Screen->format->BitsPerPixel) - scalebuffer = SDL_Video; - - if (transition_amount != 255) - { - backbuffer = fade_temp; - SDL_BlitSurface (SDL_Screen, NULL, backbuffer, NULL); - - SDL_SetAlpha (TransitionScreen, SDL_SRCALPHA, - 255 - transition_amount); - SDL_BlitSurface (TransitionScreen, &TransitionClipRect, - backbuffer, &TransitionClipRect); - } - - if (fade_amount != 255) - { - if (transition_amount == 255) - { - backbuffer = fade_temp; - SDL_BlitSurface (SDL_Screen, NULL, backbuffer, NULL); - } - - if (fade_amount < 255) - { - SDL_SetAlpha (fade_black, SDL_SRCALPHA, 255 - fade_amount); - SDL_BlitSurface (fade_black, NULL, backbuffer, NULL); - } - else - { - SDL_SetAlpha (fade_white, SDL_SRCALPHA, fade_amount - 255); - SDL_BlitSurface (fade_white, NULL, backbuffer, NULL); - } - } - - SDL_LockSurface (scalebuffer); - SDL_LockSurface (backbuffer); - - if (scaler) - scaler (backbuffer, scalebuffer, &updated); - - if (GfxFlags & TFB_GFXFLAGS_SCANLINES) - ScanLines (scalebuffer, &updated); - - SDL_UnlockSurface (backbuffer); - SDL_UnlockSurface (scalebuffer); - - updated.x *= 2; - updated.y *= 2; - updated.w *= 2; - updated.h *= 2; - if (scalebuffer != SDL_Video) - SDL_BlitSurface (scalebuffer, &updated, SDL_Video, &updated); - - SDL_UpdateRects (SDL_Video, 1, &updated); + updated.x = updated.y = 0; + updated.w = ScreenWidth; + updated.h = ScreenHeight; } else { - // resolution is 320x240 so we can blit directly - - SDL_BlitSurface (SDL_Screen, &updated, SDL_Video, &updated); - - if (transition_amount != 255) - { - SDL_SetAlpha (TransitionScreen, SDL_SRCALPHA, - 255 - transition_amount); - SDL_BlitSurface (TransitionScreen, &TransitionClipRect, - SDL_Video, &TransitionClipRect); - } - - if (fade_amount != 255) - { - if (fade_amount < 255) - { - SDL_SetAlpha (fade_black, SDL_SRCALPHA, 255 - fade_amount); - SDL_BlitSurface (fade_black, NULL, SDL_Video, NULL); - } - else - { - SDL_SetAlpha (fade_white, SDL_SRCALPHA, fade_amount - 255); - SDL_BlitSurface (fade_white, NULL, SDL_Video, NULL); - } - } - - SDL_UpdateRect (SDL_Video, updated.x, updated.y, - updated.w, updated.h); + updated.x = TFB_BBox.region.corner.x; + updated.y = TFB_BBox.region.corner.y; + updated.w = TFB_BBox.region.extent.width; + updated.h = TFB_BBox.region.extent.height; } + + backbuffer = SDL_Video; + (void)transition_amount; + (void)fade_amount; +} + +static void +TFB_Pure_Scaled_Postprocess (void) +{ + SDL_LockSurface (scalebuffer); + SDL_LockSurface (backbuffer); + + if (scaler) + scaler (backbuffer, scalebuffer, &updated); + + if (GfxFlags & TFB_GFXFLAGS_SCANLINES) + ScanLines (scalebuffer, &updated); + + SDL_UnlockSurface (backbuffer); + SDL_UnlockSurface (scalebuffer); + + updated.x *= 2; + updated.y *= 2; + updated.w *= 2; + updated.h *= 2; + if (scalebuffer != SDL_Video) + SDL_BlitSurface (scalebuffer, &updated, SDL_Video, &updated); + + SDL_UpdateRects (SDL_Video, 1, &updated); +} + +static void +TFB_Pure_Unscaled_Postprocess (void) +{ + SDL_UpdateRect (SDL_Video, updated.x, updated.y, + updated.w, updated.h); +} + +static void +TFB_Pure_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect) +{ + if (SDL_Screens[screen] == backbuffer) + return; + SDL_SetAlpha (SDL_Screens[screen], SDL_SRCALPHA, a); + SDL_BlitSurface (SDL_Screens[screen], rect, backbuffer, rect); +} + +static void +TFB_Pure_ColorLayer (Uint8 r, Uint8 g, Uint8 b, Uint8 a, SDL_Rect *rect) +{ + Uint32 col = SDL_MapRGB (fade_color_surface->format, r, g, b); + if (col != fade_color) + { + fade_color = col; + SDL_FillRect (fade_color_surface, NULL, fade_color); + } + SDL_SetAlpha (fade_color_surface, SDL_SRCALPHA, a); + SDL_BlitSurface (fade_color_surface, rect, backbuffer, rect); } void diff --git a/sc2/src/sc2code/libs/graphics/sdl/pure.h b/sc2/src/sc2code/libs/graphics/sdl/pure.h index 6b12d130f..8d0a82567 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/pure.h +++ b/sc2/src/sc2code/libs/graphics/sdl/pure.h @@ -23,6 +23,5 @@ int TFB_Pure_InitGraphics (int driver, int flags, int width, int height); int TFB_Pure_ConfigureVideo (int driver, int flags, int width, int height); -void TFB_Pure_SwapBuffers (int force_full_redraw); #endif diff --git a/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c b/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c index 695531162..ef81daf21 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c +++ b/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c @@ -52,6 +52,8 @@ int GfxFlags = 0; static TFB_Palette palette[256]; +TFB_GRAPHICS_BACKEND *graphics_backend = NULL; + #define FPS_PERIOD 100 int RenderedFrames = 0; @@ -116,9 +118,15 @@ TFB_ReInitGraphics (int driver, int flags, int width, int height) int TFB_InitGraphics (int driver, int flags, int width, int height) { - int result; + int result, i; char caption[200]; + /* Null out screen pointers the first time */ + for (i = 0; i < TFB_GFX_NUMSCREENS; i++) + { + SDL_Screens[i] = NULL; + } + GfxFlags = flags; if (driver == TFB_GFXDRIVER_SDL_OPENGL) @@ -209,14 +217,49 @@ TFB_ProcessEvents () void TFB_SwapBuffers (int force_full_redraw) { -#ifdef HAVE_OPENGL - if (GraphicsDriver == TFB_GFXDRIVER_SDL_OPENGL) - TFB_GL_SwapBuffers (force_full_redraw); - else - TFB_Pure_SwapBuffers (force_full_redraw); -#else - TFB_Pure_SwapBuffers (force_full_redraw); -#endif + static int last_fade_amount = 255, last_transition_amount = 255; + static int fade_amount = 255, transition_amount = 255; + + fade_amount = FadeAmount; + transition_amount = TransitionAmount; + + if (!force_full_redraw && !TFB_BBox.valid && + fade_amount == 255 && transition_amount == 255 && + last_fade_amount == 255 && last_transition_amount == 255) + return; + + if (fade_amount != 255 || transition_amount != 255 || + last_fade_amount != 255 || last_transition_amount != 255) + { + force_full_redraw = 1; + } + + last_fade_amount = fade_amount; + last_transition_amount = transition_amount; + + graphics_backend->preprocess (force_full_redraw, transition_amount, fade_amount); + graphics_backend->screen (TFB_SCREEN_MAIN, 255, NULL); + + if (transition_amount != 255) + { + graphics_backend->screen (TFB_SCREEN_TRANSITION, + 255 - transition_amount, &TransitionClipRect); + } + + if (fade_amount != 255) + { + if (fade_amount < 255) + { + graphics_backend->color (0, 0, 0, 255 - fade_amount, NULL); + } + else + { + graphics_backend->color (255, 255, 255, + fade_amount - 255, NULL); + } + } + + graphics_backend->postprocess (); } /* Probably ought to clean this away at some point. */ diff --git a/sc2/src/sc2code/libs/graphics/sdl/sdl_common.h b/sc2/src/sc2code/libs/graphics/sdl/sdl_common.h index 947c97824..be67596ef 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/sdl_common.h +++ b/sc2/src/sc2code/libs/graphics/sdl/sdl_common.h @@ -31,6 +31,16 @@ #include "libs/input/sdl/input.h" #include "libs/threadlib.h" +// The Graphics Backend vtable +typedef struct _tfb_graphics_backend { + void (*preprocess) (int force_redraw, int transition_amount, int fade_amount); + void (*postprocess) (void); + void (*screen) (SCREEN screen, Uint8 alpha, SDL_Rect *rect); + void (*color) (Uint8 r, Uint8 g, Uint8 b, Uint8 a, SDL_Rect *rect); +} TFB_GRAPHICS_BACKEND; + +extern TFB_GRAPHICS_BACKEND *graphics_backend; + // constants for TFB_InitGraphics extern SDL_Surface *SDL_Video;