@@ -24,7 +24,12 @@ liblol_a_SOURCES = \ | |||||
\ | \ | ||||
shader/shader.cpp shader/shader.h \ | 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 \ | loldebug.h \ | ||||
debug/fps.cpp debug/fps.h debug/sphere.cpp debug/sphere.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> | #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 "core.h" | ||||
#include "image-private.h" | |||||
using namespace std; | using namespace std; | ||||
namespace lol | namespace lol | ||||
{ | { | ||||
bool ImageLoader::RegisterAllLoaders() | |||||
{ | |||||
#if defined __ANDROID__ | #if defined __ANDROID__ | ||||
extern JavaVM *g_vm; | |||||
extern jobject g_activity; | |||||
REGISTER_IMAGE_LOADER(AndroidImageData) | |||||
#endif | #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__ | #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 | #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 | * Public Image class | ||||
*/ | */ | ||||
Image::Image(char const *path) | 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 | ivec2 Image::GetSize() const | ||||
@@ -332,50 +64,12 @@ Image::format_t Image::GetFormat() const | |||||
void * Image::GetData() 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() | 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; | delete data; | ||||
} | } | ||||