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;