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
This commit is contained in:
mcmartin
2003-01-30 21:24:51 +00:00
parent 3e5aad5001
commit b278956958
8 changed files with 216 additions and 26 deletions
+8
View File
@@ -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
+1 -1
View File
@@ -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"
+103
View File
@@ -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);
}
+30
View File
@@ -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
+34 -12
View File
@@ -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)
{
+38 -8
View File
@@ -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;
}
-5
View File
@@ -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;