From b278956958c3264b00a8fb6bbd7cf27a32049d60 Mon Sep 17 00:00:00 2001 From: mcmartin Date: Thu, 30 Jan 2003 21:24:51 +0000 Subject: [PATCH] TFB_FlushGraphics tracks smallest required rectangle to update or rescale A partial version of only updating the smallest rectangle possible has been implemented for no scaling and for ScaleNearest. git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@618 8092fc87-c524-0410-9efc-e669fe64eaf9 --- sc2/ChangeLog | 2 + sc2/src/msvc++/UrQuanMasters.dsp | 8 ++ sc2/src/sc2code/libs/graphics/sdl/Makeinfo | 2 +- sc2/src/sc2code/libs/graphics/sdl/bbox.c | 103 ++++++++++++++++++ sc2/src/sc2code/libs/graphics/sdl/bbox.h | 30 +++++ sc2/src/sc2code/libs/graphics/sdl/pure.c | 46 ++++++-- .../sc2code/libs/graphics/sdl/sdl_common.c | 46 ++++++-- sc2/src/sc2code/libs/graphics/tfb_draw.h | 5 - 8 files changed, 216 insertions(+), 26 deletions(-) create mode 100644 sc2/src/sc2code/libs/graphics/sdl/bbox.c create mode 100644 sc2/src/sc2code/libs/graphics/sdl/bbox.h diff --git a/sc2/ChangeLog b/sc2/ChangeLog index 03ae67b5a..1f224665d 100644 --- a/sc2/ChangeLog +++ b/sc2/ChangeLog @@ -1,4 +1,6 @@ Changes towards version 0.2: +- TFB_FlushGraphics keeps track of smallest bounding box that requires + updating, allowing for faster scaling - Added a TFB_Canvas data buffer to let TFB_Image be more accessible - Added new graphics primitives - Added 'smooth' scolling for ff, frev (similar to the 3DO) - PhracturedBlue diff --git a/sc2/src/msvc++/UrQuanMasters.dsp b/sc2/src/msvc++/UrQuanMasters.dsp index f8da25f77..8de67feaa 100644 --- a/sc2/src/msvc++/UrQuanMasters.dsp +++ b/sc2/src/msvc++/UrQuanMasters.dsp @@ -164,6 +164,14 @@ SOURCE=..\sc2code\libs\graphics\sdl\3do_getbody.c # End Source File # Begin Source File +SOURCE=..\sc2code\libs\graphics\sdl\bbox.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\graphics\sdl\bbox.h +# End Source File +# Begin Source File + SOURCE=..\sc2code\libs\graphics\sdl\canvas.c # End Source File # Begin Source File diff --git a/sc2/src/sc2code/libs/graphics/sdl/Makeinfo b/sc2/src/sc2code/libs/graphics/sdl/Makeinfo index 1efc7a0ec..9814ebd90 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/Makeinfo +++ b/sc2/src/sc2code/libs/graphics/sdl/Makeinfo @@ -1,3 +1,3 @@ uqm_CFILES="3do_blt.c 3do_funcs.c 3do_getbody.c dcqueue.c opengl.c primitives.c pure.c rndzoom.c rotozoom.c sdl_common.c oscilloscope.c - canvas.c" + canvas.c bbox.c" diff --git a/sc2/src/sc2code/libs/graphics/sdl/bbox.c b/sc2/src/sc2code/libs/graphics/sdl/bbox.c new file mode 100644 index 000000000..e618b2cf7 --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/sdl/bbox.c @@ -0,0 +1,103 @@ +#include "SDL.h" +#include "bbox.h" + +TFB_BoundingBox TFB_BBox; + +void +TFB_BBox_Reset () +{ + TFB_BBox.valid = 0; + TFB_BBox.clip.corner.x = 0; + TFB_BBox.clip.corner.y = 0; + TFB_BBox.clip.extent.width = ScreenWidth; + TFB_BBox.clip.extent.height = ScreenHeight; +} + +void +TFB_BBox_GetClipRect (TFB_Canvas c) +{ + SDL_Rect r; + SDL_GetClipRect ((SDL_Surface *)c, &r); + TFB_BBox.clip.corner.x = r.x; + TFB_BBox.clip.corner.y = r.y; + TFB_BBox.clip.extent.width = r.w; + TFB_BBox.clip.extent.height = r.h; +} + +void +TFB_BBox_RegisterPoint (int x, int y) +{ + int x1 = TFB_BBox.clip.corner.x; + int y1 = TFB_BBox.clip.corner.y; + int x2 = TFB_BBox.clip.corner.x + TFB_BBox.clip.extent.width - 1; + int y2 = TFB_BBox.clip.corner.y + TFB_BBox.clip.extent.height - 1; + + /* Make sure the cliprect is sane */ + + if (x1 < 0) x1 = TFB_BBox.clip.corner.x = 0; + if (y1 < 0) y1 = TFB_BBox.clip.corner.y = 0; + if (x2 >= ScreenWidth) + { + TFB_BBox.clip.extent.width = ScreenWidth - x1; + x2 = ScreenWidth - 1; + } + if (y2 >= ScreenHeight) + { + TFB_BBox.clip.extent.height = ScreenHeight - y1; + y2 = ScreenHeight - 1; + } + + + /* Constrain coordinates */ + if (x < x1) x = x1; + if (x >= x2) x = x2; + if (y < y1) y = y1; + if (y >= y2) y = y2; + + /* Is this the first point? If so, set a pixel-region and return. */ + if (!TFB_BBox.valid) + { + TFB_BBox.valid = 1; + TFB_BBox.region.corner.x = x; + TFB_BBox.region.corner.y = y; + TFB_BBox.region.extent.width = 1; + TFB_BBox.region.extent.height = 1; + return; + } + + /* Otherwise expand the rectangle if necessary. */ + x1 = TFB_BBox.region.corner.x; + y1 = TFB_BBox.region.corner.y; + x2 = TFB_BBox.region.corner.x + TFB_BBox.region.extent.width - 1; + y2 = TFB_BBox.region.corner.y + TFB_BBox.region.extent.height - 1; + + if (x < x1) { + TFB_BBox.region.corner.x = x; + TFB_BBox.region.extent.width += x1 - x; + } + if (y < y1) { + TFB_BBox.region.corner.y = y; + TFB_BBox.region.extent.height += y1 - y; + } + if (x > x2) { + TFB_BBox.region.extent.width += x - x2; + } + if (y > y2) { + TFB_BBox.region.extent.height += y - y2; + } +} + +void +TFB_BBox_RegisterRect (PRECT r) +{ + TFB_BBox_RegisterPoint (r->corner.x, r->corner.y); + TFB_BBox_RegisterPoint (r->corner.x + r->extent.width, r->corner.y + r->extent.height); +} + +void +TFB_BBox_RegisterCanvas (TFB_Canvas c, int x, int y) +{ + SDL_Surface *s = (SDL_Surface *)c; + TFB_BBox_RegisterPoint (x, y); + TFB_BBox_RegisterPoint (x + s->w, y + s->h); +} diff --git a/sc2/src/sc2code/libs/graphics/sdl/bbox.h b/sc2/src/sc2code/libs/graphics/sdl/bbox.h new file mode 100644 index 000000000..23fda20b4 --- /dev/null +++ b/sc2/src/sc2code/libs/graphics/sdl/bbox.h @@ -0,0 +1,30 @@ +#include "gfxlib.h" +#include "graphics/tfb_draw.h" +#include "graphics/gfx_common.h" + +#ifndef _BBOX_H_ +#define _BBOX_H_ + +/* Bounding Box operations. These operations are NOT synchronized. + * However, they should only be accessed by TFB_FlushGraphics and + * TFB_SwapBuffers, or the routines that they exclusively call -- all + * of which are only callable by the thread that is permitted to touch + * the screen. No explicit locks should therefore be required. */ + +typedef struct { + int valid; // If zero, the next point registered becomes the region + RECT region; // The actual modified rectangle + RECT clip; // Points outside of this rectangle are pushed to + // the closest border point +} TFB_BoundingBox; + +extern TFB_BoundingBox TFB_BBox; + +void TFB_BBox_RegisterPoint (int x, int y); +void TFB_BBox_RegisterRect (PRECT r); +void TFB_BBox_RegisterCanvas (TFB_Canvas c, int x, int y); + +void TFB_BBox_Reset (); +void TFB_BBox_GetClipRect (TFB_Canvas c); + +#endif diff --git a/sc2/src/sc2code/libs/graphics/sdl/pure.c b/sc2/src/sc2code/libs/graphics/sdl/pure.c index f3e20999d..e1c5967e6 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/pure.c +++ b/sc2/src/sc2code/libs/graphics/sdl/pure.c @@ -20,6 +20,7 @@ #include "pure.h" #include "primitives.h" +#include "bbox.h" static SDL_Surface *fade_black; static SDL_Surface *fade_white; @@ -831,10 +832,12 @@ Scale_BiAdaptFilter (SDL_Surface *src, SDL_Surface *dst) } // nearest neighbor scaling to 2x -static void Scale_Nearest (SDL_Surface *src, SDL_Surface *dst) +static void Scale_Nearest (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r) { int x, y; const int w = src->w, h = src->h, dw = dst->w; + const int x0 = r->x, y0 = r->y, rw = r->w, rh = r->h; + const int ds = w-rw, dd = (dw-rw) * 2; switch (dst->format->BytesPerPixel) { @@ -842,9 +845,11 @@ static void Scale_Nearest (SDL_Surface *src, SDL_Surface *dst) { Uint16 *src_p = (Uint16 *)src->pixels, *dst_p = (Uint16 *)dst->pixels; Uint16 pixval_16; - for (y = 0; y < h; ++y) + src_p += w*y0 + x0; + dst_p += (dw*y0 + x0) * 2; + for (y = 0; y < rh; ++y) { - for (x = 0; x < w; ++x) + for (x = 0; x < rw; ++x) { pixval_16 = *src_p++; dst_p[dw] = pixval_16; @@ -852,7 +857,8 @@ static void Scale_Nearest (SDL_Surface *src, SDL_Surface *dst) dst_p[dw] = pixval_16; *dst_p++ = pixval_16; } - dst_p += dw; + dst_p += dd; + src_p += ds; } break; } @@ -889,9 +895,11 @@ static void Scale_Nearest (SDL_Surface *src, SDL_Surface *dst) { Uint32 *src_p = (Uint32 *)src->pixels, *dst_p = (Uint32 *)dst->pixels; Uint32 pixval_32; - for (y = 0; y < h; ++y) + src_p += w*y0 + x0; + dst_p += (dw*y0 + x0) * 2; + for (y = 0; y < rh; ++y) { - for (x = 0; x < w; ++x) + for (x = 0; x < rw; ++x) { pixval_32 = *src_p++; dst_p[dw] = pixval_32; @@ -899,7 +907,8 @@ static void Scale_Nearest (SDL_Surface *src, SDL_Surface *dst) dst_p[dw] = pixval_32; *dst_p++ = pixval_32; } - dst_p += dw; + dst_p += dd; + src_p += ds; } break; } @@ -907,7 +916,7 @@ static void Scale_Nearest (SDL_Surface *src, SDL_Surface *dst) } // bilinear scaling to 2x -static void Scale_BilinearFilter (SDL_Surface *src, SDL_Surface *dst) +static void Scale_BilinearFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r) { int x, y, i = 0, j, fa, fb, fc, fd; const int w = dst->w, h = dst->h; @@ -1002,7 +1011,7 @@ static void Scale_BilinearFilter (SDL_Surface *src, SDL_Surface *dst) { // 24bpp mode bilinear scaling isn't implemented currently // it would probably be too slow to be useful anyway - Scale_Nearest (src, dst); + Scale_Nearest (src, dst, r); break; } case 4: @@ -1169,6 +1178,19 @@ TFB_Pure_SwapBuffers () { int fade_amount = FadeAmount; int transition_amount = TransitionAmount; + 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 ((transition_amount != 255) || (fade_amount != 255)) + { + updated.x = updated.y = 0; + updated.w = ScreenWidth; + updated.h = ScreenHeight; + } if (ScreenWidth == 320 && ScreenHeight == 240 && ScreenWidthActual == 640 && ScreenHeightActual == 480) @@ -1210,11 +1232,11 @@ TFB_Pure_SwapBuffers () SDL_LockSurface (backbuffer); if (gfx_flags & TFB_GFXFLAGS_SCALE_BILINEAR) - Scale_BilinearFilter (backbuffer, SDL_Video); + Scale_BilinearFilter (backbuffer, SDL_Video, &updated); else if (gfx_flags & TFB_GFXFLAGS_SCALE_BIADAPT) Scale_BiAdaptFilter (backbuffer, SDL_Video); else - Scale_Nearest (backbuffer, SDL_Video); + Scale_Nearest (backbuffer, SDL_Video, &updated); if (gfx_flags & TFB_GFXFLAGS_SCANLINES) ScanLines (SDL_Video); @@ -1226,7 +1248,7 @@ TFB_Pure_SwapBuffers () { // resolution is 320x240 so we can blit directly - SDL_BlitSurface (SDL_Screen, NULL, SDL_Video, NULL); + SDL_BlitSurface (SDL_Screen, &updated, SDL_Video, &updated); if (transition_amount != 255) { diff --git a/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c b/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c index e3de82765..88c8bab1e 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c +++ b/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c @@ -27,6 +27,7 @@ #include "options.h" #include "SDL_thread.h" #include "libs/graphics/drawcmd.h" +#include "bbox.h" SDL_Surface *SDL_Video; SDL_Surface *SDL_Screen; @@ -521,6 +522,9 @@ TFB_FlushGraphics () // Only call from main thread!! livelock_deterrence = TRUE; } + TFB_BBox_Reset (); + TFB_BBox_GetClipRect (SDL_Screens[0]); + done = FALSE; while (!done) { @@ -560,8 +564,15 @@ TFB_FlushGraphics () // Only call from main thread!! } case TFB_DRAWCOMMANDTYPE_IMAGE: { - TFB_Image *DC_image = (TFB_Image *)DC.data.image.image; + TFB_Image *DC_image = DC.data.image.image; TFB_Palette *pal; + int x = DC.data.image.x; + int y = DC.data.image.y; + + if (DC.data.image.UseScaling) + TFB_BBox_RegisterCanvas (DC_image->ScaledImg, x, y); + else + TFB_BBox_RegisterCanvas (DC_image->NormalImg, x, y); if (DC.data.image.UsePalette) { @@ -572,7 +583,7 @@ TFB_FlushGraphics () // Only call from main thread!! pal = DC_image->Palette; } - TFB_DrawCanvas_Image (DC_image, DC.data.image.x, DC.data.image.y, + TFB_DrawCanvas_Image (DC_image, x, y, DC.data.image.UseScaling, pal, SDL_Screens[DC.data.image.destBuffer], DC.data.image.BlendNumerator, DC.data.image.BlendDenominator); @@ -581,6 +592,15 @@ TFB_FlushGraphics () // Only call from main thread!! } case TFB_DRAWCOMMANDTYPE_FILLEDIMAGE: { + TFB_Image *DC_image = DC.data.filledimage.image; + int x = DC.data.filledimage.x; + int y = DC.data.filledimage.y; + + if (DC.data.filledimage.UseScaling) + TFB_BBox_RegisterCanvas (DC_image->ScaledImg, x, y); + else + TFB_BBox_RegisterCanvas (DC_image->NormalImg, x, y); + TFB_DrawCanvas_FilledImage (DC.data.filledimage.image, DC.data.filledimage.x, DC.data.filledimage.y, DC.data.filledimage.UseScaling, DC.data.filledimage.r, DC.data.filledimage.g, DC.data.filledimage.b, SDL_Screens[DC.data.filledimage.destBuffer], @@ -589,6 +609,8 @@ TFB_FlushGraphics () // Only call from main thread!! } case TFB_DRAWCOMMANDTYPE_LINE: { + TFB_BBox_RegisterPoint (DC.data.line.x1, DC.data.line.y1); + TFB_BBox_RegisterPoint (DC.data.line.x2, DC.data.line.y2); TFB_DrawCanvas_Line (DC.data.line.x1, DC.data.line.y1, DC.data.line.x2, DC.data.line.y2, DC.data.line.r, DC.data.line.g, DC.data.line.b, @@ -597,6 +619,7 @@ TFB_FlushGraphics () // Only call from main thread!! } case TFB_DRAWCOMMANDTYPE_RECTANGLE: { + TFB_BBox_RegisterRect (&DC.data.rect.rect); TFB_DrawCanvas_Rect (&DC.data.rect.rect, DC.data.rect.r, DC.data.rect.g, DC.data.rect.b, SDL_Screens[DC.data.rect.destBuffer]); @@ -606,21 +629,24 @@ TFB_FlushGraphics () // Only call from main thread!! case TFB_DRAWCOMMANDTYPE_SCISSORENABLE: { SDL_Rect r; - r.x = DC.data.scissor.x; - r.y = DC.data.scissor.y; - r.w = DC.data.scissor.w; - r.h = DC.data.scissor.h; - + r.x = TFB_BBox.clip.corner.x = DC.data.scissor.x; + r.y = TFB_BBox.clip.corner.y = DC.data.scissor.y; + r.w = TFB_BBox.clip.extent.width = DC.data.scissor.w; + r.h = TFB_BBox.clip.extent.height = DC.data.scissor.h; SDL_SetClipRect(SDL_Screens[0], &r); break; } case TFB_DRAWCOMMANDTYPE_SCISSORDISABLE: SDL_SetClipRect(SDL_Screens[0], NULL); + TFB_BBox.clip.corner.x = 0; + TFB_BBox.clip.corner.y = 0; + TFB_BBox.clip.extent.width = ScreenWidth; + TFB_BBox.clip.extent.height = ScreenHeight; break; case TFB_DRAWCOMMANDTYPE_COPYTOIMAGE: { SDL_Rect src, dest; - TFB_Image *DC_image = (TFB_Image *)DC.data.copytoimage.image; + TFB_Image *DC_image = DC.data.copytoimage.image; if (DC_image == 0) { @@ -648,6 +674,10 @@ TFB_FlushGraphics () // Only call from main thread!! src.w = DC.data.copy.w; src.h = DC.data.copy.h; + TFB_BBox_RegisterPoint (src.x, src.y); + TFB_BBox_RegisterPoint (src.x + src.w, src.y + src.h); + + TFB_BlitSurface(SDL_Screens[DC.data.copy.srcBuffer], &src, SDL_Screens[DC.data.copy.destBuffer], &dest, DC.data.copy.BlendNumerator, DC.data.copy.BlendDenominator); break; } diff --git a/sc2/src/sc2code/libs/graphics/tfb_draw.h b/sc2/src/sc2code/libs/graphics/tfb_draw.h index 59636ca2d..51677d84e 100644 --- a/sc2/src/sc2code/libs/graphics/tfb_draw.h +++ b/sc2/src/sc2code/libs/graphics/tfb_draw.h @@ -37,11 +37,6 @@ typedef struct tfb_palette UBYTE unused; } TFB_Palette; -// This code will be replaced with appropriately modularized stuff -// later However, right now the code that uses it in graphics/sdl -// assumes these are all SDL_Surface *s. I need to rewrite them to -// make them use the DrawCanvas commands. -- Michael - typedef struct tfb_image { TFB_Canvas NormalImg;