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:
@@ -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
|
||||
|
||||
@@ -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,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"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user