Mercurial > sdl-ios-xcode
view test/testsprite.c @ 983:7f08bd66f1ca
Date: Fri, 19 Nov 2004 06:23:53 -0800 (PST)
From: Eric Wing
Subject: OS X Mouse inversion problem fix (again)
Here's yet another patch for the OS X mouse inversion
problem. This should fix the problem once and for all.
I know I've said this before, but *This time for
sure!* :)
If you recall, my last patch broke the non-OpenGL
windowed code and caused the inversion to occur there
instead. Max submitted a patch that partially reverted
the changes back which included the os version hack
which is currently the most recent CVS.
Aaron Sullivan identified and reported to the mailing
list the other day, that the last partial regression
of the code broke OS X 10.2. Looking over the results,
I'm thinking that I was slightly more successful than
I thought at unifying the code. I think I was trying
to unify the code base for OpenGL and non-OpenGL
windowed modes for all versions of the OS. It looks
like I failed at at unifying the OpenGL and non-OpenGL
code, but I did succeed at unifying the OS versions.
Thus, we no longer need the hack for the OS version
checks. The partial regression still included an OS
check which is what broke things for < 10.3.
Attached is the patch for SDL_QuartzWM.m. It basically
is a half-line change that removes one of the two
checks that decides if the mouse coordinates need to
be inverted, i.e:
if (system_version >= 0x1030 &&
(SDL_VideoSurface->flags & SDL_OPENGL) )
becomes this:
if(SDL_VideoSurface->flags & SDL_OPENGL)
With Aaron's outstanding help, we have collectively
tested:
windowed OpenGL
windowed non-OpenGL
fullscreen OpenGL
fullscreen non-OpenGL
under OS X 10.2 (Jaguar), 10.3 (Panther), and 10.4
(Tiger).
We don't have access to 10.0 or 10.1, but since the
original problem didn't materialize until 10.3, I'm
hopeful that testing 10.2 is sufficient. And now that
the code is uniform, I'm also hoping we'll be safe
moving forward to deal with future revisions of the OS
with this issue.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 21 Nov 2004 00:57:47 +0000 |
parents | b14fdadd8311 |
children | be9c9c8f6d53 |
line wrap: on
line source
/* Simple program: Move N sprites around on the screen as fast as possible */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <math.h> #include <time.h> #include "SDL.h" #define DEBUG_FLIP 1 #define NUM_SPRITES 100 #define MAX_SPEED 1 SDL_Surface *sprite; int numsprites; SDL_Rect *sprite_rects; SDL_Rect *positions; SDL_Rect *velocities; int sprites_visible; Uint16 sprite_w, sprite_h; int LoadSprite(SDL_Surface *screen, char *file) { SDL_Surface *temp; /* Load the sprite image */ sprite = SDL_LoadBMP(file); if ( sprite == NULL ) { fprintf(stderr, "Couldn't load %s: %s", file, SDL_GetError()); return(-1); } /* Set transparent pixel as the pixel at (0,0) */ if ( sprite->format->palette ) { SDL_SetColorKey(sprite, (SDL_SRCCOLORKEY|SDL_RLEACCEL), *(Uint8 *)sprite->pixels); } /* Convert sprite to video format */ temp = SDL_DisplayFormat(sprite); SDL_FreeSurface(sprite); if ( temp == NULL ) { fprintf(stderr, "Couldn't convert background: %s\n", SDL_GetError()); return(-1); } sprite = temp; /* We're ready to roll. :) */ return(0); } void MoveSprites(SDL_Surface *screen, Uint32 background) { int i, nupdates; SDL_Rect area, *position, *velocity; nupdates = 0; /* Erase all the sprites if necessary */ if ( sprites_visible ) { SDL_FillRect(screen, NULL, background); } /* Move the sprite, bounce at the wall, and draw */ for ( i=0; i<numsprites; ++i ) { position = &positions[i]; velocity = &velocities[i]; position->x += velocity->x; if ( (position->x < 0) || (position->x >= (screen->w - sprite_w)) ) { velocity->x = -velocity->x; position->x += velocity->x; } position->y += velocity->y; if ( (position->y < 0) || (position->y >= (screen->h - sprite_w)) ) { velocity->y = -velocity->y; position->y += velocity->y; } /* Blit the sprite onto the screen */ area = *position; SDL_BlitSurface(sprite, NULL, screen, &area); sprite_rects[nupdates++] = area; } #if DEBUG_FLIP { if ( (screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { static int t = 0; Uint32 color = SDL_MapRGB (screen->format, 255, 0, 0); SDL_Rect r; r.x = (sin((float)t * 2 * 3.1459) + 1.0) / 2.0 * (screen->w-20); r.y = 0; r.w = 20; r.h = screen->h; SDL_FillRect (screen, &r, color); t+=2; } } #endif /* Update the screen! */ if ( (screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { SDL_Flip(screen); } else { SDL_UpdateRects(screen, nupdates, sprite_rects); } sprites_visible = 1; } /* This is a way of telling whether or not to use hardware surfaces */ Uint32 FastestFlags(Uint32 flags, int width, int height, int bpp) { const SDL_VideoInfo *info; /* Hardware acceleration is only used in fullscreen mode */ flags |= SDL_FULLSCREEN; /* Check for various video capabilities */ info = SDL_GetVideoInfo(); if ( info->blit_hw_CC && info->blit_fill ) { /* We use accelerated colorkeying and color filling */ flags |= SDL_HWSURFACE; } /* If we have enough video memory, and will use accelerated blits directly to it, then use page flipping. */ if ( (flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { /* Direct hardware blitting without double-buffering causes really bad flickering. */ if ( info->video_mem*1024 > (height*width*bpp/8) ) { flags |= SDL_DOUBLEBUF; } else { flags &= ~SDL_HWSURFACE; } } /* Return the flags */ return(flags); } int main(int argc, char *argv[]) { SDL_Surface *screen; Uint8 *mem; int width, height; Uint8 video_bpp; Uint32 videoflags; Uint32 background; int i, done; SDL_Event event; Uint32 then, now, frames; /* Initialize SDL */ if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError()); exit(1); } atexit(SDL_Quit); numsprites = NUM_SPRITES; videoflags = SDL_SWSURFACE|SDL_ANYFORMAT; width = 640; height = 480; video_bpp = 8; while ( argc > 1 ) { --argc; if ( strcmp(argv[argc-1], "-width") == 0 ) { width = atoi(argv[argc]); --argc; } else if ( strcmp(argv[argc-1], "-height") == 0 ) { height = atoi(argv[argc]); --argc; } else if ( strcmp(argv[argc-1], "-bpp") == 0 ) { video_bpp = atoi(argv[argc]); videoflags &= ~SDL_ANYFORMAT; --argc; } else if ( strcmp(argv[argc], "-fast") == 0 ) { videoflags = FastestFlags(videoflags, width, height, video_bpp); } else if ( strcmp(argv[argc], "-hw") == 0 ) { videoflags ^= SDL_HWSURFACE; } else if ( strcmp(argv[argc], "-flip") == 0 ) { videoflags ^= SDL_DOUBLEBUF; } else if ( strcmp(argv[argc], "-fullscreen") == 0 ) { videoflags ^= SDL_FULLSCREEN; } else if ( isdigit(argv[argc][0]) ) { numsprites = atoi(argv[argc]); } else { fprintf(stderr, "Usage: %s [-bpp N] [-hw] [-flip] [-fast] [-fullscreen] [numsprites]\n", argv[0]); exit(1); } } /* Set video mode */ screen = SDL_SetVideoMode(width, height, video_bpp, videoflags); if ( ! screen ) { fprintf(stderr, "Couldn't set %dx%d video mode: %s\n", width, height, SDL_GetError()); exit(2); } /* Load the sprite */ if ( LoadSprite(screen, "icon.bmp") < 0 ) { exit(1); } /* Allocate memory for the sprite info */ mem = (Uint8 *)malloc(4*sizeof(SDL_Rect)*numsprites); if ( mem == NULL ) { SDL_FreeSurface(sprite); fprintf(stderr, "Out of memory!\n"); exit(2); } sprite_rects = (SDL_Rect *)mem; positions = sprite_rects; sprite_rects += numsprites; velocities = sprite_rects; sprite_rects += numsprites; sprite_w = sprite->w; sprite_h = sprite->h; srand(time(NULL)); for ( i=0; i<numsprites; ++i ) { positions[i].x = rand()%(screen->w - sprite_w); positions[i].y = rand()%(screen->h - sprite_h); positions[i].w = sprite->w; positions[i].h = sprite->h; velocities[i].x = 0; velocities[i].y = 0; while ( ! velocities[i].x && ! velocities[i].y ) { velocities[i].x = (rand()%(MAX_SPEED*2+1))-MAX_SPEED; velocities[i].y = (rand()%(MAX_SPEED*2+1))-MAX_SPEED; } } background = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00); /* Print out information about our surfaces */ printf("Screen is at %d bits per pixel\n",screen->format->BitsPerPixel); if ( (screen->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { printf("Screen is in video memory\n"); } else { printf("Screen is in system memory\n"); } if ( (screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { printf("Screen has double-buffering enabled\n"); } if ( (sprite->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { printf("Sprite is in video memory\n"); } else { printf("Sprite is in system memory\n"); } /* Run a sample blit to trigger blit acceleration */ { SDL_Rect dst; dst.x = 0; dst.y = 0; dst.w = sprite->w; dst.h = sprite->h; SDL_BlitSurface(sprite, NULL, screen, &dst); SDL_FillRect(screen, &dst, background); } if ( (sprite->flags & SDL_HWACCEL) == SDL_HWACCEL ) { printf("Sprite blit uses hardware acceleration\n"); } if ( (sprite->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { printf("Sprite blit uses RLE acceleration\n"); } /* Loop, blitting sprites and waiting for a keystroke */ frames = 0; then = SDL_GetTicks(); done = 0; sprites_visible = 0; while ( !done ) { /* Check for events */ ++frames; while ( SDL_PollEvent(&event) ) { switch (event.type) { case SDL_MOUSEBUTTONDOWN: SDL_WarpMouse(screen->w/2, screen->h/2); break; case SDL_KEYDOWN: /* Any keypress quits the app... */ case SDL_QUIT: done = 1; break; default: break; } } MoveSprites(screen, background); } SDL_FreeSurface(sprite); free(mem); /* Print out some timing information */ now = SDL_GetTicks(); if ( now > then ) { printf("%2.2f frames per second\n", ((double)frames*1000)/(now-then)); } SDL_Quit(); return(0); }