Mercurial > sdl-ios-xcode
view test/testalpha.c @ 3487:24d13328c44a
Eric Wing to Sam, hfutrell
This one is quite puzzling. I found a partial workaround, but I don't fully understand the reasons yet.
First, the console is complaining about not finding a nib for MainWindow.
I tried removing the entry for this in the info.plist, and the message went away, but it didn't really change anything.
Second, I stepped through this with the debugger and broke up some lines. It seems that the basic act of calling
view = [SDL_uikitopenglview alloc];
or even
view = [SDL_uikitview alloc]
will crash the program. The debugger messages plus the stack trace make me think it's not finding the SDL_uikitview classes for some reason. But I don't understand why this would be.
view = [UIView alloc] will not crash the program.
For kicks, I added a new definition of a class called SDL_object which subclasses NSObject in the same files as SDL_uikitopenglview and then call
view = [SDL_object alloc];
This does not crash the program.
So, then I modified SDL_object to subclass UIView. No crash.
Next, I made SDL_object subclass UIView<UITextFieldDelegate> . This crashes.
So it is the act of conforming to the UITextFieldDelegate protocol that is crashing things.
I don't understand why it would crash on alloc though. I'm guessing either a delegate needs to be set somewhere or one of the required methods needs to be implemented. But in the former case, I would not expect a crash, but a silent message to nil and something else doesn't work. And in the latter case, I would expect a compiler warning and an exception thrown instead of a crash.
Anyway, my temporary workaround is to change the interface declaration for SDL_uikitview to look like:
#if SDL_IPHONE_KEYBOARD
@interface SDL_uikitview : UIView<UITextFieldDelegate> {
#else
@interface SDL_uikitview : UIView {
#endif
And then disable the keyboard support in the SDL_config_iphoneos.h file.
/* enable iPhone keyboard support */
#define SDL_IPHONE_KEYBOARD 0
-Eric
On Nov 23, 2009, at 1:43 AM, Sam Lantinga wrote:
> I ran into a blocking startup crash with the Happy demo on iPhone OS 3.1.2 on my new iPhone:
>
> #0 0x323fea14 in _class_isInitialized
> #1 0x323fea68 in _class_initialize
> #2 0x32403e92 in prepareForMethodLookup
> #3 0x32401244 in lookUpMethod
> #4 0x323fea10 in _class_lookupMethodAndLoadCache
> #5 0x323fe746 in objc_msgSend_uncached
> #6 0x323feb26 in _class_initialize
> #7 0x323fea58 in _class_initialize
> #8 0x32403e92 in prepareForMethodLookup
> #9 0x32401244 in lookUpMethod
> #10 0x323fea10 in _class_lookupMethodAndLoadCache
> #11 0x323fe746 in objc_msgSend_uncached
> #12 0x000554dc in UIKit_GL_CreateContext at SDL_uikitopengles.m:103
> #13 0x0004f89e in SDL_GL_CreateContext at SDL_video.c:3155
> #14 0x000579e8 in GLES_CreateRenderer at SDL_renderer_gles.c:282
> #15 0x0004d7b8 in SDL_CreateRenderer at SDL_video.c:1509
> #16 0x00002bc2 in SDL_main at happy.c:156
> #17 0x000571b2 in -[SDLUIKitDelegate postFinishLaunch] at
> SDL_uikitappdelegate.m:77
> #18 0x313f9ef2 in __NSFireDelayedPerform
> #19 0x32567bb2 in CFRunLoopRunSpecific
> #20 0x3256735c in CFRunLoopRunInMode
> #21 0x32912cbe in GSEventRunModal
> #22 0x32912d6a in GSEventRun
> #23 0x32b6276e in -[UIApplication _run]
> #24 0x32b61472 in UIApplicationMain
> #25 0x00057088 in main at SDL_uikitappdelegate.m:50
>
> Any ideas?
>
> See ya!
> --
> -Sam Lantinga, Founder and President, Galaxy Gameworks LLC
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Tue, 24 Nov 2009 08:12:32 +0000 |
parents | cf271ff76061 |
children | f8816ffa210b |
line wrap: on
line source
/* Simple program: Fill a colormap with gray and stripe it down the screen, Then move an alpha valued sprite around the screen. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include "SDL.h" #define FRAME_TICKS (1000/30) /* 30 frames/second */ /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ static void quit(int rc) { SDL_Quit(); exit(rc); } /* Fill the screen with a gradient */ static void FillBackground(SDL_Surface * screen) { Uint8 *buffer; Uint8 gradient; int i, k; /* Set the surface pixels and refresh! */ if (SDL_LockSurface(screen) < 0) { fprintf(stderr, "Couldn't lock the display surface: %s\n", SDL_GetError()); quit(2); } buffer = (Uint8 *) screen->pixels; switch (screen->format->BytesPerPixel) { case 1: case 3: for (i = 0; i < screen->h; ++i) { memset(buffer, (i * 255) / screen->h, screen->w * screen->format->BytesPerPixel); buffer += screen->pitch; } break; case 2: for (i = 0; i < screen->h; ++i) { Uint16 *buffer16; Uint16 color; gradient = ((i * 255) / screen->h); color = (Uint16) SDL_MapRGB(screen->format, gradient, gradient, gradient); buffer16 = (Uint16 *) buffer; for (k = 0; k < screen->w; k++) { *buffer16++ = color; } buffer += screen->pitch; } break; case 4: for (i = 0; i < screen->h; ++i) { Uint32 *buffer32; Uint32 color; gradient = ((i * 255) / screen->h); color = SDL_MapRGB(screen->format, gradient, gradient, gradient); buffer32 = (Uint32 *) buffer; for (k = 0; k < screen->w; k++) { *buffer32++ = color; } buffer += screen->pitch; } break; } SDL_UnlockSurface(screen); SDL_UpdateRect(screen, 0, 0, 0, 0); } /* Create a "light" -- a yellowish surface with variable alpha */ SDL_Surface * CreateLight(int radius) { Uint8 trans, alphamask; int range, addition; int xdist, ydist; Uint16 x, y; Uint16 skip; Uint32 pixel; SDL_Surface *light; #ifdef LIGHT_16BIT Uint16 *buf; /* Create a 16 (4/4/4/4) bpp square with a full 4-bit alpha channel */ /* Note: this isn't any faster than a 32 bit alpha surface */ alphamask = 0x0000000F; light = SDL_CreateRGBSurface(SDL_SWSURFACE, 2 * radius, 2 * radius, 16, 0x0000F000, 0x00000F00, 0x000000F0, alphamask); #else Uint32 *buf; /* Create a 32 (8/8/8/8) bpp square with a full 8-bit alpha channel */ alphamask = 0x000000FF; light = SDL_CreateRGBSurface(SDL_SWSURFACE, 2 * radius, 2 * radius, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, alphamask); if (light == NULL) { fprintf(stderr, "Couldn't create light: %s\n", SDL_GetError()); return (NULL); } #endif /* Fill with a light yellow-orange color */ skip = light->pitch - (light->w * light->format->BytesPerPixel); #ifdef LIGHT_16BIT buf = (Uint16 *) light->pixels; #else buf = (Uint32 *) light->pixels; #endif /* Get a tranparent pixel value - we'll add alpha later */ pixel = SDL_MapRGBA(light->format, 0xFF, 0xDD, 0x88, 0); for (y = 0; y < light->h; ++y) { for (x = 0; x < light->w; ++x) { *buf++ = pixel; } buf += skip; /* Almost always 0, but just in case... */ } /* Calculate alpha values for the surface. */ #ifdef LIGHT_16BIT buf = (Uint16 *) light->pixels; #else buf = (Uint32 *) light->pixels; #endif for (y = 0; y < light->h; ++y) { for (x = 0; x < light->w; ++x) { /* Slow distance formula (from center of light) */ xdist = x - (light->w / 2); ydist = y - (light->h / 2); range = (int) sqrt(xdist * xdist + ydist * ydist); /* Scale distance to range of transparency (0-255) */ if (range > radius) { trans = alphamask; } else { /* Increasing transparency with distance */ trans = (Uint8) ((range * alphamask) / radius); /* Lights are very transparent */ addition = (alphamask + 1) / 8; if ((int) trans + addition > alphamask) { trans = alphamask; } else { trans += addition; } } /* We set the alpha component as the right N bits */ *buf++ |= (255 - trans); } buf += skip; /* Almost always 0, but just in case... */ } /* Enable RLE acceleration of this alpha surface */ SDL_SetAlpha(light, SDL_SRCALPHA | SDL_RLEACCEL, 0); /* We're done! */ return (light); } static Uint32 flashes = 0; static Uint32 flashtime = 0; void FlashLight(SDL_Surface * screen, SDL_Surface * light, int x, int y) { SDL_Rect position; Uint32 ticks1; Uint32 ticks2; /* Easy, center light */ position.x = x - (light->w / 2); position.y = y - (light->h / 2); position.w = light->w; position.h = light->h; ticks1 = SDL_GetTicks(); SDL_BlitSurface(light, NULL, screen, &position); ticks2 = SDL_GetTicks(); SDL_UpdateRects(screen, 1, &position); ++flashes; /* Update time spend doing alpha blitting */ flashtime += (ticks2 - ticks1); } static int sprite_visible = 0; static SDL_Surface *sprite; static SDL_Surface *backing; static SDL_Rect position; static int x_vel, y_vel; static int alpha_vel; int LoadSprite(SDL_Surface * screen, char *file) { SDL_Surface *converted; /* 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, *(Uint8 *) sprite->pixels); } /* Convert sprite to video format */ converted = SDL_DisplayFormat(sprite); SDL_FreeSurface(sprite); if (converted == NULL) { fprintf(stderr, "Couldn't convert background: %s\n", SDL_GetError()); return (-1); } sprite = converted; /* Create the background */ backing = SDL_CreateRGBSurface(SDL_SWSURFACE, sprite->w, sprite->h, 8, 0, 0, 0, 0); if (backing == NULL) { fprintf(stderr, "Couldn't create background: %s\n", SDL_GetError()); SDL_FreeSurface(sprite); return (-1); } /* Convert background to video format */ converted = SDL_DisplayFormat(backing); SDL_FreeSurface(backing); if (converted == NULL) { fprintf(stderr, "Couldn't convert background: %s\n", SDL_GetError()); SDL_FreeSurface(sprite); return (-1); } backing = converted; /* Set the initial position of the sprite */ position.x = (screen->w - sprite->w) / 2; position.y = (screen->h - sprite->h) / 2; position.w = sprite->w; position.h = sprite->h; x_vel = 0; y_vel = 0; alpha_vel = 1; /* We're ready to roll. :) */ return (0); } void AttractSprite(Uint16 x, Uint16 y) { x_vel = ((int) x - position.x) / 10; y_vel = ((int) y - position.y) / 10; } void MoveSprite(SDL_Surface * screen, SDL_Surface * light) { SDL_Rect updates[2]; Uint8 alpha; /* Erase the sprite if it was visible */ if (sprite_visible) { updates[0] = position; SDL_BlitSurface(backing, NULL, screen, &updates[0]); } else { updates[0].x = 0; updates[0].y = 0; updates[0].w = 0; updates[0].h = 0; sprite_visible = 1; } /* Since the sprite is off the screen, we can do other drawing without being overwritten by the saved area behind the sprite. */ if (light != NULL) { int x, y; SDL_GetMouseState(0, &x, &y); FlashLight(screen, light, x, y); } /* Move the sprite, bounce at the wall */ position.x += x_vel; if ((position.x < 0) || (position.x >= screen->w)) { x_vel = -x_vel; position.x += x_vel; } position.y += y_vel; if ((position.y < 0) || (position.y >= screen->h)) { y_vel = -y_vel; position.y += y_vel; } /* Update transparency (fade in and out) */ SDL_GetSurfaceAlphaMod(sprite, &alpha); if (((int) alpha + alpha_vel) < 0) { alpha_vel = -alpha_vel; } else if (((int) alpha + alpha_vel) > 255) { alpha_vel = -alpha_vel; } SDL_SetAlpha(sprite, SDL_SRCALPHA, (Uint8) (alpha + alpha_vel)); /* Save the area behind the sprite */ updates[1] = position; SDL_BlitSurface(screen, &updates[1], backing, NULL); /* Blit the sprite onto the screen */ updates[1] = position; SDL_BlitSurface(sprite, NULL, screen, &updates[1]); /* Make it so! */ SDL_UpdateRects(screen, 2, updates); } int main(int argc, char *argv[]) { const SDL_VideoInfo *info; SDL_Surface *screen; int w, h; Uint8 video_bpp; Uint32 videoflags; int i, done; SDL_Event event; SDL_Surface *light; int mouse_pressed; Uint32 ticks, lastticks; /* Initialize SDL */ if (SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); return (1); } /* Alpha blending doesn't work well at 8-bit color */ #ifdef _WIN32_WCE /* Pocket PC */ w = 240; h = 320; #else w = 640; h = 480; #endif info = SDL_GetVideoInfo(); if (info->vfmt->BitsPerPixel > 8) { video_bpp = info->vfmt->BitsPerPixel; } else { video_bpp = 16; fprintf(stderr, "forced 16 bpp mode\n"); } videoflags = SDL_SWSURFACE; for (i = 1; argv[i]; ++i) { if (strcmp(argv[i], "-bpp") == 0) { video_bpp = atoi(argv[++i]); if (video_bpp <= 8) { video_bpp = 16; fprintf(stderr, "forced 16 bpp mode\n"); } } else if (strcmp(argv[i], "-hw") == 0) { videoflags |= SDL_HWSURFACE; } else if (strcmp(argv[i], "-warp") == 0) { videoflags |= SDL_HWPALETTE; } else if (strcmp(argv[i], "-width") == 0 && argv[i + 1]) { w = atoi(argv[++i]); } else if (strcmp(argv[i], "-height") == 0 && argv[i + 1]) { h = atoi(argv[++i]); } else if (strcmp(argv[i], "-resize") == 0) { videoflags |= SDL_RESIZABLE; } else if (strcmp(argv[i], "-noframe") == 0) { videoflags |= SDL_NOFRAME; } else if (strcmp(argv[i], "-fullscreen") == 0) { videoflags |= SDL_FULLSCREEN; } else { fprintf(stderr, "Usage: %s [-width N] [-height N] [-bpp N] [-warp] [-hw] [-fullscreen]\n", argv[0]); quit(1); } } /* Set video mode */ if ((screen = SDL_SetVideoMode(w, h, video_bpp, videoflags)) == NULL) { fprintf(stderr, "Couldn't set %dx%dx%d video mode: %s\n", w, h, video_bpp, SDL_GetError()); quit(2); } FillBackground(screen); /* Create the light */ light = CreateLight(82); if (light == NULL) { quit(1); } /* Load the sprite */ if (LoadSprite(screen, "icon.bmp") < 0) { SDL_FreeSurface(light); quit(1); } /* 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 */ MoveSprite(screen, NULL); if ((sprite->flags & SDL_HWACCEL) == SDL_HWACCEL) { printf("Sprite blit uses hardware alpha acceleration\n"); } else { printf("Sprite blit dosn't uses hardware alpha acceleration\n"); } /* Set a clipping rectangle to clip the outside edge of the screen */ { SDL_Rect clip; clip.x = 32; clip.y = 32; clip.w = screen->w - (2 * 32); clip.h = screen->h - (2 * 32); SDL_SetClipRect(screen, &clip); } /* Wait for a keystroke */ lastticks = SDL_GetTicks(); done = 0; mouse_pressed = 0; while (!done) { /* Update the frame -- move the sprite */ if (mouse_pressed) { MoveSprite(screen, light); mouse_pressed = 0; } else { MoveSprite(screen, NULL); } /* Slow down the loop to 30 frames/second */ ticks = SDL_GetTicks(); if ((ticks - lastticks) < FRAME_TICKS) { #ifdef CHECK_SLEEP_GRANULARITY fprintf(stderr, "Sleeping %d ticks\n", FRAME_TICKS - (ticks - lastticks)); #endif SDL_Delay(FRAME_TICKS - (ticks - lastticks)); #ifdef CHECK_SLEEP_GRANULARITY fprintf(stderr, "Slept %d ticks\n", (SDL_GetTicks() - ticks)); #endif } lastticks = ticks; /* Check for events */ while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_VIDEORESIZE: screen = SDL_SetVideoMode(event.resize.w, event.resize.h, video_bpp, videoflags); if (screen) { FillBackground(screen); } break; /* Attract sprite while mouse is held down */ case SDL_MOUSEMOTION: if (event.motion.state != 0) { AttractSprite(event.motion.x, event.motion.y); mouse_pressed = 1; } break; case SDL_MOUSEBUTTONDOWN: if (event.button.button == 1) { AttractSprite(event.button.x, event.button.y); mouse_pressed = 1; } else { SDL_Rect area; area.x = event.button.x - 16; area.y = event.button.y - 16; area.w = 32; area.h = 32; SDL_FillRect(screen, &area, SDL_MapRGB(screen->format, 0, 0, 0)); SDL_UpdateRects(screen, 1, &area); } break; case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_ESCAPE) { done = 1; } break; case SDL_QUIT: done = 1; break; default: break; } } } SDL_FreeSurface(light); SDL_FreeSurface(sprite); SDL_FreeSurface(backing); /* Print out some timing information */ if (flashes > 0) { printf("%d alpha blits, ~%4.4f ms per blit\n", flashes, (float) flashtime / flashes); } SDL_Quit(); return (0); }