CVS Update (24 bpp YUV support) - bug test

This is a multi-part message in MIME format.
--------------6C81AF16FE93D964AB07738E
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit

Mattias Engdeg?rd wrote:

Argh… Why did you “fix” things, Yorick?
I’m thinking about reverting the FillRect code to 1.1.7 unless you have
a good reason not to.

the code is cleaner and faster now, and if this is a bug then reverting is
not the answer. Andreas Schiffler, can you put together a complete program?

Attached is my test program. It is a modified version of graywin.c that
includes my pixel drawing routines. The pixel drawing routines are used for a
whole range of drawing routines that I made (and will release soon) that
provide graphics primitives. It uses 1x1 bitmap blits to get alpha blended
drawing correct on a pixel level.

Check for the sections following the string “ADDED”. Just substitute this for
graywin.c in /test and recompile. Trigger by clicking the mouse in the window.

I do assume it is my compiler and/or nasm setup. Since the problems started
after I updated from RedHat 6.2 to Mandrake 7.2.

This is the error I get when I run the test program in gdb.

Program received signal SIGSEGV, Segmentation fault.
0x40031fc0 in BlitNto1PixelAlpha (info=0xbffff5dc) at SDL_blit_A.c:130
130 width);

Ciao
Andreas–
| Andreas Schiffler aschiffler at home.com |
| Senior Systems Engineer - Deskplayer Inc., Buffalo |
| 4707 Eastwood Cres., Niagara Falls, Ont L2E 1B4, Canada |
| +1-905-371-3652 (private) - +1-905-371-8834 (work/fax) |

--------------6C81AF16FE93D964AB07738E
Content-Type: text/plain; charset=us-ascii;
name="graywin-1x1blittest.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename=“graywin-1x1blittest.c”

/* Simple program: Fill a colormap with gray and stripe it down the screen */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include “SDL.h”

#ifdef TEST_VGA16 /* Define this if you want to test VGA 16-color video modes */
#define NUM_COLORS 16
#else
#define NUM_COLORS 256
#endif

/* ======== ADDED for debugging purposes. A. Schiffler. aschiffler at home.com */

/* ----- Pixel - fast, no blending */

#define clip_xmin(surface) surface->clip_rect.x
#define clip_xmax(surface) surface->clip_rect.x+surface->clip_rect.w-1
#define clip_ymin(surface) surface->clip_rect.y
#define clip_ymax(surface) surface->clip_rect.y+surface->clip_rect.h-1

int fastPixelColor(SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color)
{
int bpp;
Uint8 *p;

/* Honor clipping setup at pixel level */
if ( (x >= clip_xmin(dst)) &&
(x <= clip_xmax(dst)) &&
(y >= clip_ymin(dst)) &&
(y <= clip_ymax(dst)) ) {

/* Get destination format */
bpp = dst->format->BytesPerPixel;
p = (Uint8 *)dst->pixels + y * dst->pitch + x * bpp;
switch(bpp) {
case 1:
    *p = color;
    break;
case 2:
    *(Uint16 *)p = color;
    break;
case 3:
    if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
        p[0] = (color >> 16) & 0xff;
        p[1] = (color >> 8) & 0xff;
        p[2] = color & 0xff;
    } else {
        p[0] = color & 0xff;
        p[1] = (color >> 8) & 0xff;
        p[2] = (color >> 16) & 0xff;
    }
    break;
case 4:
    *(Uint32 *)p = color;
    break;
}

}

return(0);
}

int fastPixelRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
Uint32 color;

/* Setup color */
color=SDL_MapRGBA(dst->format, r, g, b, a);

/* Draw */
return(fastPixelColor(dst, x, y, color));

}

/* ----- Pixel - using single pixel blit with blending enabled. */

static SDL_Surface *gfxPrimitivesSinglePixel=NULL;

int pixelColor (SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color)
{
SDL_Rect srect;
SDL_Rect drect;
int result;

/* Setup source rectangle for pixel */
srect.x=0;
srect.y=0;
srect.w=1;
srect.h=1;

/* Setup destination rectangle for pixel */
drect.x=x;
drect.y=y;
drect.w=1;
drect.h=1;

/* Create single pixel from destination surface format and add alpha channel to it */
if (gfxPrimitivesSinglePixel==NULL) {
gfxPrimitivesSinglePixel=SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_HWSURFACE | SDL_SRCALPHA, 1, 1, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
SDL_SetAlpha (gfxPrimitivesSinglePixel, SDL_SRCALPHA, 255);
}

/* Draw color into pixel*/
SDL_FillRect (gfxPrimitivesSinglePixel, &srect, color);

/* Draw pixel onto destination surface */
result=SDL_BlitSurface (gfxPrimitivesSinglePixel, &srect, dst, &drect);

return(result);
}

/* Alpha weight the colors for AA-drawing */

int pixelColorWeight (SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight)
{
Sint32 r,g,b,a;

r=((color >> 24) & 255);
g=((color >> 16) & 255);
b=((color >> 8) & 255);
a=(color & 255);

/* Modify Alpha by weight */
a -= weight;
if (a<0) a=0;

pixelColor (dst,x,y,((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a);
}

int pixelRGBA (SDL_Surface dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
/
Draw */
return(pixelColor (dst, x, y, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a ));
}

/* ======================= */

/* Draw a randomly sized and colored box centered about (X,Y) */
void DrawBox(SDL_Surface *screen, int X, int Y)
{
static unsigned int seeded = 0;
SDL_Rect area;
Uint32 color;
int i;

/* Seed the random number generator */
if ( seeded == 0 ) {
	srand(time(NULL));
	seeded = 1;
}

/* Get the bounds of the rectangle */
area.w = (rand()%640);
area.h = (rand()%480);
area.x = X-(area.w/2);
area.y = Y-(area.h/2);
color = (rand()%NUM_COLORS);

/* Do it! */
SDL_FillRect(screen, &area, color);

/* ======== ADDED for debugging purposes */

for (i=0; i<100; i++) {
 pixelRGBA(screen, area.x+(rand() % area.w), area.y+(rand() % (area.h/2)),rand() & 255,rand() & 255,rand() & 255,rand() & 255);
 fastPixelRGBA(screen, area.x+(rand() % area.w), area.y+area.h/2+(rand() % (area.h/2)),rand() & 255,rand() & 255,rand() & 255,rand() & 255);
}

SDL_UpdateRects(screen, 1, &area);

}

SDL_Surface *CreateScreen(Uint16 w, Uint16 h, Uint8 bpp, Uint32 flags)
{
SDL_Surface *screen;
int i;
SDL_Color palette[NUM_COLORS];
Uint8 *buffer;

/* Set the video mode */
screen = SDL_SetVideoMode(w, h, bpp, flags);
if ( screen == NULL ) {
	fprintf(stderr, "Couldn't set display mode: %s\n",
						SDL_GetError());
	return(NULL);
}
fprintf(stderr, "Screen is in %s mode\n",
	(screen->flags & SDL_FULLSCREEN) ? "fullscreen" : "windowed");

/* Set a gray colormap, reverse order from white to black */
for ( i=0; i<NUM_COLORS; ++i ) {
	palette[i].r = (NUM_COLORS-1)-i * (256 / NUM_COLORS);
	palette[i].g = (NUM_COLORS-1)-i * (256 / NUM_COLORS);
	palette[i].b = (NUM_COLORS-1)-i * (256 / NUM_COLORS);
}
SDL_SetColors(screen, palette, 0, NUM_COLORS);

/* Set the surface pixels and refresh! */
if ( SDL_LockSurface(screen) < 0 ) {
	fprintf(stderr, "Couldn't lock display surface: %s\n",
						SDL_GetError());
	return(NULL);
}
buffer = (Uint8 *)screen->pixels;
for ( i=0; i<screen->h; ++i ) {
	memset(buffer,(i*(NUM_COLORS-1))/screen->h, screen->w);
	buffer += screen->pitch;
}
SDL_UnlockSurface(screen);
SDL_UpdateRect(screen, 0, 0, 0, 0);

return(screen);

}

int main(int argc, char *argv[])
{
SDL_Surface *screen;
Uint32 videoflags;
int done;
SDL_Event event;
int width, height, bpp;

/* Initialize SDL */
if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
	fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
	exit(1);
}

/* See if we try to get a hardware colormap */
width = 640;
height = 480;
bpp = 8;
videoflags = SDL_SWSURFACE;
while ( argc > 1 ) {
	--argc;
	if ( argv[argc-1] && (strcmp(argv[argc-1], "-width") == 0) ) {
		width = atoi(argv[argc]);
		--argc;
	} else
	if ( argv[argc-1] && (strcmp(argv[argc-1], "-height") == 0) ) {
		height = atoi(argv[argc]);
		--argc;
	} else
	if ( argv[argc-1] && (strcmp(argv[argc-1], "-bpp") == 0) ) {
		bpp = atoi(argv[argc]);
		--argc;
	} else
	if ( argv[argc] && (strcmp(argv[argc], "-hw") == 0) ) {
		videoflags |= SDL_HWSURFACE;
	} else
	if ( argv[argc] && (strcmp(argv[argc], "-hwpalette") == 0) ) {
		videoflags |= SDL_HWPALETTE;
	} else
	if ( argv[argc] && (strcmp(argv[argc], "-noframe") == 0) ) {
		videoflags |= SDL_NOFRAME;
	} else
	if ( argv[argc] && (strcmp(argv[argc], "-fullscreen") == 0) ) {
		videoflags |= SDL_FULLSCREEN;
	} else {
		fprintf(stderr, "Usage: %s [-warp] [-fullscreen]\n",
							argv[0]);
		exit(1);
	}
}

/* Set a video mode */
screen = CreateScreen(width, height, bpp, videoflags);
if ( screen == NULL ) {
	exit(2);
}
	
/* Wait for a keystroke */
done = 0;
while ( !done && SDL_WaitEvent(&event) ) {
	switch (event.type) {
		case SDL_MOUSEBUTTONDOWN:
			DrawBox(screen, event.button.x, event.button.y);
			break;
		case SDL_KEYDOWN:
			/* Ignore ALT-TAB for windows */
			if ( (event.key.keysym.sym == SDLK_LALT) ||
			     (event.key.keysym.sym == SDLK_TAB) ) {
				break;
			}
			/* Center the mouse on <SPACE> */
			if ( event.key.keysym.sym == SDLK_SPACE ) {
				SDL_WarpMouse(640/2, 480/2);
				break;
			}
			/* Toggle fullscreen mode on <RETURN> */
			if ( event.key.keysym.sym == SDLK_RETURN ) {
				videoflags ^= SDL_FULLSCREEN;
				screen = CreateScreen(
					screen->w, screen->h,
					screen->format->BitsPerPixel,
							videoflags);
				if ( screen == NULL ) {
					fprintf(stderr,
				"Couldn't toggle fullscreen mode\n");
					done = 1;
				}
				break;
			}
			/* Any other key quits the application... */
		case SDL_QUIT:
			done = 1;
			break;
		default:
			break;
	}
}
SDL_Quit();
return(0);

}

--------------6C81AF16FE93D964AB07738E–

ok, found the problem. it was neither related to FillRect or 1x1 surfaces,
but exercised rarely used code for alpha-blending onto 8bpp surfaces.
Please apply

Index: SDL_blit_A.c===================================================================
RCS file: /cvs/SDL/src/video/SDL_blit_A.c,v
retrieving revision 1.3.2.7
diff -u -r1.3.2.7 SDL_blit_A.c
— SDL_blit_A.c 2001/02/10 07:20:05 1.3.2.7
+++ SDL_blit_A.c 2001/02/23 14:56:15
@@ -64,6 +64,9 @@
dG = dstfmt->palette->colors[*dst].g;
dB = dstfmt->palette->colors[*dst].b;
ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);

  •           dR &= 0xff;
    
  •           dG &= 0xff;
    
  •           dB &= 0xff;
              /* Pack RGB into 8bit pixel */
              if ( palmap == NULL ) {
                  *dst =((dR>>5)<<(3+2))|
    

@@ -114,6 +117,9 @@
dG = dstfmt->palette->colors[*dst].g;
dB = dstfmt->palette->colors[*dst].b;
ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB);

  •           dR &= 0xff;
    
  •           dG &= 0xff;
    
  •           dB &= 0xff;
              /* Pack RGB into 8bit pixel */
              if ( palmap == NULL ) {
                  *dst =((dR>>5)<<(3+2))|
    

@@ -166,6 +172,9 @@
dG = dstfmt->palette->colors[*dst].g;
dB = dstfmt->palette->colors[*dst].b;
ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);

  •               dR &= 0xff;
    
  •               dG &= 0xff;
    
  •               dB &= 0xff;
                  /* Pack RGB into 8bit pixel */
                  if ( palmap == NULL ) {
                      *dst =((dR>>5)<<(3+2))|

ok, found the problem. it was neither related to FillRect or 1x1 surfaces,
but exercised rarely used code for alpha-blending onto 8bpp surfaces.
Please apply

Got it, thanks.

See ya,
-Sam Lantinga, Lead Programmer, Loki Entertainment Software

Sam Lantinga wrote:

ok, found the problem. it was neither related to FillRect or 1x1 surfaces,
but exercised rarely used code for alpha-blending onto 8bpp surfaces.
Please apply

Got it, thanks.

Yes, that fixes things … great!

And my report of “no drawing” was a bloke on my part. My switch from
SDL1.1.7/Xfree4.0.1 to SDL1.2/XFree4.0.2 exposed a bug in my code (I was trying
to blit with a surface lock “on”).

Ciao
Andreas–
| Andreas Schiffler aschiffler at home.com |
| Senior Systems Engineer - Deskplayer Inc., Buffalo |
| 4707 Eastwood Cres., Niagara Falls, Ont L2E 1B4, Canada |
| +1-905-371-3652 (private) - +1-905-371-8834 (work/fax) |