Tests using 1000000 iterations on a Pentium 133 processor under zero load.
Clipping DISABLED:
Clipping calculations using { minx, miny, maxx, maxx }
No optimization: ~2.0 seconds
O2 optimization: ~1.4 seconds
Clipping calculations using { x, y, w, h }
With Uint16 (w, h)
No optimization: ~1.4 seconds
O2 optimization: ~1.0 seconds
With int (w, h)
No optimization: ~1.3 seconds (consistently ~0.1 seconds faster)
O2 optimization: ~0.95 seconds (consistently ~0.05 seconds faster)
Clipping ENABLED:
Clipping calculations using { minx, miny, maxx, maxx }
No optimization: ~2.0 seconds
O2 optimization: ~1.4 seconds
Clipping calculations using { x, y, w, h }
No optimization: ~1.8 seconds
O2 optimization: ~1.4 seconds
Clipping WORST CASE:
Clipping calculations using { minx, miny, maxx, maxx }
No optimization: ~31.5 seconds
O2 optimization: ~31.0 seconds
Clipping calculations using { x, y, w, h }
No optimization: ~32.5 seconds
O2 optimization: ~30.0 seconds-------------------------------------------------
I think I’ll stick with the original clipping code.
The source to the test code is included as an attachment.
See ya!
-Sam Lantinga (slouken at devolution.com)
–
Author of Simple DirectMedia Layer -
http://www.devolution.com/~slouken/SDL/
-------------- next part --------------
#include <stdio.h>
#include “SDL.h”
int SDL_UpperBlit1 (SDL_Surface *src, SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect)
{
SDL_Area srcarea, dstarea;
int clip_diff;
/* Set source and destination blit area rectangles */
if ( dstrect == NULL ) {
SDL_SetAreaWH(&dstarea, 0, 0, dst->w, dst->h);
} else {
SDL_SetAreaWH(&dstarea, dstrect->x, dstrect->y,
dstrect->w, dstrect->h);
}
if ( srcrect == NULL ) {
SDL_SetAreaWH(&srcarea, 0, 0, src->w, src->h);
} else {
SDL_SetAreaWH(&srcarea, srcrect->x, srcrect->y,
srcrect->w, srcrect->h);
}
/* Perform destination clipping */
clip_diff = dst->clip.minx-dstarea.minx;
if ( clip_diff > 0 ) {
dstarea.minx += clip_diff;
srcarea.minx += clip_diff;
}
clip_diff = dst->clip.miny-dstarea.miny;
if ( clip_diff > 0 ) {
dstarea.miny += clip_diff;
srcarea.miny += clip_diff;
}
clip_diff = dstarea.maxx-dst->clip.maxx;
if ( clip_diff > 0 ) {
dstarea.maxx -= clip_diff;
srcarea.maxx -= clip_diff;
}
clip_diff = dstarea.maxy-dst->clip.maxy;
if ( clip_diff > 0 ) {
dstarea.maxy -= clip_diff;
srcarea.maxy -= clip_diff;
}
/* Perform source clipping */
if ( srcarea.minx < 0 ) {
dstarea.minx -= srcarea.minx;
srcarea.minx = 0;
}
if ( srcarea.miny < 0 ) {
dstarea.miny -= srcarea.miny;
srcarea.miny = 0;
}
clip_diff = srcarea.maxx-src->w+1;
if ( clip_diff > 0 ) {
dstarea.maxx -= clip_diff;
srcarea.maxx -= clip_diff;
}
clip_diff = srcarea.maxy-src->h+1;
if ( clip_diff > 0 ) {
dstarea.maxy -= clip_diff;
srcarea.maxy -= clip_diff;
}
/* Verify blit areas */
if ( (srcarea.minx > srcarea.maxx) ) {
SDL_SetError("src rectangle minx > maxx after clipping");
return(-1);
}
if ( (srcarea.miny > srcarea.maxy) ) {
SDL_SetError("src rectangle miny > maxy after clipping");
return(-1);
}
if ( (dstarea.minx > dstarea.maxx) ) {
SDL_SetError("dst rectangle minx > maxx after clipping");
return(-1);
}
if ( (dstarea.miny > dstarea.maxy) ) {
SDL_SetError("dst rectangle miny > maxy after clipping");
return(-1);
}
if ( ((srcarea.maxx-srcarea.minx) != (dstarea.maxx-dstarea.minx)) ||
((srcarea.maxy-srcarea.miny) != (dstarea.maxy-dstarea.miny)) ) {
SDL_SetError("src and dst rectangles have different size");
return(-1);
}
/* Update the destination rectangle with clipped area */
if ( dstrect != NULL ) {
SDL_AreaToRect(&dstarea, dstrect);
}
/* Do the blit */
return(0);
}
int SDL_UpperBlit2 (SDL_Surface *src, SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect)
{
SDL_Rect fullsrc, fulldst;
int clip_diff;
/* Set default rectangles */
if ( dstrect == NULL ) {
fulldst.x = 0;
fulldst.y = 0;
fulldst.w = dst->w;
fulldst.h = dst->h;
dstrect = &fulldst;
}
if ( srcrect == NULL ) {
fullsrc.x = 0;
fullsrc.y = 0;
fullsrc.w = src->w;
fullsrc.h = src->h;
srcrect = &fullsrc;
}
/* Verify the destination coordinates */
if ( dstrect != &fulldst ) {
/* Check for negative destination coordinates */
if ( dstrect->x < 0 ) {
if ( -dstrect->x >= dstrect->w ) {
srcrect->w = 0;
dstrect->w = 0;
return(0);
}
srcrect->x -= dstrect->x;
srcrect->w += dstrect->x;
dstrect->w += dstrect->x;
dstrect->x = 0;
}
if ( dstrect->y < 0 ) {
if ( -dstrect->y >= dstrect->h ) {
srcrect->h = 0;
dstrect->h = 0;
return(0);
}
srcrect->y -= dstrect->y;
srcrect->h += dstrect->y;
dstrect->h += dstrect->y;
dstrect->y = 0;
}
/* Check for overlarge destination rectangle */
clip_diff = (dstrect->x+dstrect->w)-(dst->w);
if ( clip_diff > 0 ) {
if ( clip_diff >= dstrect->w ) {
srcrect->w = 0;
dstrect->w = 0;
return(0);
}
dstrect->w -= clip_diff;
srcrect->w -= clip_diff;
}
clip_diff = (dstrect->y+dstrect->h)-(dst->h);
if ( clip_diff > 0 ) {
if ( clip_diff >= dstrect->h ) {
srcrect->h = 0;
dstrect->h = 0;
return(0);
}
dstrect->h -= clip_diff;
srcrect->h -= clip_diff;
}
}
/* Verify the source coordinates */
if ( srcrect != &fullsrc ) {
/* Check for negative destination coordinates */
if ( srcrect->x < 0 ) {
if ( -srcrect->x >= srcrect->w ) {
srcrect->w = 0;
dstrect->w = 0;
return(0);
}
srcrect->w += srcrect->x;
dstrect->w += srcrect->x;
srcrect->x = 0;
}
if ( srcrect->y < 0 ) {
if ( -srcrect->y >= srcrect->h ) {
srcrect->h = 0;
dstrect->h = 0;
return(0);
}
srcrect->h += srcrect->y;
dstrect->h += srcrect->y;
srcrect->y = 0;
}
/* Check for overlarge source rectangle */
clip_diff = (srcrect->x+srcrect->w)-(src->w);
if ( clip_diff > 0 ) {
if ( clip_diff >= dstrect->w ) {
srcrect->w = 0;
dstrect->w = 0;
return(0);
}
dstrect->w -= clip_diff;
srcrect->w -= clip_diff;
}
clip_diff = (srcrect->y+srcrect->h)-(src->h);
if ( clip_diff > 0 ) {
if ( clip_diff >= dstrect->h ) {
srcrect->h = 0;
dstrect->h = 0;
return(0);
}
dstrect->h -= clip_diff;
srcrect->h -= clip_diff;
}
}
/* Check for clipping */
if ( 0 ) {
/* Check for clipping and adjust rectangles */
clip_diff = src->clip.minx-dstrect->x;
if ( clip_diff > 0 ) {
if ( clip_diff >= dstrect->w ) {
srcrect->w = 0;
dstrect->w = 0;
return(0);
}
#ifdef BLIT_DEBUG
fprintf(stderr,
“Blit of %dx%d at (%d,%d) extends %d pixels beyond left edge\n”,
dstrect->w, dstrect->h, dstrect->x, dstrect->y, clip_diff);
#endif
dstrect->x += clip_diff;
dstrect->w -= clip_diff;
srcrect->x += clip_diff;
srcrect->w -= clip_diff;
}
clip_diff = (dstrect->x+dstrect->w)-src->clip.maxx;
if ( clip_diff > 0 ) {
if ( clip_diff >= dstrect->w ) {
srcrect->w = 0;
dstrect->w = 0;
return(0);
}
#ifdef BLIT_DEBUG
fprintf(stderr,
“Blit of %dx%d at (%d,%d) extends %d pixels beyond right edge (%d)\n”,
dstrect->w, dstrect->h, dstrect->x, dstrect->y, clip_diff,
src->clip_maxx);
#endif
dstrect->w -= clip_diff;
srcrect->w -= clip_diff;
}
clip_diff = src->clip.miny-dstrect->y;
if ( clip_diff > 0 ) {
if ( clip_diff >= dstrect->h ) {
srcrect->h = 0;
dstrect->h = 0;
return(0);
}
#ifdef BLIT_DEBUG
fprintf(stderr,
“Blit of %dx%d at (%d,%d) extends %d pixels beyond top edge\n”,
dstrect->w, dstrect->h, dstrect->x, dstrect->y, clip_diff);
#endif
dstrect->y += clip_diff;
dstrect->h -= clip_diff;
srcrect->y += clip_diff;
srcrect->h -= clip_diff;
}
clip_diff = (dstrect->y+dstrect->h)-src->clip.maxy;
if ( clip_diff > 0 ) {
if ( clip_diff >= dstrect->h ) {
srcrect->h = 0;
dstrect->h = 0;
return(0);
}
#ifdef BLIT_DEBUG
fprintf(stderr,
“Blit of %dx%d at (%d,%d) extends %d pixels beyond bottom edge\n”,
dstrect->w, dstrect->h, dstrect->x, dstrect->y, clip.diff);
#endif
dstrect->h -= clip_diff;
srcrect->h -= clip_diff;
}
}
/* Check to make sure the blit rectangles are valid */
if ( (srcrect->w != dstrect->w) || (srcrect->h != dstrect->h) ) {
SDL_SetError(“SDL_UpperBlit: Passed mismatched rectangles”);
return(-1);
}
return(0);
}
main()
{
SDL_Surface src, dst;
SDL_Rect srect, drect;
int i;
Uint32 then, now;
if ( SDL_Init(0) < 0 )
exit(1);
/* Initialize the surfaces */
srect.x = srect.y = 0;
srect.w = src.w = 100;
srect.h = src.h = 100;
drect.x = drect.y = 0;
drect.w = dst.w = 100;
drect.h = dst.h = 100;
#if 0
SDL_SetClipping(&src, 1, 1, src.w-1, src.h-1);
SDL_SetClipping(&dst, 1, 1, dst.w-1, dst.h-1);
#else
SDL_SetClipping(&src, 0, 0, 0, 0);
SDL_SetClipping(&dst, 0, 0, 0, 0);
#endif
printf("Performing 1000000 iterations of Blit #1\n");
then = SDL_GetTicks();
for ( i=0; i<1000000; ++i ) {
SDL_UpperBlit1(&src, &srect, &dst, &drect);
}
now = SDL_GetTicks();
printf("Test took %d ms\n", now-then);
printf("Performing 1000000 iterations of Blit #2\n");
then = SDL_GetTicks();
for ( i=0; i<1000000; ++i ) {
SDL_UpperBlit2(&src, &srect, &dst, &drect);
}
now = SDL_GetTicks();
printf("Test took %d ms\n", now-then);
exit(0);
}