| @@ -24,7 +24,12 @@ liblol_a_SOURCES = \ | |||
| \ | |||
| shader/shader.cpp shader/shader.h \ | |||
| \ | |||
| image/image.cpp image/image.h \ | |||
| image/image.cpp image/image.h image/image-private.h \ | |||
| image/codec/android-image.cpp \ | |||
| image/codec/ios-image.cpp \ | |||
| image/codec/sdl-image.cpp \ | |||
| image/codec/ps3-image.cpp \ | |||
| image/codec/dummy-image.cpp \ | |||
| \ | |||
| loldebug.h \ | |||
| debug/fps.cpp debug/fps.h debug/sphere.cpp debug/sphere.h \ | |||
| @@ -0,0 +1,136 @@ | |||
| // | |||
| // Lol Engine | |||
| // | |||
| // Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net> | |||
| // This program is free software; you can redistribute it and/or | |||
| // modify it under the terms of the Do What The Fuck You Want To | |||
| // Public License, Version 2, as published by Sam Hocevar. See | |||
| // http://sam.zoy.org/projects/COPYING.WTFPL for more details. | |||
| // | |||
| #if defined HAVE_CONFIG_H | |||
| # include "config.h" | |||
| #endif | |||
| #if defined __ANDROID__ | |||
| #include <cmath> | |||
| #include <jni.h> | |||
| #include <android/log.h> | |||
| #include "core.h" | |||
| #include "image-private.h" | |||
| using namespace std; | |||
| namespace lol | |||
| { | |||
| extern JavaVM *g_vm; | |||
| extern jobject g_activity; | |||
| /* | |||
| * Image implementation class | |||
| */ | |||
| DECLARE_IMAGE_LOADER(AndroidImageData, 100) | |||
| { | |||
| public: | |||
| virtual bool Open(char const *); | |||
| virtual bool Close(); | |||
| virtual void *GetData() const; | |||
| private: | |||
| jobject bmp; | |||
| jintArray array; | |||
| jint *pixels; | |||
| }; | |||
| bool AndroidImageData::Open(char const *path) | |||
| { | |||
| JNIEnv *env; | |||
| jint res = g_vm->GetEnv((void **)&env, JNI_VERSION_1_2); | |||
| if (res < 0) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not get JVM environment\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| jclass cls = env->GetObjectClass(g_activity); | |||
| jmethodID mid; | |||
| mid = env->GetMethodID(cls, "openImage", | |||
| "(Ljava/lang/String;)Landroid/graphics/Bitmap;"); | |||
| jstring name = env->NewStringUTF(path); | |||
| bmp = env->CallObjectMethod(g_activity, mid, name); | |||
| env->DeleteLocalRef(name); | |||
| if (!bmp) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not load %s\n", path); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| env->NewGlobalRef(bmp); | |||
| /* Get image dimensions */ | |||
| mid = env->GetMethodID(cls, "getWidth", "(Landroid/graphics/Bitmap;)I"); | |||
| size.x = env->CallIntMethod(g_activity, mid, bmp); | |||
| mid = env->GetMethodID(cls, "getHeight", "(Landroid/graphics/Bitmap;)I"); | |||
| size.y = env->CallIntMethod(g_activity, mid, bmp); | |||
| /* Get pixels */ | |||
| array = env->NewIntArray(size.x * size.y); | |||
| env->NewGlobalRef(array); | |||
| mid = env->GetMethodID(cls, "getPixels", "(Landroid/graphics/Bitmap;[I)V"); | |||
| env->CallVoidMethod(g_activity, mid, bmp, array); | |||
| pixels = env->GetIntArrayElements(array, 0); | |||
| for (int n = 0; n < size.x * size.y; n++) | |||
| { | |||
| uint32_t u = pixels[n]; | |||
| u = (u & 0xff00ff00) | ((u & 0xff0000) >> 16) | ((u & 0xff) << 16); | |||
| pixels[n] = u; | |||
| } | |||
| format = FORMAT_RGBA; | |||
| return true; | |||
| } | |||
| bool AndroidImageData::Close() | |||
| { | |||
| JNIEnv *env; | |||
| jint res = g_vm->GetEnv((void **)&env, JNI_VERSION_1_2); | |||
| if (res < 0) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not get JVM environment\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| jclass cls = env->GetObjectClass(g_activity); | |||
| jmethodID mid; | |||
| env->ReleaseIntArrayElements(array, pixels, 0); | |||
| env->DeleteGlobalRef(array); | |||
| /* Free image */ | |||
| mid = env->GetMethodID(cls, "closeImage", "(Landroid/graphics/Bitmap;)V"); | |||
| env->CallVoidMethod(g_activity, mid, bmp); | |||
| env->DeleteGlobalRef(bmp); | |||
| return true; | |||
| } | |||
| void * AndroidImageData::GetData() const | |||
| { | |||
| return pixels; | |||
| } | |||
| } /* namespace lol */ | |||
| #endif /* __ANDROID__ */ | |||
| @@ -0,0 +1,76 @@ | |||
| // | |||
| // Lol Engine | |||
| // | |||
| // Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net> | |||
| // This program is free software; you can redistribute it and/or | |||
| // modify it under the terms of the Do What The Fuck You Want To | |||
| // Public License, Version 2, as published by Sam Hocevar. See | |||
| // http://sam.zoy.org/projects/COPYING.WTFPL for more details. | |||
| // | |||
| #if defined HAVE_CONFIG_H | |||
| # include "config.h" | |||
| #endif | |||
| #include <cmath> | |||
| #include "core.h" | |||
| #include "image/image-private.h" | |||
| using namespace std; | |||
| namespace lol | |||
| { | |||
| /* | |||
| * Image implementation class | |||
| */ | |||
| DECLARE_IMAGE_LOADER(DummyImageData, 0) | |||
| { | |||
| public: | |||
| virtual bool Open(char const *); | |||
| virtual bool Close(); | |||
| virtual void *GetData() const; | |||
| private: | |||
| uint8_t *pixels; | |||
| }; | |||
| /* | |||
| * Public Image class | |||
| */ | |||
| bool DummyImageData::Open(char const *path) | |||
| { | |||
| size = 256; | |||
| format = Image::FORMAT_RGBA; | |||
| pixels = (uint8_t *)malloc(256 * 256 * 4 * sizeof(*pixels)); | |||
| uint8_t *parser = pixels; | |||
| for (int j = 0; j < 256; j++) | |||
| for (int i = 0; i < 256; i++) | |||
| { | |||
| *parser++ = ((i ^ j) & 1) * 0xff; | |||
| *parser++ = (uint8_t)i; | |||
| *parser++ = (uint8_t)j; | |||
| *parser++ = (((i >> 4) ^ (j >> 4)) & 1) * 0xff; | |||
| } | |||
| return true; | |||
| } | |||
| bool DummyImageData::Close() | |||
| { | |||
| free(pixels); | |||
| return true; | |||
| } | |||
| void * DummyImageData::GetData() const | |||
| { | |||
| return pixels; | |||
| } | |||
| } /* namespace lol */ | |||
| @@ -0,0 +1,101 @@ | |||
| // | |||
| // Lol Engine | |||
| // | |||
| // Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net> | |||
| // This program is free software; you can redistribute it and/or | |||
| // modify it under the terms of the Do What The Fuck You Want To | |||
| // Public License, Version 2, as published by Sam Hocevar. See | |||
| // http://sam.zoy.org/projects/COPYING.WTFPL for more details. | |||
| // | |||
| #if defined HAVE_CONFIG_H | |||
| # include "config.h" | |||
| #endif | |||
| #if defined __APPLE__ && defined __MACH__ | |||
| #include <cmath> | |||
| #import <UIKit/UIKit.h> | |||
| #include "core.h" | |||
| using namespace std; | |||
| namespace lol | |||
| { | |||
| /* | |||
| * Image implementation class | |||
| */ | |||
| DECLARE_IMAGE_LOADER(IosImageData, 100) | |||
| { | |||
| public: | |||
| virtual bool Open(char const *); | |||
| virtual bool Close(); | |||
| virtual void *GetData() const; | |||
| private: | |||
| uint8_t *pixels; | |||
| }; | |||
| /* | |||
| * Public Image class | |||
| */ | |||
| bool IosImageData::Open(char const *path) | |||
| { | |||
| NSString *fullpath = [NSString stringWithUTF8String:path]; | |||
| NSArray *chunks = [fullpath componentsSeparatedByString: @"/"]; | |||
| NSString *filename = [chunks objectAtIndex: [chunks count] - 1]; | |||
| chunks = [filename componentsSeparatedByString: @"."]; | |||
| NSString *prefix = [chunks objectAtIndex: 0]; | |||
| NSString *mypath = [[NSBundle mainBundle] pathForResource:prefix ofType:@"png"]; | |||
| NSData *pngdata = [[NSData alloc] initWithContentsOfFile:mypath]; | |||
| UIImage *image = [[UIImage alloc] initWithData:pngdata]; | |||
| if (!image) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not load %s\n", path); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| int w = CGImageGetWidth(image.CGImage); | |||
| int h = CGImageGetHeight(image.CGImage); | |||
| size = ivec2(w, h); | |||
| format = FORMAT_RGBA; | |||
| CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB(); | |||
| pixels = (uint8_t *)malloc(w * h * 4); | |||
| CGContextRef ctx = | |||
| CGBitmapContextCreate(pixels, w, h, 8, 4 * w, cspace, | |||
| kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); | |||
| CGColorSpaceRelease(cspace); | |||
| CGContextClearRect(ctx, CGRectMake(0, 0, w, h)); | |||
| CGContextTranslateCTM(ctx, 0, h - h); | |||
| CGContextDrawImage(ctx, CGRectMake(0, 0, w, h), image.CGImage); | |||
| CGContextRelease(ctx); | |||
| [image release]; | |||
| [pngdata release]; | |||
| return true; | |||
| } | |||
| bool IosImageData::Close() | |||
| { | |||
| free(pixels); | |||
| return true; | |||
| } | |||
| void * IosImageData::GetData() const | |||
| { | |||
| return pixels; | |||
| } | |||
| } /* namespace lol */ | |||
| #endif /* defined __APPLE__ && defined __MACH__ */ | |||
| @@ -0,0 +1,203 @@ | |||
| // | |||
| // Lol Engine | |||
| // | |||
| // Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net> | |||
| // This program is free software; you can redistribute it and/or | |||
| // modify it under the terms of the Do What The Fuck You Want To | |||
| // Public License, Version 2, as published by Sam Hocevar. See | |||
| // http://sam.zoy.org/projects/COPYING.WTFPL for more details. | |||
| // | |||
| #if defined HAVE_CONFIG_H | |||
| # include "config.h" | |||
| #endif | |||
| #if defined __CELLOS_LV2__ | |||
| #include <cmath> | |||
| #include <cell/sysmodule.h> | |||
| #include <cell/codec/pngdec.h> | |||
| #include "core.h" | |||
| using namespace std; | |||
| namespace lol | |||
| { | |||
| /* | |||
| * Image implementation class | |||
| */ | |||
| DECLARE_IMAGE_LOADER(Ps3ImageData, 100) | |||
| { | |||
| public: | |||
| virtual bool Open(char const *); | |||
| virtual bool Close(); | |||
| virtual void *GetData() const; | |||
| private: | |||
| static void* Malloc(uint32_t size, void* data) { return malloc(size); }; | |||
| static int32_t Free(void* ptr, void* data) { free(ptr); return 0; }; | |||
| uint8_t *pixels; | |||
| }; | |||
| /* | |||
| * Public Image class | |||
| */ | |||
| bool Ps3ImageData::Open(char const *path) | |||
| { | |||
| int32_t err; | |||
| /* Initialise decoding library */ | |||
| CellPngDecMainHandle hmain; | |||
| err = cellSysmoduleLoadModule(CELL_SYSMODULE_FS); | |||
| if (err != CELL_OK) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not open Fs sysmodule\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| err = cellSysmoduleLoadModule(CELL_SYSMODULE_PNGDEC); | |||
| if (err != CELL_OK) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not open PngDec sysmodule\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| CellPngDecThreadInParam in_param; | |||
| in_param.spuThreadEnable = CELL_PNGDEC_SPU_THREAD_ENABLE; | |||
| in_param.ppuThreadPriority = 1000; | |||
| in_param.spuThreadPriority = 200; | |||
| in_param.cbCtrlMallocFunc = ImageData::Malloc; | |||
| in_param.cbCtrlMallocArg = NULL; | |||
| in_param.cbCtrlFreeFunc = ImageData::Free; | |||
| in_param.cbCtrlFreeArg = NULL; | |||
| CellPngDecThreadOutParam out_param; | |||
| err = cellPngDecCreate(&hmain, &in_param, &out_param); | |||
| if (err != CELL_OK) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not create PngDec library\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| /* Create decoder */ | |||
| CellPngDecSubHandle hsub; | |||
| char file[1024]; | |||
| sprintf(file, "/app_home/c:/Users/s.hocevar/lolengine/%s", path); | |||
| CellPngDecSrc dec_src; | |||
| dec_src.srcSelect = CELL_PNGDEC_FILE; | |||
| dec_src.fileName = file; | |||
| dec_src.fileOffset = 0; | |||
| dec_src.fileSize = 0; | |||
| dec_src.streamPtr = NULL; | |||
| dec_src.streamSize = 0; | |||
| dec_src.spuThreadEnable = CELL_PNGDEC_SPU_THREAD_ENABLE; | |||
| CellPngDecOpnInfo open_info; | |||
| err = cellPngDecOpen(hmain, &hsub, &dec_src, &open_info); | |||
| if (err != CELL_OK) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not open %s for decoding\n", file); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| CellPngDecInfo info; | |||
| err = cellPngDecReadHeader(hmain, hsub, &info); | |||
| if (err != CELL_OK) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not read image header\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| CellPngDecInParam in_dec_param; | |||
| in_dec_param.commandPtr = NULL; | |||
| in_dec_param.outputMode = CELL_PNGDEC_TOP_TO_BOTTOM; | |||
| in_dec_param.outputColorSpace = CELL_PNGDEC_RGBA; | |||
| in_dec_param.outputBitDepth = 8; | |||
| in_dec_param.outputPackFlag = CELL_PNGDEC_1BYTE_PER_1PIXEL; | |||
| in_dec_param.outputAlphaSelect = CELL_PNGDEC_STREAM_ALPHA; | |||
| in_dec_param.outputColorAlpha = 0xff; | |||
| CellPngDecOutParam out_dec_param; | |||
| err = cellPngDecSetParameter(hmain, hsub, &in_dec_param, &out_dec_param); | |||
| if (err != CELL_OK) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not configure PngDec decoder\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| /* Decode image */ | |||
| size = ivec2(info.imageWidth, info.imageHeight); | |||
| format = FORMAT_RGBA; | |||
| pixels = (uint8_t *)malloc(info.imageWidth * 4 * info.imageHeight); | |||
| CellPngDecDataCtrlParam data_ctrl_param; | |||
| data_ctrl_param.outputBytesPerLine = info.imageWidth * 4; | |||
| CellPngDecDataOutInfo data_out_info; | |||
| err = cellPngDecDecodeData(hmain, hsub, pixels, | |||
| &data_ctrl_param, &data_out_info); | |||
| if (err != CELL_OK) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not run PngDec decoder\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| /* Close decoder */ | |||
| err = cellPngDecClose(hmain, hsub); | |||
| if (err != CELL_OK) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not close PngDec decoder\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| /* Deinitialise library */ | |||
| err = cellPngDecDestroy(hmain); | |||
| if (err != CELL_OK) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not destroy PngDec decoder\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| err = cellSysmoduleUnloadModule(CELL_SYSMODULE_PNGDEC); | |||
| err = cellSysmoduleUnloadModule(CELL_SYSMODULE_FS); | |||
| return true; | |||
| } | |||
| bool Ps3ImageData::Close() | |||
| { | |||
| free(pixels); | |||
| return true; | |||
| } | |||
| void * Ps3ImageData::GetData() const | |||
| { | |||
| return pixels; | |||
| } | |||
| } /* namespace lol */ | |||
| #endif /* defined __CELLOS_LV2__ */ | |||
| @@ -0,0 +1,86 @@ | |||
| // | |||
| // Lol Engine | |||
| // | |||
| // Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net> | |||
| // This program is free software; you can redistribute it and/or | |||
| // modify it under the terms of the Do What The Fuck You Want To | |||
| // Public License, Version 2, as published by Sam Hocevar. See | |||
| // http://sam.zoy.org/projects/COPYING.WTFPL for more details. | |||
| // | |||
| #if defined HAVE_CONFIG_H | |||
| # include "config.h" | |||
| #endif | |||
| #if defined USE_SDL_IMAGE | |||
| #include <cmath> | |||
| #include <SDL.h> | |||
| #include <SDL_image.h> | |||
| #include "core.h" | |||
| #include "image/image-private.h" | |||
| using namespace std; | |||
| namespace lol | |||
| { | |||
| /* | |||
| * Image implementation class | |||
| */ | |||
| DECLARE_IMAGE_LOADER(SdlImageData, 50) | |||
| { | |||
| public: | |||
| virtual bool Open(char const *); | |||
| virtual bool Close(); | |||
| virtual void *GetData() const; | |||
| private: | |||
| SDL_Surface *img; | |||
| }; | |||
| /* | |||
| * Public Image class | |||
| */ | |||
| bool SdlImageData::Open(char const *path) | |||
| { | |||
| for (char const *name = path; *name; name++) | |||
| if ((img = IMG_Load(name))) | |||
| break; | |||
| if (!img) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not load %s\n", path); | |||
| #endif | |||
| SDL_Quit(); | |||
| exit(1); | |||
| } | |||
| size = ivec2(img->w, img->h); | |||
| format = img->format->Amask ? Image::FORMAT_RGBA : Image::FORMAT_RGB; | |||
| return true; | |||
| } | |||
| bool SdlImageData::Close() | |||
| { | |||
| SDL_FreeSurface(img); | |||
| return true; | |||
| } | |||
| void * SdlImageData::GetData() const | |||
| { | |||
| return img->pixels; | |||
| } | |||
| } /* namespace lol */ | |||
| #endif /* defined USE_SDL_IMAGE */ | |||
| @@ -0,0 +1,127 @@ | |||
| // | |||
| // Lol Engine | |||
| // | |||
| // Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net> | |||
| // This program is free software; you can redistribute it and/or | |||
| // modify it under the terms of the Do What The Fuck You Want To | |||
| // Public License, Version 2, as published by Sam Hocevar. See | |||
| // http://sam.zoy.org/projects/COPYING.WTFPL for more details. | |||
| // | |||
| // | |||
| // The ImageData class | |||
| // ------------------- | |||
| // | |||
| #if !defined __LOL_IMAGE_PRIVATE_H__ | |||
| #define __LOL_IMAGE_PRIVATE_H__ | |||
| #include "image.h" | |||
| namespace lol | |||
| { | |||
| class ImageLoader | |||
| { | |||
| friend class Image; | |||
| friend class ImageData; | |||
| public: | |||
| ImageData *(*fun)(char const *path); | |||
| ImageLoader *next; | |||
| int priority; | |||
| static bool RegisterAllLoaders(); | |||
| static void RegisterLoader(ImageLoader *loader) | |||
| { | |||
| Helper(loader); | |||
| } | |||
| private: | |||
| static ImageData *Load(char const *path) | |||
| { | |||
| ImageLoader *parser = Helper(NULL); | |||
| ImageData *ret = NULL; | |||
| while (parser && !ret) | |||
| { | |||
| ret = parser->fun(path); | |||
| parser = parser->next; | |||
| } | |||
| return ret; | |||
| } | |||
| static ImageLoader *Helper(ImageLoader *set) | |||
| { | |||
| static ImageLoader *loaders = NULL; | |||
| if (!set) | |||
| return loaders; | |||
| ImageLoader **parser = &loaders; | |||
| while (*parser && (*parser)->priority > set->priority) | |||
| parser = &(*parser)->next; | |||
| set->next = *parser; | |||
| *parser = set; | |||
| return NULL; | |||
| } | |||
| }; | |||
| class ImageData | |||
| { | |||
| friend class Image; | |||
| public: | |||
| virtual bool Open(char const *) = 0; | |||
| virtual bool Close() = 0; | |||
| virtual void *GetData() const = 0; | |||
| protected: | |||
| ivec2 size; | |||
| Image::format_t format; | |||
| private: | |||
| }; | |||
| #define REGISTER_IMAGE_LOADER(name) \ | |||
| extern void (Register##name)(); \ | |||
| Register##name(); | |||
| #define DECLARE_IMAGE_LOADER(name, prio) \ | |||
| template<typename T> class name##ImageLoader : public ImageLoader \ | |||
| { \ | |||
| public: \ | |||
| name##ImageLoader() \ | |||
| { \ | |||
| static ImageLoader loader; \ | |||
| loader.fun = Load; \ | |||
| loader.priority = prio; \ | |||
| RegisterLoader(&loader); \ | |||
| } \ | |||
| static ImageData *Load(char const *path) \ | |||
| { \ | |||
| T *ret = new T(); \ | |||
| if (!ret->Open(path)) \ | |||
| { \ | |||
| delete ret; \ | |||
| return NULL; \ | |||
| } \ | |||
| return ret; \ | |||
| } \ | |||
| }; \ | |||
| class name; \ | |||
| name##ImageLoader<name> name##ImageLoaderInstance; \ | |||
| void Register##name() \ | |||
| { \ | |||
| (void)&name##ImageLoaderInstance; \ | |||
| } \ | |||
| class name : public ImageData | |||
| } /* namespace lol */ | |||
| #endif // __LOL_IMAGE_PRIVATE_H__ | |||
| @@ -14,310 +14,42 @@ | |||
| #include <cmath> | |||
| #if defined __APPLE__ && defined __MACH__ | |||
| # import <UIKit/UIKit.h> | |||
| #elif defined USE_SDL_IMAGE | |||
| # include <SDL.h> | |||
| # include <SDL_image.h> | |||
| #elif defined __ANDROID__ | |||
| # include <jni.h> | |||
| # include <android/log.h> | |||
| #elif defined __CELLOS_LV2__ | |||
| # include <cell/sysmodule.h> | |||
| # include <cell/codec/pngdec.h> | |||
| #endif | |||
| #include "core.h" | |||
| #include "image-private.h" | |||
| using namespace std; | |||
| namespace lol | |||
| { | |||
| bool ImageLoader::RegisterAllLoaders() | |||
| { | |||
| #if defined __ANDROID__ | |||
| extern JavaVM *g_vm; | |||
| extern jobject g_activity; | |||
| REGISTER_IMAGE_LOADER(AndroidImageData) | |||
| #endif | |||
| /* | |||
| * Image implementation class | |||
| */ | |||
| class ImageData | |||
| { | |||
| friend class Image; | |||
| private: | |||
| ivec2 size; | |||
| Image::format_t format; | |||
| REGISTER_IMAGE_LOADER(DummyImageData) | |||
| #if defined __APPLE__ && defined __MACH__ | |||
| uint8_t *pixels; | |||
| #elif defined USE_SDL_IMAGE | |||
| SDL_Surface *img; | |||
| #elif defined __ANDROID__ | |||
| jobject bmp; | |||
| jintArray array; | |||
| jint *pixels; | |||
| #elif defined __CELLOS_LV2__ | |||
| static void* Malloc(uint32_t size, void* data) { return malloc(size); }; | |||
| static int32_t Free(void* ptr, void* data) { free(ptr); return 0; }; | |||
| uint8_t *pixels; | |||
| #else | |||
| uint8_t *pixels; | |||
| REGISTER_IMAGE_LOADER(IosImageData) | |||
| #endif | |||
| }; | |||
| #if defined __CELLOS_LV2__ | |||
| REGISTER_IMAGE_LOADER(Ps3ImageData) | |||
| #endif | |||
| #if defined USE_SDL_IMAGE | |||
| REGISTER_IMAGE_LOADER(SdlImageData) | |||
| #endif | |||
| return true; | |||
| } | |||
| /* | |||
| * Public Image class | |||
| */ | |||
| Image::Image(char const *path) | |||
| : data(new ImageData()) | |||
| { | |||
| #if defined __APPLE__ && defined __MACH__ | |||
| NSString *fullpath = [NSString stringWithUTF8String:path]; | |||
| NSArray *chunks = [fullpath componentsSeparatedByString: @"/"]; | |||
| NSString *filename = [chunks objectAtIndex: [chunks count] - 1]; | |||
| chunks = [filename componentsSeparatedByString: @"."]; | |||
| NSString *prefix = [chunks objectAtIndex: 0]; | |||
| NSString *mypath = [[NSBundle mainBundle] pathForResource:prefix ofType:@"png"]; | |||
| NSData *pngdata = [[NSData alloc] initWithContentsOfFile:mypath]; | |||
| UIImage *image = [[UIImage alloc] initWithData:pngdata]; | |||
| if (!image) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not load %s\n", path); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| int w = CGImageGetWidth(image.CGImage); | |||
| int h = CGImageGetHeight(image.CGImage); | |||
| data->size = ivec2(w, h); | |||
| data->format = FORMAT_RGBA; | |||
| CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB(); | |||
| data->pixels = (uint8_t *)malloc(w * h * 4); | |||
| CGContextRef ctx = | |||
| CGBitmapContextCreate(data->pixels, w, h, 8, 4 * w, cspace, | |||
| kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); | |||
| CGColorSpaceRelease(cspace); | |||
| CGContextClearRect(ctx, CGRectMake(0, 0, w, h)); | |||
| CGContextTranslateCTM(ctx, 0, h - h); | |||
| CGContextDrawImage(ctx, CGRectMake(0, 0, w, h), image.CGImage); | |||
| CGContextRelease(ctx); | |||
| [image release]; | |||
| [pngdata release]; | |||
| #elif defined USE_SDL_IMAGE | |||
| for (char const *name = path; *name; name++) | |||
| if ((data->img = IMG_Load(name))) | |||
| break; | |||
| if (!data->img) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not load %s\n", path); | |||
| #endif | |||
| SDL_Quit(); | |||
| exit(1); | |||
| } | |||
| data->size = ivec2(data->img->w, data->img->h); | |||
| data->format = data->img->format->Amask ? FORMAT_RGBA : FORMAT_RGB; | |||
| #elif defined __ANDROID__ | |||
| JNIEnv *env; | |||
| jint res = g_vm->GetEnv((void **)&env, JNI_VERSION_1_2); | |||
| if (res < 0) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not get JVM environment\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| jclass cls = env->GetObjectClass(g_activity); | |||
| jmethodID mid; | |||
| mid = env->GetMethodID(cls, "openImage", | |||
| "(Ljava/lang/String;)Landroid/graphics/Bitmap;"); | |||
| jstring name = env->NewStringUTF(path); | |||
| data->bmp = env->CallObjectMethod(g_activity, mid, name); | |||
| env->DeleteLocalRef(name); | |||
| if (!data->bmp) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not load %s\n", path); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| env->NewGlobalRef(data->bmp); | |||
| /* Get image dimensions */ | |||
| mid = env->GetMethodID(cls, "getWidth", "(Landroid/graphics/Bitmap;)I"); | |||
| data->size.x = env->CallIntMethod(g_activity, mid, data->bmp); | |||
| mid = env->GetMethodID(cls, "getHeight", "(Landroid/graphics/Bitmap;)I"); | |||
| data->size.y = env->CallIntMethod(g_activity, mid, data->bmp); | |||
| /* Get pixels */ | |||
| data->array = env->NewIntArray(data->size.x * data->size.y); | |||
| env->NewGlobalRef(data->array); | |||
| mid = env->GetMethodID(cls, "getPixels", "(Landroid/graphics/Bitmap;[I)V"); | |||
| env->CallVoidMethod(g_activity, mid, data->bmp, data->array); | |||
| data->pixels = env->GetIntArrayElements(data->array, 0); | |||
| for (int n = 0; n < data->size.x * data->size.y; n++) | |||
| { | |||
| uint32_t u = data->pixels[n]; | |||
| u = (u & 0xff00ff00) | ((u & 0xff0000) >> 16) | ((u & 0xff) << 16); | |||
| data->pixels[n] = u; | |||
| } | |||
| data->format = FORMAT_RGBA; | |||
| #elif defined __CELLOS_LV2__ | |||
| int32_t err; | |||
| static bool unused = ImageLoader::RegisterAllLoaders(); | |||
| /* Initialise decoding library */ | |||
| CellPngDecMainHandle hmain; | |||
| err = cellSysmoduleLoadModule(CELL_SYSMODULE_FS); | |||
| if (err != CELL_OK) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not open Fs sysmodule\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| err = cellSysmoduleLoadModule(CELL_SYSMODULE_PNGDEC); | |||
| if (err != CELL_OK) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not open PngDec sysmodule\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| CellPngDecThreadInParam in_param; | |||
| in_param.spuThreadEnable = CELL_PNGDEC_SPU_THREAD_ENABLE; | |||
| in_param.ppuThreadPriority = 1000; | |||
| in_param.spuThreadPriority = 200; | |||
| in_param.cbCtrlMallocFunc = ImageData::Malloc; | |||
| in_param.cbCtrlMallocArg = NULL; | |||
| in_param.cbCtrlFreeFunc = ImageData::Free; | |||
| in_param.cbCtrlFreeArg = NULL; | |||
| CellPngDecThreadOutParam out_param; | |||
| err = cellPngDecCreate(&hmain, &in_param, &out_param); | |||
| if (err != CELL_OK) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not create PngDec library\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| /* Create decoder */ | |||
| CellPngDecSubHandle hsub; | |||
| char file[1024]; | |||
| sprintf(file, "/app_home/c:/Users/s.hocevar/lolengine/%s", path); | |||
| CellPngDecSrc dec_src; | |||
| dec_src.srcSelect = CELL_PNGDEC_FILE; | |||
| dec_src.fileName = file; | |||
| dec_src.fileOffset = 0; | |||
| dec_src.fileSize = 0; | |||
| dec_src.streamPtr = NULL; | |||
| dec_src.streamSize = 0; | |||
| dec_src.spuThreadEnable = CELL_PNGDEC_SPU_THREAD_ENABLE; | |||
| CellPngDecOpnInfo open_info; | |||
| err = cellPngDecOpen(hmain, &hsub, &dec_src, &open_info); | |||
| if (err != CELL_OK) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not open %s for decoding\n", file); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| CellPngDecInfo info; | |||
| err = cellPngDecReadHeader(hmain, hsub, &info); | |||
| if (err != CELL_OK) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not read image header\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| CellPngDecInParam in_dec_param; | |||
| in_dec_param.commandPtr = NULL; | |||
| in_dec_param.outputMode = CELL_PNGDEC_TOP_TO_BOTTOM; | |||
| in_dec_param.outputColorSpace = CELL_PNGDEC_RGBA; | |||
| in_dec_param.outputBitDepth = 8; | |||
| in_dec_param.outputPackFlag = CELL_PNGDEC_1BYTE_PER_1PIXEL; | |||
| in_dec_param.outputAlphaSelect = CELL_PNGDEC_STREAM_ALPHA; | |||
| in_dec_param.outputColorAlpha = 0xff; | |||
| CellPngDecOutParam out_dec_param; | |||
| err = cellPngDecSetParameter(hmain, hsub, &in_dec_param, &out_dec_param); | |||
| if (err != CELL_OK) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not configure PngDec decoder\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| /* Decode image */ | |||
| data->size = ivec2(info.imageWidth, info.imageHeight); | |||
| data->format = FORMAT_RGBA; | |||
| data->pixels = (uint8_t *)malloc(info.imageWidth * 4 * info.imageHeight); | |||
| CellPngDecDataCtrlParam data_ctrl_param; | |||
| data_ctrl_param.outputBytesPerLine = info.imageWidth * 4; | |||
| CellPngDecDataOutInfo data_out_info; | |||
| err = cellPngDecDecodeData(hmain, hsub, data->pixels, | |||
| &data_ctrl_param, &data_out_info); | |||
| if (err != CELL_OK) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not run PngDec decoder\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| /* Close decoder */ | |||
| err = cellPngDecClose(hmain, hsub); | |||
| if (err != CELL_OK) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not close PngDec decoder\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| /* Deinitialise library */ | |||
| err = cellPngDecDestroy(hmain); | |||
| if (err != CELL_OK) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not destroy PngDec decoder\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| err = cellSysmoduleUnloadModule(CELL_SYSMODULE_PNGDEC); | |||
| err = cellSysmoduleUnloadModule(CELL_SYSMODULE_FS); | |||
| #else | |||
| data->size = 256; | |||
| data->format = FORMAT_RGBA; | |||
| data->pixels = (uint8_t *)malloc(256 * 256 * 4 * sizeof(*data->pixels)); | |||
| uint8_t *parser = data->pixels; | |||
| for (int j = 0; j < 256; j++) | |||
| for (int i = 0; i < 256; i++) | |||
| { | |||
| *parser++ = ((i ^ j) & 1) * 0xff; | |||
| *parser++ = (uint8_t)i; | |||
| *parser++ = (uint8_t)j; | |||
| *parser++ = (((i >> 4) ^ (j >> 4)) & 1) * 0xff; | |||
| } | |||
| #endif | |||
| data = ImageLoader::Load(path); | |||
| } | |||
| ivec2 Image::GetSize() const | |||
| @@ -332,50 +64,12 @@ Image::format_t Image::GetFormat() const | |||
| void * Image::GetData() const | |||
| { | |||
| #if defined __APPLE__ && defined __MACH__ | |||
| return data->pixels; | |||
| #elif defined USE_SDL_IMAGE | |||
| return data->img->pixels; | |||
| #elif defined __ANDROID__ | |||
| return data->pixels; | |||
| #elif defined __CELLOS_LV2__ | |||
| return data->pixels; | |||
| #else | |||
| return data->pixels; | |||
| #endif | |||
| return data->GetData(); | |||
| } | |||
| Image::~Image() | |||
| { | |||
| #if defined __APPLE__ && defined __MACH__ | |||
| free(data->pixels); | |||
| #elif defined USE_SDL_IMAGE | |||
| SDL_FreeSurface(data->img); | |||
| #elif defined __ANDROID__ | |||
| JNIEnv *env; | |||
| jint res = g_vm->GetEnv((void **)&env, JNI_VERSION_1_2); | |||
| if (res < 0) | |||
| { | |||
| #if !LOL_RELEASE | |||
| Log::Error("could not get JVM environment\n"); | |||
| #endif | |||
| exit(1); | |||
| } | |||
| jclass cls = env->GetObjectClass(g_activity); | |||
| jmethodID mid; | |||
| env->ReleaseIntArrayElements(data->array, data->pixels, 0); | |||
| env->DeleteGlobalRef(data->array); | |||
| /* Free image */ | |||
| mid = env->GetMethodID(cls, "closeImage", "(Landroid/graphics/Bitmap;)V"); | |||
| env->CallVoidMethod(g_activity, mid, data->bmp); | |||
| env->DeleteGlobalRef(data->bmp); | |||
| #elif defined __CELLOS_LV2__ | |||
| free(data->pixels); | |||
| #else | |||
| free(data->pixels); | |||
| #endif | |||
| data->Close(); | |||
| delete data; | |||
| } | |||