From 32c68280bfddad0727852a5fd93d23a2f156d531 Mon Sep 17 00:00:00 2001 From: pelya Date: Tue, 3 Jan 2012 17:26:17 +0200 Subject: [PATCH] Alien Blaster compiles and works with new SDL 1.3, but the alpha channel fails for SDL_Texture (is that an SDL bug?) --- build.sh | 2 +- .../alienblaster/SdlForwardCompat.h | 47 +++++++++++++++---- .../application/alienblaster/surfaceDB.cpp | 7 ++- .../jni/application/alienblaster/video.cpp | 40 +++++++++++----- project/jni/application/src | 2 +- project/jni/sdl-1.3/src/video/SDL_pixels.c | 4 +- project/jni/sdl-1.3/src/video/SDL_surface.c | 2 +- project/jni/sdl_image/IMG_png.c | 14 ++++-- 8 files changed, 86 insertions(+), 32 deletions(-) diff --git a/build.sh b/build.sh index e8fe55a6b..6b66e10fe 100755 --- a/build.sh +++ b/build.sh @@ -24,7 +24,7 @@ if uname -s | grep -i "windows" > /dev/null ; then MYARCH=windows-x86 fi -rm -f project/bin/*.apk project/bin/*.apk.d project/bin/*.ap_ project/bin/*.ap_.d # New Android SDK introduced some lame-ass optimizations to the build system which we should take care about +rm -r -f project/bin/* # New Android SDK introduced some lame-ass optimizations to the build system which we should take care about cd project && env PATH=$NDKBUILDPATH nice -n19 ndk-build V=1 -j4 && \ { grep "CustomBuildScript=y" ../AndroidAppSettings.cfg > /dev/null && \ diff --git a/project/jni/application/alienblaster/SdlForwardCompat.h b/project/jni/application/alienblaster/SdlForwardCompat.h index b0040c1d1..817ab3461 100644 --- a/project/jni/application/alienblaster/SdlForwardCompat.h +++ b/project/jni/application/alienblaster/SdlForwardCompat.h @@ -22,6 +22,8 @@ struct SdlCompat_AcceleratedSurface SDL_PixelFormat * format; }; +extern SDL_Renderer * SDL_global_renderer; + static inline SdlCompat_AcceleratedSurface * SdlCompat_CreateAcceleratedSurface(SDL_Surface * surface) { SdlCompat_AcceleratedSurface * ret = new SdlCompat_AcceleratedSurface(); @@ -34,10 +36,36 @@ static inline SdlCompat_AcceleratedSurface * SdlCompat_CreateAcceleratedSurface( *(ret->format) = *(surface->format); format = SDL_PIXELFORMAT_RGB565; + SDL_Surface * surface2 = surface; if( surface->flags & SDL_SRCCOLORKEY ) + { format = SDL_PIXELFORMAT_RGBA4444; + //surface2 = SDL_ConvertSurfaceFormat(surface, format, 0); // Does not copy alpha + int bpp; + Uint32 r,g,b,a; + SDL_PixelFormatEnumToMasks(format, &bpp, &r, &g, &b, &a); + surface2 = SDL_CreateRGBSurface(0, surface->w, surface->h, bpp, r, g, b, a); + SDL_FillRect(surface2, NULL, 0); + SDL_BlitSurface(surface, NULL, surface2, NULL); + // Fix the alpha channel, using ugly pixel access + SDL_LockSurface(surface2); + SDL_LockSurface(surface); + for(int y = 0; y < surface->h; y++) + for(int x = 0; x < surface->w; x++) + { + // Assume 24-bit or 32-bit surface + Uint8 * pixel = ((Uint8 *) surface->pixels) + y*surface->pitch + x*surface->format->BytesPerPixel; + if( pixel[0] == 255 && pixel[1] == 0 && pixel[2] == 255 ) + *(Uint16 *)(((Uint8 *) surface2->pixels) + y*surface2->pitch + x*surface2->format->BytesPerPixel) = 0; + } + SDL_UnlockSurface(surface); + SDL_UnlockSurface(surface2); + } - ret->t = SDL_CreateTextureFromSurface(format, surface); + ret->t = SDL_CreateTextureFromSurface(SDL_global_renderer, surface2); + + if(surface != surface2) + SDL_FreeSurface(surface2); if( ! ret->t ) { @@ -45,21 +73,23 @@ static inline SdlCompat_AcceleratedSurface * SdlCompat_CreateAcceleratedSurface( return ret; } + SDL_SetTextureBlendMode( ret->t, SDL_BLENDMODE_BLEND ); + //SDL_SetTextureAlphaMod( ret->t, SDL_ALPHA_OPAQUE ); + SDL_SetTextureAlphaMod( ret->t, 128 ); if( surface->flags & SDL_SRCALPHA ) { - SDL_SetTextureBlendMode( ret->t, SDL_BLENDMODE_BLEND ); Uint8 alpha = 128; if( SDL_GetSurfaceAlphaMod( surface, &alpha ) < 0 ) alpha = 128; SDL_SetTextureAlphaMod( ret->t, alpha ); } - + return ret; }; static inline int SDL_BlitSurface( SdlCompat_AcceleratedSurface * src, SDL_Rect * srcR, SdlCompat_AcceleratedSurface * unused, SDL_Rect * destR ) { - return SDL_RenderCopy(src->t, srcR, destR); + return SDL_RenderCopy(SDL_global_renderer, src->t, srcR, destR); }; static inline void SDL_FreeSurface(SdlCompat_AcceleratedSurface * surface) @@ -71,15 +101,14 @@ static inline void SDL_FreeSurface(SdlCompat_AcceleratedSurface * surface) static inline void SDL_FillRect( SdlCompat_AcceleratedSurface * unused, const SDL_Rect* rect, Uint32 color ) { - Uint8 r, g, b, a; - SDL_GetRGBA( color, SDL_GetVideoSurface()->format, &r, &g, &b, &a ); - SDL_SetRenderDrawColor(r, g, b, SDL_ALPHA_OPAQUE /* a */); - SDL_RenderFillRect(rect); + Uint8 r = color & 0xff, g = (color >> 8) & 0xff, b = (color >> 16) & 0xff; + SDL_SetRenderDrawColor(SDL_global_renderer, r, g, b, SDL_ALPHA_OPAQUE /* a */); + SDL_RenderFillRect(SDL_global_renderer, rect); }; static inline int SDL_Flip(SdlCompat_AcceleratedSurface * unused) { - SDL_RenderPresent(); + SDL_RenderPresent(SDL_global_renderer); return 0; }; diff --git a/project/jni/application/alienblaster/surfaceDB.cpp b/project/jni/application/alienblaster/surfaceDB.cpp index e2edc7095..5bd4f1158 100644 --- a/project/jni/application/alienblaster/surfaceDB.cpp +++ b/project/jni/application/alienblaster/surfaceDB.cpp @@ -100,13 +100,18 @@ SDL_Surface *SurfaceDB::loadSurfaceInternal( string fn, bool alpha ) { SDL_SetColorKey( newSurface, SDL_SRCCOLORKEY, SDL_MapRGB(newSurface->format, transR, transG, transB) ); + +#if SDL_VERSION_ATLEAST(1,3,0) + // Do not even think of calling SDL_DisplayFormat(), it will return NULL and crash your code! (and kill your cat also) +#else SDL_Surface * hwSurface = SDL_DisplayFormat(newSurface); if( hwSurface ) { SDL_FreeSurface(newSurface); newSurface = hwSurface; } - +#endif + return newSurface; } diff --git a/project/jni/application/alienblaster/video.cpp b/project/jni/application/alienblaster/video.cpp index 3e984cb6d..3e2a5014e 100644 --- a/project/jni/application/alienblaster/video.cpp +++ b/project/jni/application/alienblaster/video.cpp @@ -23,6 +23,7 @@ #include "global.h" #include "surfaceDB.h" #include +#include using namespace std; @@ -36,6 +37,8 @@ Video::~Video(){ // kill something } +SDL_Renderer * SDL_global_renderer = NULL; + SdlCompat_AcceleratedSurface *Video::init(){ // -------------------------------------------------- // SDL initialisation @@ -48,28 +51,41 @@ SdlCompat_AcceleratedSurface *Video::init(){ __android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", "Couldn't initialize SDL video subsystem: %s\n", SDL_GetError()); exit(1); } +#if SDL_VERSION_ATLEAST(1,3,0) +// SDL_VideoInit(NULL); + SDL_Window * window = SDL_CreateWindow("Alien Blaster", 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_BORDERLESS | SDL_WINDOW_SHOWN | SDL_WINDOW_INPUT_GRABBED); + if (!window) { + __android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", "SDL_CreateWindow() failed: %s", SDL_GetError()); + exit(1); + } + __android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "SDL_CreateWindow() ret %p", window); + SDL_global_renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); + if (!SDL_global_renderer) { + __android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", "SDL_CreateRenderer() ret %p", SDL_global_renderer); + exit(1); + } + __android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "SDL_CreateRenderer() ret %p", SDL_global_renderer); + // Dummy texture + __android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Creating dummy video surface"); + SDL_Surface *screen2 = IMG_Load( "images/bomber.png" ); + __android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Creating dummy video surface 2"); + screen = SdlCompat_CreateAcceleratedSurface(screen2); + screen->w = SCREEN_WIDTH; + screen->h = SCREEN_HEIGHT; + SDL_FreeSurface(screen2); + __android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "video init done"); +#else SDL_Surface * screen2 = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, BIT_DEPTH, SDL_DOUBLEBUF | SDL_HWSURFACE ); if (!screen2) { printf("Couldn't set %dx%d, %dbit video mode: %s\n", SCREEN_WIDTH, SCREEN_HEIGHT, BIT_DEPTH, SDL_GetError()); __android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", "Couldn't set %dx%d, %dbit video mode: %s\n", SCREEN_WIDTH, SCREEN_HEIGHT, BIT_DEPTH, SDL_GetError()); exit(2); } -#if SDL_VERSION_ATLEAST(1,3,0) - // Dummy texture - screen2 = SDL_CreateRGBSurface( 0, 16, 16, 16, 0xff, 0x00ff, 0x0000ff, 0 ); - SDL_Surface * screen3 = SDL_DisplayFormat( screen2 ); - SDL_FreeSurface(screen2); - screen = SdlCompat_CreateAcceleratedSurface(screen3); - screen->w = SCREEN_WIDTH; - screen->h = SCREEN_HEIGHT; - SDL_FreeSurface(screen3); -#else screen = screen2; -#endif SDL_WM_SetCaption("AlienBlaster", "AlienBlaster"); SDL_WM_SetIcon(SDL_LoadBMP( FN_ALIENBLASTER_ICON.c_str() ), NULL); SDL_ShowCursor(SDL_DISABLE); - +#endif __android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Initializing video done"); return screen; diff --git a/project/jni/application/src b/project/jni/application/src index 104f796a6..4de17cd97 120000 --- a/project/jni/application/src +++ b/project/jni/application/src @@ -1 +1 @@ -ballfield \ No newline at end of file +alienblaster \ No newline at end of file diff --git a/project/jni/sdl-1.3/src/video/SDL_pixels.c b/project/jni/sdl-1.3/src/video/SDL_pixels.c index 30af46f1c..b8b6d1e3a 100644 --- a/project/jni/sdl-1.3/src/video/SDL_pixels.c +++ b/project/jni/sdl-1.3/src/video/SDL_pixels.c @@ -231,7 +231,7 @@ SDL_PixelFormatEnumToMasks(Uint32 format, int *bpp, Uint32 * Rmask, masks[3] = 0x00000003; break; default: - SDL_SetError("Unknown pixel format"); + SDL_SetError("SDL_PixelFormatEnumToMasks: Unknown pixel format - unknown pixel layout"); return SDL_FALSE; } @@ -281,7 +281,7 @@ SDL_PixelFormatEnumToMasks(Uint32 format, int *bpp, Uint32 * Rmask, *Rmask = masks[3]; break; default: - SDL_SetError("Unknown pixel format"); + SDL_SetError("SDL_PixelFormatEnumToMasks: Unknown pixel format - unknown pixel order"); return SDL_FALSE; } return SDL_TRUE; diff --git a/project/jni/sdl-1.3/src/video/SDL_surface.c b/project/jni/sdl-1.3/src/video/SDL_surface.c index 62c5f5f3d..1ed3aeaa2 100644 --- a/project/jni/sdl-1.3/src/video/SDL_surface.c +++ b/project/jni/sdl-1.3/src/video/SDL_surface.c @@ -46,7 +46,7 @@ SDL_CreateRGBSurface(Uint32 flags, /* Get the pixel format */ format = SDL_MasksToPixelFormatEnum(depth, Rmask, Gmask, Bmask, Amask); if (format == SDL_PIXELFORMAT_UNKNOWN) { - SDL_SetError("Unknown pixel format"); + SDL_SetError("SDL_CreateRGBSurface: Unknown pixel format: depth %d masks 0x%x 0x%x 0x%x 0x%x", depth, Rmask, Gmask, Bmask, Amask); return NULL; } diff --git a/project/jni/sdl_image/IMG_png.c b/project/jni/sdl_image/IMG_png.c index 99d5b5718..6fe9355c3 100644 --- a/project/jni/sdl_image/IMG_png.c +++ b/project/jni/sdl_image/IMG_png.c @@ -340,7 +340,7 @@ SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src) png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; - int bit_depth, color_type, interlace_type; + int bit_depth, color_type, interlace_type, num_channels; Uint32 Rmask; Uint32 Gmask; Uint32 Bmask; @@ -452,15 +452,19 @@ SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src) &color_type, &interlace_type, NULL, NULL); /* Allocate the SDL surface to hold the image */ - Rmask = Gmask = Bmask = Amask = 0 ; + Rmask = Gmask = Bmask = Amask = 0 ; + num_channels = lib.png_get_channels(png_ptr, info_ptr); + /* Some .png files are monochrome, with as much as 1 channel and 1 bit per pixel */ + if( num_channels != 3 && num_channels != 4 ) + num_channels = 3; if ( color_type != PNG_COLOR_TYPE_PALETTE ) { if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) { Rmask = 0x000000FF; Gmask = 0x0000FF00; Bmask = 0x00FF0000; - Amask = (lib.png_get_channels(png_ptr, info_ptr) == 4) ? 0xFF000000 : 0; + Amask = (num_channels == 4) ? 0xFF000000 : 0; } else { - int s = (lib.png_get_channels(png_ptr, info_ptr) == 4) ? 0 : 8; + int s = (num_channels == 4) ? 0 : 8; Rmask = 0xFF000000 >> s; Gmask = 0x00FF0000 >> s; Bmask = 0x0000FF00 >> s; @@ -468,7 +472,7 @@ SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src) } } surface = SDL_AllocSurface(SDL_SWSURFACE, width, height, - bit_depth*lib.png_get_channels(png_ptr, info_ptr), Rmask,Gmask,Bmask,Amask); + bit_depth*num_channels, Rmask,Gmask,Bmask,Amask); if ( surface == NULL ) { error = "Out of memory"; goto done;