ANDROID: Rewrite to make use of OpenGLGraphicsManager (#1695)
* ANDROID: Rewrite to make use of OpenGLGraphicsManager * ANDROID: Fix emulated mouse button up events
This commit is contained in:
parent
997e15878a
commit
7a05624e1b
15 changed files with 271 additions and 2039 deletions
|
@ -69,6 +69,9 @@
|
|||
#include <FGraphicsOpengl.h>
|
||||
using namespace Tizen::Graphics::Opengl;
|
||||
#define USE_BUILTIN_OPENGL
|
||||
#elif defined(__ANDROID__)
|
||||
#include <GLES/gl.h>
|
||||
#define USE_BUILTIN_OPENGL
|
||||
#else
|
||||
#include "backends/graphics/opengl/opengl-defs.h"
|
||||
#endif
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
|
||||
#include "backends/platform/android/jni.h"
|
||||
#include "backends/platform/android/android.h"
|
||||
#include "backends/platform/android/graphics.h"
|
||||
|
||||
const char *android_log_tag = "ScummVM";
|
||||
|
||||
|
@ -80,62 +81,11 @@ extern "C" {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef ANDROID_DEBUG_GL
|
||||
static const char *getGlErrStr(GLenum error) {
|
||||
switch (error) {
|
||||
case GL_INVALID_ENUM:
|
||||
return "GL_INVALID_ENUM";
|
||||
case GL_INVALID_VALUE:
|
||||
return "GL_INVALID_VALUE";
|
||||
case GL_INVALID_OPERATION:
|
||||
return "GL_INVALID_OPERATION";
|
||||
case GL_STACK_OVERFLOW:
|
||||
return "GL_STACK_OVERFLOW";
|
||||
case GL_STACK_UNDERFLOW:
|
||||
return "GL_STACK_UNDERFLOW";
|
||||
case GL_OUT_OF_MEMORY:
|
||||
return "GL_OUT_OF_MEMORY";
|
||||
}
|
||||
|
||||
static char buf[40];
|
||||
snprintf(buf, sizeof(buf), "(Unknown GL error code 0x%x)", error);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void checkGlError(const char *expr, const char *file, int line) {
|
||||
GLenum error = glGetError();
|
||||
|
||||
if (error != GL_NO_ERROR)
|
||||
LOGE("GL ERROR: %s on %s (%s:%d)", getGlErrStr(error), expr, file, line);
|
||||
}
|
||||
#endif
|
||||
|
||||
OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) :
|
||||
_audio_sample_rate(audio_sample_rate),
|
||||
_audio_buffer_size(audio_buffer_size),
|
||||
_screen_changeid(0),
|
||||
_egl_surface_width(0),
|
||||
_egl_surface_height(0),
|
||||
_htc_fail(true),
|
||||
_force_redraw(false),
|
||||
_game_texture(0),
|
||||
_overlay_texture(0),
|
||||
_mouse_texture(0),
|
||||
_mouse_texture_palette(0),
|
||||
_mouse_texture_rgb(0),
|
||||
_mouse_hotspot(),
|
||||
_mouse_keycolor(0),
|
||||
_use_mouse_palette(false),
|
||||
_graphicsMode(0),
|
||||
_fullscreen(true),
|
||||
_ar_correction(true),
|
||||
_show_mouse(false),
|
||||
_show_overlay(false),
|
||||
_enable_zoning(false),
|
||||
_mutexManager(0),
|
||||
_mixer(0),
|
||||
_shake_offset(0),
|
||||
_queuedEventTime(0),
|
||||
_event_queue_lock(0),
|
||||
_touch_pt_down(),
|
||||
|
@ -153,22 +103,14 @@ OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) :
|
|||
|
||||
_fsFactory = new POSIXFilesystemFactory();
|
||||
|
||||
Common::String mf = getSystemProperty("ro.product.manufacturer");
|
||||
|
||||
LOGI("Running on: [%s] [%s] [%s] [%s] [%s] SDK:%s ABI:%s",
|
||||
mf.c_str(),
|
||||
getSystemProperty("ro.product.manufacturer").c_str(),
|
||||
getSystemProperty("ro.product.model").c_str(),
|
||||
getSystemProperty("ro.product.brand").c_str(),
|
||||
getSystemProperty("ro.build.fingerprint").c_str(),
|
||||
getSystemProperty("ro.build.display.id").c_str(),
|
||||
getSystemProperty("ro.build.version.sdk").c_str(),
|
||||
getSystemProperty("ro.product.cpu.abi").c_str());
|
||||
|
||||
mf.toLowercase();
|
||||
/*_htc_fail = mf.contains("htc");
|
||||
|
||||
if (_htc_fail)
|
||||
LOGI("Enabling HTC workaround");*/
|
||||
}
|
||||
|
||||
OSystem_Android::~OSystem_Android() {
|
||||
|
@ -182,9 +124,6 @@ OSystem_Android::~OSystem_Android() {
|
|||
_timerManager = 0;
|
||||
|
||||
deleteMutex(_event_queue_lock);
|
||||
|
||||
delete _mutexManager;
|
||||
_mutexManager = 0;
|
||||
}
|
||||
|
||||
void *OSystem_Android::timerThreadFunc(void *arg) {
|
||||
|
@ -390,15 +329,7 @@ void OSystem_Android::initBackend() {
|
|||
_audio_thread_exit = false;
|
||||
pthread_create(&_audio_thread, 0, audioThreadFunc, this);
|
||||
|
||||
initSurface();
|
||||
initViewport();
|
||||
|
||||
_game_texture = new GLESFakePalette565Texture();
|
||||
_overlay_texture = new GLES4444Texture();
|
||||
_mouse_texture_palette = new GLESFakePalette5551Texture();
|
||||
_mouse_texture = _mouse_texture_palette;
|
||||
|
||||
initOverlay();
|
||||
_graphicsManager = new AndroidGraphicsManager();
|
||||
|
||||
// renice this thread to boost the audio thread
|
||||
if (setpriority(PRIO_PROCESS, 0, 19) < 0)
|
||||
|
@ -406,42 +337,28 @@ void OSystem_Android::initBackend() {
|
|||
|
||||
JNI::setReadyForEvents(true);
|
||||
|
||||
EventsBaseBackend::initBackend();
|
||||
ModularBackend::initBackend();
|
||||
}
|
||||
|
||||
bool OSystem_Android::hasFeature(Feature f) {
|
||||
return (f == kFeatureFullscreenMode ||
|
||||
f == kFeatureAspectRatioCorrection ||
|
||||
f == kFeatureCursorPalette ||
|
||||
f == kFeatureVirtualKeyboard ||
|
||||
f == kFeatureOverlaySupportsAlpha ||
|
||||
if (f == kFeatureVirtualKeyboard ||
|
||||
f == kFeatureOpenUrl ||
|
||||
f == kFeatureTouchpadMode ||
|
||||
f == kFeatureOnScreenControl ||
|
||||
f == kFeatureClipboardSupport);
|
||||
f == kFeatureClipboardSupport) {
|
||||
return true;
|
||||
}
|
||||
return ModularBackend::hasFeature(f);
|
||||
}
|
||||
|
||||
void OSystem_Android::setFeatureState(Feature f, bool enable) {
|
||||
ENTER("%d, %d", f, enable);
|
||||
|
||||
switch (f) {
|
||||
case kFeatureFullscreenMode:
|
||||
_fullscreen = enable;
|
||||
updateScreenRect();
|
||||
break;
|
||||
case kFeatureAspectRatioCorrection:
|
||||
_ar_correction = enable;
|
||||
updateScreenRect();
|
||||
break;
|
||||
case kFeatureVirtualKeyboard:
|
||||
_virtkeybd_on = enable;
|
||||
showVirtualKeyboard(enable);
|
||||
break;
|
||||
case kFeatureCursorPalette:
|
||||
_use_mouse_palette = enable;
|
||||
if (!enable)
|
||||
disableCursorPalette();
|
||||
break;
|
||||
case kFeatureTouchpadMode:
|
||||
ConfMan.setBool("touchpad_mouse_mode", enable);
|
||||
_touchpad_mode = enable;
|
||||
|
@ -451,26 +368,21 @@ void OSystem_Android::setFeatureState(Feature f, bool enable) {
|
|||
JNI::showKeyboardControl(enable);
|
||||
break;
|
||||
default:
|
||||
ModularBackend::setFeatureState(f, enable);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool OSystem_Android::getFeatureState(Feature f) {
|
||||
switch (f) {
|
||||
case kFeatureFullscreenMode:
|
||||
return _fullscreen;
|
||||
case kFeatureAspectRatioCorrection:
|
||||
return _ar_correction;
|
||||
case kFeatureVirtualKeyboard:
|
||||
return _virtkeybd_on;
|
||||
case kFeatureCursorPalette:
|
||||
return _use_mouse_palette;
|
||||
case kFeatureTouchpadMode:
|
||||
return ConfMan.getBool("touchpad_mouse_mode");
|
||||
case kFeatureOnScreenControl:
|
||||
return ConfMan.getBool("onscreen_control");
|
||||
default:
|
||||
return false;
|
||||
return ModularBackend::getFeatureState(f);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -487,26 +399,6 @@ void OSystem_Android::delayMillis(uint msecs) {
|
|||
usleep(msecs * 1000);
|
||||
}
|
||||
|
||||
OSystem::MutexRef OSystem_Android::createMutex() {
|
||||
assert(_mutexManager);
|
||||
return _mutexManager->createMutex();
|
||||
}
|
||||
|
||||
void OSystem_Android::lockMutex(MutexRef mutex) {
|
||||
assert(_mutexManager);
|
||||
_mutexManager->lockMutex(mutex);
|
||||
}
|
||||
|
||||
void OSystem_Android::unlockMutex(MutexRef mutex) {
|
||||
assert(_mutexManager);
|
||||
_mutexManager->unlockMutex(mutex);
|
||||
}
|
||||
|
||||
void OSystem_Android::deleteMutex(MutexRef mutex) {
|
||||
assert(_mutexManager);
|
||||
_mutexManager->deleteMutex(mutex);
|
||||
}
|
||||
|
||||
void OSystem_Android::quit() {
|
||||
ENTER();
|
||||
|
||||
|
@ -517,13 +409,6 @@ void OSystem_Android::quit() {
|
|||
|
||||
_timer_thread_exit = true;
|
||||
pthread_join(_timer_thread, 0);
|
||||
|
||||
delete _game_texture;
|
||||
delete _overlay_texture;
|
||||
delete _mouse_texture_palette;
|
||||
delete _mouse_texture_rgb;
|
||||
|
||||
deinitSurface();
|
||||
}
|
||||
|
||||
void OSystem_Android::setWindowCaption(const char *caption) {
|
||||
|
@ -532,12 +417,6 @@ void OSystem_Android::setWindowCaption(const char *caption) {
|
|||
JNI::setWindowCaption(caption);
|
||||
}
|
||||
|
||||
void OSystem_Android::displayMessageOnOSD(const char *msg) {
|
||||
ENTER("%s", msg);
|
||||
|
||||
JNI::displayMessageOnOSD(msg);
|
||||
}
|
||||
|
||||
void OSystem_Android::showVirtualKeyboard(bool enable) {
|
||||
ENTER("%d", enable);
|
||||
|
||||
|
@ -563,15 +442,13 @@ void OSystem_Android::getTimeAndDate(TimeDate &td) const {
|
|||
td.tm_wday = tm.tm_wday;
|
||||
}
|
||||
|
||||
void OSystem_Android::addSysArchivesToSearchSet(Common::SearchSet &s,
|
||||
int priority) {
|
||||
void OSystem_Android::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
|
||||
ENTER("");
|
||||
|
||||
JNI::addSysArchivesToSearchSet(s, priority);
|
||||
}
|
||||
|
||||
void OSystem_Android::logMessage(LogMessageType::Type type,
|
||||
const char *message) {
|
||||
void OSystem_Android::logMessage(LogMessageType::Type type, const char *message) {
|
||||
switch (type) {
|
||||
case LogMessageType::kInfo:
|
||||
__android_log_write(ANDROID_LOG_INFO, android_log_tag, message);
|
||||
|
|
|
@ -28,25 +28,16 @@
|
|||
#include "common/fs.h"
|
||||
#include "common/archive.h"
|
||||
#include "audio/mixer_intern.h"
|
||||
#include "graphics/palette.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "backends/base-backend.h"
|
||||
#include "backends/modular-backend.h"
|
||||
#include "backends/plugins/posix/posix-provider.h"
|
||||
#include "backends/fs/posix/posix-fs-factory.h"
|
||||
|
||||
#include "backends/platform/android/texture.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
|
||||
// toggles start
|
||||
//#define ANDROID_DEBUG_ENTER
|
||||
//#define ANDROID_DEBUG_GL
|
||||
//#define ANDROID_DEBUG_GL_CALLS
|
||||
// toggles end
|
||||
|
||||
extern const char *android_log_tag;
|
||||
|
@ -63,76 +54,13 @@ extern const char *android_log_tag;
|
|||
#define ENTER(fmt, args...) do { } while (false)
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID_DEBUG_GL
|
||||
extern void checkGlError(const char *expr, const char *file, int line);
|
||||
|
||||
#ifdef ANDROID_DEBUG_GL_CALLS
|
||||
#define GLCALLLOG(x, before) \
|
||||
do { \
|
||||
if (before) \
|
||||
LOGD("calling '%s' (%s:%d)", x, __FILE__, __LINE__); \
|
||||
else \
|
||||
LOGD("returned from '%s' (%s:%d)", x, __FILE__, __LINE__); \
|
||||
} while (false)
|
||||
#else
|
||||
#define GLCALLLOG(x, before) do { } while (false)
|
||||
#endif
|
||||
|
||||
#define GLCALL(x) \
|
||||
do { \
|
||||
GLCALLLOG(#x, true); \
|
||||
(x); \
|
||||
GLCALLLOG(#x, false); \
|
||||
checkGlError(#x, __FILE__, __LINE__); \
|
||||
} while (false)
|
||||
|
||||
#define GLTHREADCHECK \
|
||||
do { \
|
||||
assert(pthread_self() == _main_thread); \
|
||||
} while (false)
|
||||
|
||||
#else
|
||||
#define GLCALL(x) do { (x); } while (false)
|
||||
#define GLTHREADCHECK do { } while (false)
|
||||
#endif
|
||||
|
||||
class MutexManager;
|
||||
|
||||
class OSystem_Android : public EventsBaseBackend, public PaletteManager {
|
||||
class OSystem_Android : public ModularBackend, Common::EventSource {
|
||||
private:
|
||||
// passed from the dark side
|
||||
int _audio_sample_rate;
|
||||
int _audio_buffer_size;
|
||||
|
||||
int _screen_changeid;
|
||||
int _egl_surface_width;
|
||||
int _egl_surface_height;
|
||||
bool _htc_fail;
|
||||
|
||||
bool _force_redraw;
|
||||
|
||||
// Game layer
|
||||
GLESBaseTexture *_game_texture;
|
||||
int _shake_offset;
|
||||
Common::Rect _focus_rect;
|
||||
|
||||
// Overlay layer
|
||||
GLES4444Texture *_overlay_texture;
|
||||
bool _show_overlay;
|
||||
|
||||
// Mouse layer
|
||||
GLESBaseTexture *_mouse_texture;
|
||||
GLESBaseTexture *_mouse_texture_palette;
|
||||
GLES5551Texture *_mouse_texture_rgb;
|
||||
Common::Point _mouse_hotspot;
|
||||
uint32 _mouse_keycolor;
|
||||
int _mouse_targetscale;
|
||||
bool _show_mouse;
|
||||
bool _use_mouse_palette;
|
||||
|
||||
int _graphicsMode;
|
||||
bool _fullscreen;
|
||||
bool _ar_correction;
|
||||
|
||||
pthread_t _main_thread;
|
||||
|
||||
|
@ -144,70 +72,27 @@ private:
|
|||
pthread_t _audio_thread;
|
||||
static void *audioThreadFunc(void *arg);
|
||||
|
||||
bool _enable_zoning;
|
||||
bool _virtkeybd_on;
|
||||
|
||||
MutexManager *_mutexManager;
|
||||
Audio::MixerImpl *_mixer;
|
||||
timeval _startTime;
|
||||
|
||||
Common::String getSystemProperty(const char *name) const;
|
||||
|
||||
void initSurface();
|
||||
void deinitSurface();
|
||||
void initViewport();
|
||||
|
||||
void initOverlay();
|
||||
|
||||
#ifdef USE_RGB_COLOR
|
||||
void initTexture(GLESBaseTexture **texture, uint width, uint height,
|
||||
const Graphics::PixelFormat *format);
|
||||
#endif
|
||||
|
||||
void setupKeymapper();
|
||||
void setCursorPaletteInternal(const byte *colors, uint start, uint num);
|
||||
|
||||
protected:
|
||||
virtual Common::EventSource *getDefaultEventSource() { return this; }
|
||||
|
||||
public:
|
||||
OSystem_Android(int audio_sample_rate, int audio_buffer_size);
|
||||
virtual ~OSystem_Android();
|
||||
|
||||
virtual void initBackend();
|
||||
void enableZoning(bool enable) { _enable_zoning = enable; }
|
||||
|
||||
virtual bool hasFeature(Feature f);
|
||||
virtual void setFeatureState(Feature f, bool enable);
|
||||
virtual bool getFeatureState(Feature f);
|
||||
|
||||
virtual const GraphicsMode *getSupportedGraphicsModes() const;
|
||||
virtual int getDefaultGraphicsMode() const;
|
||||
virtual bool setGraphicsMode(int mode);
|
||||
virtual int getGraphicsMode() const;
|
||||
|
||||
#ifdef USE_RGB_COLOR
|
||||
virtual Graphics::PixelFormat getScreenFormat() const;
|
||||
virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
|
||||
#endif
|
||||
|
||||
virtual void initSize(uint width, uint height,
|
||||
const Graphics::PixelFormat *format);
|
||||
|
||||
enum FixupType {
|
||||
kClear = 0, // glClear
|
||||
kClearSwap, // glClear + swapBuffers
|
||||
kClearUpdate // glClear + updateScreen
|
||||
};
|
||||
|
||||
void clearScreen(FixupType type, byte count = 1);
|
||||
|
||||
void updateScreenRect();
|
||||
virtual int getScreenChangeID() const;
|
||||
|
||||
virtual int16 getHeight();
|
||||
virtual int16 getWidth();
|
||||
|
||||
virtual PaletteManager *getPaletteManager() {
|
||||
return this;
|
||||
}
|
||||
virtual bool hasFeature(OSystem::Feature f);
|
||||
virtual void setFeatureState(OSystem::Feature f, bool enable);
|
||||
virtual bool getFeatureState(OSystem::Feature f);
|
||||
|
||||
public:
|
||||
void pushEvent(int type, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6);
|
||||
|
@ -230,58 +115,16 @@ private:
|
|||
|
||||
void clipMouse(Common::Point &p);
|
||||
void scaleMouse(Common::Point &p, int x, int y, bool deductDrawRect = true, bool touchpadMode = false);
|
||||
void updateEventScale();
|
||||
void disableCursorPalette();
|
||||
|
||||
protected:
|
||||
// PaletteManager API
|
||||
virtual void setPalette(const byte *colors, uint start, uint num);
|
||||
virtual void grabPalette(byte *colors, uint start, uint num) const;
|
||||
|
||||
public:
|
||||
virtual void copyRectToScreen(const void *buf, int pitch, int x, int y,
|
||||
int w, int h);
|
||||
virtual void updateScreen();
|
||||
virtual Graphics::Surface *lockScreen();
|
||||
virtual void unlockScreen();
|
||||
virtual void setShakePos(int shakeOffset);
|
||||
virtual void fillScreen(uint32 col);
|
||||
virtual void setFocusRectangle(const Common::Rect& rect);
|
||||
virtual void clearFocusRectangle();
|
||||
|
||||
virtual void showOverlay();
|
||||
virtual void hideOverlay();
|
||||
virtual void clearOverlay();
|
||||
virtual void grabOverlay(void *buf, int pitch);
|
||||
virtual void copyRectToOverlay(const void *buf, int pitch,
|
||||
int x, int y, int w, int h);
|
||||
virtual int16 getOverlayHeight();
|
||||
virtual int16 getOverlayWidth();
|
||||
virtual Graphics::PixelFormat getOverlayFormat() const;
|
||||
|
||||
virtual bool showMouse(bool visible);
|
||||
|
||||
virtual void warpMouse(int x, int y);
|
||||
virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX,
|
||||
int hotspotY, uint32 keycolor,
|
||||
bool dontScale,
|
||||
const Graphics::PixelFormat *format);
|
||||
virtual void setCursorPalette(const byte *colors, uint start, uint num);
|
||||
|
||||
virtual void pushEvent(const Common::Event &event);
|
||||
virtual bool pollEvent(Common::Event &event);
|
||||
virtual uint32 getMillis(bool skipRecord = false);
|
||||
virtual void delayMillis(uint msecs);
|
||||
|
||||
virtual MutexRef createMutex(void);
|
||||
virtual void lockMutex(MutexRef mutex);
|
||||
virtual void unlockMutex(MutexRef mutex);
|
||||
virtual void deleteMutex(MutexRef mutex);
|
||||
|
||||
virtual void quit();
|
||||
|
||||
virtual void setWindowCaption(const char *caption);
|
||||
virtual void displayMessageOnOSD(const char *msg);
|
||||
virtual void showVirtualKeyboard(bool enable);
|
||||
|
||||
virtual Audio::Mixer *getMixer();
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#define FORBIDDEN_SYMBOL_EXCEPTION_printf
|
||||
|
||||
#include "backends/platform/android/android.h"
|
||||
#include "backends/platform/android/graphics.h"
|
||||
#include "backends/platform/android/events.h"
|
||||
#include "backends/platform/android/jni.h"
|
||||
|
||||
|
@ -76,69 +77,6 @@ void OSystem_Android::setupKeymapper() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void OSystem_Android::warpMouse(int x, int y) {
|
||||
ENTER("%d, %d", x, y);
|
||||
|
||||
Common::Event e;
|
||||
|
||||
e.type = Common::EVENT_MOUSEMOVE;
|
||||
e.mouse.x = x;
|
||||
e.mouse.y = y;
|
||||
|
||||
clipMouse(e.mouse);
|
||||
|
||||
pushEvent(e);
|
||||
}
|
||||
|
||||
void OSystem_Android::clipMouse(Common::Point &p) {
|
||||
const GLESBaseTexture *tex;
|
||||
|
||||
if (_show_overlay)
|
||||
tex = _overlay_texture;
|
||||
else
|
||||
tex = _game_texture;
|
||||
|
||||
p.x = CLIP(p.x, int16(0), int16(tex->width() - 1));
|
||||
p.y = CLIP(p.y, int16(0), int16(tex->height() - 1));
|
||||
}
|
||||
|
||||
void OSystem_Android::scaleMouse(Common::Point &p, int x, int y,
|
||||
bool deductDrawRect, bool touchpadMode) {
|
||||
const GLESBaseTexture *tex;
|
||||
|
||||
if (_show_overlay)
|
||||
tex = _overlay_texture;
|
||||
else
|
||||
tex = _game_texture;
|
||||
|
||||
const Common::Rect &r = tex->getDrawRect();
|
||||
|
||||
if (touchpadMode) {
|
||||
x = x * 100 / _touchpad_scale;
|
||||
y = y * 100 / _touchpad_scale;
|
||||
}
|
||||
|
||||
if (deductDrawRect) {
|
||||
x -= r.left;
|
||||
y -= r.top;
|
||||
}
|
||||
|
||||
p.x = scalef(x, tex->width(), r.width());
|
||||
p.y = scalef(y, tex->height(), r.height());
|
||||
}
|
||||
|
||||
void OSystem_Android::updateEventScale() {
|
||||
const GLESBaseTexture *tex;
|
||||
|
||||
if (_show_overlay)
|
||||
tex = _overlay_texture;
|
||||
else
|
||||
tex = _game_texture;
|
||||
|
||||
_eventScaleY = 100 * 480 / tex->height();
|
||||
_eventScaleX = 100 * 640 / tex->width();
|
||||
}
|
||||
|
||||
void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
||||
int arg4, int arg5, int arg6) {
|
||||
Common::Event e;
|
||||
|
@ -199,7 +137,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
else
|
||||
e.type = Common::EVENT_RBUTTONUP;
|
||||
|
||||
e.mouse = getEventManager()->getMousePos();
|
||||
e.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
|
||||
|
||||
pushEvent(e);
|
||||
|
||||
|
@ -324,7 +262,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
|
||||
e.type = Common::EVENT_MOUSEMOVE;
|
||||
|
||||
e.mouse = getEventManager()->getMousePos();
|
||||
e.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
|
||||
|
||||
{
|
||||
int16 *c;
|
||||
|
@ -348,8 +286,6 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
*c += f;
|
||||
}
|
||||
|
||||
clipMouse(e.mouse);
|
||||
|
||||
pushEvent(e);
|
||||
|
||||
return;
|
||||
|
@ -367,7 +303,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
return;
|
||||
}
|
||||
|
||||
e.mouse = getEventManager()->getMousePos();
|
||||
e.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
|
||||
|
||||
pushEvent(e);
|
||||
|
||||
|
@ -375,7 +311,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
}
|
||||
|
||||
case JE_DOWN:
|
||||
_touch_pt_down = getEventManager()->getMousePos();
|
||||
_touch_pt_down = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
|
||||
_touch_pt_scroll.x = -1;
|
||||
_touch_pt_scroll.y = -1;
|
||||
break;
|
||||
|
@ -390,13 +326,13 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
return;
|
||||
}
|
||||
|
||||
scaleMouse(e.mouse, arg3 - _touch_pt_scroll.x,
|
||||
arg4 - _touch_pt_scroll.y, false, true);
|
||||
e.mouse.x = (arg3 - _touch_pt_scroll.x) * 100 / _touchpad_scale;
|
||||
e.mouse.y = (arg4 - _touch_pt_scroll.y) * 100 / _touchpad_scale;
|
||||
e.mouse += _touch_pt_down;
|
||||
clipMouse(e.mouse);
|
||||
|
||||
} else {
|
||||
scaleMouse(e.mouse, arg3, arg4);
|
||||
clipMouse(e.mouse);
|
||||
e.mouse.x = arg3;
|
||||
e.mouse.y = arg4;
|
||||
}
|
||||
|
||||
pushEvent(e);
|
||||
|
@ -412,10 +348,10 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
e.type = Common::EVENT_MOUSEMOVE;
|
||||
|
||||
if (_touchpad_mode) {
|
||||
e.mouse = getEventManager()->getMousePos();
|
||||
e.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
|
||||
} else {
|
||||
scaleMouse(e.mouse, arg1, arg2);
|
||||
clipMouse(e.mouse);
|
||||
e.mouse.x = arg1;
|
||||
e.mouse.y = arg2;
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -457,10 +393,10 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
e.type = Common::EVENT_MOUSEMOVE;
|
||||
|
||||
if (_touchpad_mode) {
|
||||
e.mouse = getEventManager()->getMousePos();
|
||||
e.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
|
||||
} else {
|
||||
scaleMouse(e.mouse, arg1, arg2);
|
||||
clipMouse(e.mouse);
|
||||
e.mouse.x = arg1;
|
||||
e.mouse.y = arg2;
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -486,11 +422,9 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
dptype = Common::EVENT_MOUSEMOVE;
|
||||
|
||||
if (_touchpad_mode) {
|
||||
scaleMouse(e.mouse, arg1 - _touch_pt_dt.x,
|
||||
arg2 - _touch_pt_dt.y, false, true);
|
||||
e.mouse.x = (arg1 - _touch_pt_dt.x) * 100 / _touchpad_scale;
|
||||
e.mouse.y = (arg2 - _touch_pt_dt.y) * 100 / _touchpad_scale;
|
||||
e.mouse += _touch_pt_down;
|
||||
|
||||
clipMouse(e.mouse);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -537,7 +471,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
return;
|
||||
}
|
||||
|
||||
e.mouse = getEventManager()->getMousePos();
|
||||
e.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
|
||||
|
||||
lockMutex(_event_queue_lock);
|
||||
|
||||
|
@ -562,7 +496,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
return;
|
||||
|
||||
case JE_BALL:
|
||||
e.mouse = getEventManager()->getMousePos();
|
||||
e.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
|
||||
|
||||
switch (arg1) {
|
||||
case JACTION_DOWN:
|
||||
|
@ -578,8 +512,6 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
e.mouse.x += arg2 * _trackball_scale / _eventScaleX;
|
||||
e.mouse.y += arg3 * _trackball_scale / _eventScaleY;
|
||||
|
||||
clipMouse(e.mouse);
|
||||
|
||||
break;
|
||||
default:
|
||||
LOGE("unhandled jaction on system key: %d", arg1);
|
||||
|
@ -592,9 +524,8 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
|
||||
case JE_MOUSE_MOVE:
|
||||
e.type = Common::EVENT_MOUSEMOVE;
|
||||
|
||||
scaleMouse(e.mouse, arg1, arg2);
|
||||
clipMouse(e.mouse);
|
||||
e.mouse.x = arg1;
|
||||
e.mouse.y = arg2;
|
||||
|
||||
pushEvent(e);
|
||||
|
||||
|
@ -602,9 +533,8 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
|
||||
case JE_LMB_DOWN:
|
||||
e.type = Common::EVENT_LBUTTONDOWN;
|
||||
|
||||
scaleMouse(e.mouse, arg1, arg2);
|
||||
clipMouse(e.mouse);
|
||||
e.mouse.x = arg1;
|
||||
e.mouse.y = arg2;
|
||||
|
||||
pushEvent(e);
|
||||
|
||||
|
@ -612,9 +542,8 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
|
||||
case JE_LMB_UP:
|
||||
e.type = Common::EVENT_LBUTTONUP;
|
||||
|
||||
scaleMouse(e.mouse, arg1, arg2);
|
||||
clipMouse(e.mouse);
|
||||
e.mouse.x = arg1;
|
||||
e.mouse.y = arg2;
|
||||
|
||||
pushEvent(e);
|
||||
|
||||
|
@ -622,9 +551,8 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
|
||||
case JE_RMB_DOWN:
|
||||
e.type = Common::EVENT_RBUTTONDOWN;
|
||||
|
||||
scaleMouse(e.mouse, arg1, arg2);
|
||||
clipMouse(e.mouse);
|
||||
e.mouse.x = arg1;
|
||||
e.mouse.y = arg2;
|
||||
|
||||
pushEvent(e);
|
||||
|
||||
|
@ -632,9 +560,8 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
|
||||
case JE_RMB_UP:
|
||||
e.type = Common::EVENT_RBUTTONUP;
|
||||
|
||||
scaleMouse(e.mouse, arg1, arg2);
|
||||
clipMouse(e.mouse);
|
||||
e.mouse.x = arg1;
|
||||
e.mouse.y = arg2;
|
||||
|
||||
pushEvent(e);
|
||||
|
||||
|
@ -669,7 +596,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
break;
|
||||
}
|
||||
|
||||
e.mouse = getEventManager()->getMousePos();
|
||||
e.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
|
||||
|
||||
break;
|
||||
|
||||
|
@ -692,7 +619,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
break;
|
||||
|
||||
case JE_JOYSTICK:
|
||||
e.mouse = getEventManager()->getMousePos();
|
||||
e.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
|
||||
|
||||
switch (arg1) {
|
||||
case JACTION_MULTIPLE:
|
||||
|
@ -702,8 +629,6 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
|||
e.mouse.x += arg2 * _joystick_scale / _eventScaleX;
|
||||
e.mouse.y += arg3 * _joystick_scale / _eventScaleY;
|
||||
|
||||
clipMouse(e.mouse);
|
||||
|
||||
break;
|
||||
default:
|
||||
LOGE("unhandled jaction on joystick: %d", arg1);
|
||||
|
@ -745,23 +670,19 @@ bool OSystem_Android::pollEvent(Common::Event &event) {
|
|||
|
||||
if (pthread_self() == _main_thread) {
|
||||
if (_screen_changeid != JNI::surface_changeid) {
|
||||
_screen_changeid = JNI::surface_changeid;
|
||||
|
||||
if (JNI::egl_surface_width > 0 && JNI::egl_surface_height > 0) {
|
||||
// surface changed
|
||||
JNI::deinitSurface();
|
||||
initSurface();
|
||||
initViewport();
|
||||
updateScreenRect();
|
||||
updateEventScale();
|
||||
|
||||
// double buffered, flip twice
|
||||
clearScreen(kClearUpdate, 2);
|
||||
dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->deinitSurface();
|
||||
dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->initSurface();
|
||||
|
||||
event.type = Common::EVENT_SCREEN_CHANGED;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
// surface lost
|
||||
deinitSurface();
|
||||
dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->deinitSurface();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -777,24 +698,28 @@ bool OSystem_Android::pollEvent(Common::Event &event) {
|
|||
if (_queuedEventTime && (getMillis() > _queuedEventTime)) {
|
||||
event = _queuedEvent;
|
||||
_queuedEventTime = 0;
|
||||
unlockMutex(_event_queue_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_event_queue.empty()) {
|
||||
// unlockMutex(_event_queue_lock);
|
||||
// return true;
|
||||
} else if (_event_queue.empty()) {
|
||||
unlockMutex(_event_queue_lock);
|
||||
return false;
|
||||
} else {
|
||||
event = _event_queue.pop();
|
||||
}
|
||||
|
||||
event = _event_queue.pop();
|
||||
|
||||
unlockMutex(_event_queue_lock);
|
||||
|
||||
if (event.type == Common::EVENT_MOUSEMOVE) {
|
||||
const Common::Point &m = getEventManager()->getMousePos();
|
||||
|
||||
if (m != event.mouse)
|
||||
_force_redraw = true;
|
||||
switch (event.type) {
|
||||
case Common::EVENT_MOUSEMOVE:
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
case Common::EVENT_RBUTTONDOWN:
|
||||
case Common::EVENT_RBUTTONUP:
|
||||
if (_graphicsManager)
|
||||
return dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->notifyMousePosition(event.mouse);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -1,814 +0,0 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
// Allow use of stuff in <time.h>
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
|
||||
|
||||
// Disable printf override in common/forbidden.h to avoid
|
||||
// clashes with log.h from the Android SDK.
|
||||
// That header file uses
|
||||
// __attribute__ ((format(printf, 3, 4)))
|
||||
// which gets messed up by our override mechanism; this could
|
||||
// be avoided by either changing the Android SDK to use the equally
|
||||
// legal and valid
|
||||
// __attribute__ ((format(printf, 3, 4)))
|
||||
// or by refining our printf override to use a varadic macro
|
||||
// (which then wouldn't be portable, though).
|
||||
// Anyway, for now we just disable the printf override globally
|
||||
// for the Android port
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_printf
|
||||
|
||||
#include "common/endian.h"
|
||||
#include "graphics/conversion.h"
|
||||
|
||||
#include "backends/platform/android/android.h"
|
||||
#include "backends/platform/android/jni.h"
|
||||
|
||||
static inline GLfixed xdiv(int numerator, int denominator) {
|
||||
assert(numerator < (1 << 16));
|
||||
return (numerator << 16) / denominator;
|
||||
}
|
||||
|
||||
const OSystem::GraphicsMode *OSystem_Android::getSupportedGraphicsModes() const {
|
||||
static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
|
||||
{ "default", "Default", 0 },
|
||||
{ "filter", "Linear filtering", 1 },
|
||||
{ 0, 0, 0 },
|
||||
};
|
||||
|
||||
return s_supportedGraphicsModes;
|
||||
}
|
||||
|
||||
int OSystem_Android::getDefaultGraphicsMode() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool OSystem_Android::setGraphicsMode(int mode) {
|
||||
ENTER("%d", mode);
|
||||
|
||||
if (_game_texture)
|
||||
_game_texture->setLinearFilter(mode == 1);
|
||||
|
||||
if (_overlay_texture)
|
||||
_overlay_texture->setLinearFilter(mode == 1);
|
||||
|
||||
if (_mouse_texture)
|
||||
_mouse_texture->setLinearFilter(mode == 1);
|
||||
|
||||
_graphicsMode = mode;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int OSystem_Android::getGraphicsMode() const {
|
||||
return _graphicsMode;
|
||||
}
|
||||
|
||||
#ifdef USE_RGB_COLOR
|
||||
Graphics::PixelFormat OSystem_Android::getScreenFormat() const {
|
||||
return _game_texture->getPixelFormat();
|
||||
}
|
||||
|
||||
Common::List<Graphics::PixelFormat> OSystem_Android::getSupportedFormats() const {
|
||||
Common::List<Graphics::PixelFormat> res;
|
||||
res.push_back(GLES565Texture::pixelFormat());
|
||||
res.push_back(GLES5551Texture::pixelFormat());
|
||||
res.push_back(GLES8888Texture::pixelFormat());
|
||||
res.push_back(GLES4444Texture::pixelFormat());
|
||||
res.push_back(Graphics::PixelFormat::createFormatCLUT8());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void OSystem_Android::initTexture(GLESBaseTexture **texture,
|
||||
uint width, uint height,
|
||||
const Graphics::PixelFormat *format) {
|
||||
assert(texture);
|
||||
Graphics::PixelFormat format_clut8 =
|
||||
Graphics::PixelFormat::createFormatCLUT8();
|
||||
Graphics::PixelFormat format_current;
|
||||
Graphics::PixelFormat format_new;
|
||||
|
||||
if (*texture)
|
||||
format_current = (*texture)->getPixelFormat();
|
||||
else
|
||||
format_current = Graphics::PixelFormat();
|
||||
|
||||
if (format)
|
||||
format_new = *format;
|
||||
else
|
||||
format_new = format_clut8;
|
||||
|
||||
if (format_current != format_new) {
|
||||
if (*texture)
|
||||
LOGD("switching pixel format from: %s",
|
||||
(*texture)->getPixelFormat().toString().c_str());
|
||||
|
||||
delete *texture;
|
||||
|
||||
if (format_new == GLES565Texture::pixelFormat())
|
||||
*texture = new GLES565Texture();
|
||||
else if (format_new == GLES5551Texture::pixelFormat())
|
||||
*texture = new GLES5551Texture();
|
||||
else if (format_new == GLES8888Texture::pixelFormat())
|
||||
*texture = new GLES8888Texture();
|
||||
else if (format_new == GLES4444Texture::pixelFormat())
|
||||
*texture = new GLES4444Texture();
|
||||
else {
|
||||
// TODO what now?
|
||||
if (format_new != format_clut8)
|
||||
LOGE("unsupported pixel format: %s",
|
||||
format_new.toString().c_str());
|
||||
|
||||
*texture = new GLESFakePalette565Texture;
|
||||
}
|
||||
|
||||
LOGD("new pixel format: %s",
|
||||
(*texture)->getPixelFormat().toString().c_str());
|
||||
}
|
||||
|
||||
(*texture)->allocBuffer(width, height);
|
||||
}
|
||||
#endif
|
||||
|
||||
void OSystem_Android::initSurface() {
|
||||
LOGD("initializing surface");
|
||||
|
||||
assert(!JNI::haveSurface());
|
||||
|
||||
_screen_changeid = JNI::surface_changeid;
|
||||
_egl_surface_width = JNI::egl_surface_width;
|
||||
_egl_surface_height = JNI::egl_surface_height;
|
||||
|
||||
assert(_egl_surface_width > 0 && _egl_surface_height > 0);
|
||||
|
||||
JNI::initSurface();
|
||||
|
||||
// Initialize OpenGLES context.
|
||||
GLESTexture::initGLExtensions();
|
||||
|
||||
if (_game_texture)
|
||||
_game_texture->reinit();
|
||||
|
||||
if (_overlay_texture) {
|
||||
_overlay_texture->reinit();
|
||||
initOverlay();
|
||||
}
|
||||
|
||||
if (_mouse_texture)
|
||||
_mouse_texture->reinit();
|
||||
}
|
||||
|
||||
void OSystem_Android::deinitSurface() {
|
||||
if (!JNI::haveSurface())
|
||||
return;
|
||||
|
||||
LOGD("deinitializing surface");
|
||||
|
||||
_screen_changeid = JNI::surface_changeid;
|
||||
_egl_surface_width = 0;
|
||||
_egl_surface_height = 0;
|
||||
|
||||
// release texture resources
|
||||
if (_game_texture)
|
||||
_game_texture->release();
|
||||
|
||||
if (_overlay_texture)
|
||||
_overlay_texture->release();
|
||||
|
||||
if (_mouse_texture)
|
||||
_mouse_texture->release();
|
||||
|
||||
JNI::deinitSurface();
|
||||
}
|
||||
|
||||
void OSystem_Android::initViewport() {
|
||||
LOGD("initializing viewport");
|
||||
|
||||
assert(JNI::haveSurface());
|
||||
|
||||
// Turn off anything that looks like 3D ;)
|
||||
GLCALL(glDisable(GL_CULL_FACE));
|
||||
GLCALL(glDisable(GL_DEPTH_TEST));
|
||||
GLCALL(glDisable(GL_LIGHTING));
|
||||
GLCALL(glDisable(GL_FOG));
|
||||
GLCALL(glDisable(GL_DITHER));
|
||||
|
||||
GLCALL(glShadeModel(GL_FLAT));
|
||||
GLCALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST));
|
||||
|
||||
GLCALL(glEnable(GL_BLEND));
|
||||
GLCALL(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
GLCALL(glEnableClientState(GL_VERTEX_ARRAY));
|
||||
GLCALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
|
||||
|
||||
GLCALL(glEnable(GL_TEXTURE_2D));
|
||||
|
||||
GLCALL(glViewport(0, 0, _egl_surface_width, _egl_surface_height));
|
||||
|
||||
GLCALL(glMatrixMode(GL_PROJECTION));
|
||||
GLCALL(glLoadIdentity());
|
||||
GLCALL(glOrthof(0, _egl_surface_width, _egl_surface_height, 0, -1, 1));
|
||||
GLCALL(glMatrixMode(GL_MODELVIEW));
|
||||
GLCALL(glLoadIdentity());
|
||||
|
||||
clearFocusRectangle();
|
||||
}
|
||||
|
||||
void OSystem_Android::initOverlay() {
|
||||
// minimum of 320x200
|
||||
// (surface can get smaller when opening the virtual keyboard on *QVGA*)
|
||||
int overlay_width = MAX(_egl_surface_width, 320);
|
||||
int overlay_height = MAX(_egl_surface_height, 200);
|
||||
|
||||
// the 'normal' theme layout uses a max height of 400 pixels. if the
|
||||
// surface is too big we use only a quarter of the size so that the widgets
|
||||
// don't get too small. if the surface height has less than 800 pixels, this
|
||||
// enforces the 'lowres' layout, which will be scaled back up by factor 2x,
|
||||
// but this looks way better than the 'normal' layout scaled by some
|
||||
// calculated factors
|
||||
while (overlay_height > 480) {
|
||||
overlay_width /= 2;
|
||||
overlay_height /= 2;
|
||||
}
|
||||
|
||||
LOGI("overlay size is %ux%u", overlay_width, overlay_height);
|
||||
|
||||
_overlay_texture->allocBuffer(overlay_width, overlay_height);
|
||||
_overlay_texture->setDrawRect(0, 0,
|
||||
_egl_surface_width, _egl_surface_height);
|
||||
}
|
||||
|
||||
void OSystem_Android::initSize(uint width, uint height,
|
||||
const Graphics::PixelFormat *format) {
|
||||
ENTER("%d, %d, %p", width, height, format);
|
||||
|
||||
GLTHREADCHECK;
|
||||
|
||||
#ifdef USE_RGB_COLOR
|
||||
initTexture(&_game_texture, width, height, format);
|
||||
#else
|
||||
_game_texture->allocBuffer(width, height);
|
||||
#endif
|
||||
|
||||
updateScreenRect();
|
||||
updateEventScale();
|
||||
|
||||
// Don't know mouse size yet - it gets reallocated in
|
||||
// setMouseCursor. We need the palette allocated before
|
||||
// setMouseCursor however, so just take a guess at the desired
|
||||
// size (it's small).
|
||||
_mouse_texture_palette->allocBuffer(20, 20);
|
||||
|
||||
clearScreen(kClear);
|
||||
}
|
||||
|
||||
void OSystem_Android::clearScreen(FixupType type, byte count) {
|
||||
assert(count > 0);
|
||||
|
||||
bool sm = _show_mouse;
|
||||
_show_mouse = false;
|
||||
|
||||
GLCALL(glDisable(GL_SCISSOR_TEST));
|
||||
|
||||
for (byte i = 0; i < count; ++i) {
|
||||
// clear screen
|
||||
GLCALL(glClearColorx(0, 0, 0, 1 << 16));
|
||||
GLCALL(glClear(GL_COLOR_BUFFER_BIT));
|
||||
|
||||
switch (type) {
|
||||
case kClear:
|
||||
break;
|
||||
|
||||
case kClearSwap:
|
||||
JNI::swapBuffers();
|
||||
break;
|
||||
|
||||
case kClearUpdate:
|
||||
_force_redraw = true;
|
||||
updateScreen();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_show_overlay)
|
||||
GLCALL(glEnable(GL_SCISSOR_TEST));
|
||||
|
||||
_show_mouse = sm;
|
||||
_force_redraw = true;
|
||||
}
|
||||
|
||||
void OSystem_Android::updateScreenRect() {
|
||||
Common::Rect rect(0, 0, _egl_surface_width, _egl_surface_height);
|
||||
|
||||
_overlay_texture->setDrawRect(rect);
|
||||
|
||||
uint16 w = _game_texture->width();
|
||||
uint16 h = _game_texture->height();
|
||||
|
||||
if (w && h && !_fullscreen) {
|
||||
if (_ar_correction && w == 320 && h == 200)
|
||||
h = 240;
|
||||
|
||||
float dpi[2];
|
||||
JNI::getDPI(dpi);
|
||||
|
||||
float screen_ar;
|
||||
if (dpi[0] != 0.0 && dpi[1] != 0.0) {
|
||||
// horizontal orientation
|
||||
screen_ar = (dpi[1] * _egl_surface_width) /
|
||||
(dpi[0] * _egl_surface_height);
|
||||
} else {
|
||||
screen_ar = float(_egl_surface_width) / float(_egl_surface_height);
|
||||
}
|
||||
|
||||
float game_ar = float(w) / float(h);
|
||||
|
||||
if (screen_ar > game_ar) {
|
||||
rect.setWidth(round(_egl_surface_height * game_ar));
|
||||
rect.moveTo((_egl_surface_width - rect.width()) / 2, 0);
|
||||
} else {
|
||||
rect.setHeight(round(_egl_surface_width / game_ar));
|
||||
rect.moveTo((_egl_surface_height - rect.height()) / 2, 0);
|
||||
}
|
||||
}
|
||||
|
||||
glScissor(rect.left, rect.top, rect.width(), rect.height());
|
||||
|
||||
_game_texture->setDrawRect(rect);
|
||||
}
|
||||
|
||||
int OSystem_Android::getScreenChangeID() const {
|
||||
return _screen_changeid;
|
||||
}
|
||||
|
||||
int16 OSystem_Android::getHeight() {
|
||||
return _game_texture->height();
|
||||
}
|
||||
|
||||
int16 OSystem_Android::getWidth() {
|
||||
return _game_texture->width();
|
||||
}
|
||||
|
||||
void OSystem_Android::setPalette(const byte *colors, uint start, uint num) {
|
||||
ENTER("%p, %u, %u", colors, start, num);
|
||||
|
||||
#ifdef USE_RGB_COLOR
|
||||
assert(_game_texture->hasPalette());
|
||||
#endif
|
||||
|
||||
GLTHREADCHECK;
|
||||
|
||||
if (!_use_mouse_palette)
|
||||
setCursorPaletteInternal(colors, start, num);
|
||||
|
||||
const Graphics::PixelFormat &pf = _game_texture->getPalettePixelFormat();
|
||||
byte *p = _game_texture->palette() + start * 2;
|
||||
|
||||
for (uint i = 0; i < num; ++i, colors += 3, p += 2)
|
||||
WRITE_UINT16(p, pf.RGBToColor(colors[0], colors[1], colors[2]));
|
||||
}
|
||||
|
||||
void OSystem_Android::grabPalette(byte *colors, uint start, uint num) const {
|
||||
ENTER("%p, %u, %u", colors, start, num);
|
||||
|
||||
#ifdef USE_RGB_COLOR
|
||||
assert(_game_texture->hasPalette());
|
||||
#endif
|
||||
|
||||
GLTHREADCHECK;
|
||||
|
||||
const Graphics::PixelFormat &pf = _game_texture->getPalettePixelFormat();
|
||||
const byte *p = _game_texture->palette_const() + start * 2;
|
||||
|
||||
for (uint i = 0; i < num; ++i, colors += 3, p += 2)
|
||||
pf.colorToRGB(READ_UINT16(p), colors[0], colors[1], colors[2]);
|
||||
}
|
||||
|
||||
void OSystem_Android::copyRectToScreen(const void *buf, int pitch,
|
||||
int x, int y, int w, int h) {
|
||||
ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h);
|
||||
|
||||
GLTHREADCHECK;
|
||||
|
||||
_game_texture->updateBuffer(x, y, w, h, buf, pitch);
|
||||
}
|
||||
|
||||
void OSystem_Android::updateScreen() {
|
||||
//ENTER();
|
||||
|
||||
GLTHREADCHECK;
|
||||
|
||||
if (!JNI::haveSurface())
|
||||
return;
|
||||
|
||||
if (!_force_redraw &&
|
||||
!_game_texture->dirty() &&
|
||||
!_overlay_texture->dirty() &&
|
||||
!_mouse_texture->dirty())
|
||||
return;
|
||||
|
||||
_force_redraw = false;
|
||||
|
||||
// clear pointer leftovers in dead areas
|
||||
// also, HTC's GLES drivers are made of fail and don't preserve the buffer
|
||||
// ( http://www.khronos.org/registry/egl/specs/EGLTechNote0001.html )
|
||||
if ((_show_overlay || _htc_fail) && !_fullscreen)
|
||||
clearScreen(kClear);
|
||||
|
||||
GLCALL(glPushMatrix());
|
||||
|
||||
if (_shake_offset != 0 ||
|
||||
(!_focus_rect.isEmpty() &&
|
||||
!Common::Rect(_game_texture->width(),
|
||||
_game_texture->height()).contains(_focus_rect))) {
|
||||
// These are the only cases where _game_texture doesn't
|
||||
// cover the entire screen.
|
||||
clearScreen(kClear);
|
||||
|
||||
// Move everything up by _shake_offset (game) pixels
|
||||
GLCALL(glTranslatex(0, -_shake_offset << 16, 0));
|
||||
}
|
||||
|
||||
// TODO this doesn't work on those sucky drivers, do it differently
|
||||
// if (_show_overlay)
|
||||
// GLCALL(glColor4ub(0x9f, 0x9f, 0x9f, 0x9f));
|
||||
|
||||
if (_focus_rect.isEmpty()) {
|
||||
_game_texture->drawTextureRect();
|
||||
} else {
|
||||
GLCALL(glPushMatrix());
|
||||
|
||||
GLCALL(glScalex(xdiv(_egl_surface_width, _focus_rect.width()),
|
||||
xdiv(_egl_surface_height, _focus_rect.height()),
|
||||
1 << 16));
|
||||
GLCALL(glTranslatex(-_focus_rect.left << 16,
|
||||
-_focus_rect.top << 16, 0));
|
||||
GLCALL(glScalex(xdiv(_game_texture->width(), _egl_surface_width),
|
||||
xdiv(_game_texture->height(), _egl_surface_height),
|
||||
1 << 16));
|
||||
|
||||
_game_texture->drawTextureRect();
|
||||
|
||||
GLCALL(glPopMatrix());
|
||||
}
|
||||
|
||||
int cs = _mouse_targetscale;
|
||||
|
||||
if (_show_overlay) {
|
||||
// TODO see above
|
||||
// GLCALL(glColor4ub(0xff, 0xff, 0xff, 0xff));
|
||||
|
||||
// ugly, but the modern theme sets a wacko factor, only god knows why
|
||||
cs = 1;
|
||||
|
||||
GLCALL(_overlay_texture->drawTextureRect());
|
||||
}
|
||||
|
||||
if (_show_mouse && !_mouse_texture->isEmpty()) {
|
||||
GLCALL(glPushMatrix());
|
||||
|
||||
const Common::Point &mouse = getEventManager()->getMousePos();
|
||||
|
||||
// Scale up ScummVM -> OpenGL (pixel) coordinates
|
||||
if (_show_overlay) {
|
||||
GLCALL(glScalex(xdiv(_egl_surface_width,
|
||||
_overlay_texture->width()),
|
||||
xdiv(_egl_surface_height,
|
||||
_overlay_texture->height()),
|
||||
1 << 16));
|
||||
} else {
|
||||
const Common::Rect &r = _game_texture->getDrawRect();
|
||||
|
||||
GLCALL(glTranslatex(r.left << 16,
|
||||
r.top << 16,
|
||||
0));
|
||||
GLCALL(glScalex(xdiv(r.width(), _game_texture->width()),
|
||||
xdiv(r.height(), _game_texture->height()),
|
||||
1 << 16));
|
||||
}
|
||||
|
||||
GLCALL(glTranslatex((-_mouse_hotspot.x * cs) << 16,
|
||||
(-_mouse_hotspot.y * cs) << 16,
|
||||
0));
|
||||
|
||||
// Note the extra half texel to position the mouse in
|
||||
// the middle of the x,y square:
|
||||
GLCALL(glTranslatex((mouse.x << 16) | 1 << 15,
|
||||
(mouse.y << 16) | 1 << 15, 0));
|
||||
|
||||
GLCALL(glScalex(cs << 16, cs << 16, 1 << 16));
|
||||
|
||||
_mouse_texture->drawTextureOrigin();
|
||||
|
||||
GLCALL(glPopMatrix());
|
||||
}
|
||||
|
||||
GLCALL(glPopMatrix());
|
||||
|
||||
if (!JNI::swapBuffers())
|
||||
LOGW("swapBuffers failed: 0x%x", glGetError());
|
||||
}
|
||||
|
||||
Graphics::Surface *OSystem_Android::lockScreen() {
|
||||
ENTER();
|
||||
|
||||
GLTHREADCHECK;
|
||||
|
||||
Graphics::Surface *surface = _game_texture->surface();
|
||||
assert(surface->getPixels());
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
void OSystem_Android::unlockScreen() {
|
||||
ENTER();
|
||||
|
||||
GLTHREADCHECK;
|
||||
|
||||
assert(_game_texture->dirty());
|
||||
}
|
||||
|
||||
void OSystem_Android::setShakePos(int shake_offset) {
|
||||
ENTER("%d", shake_offset);
|
||||
|
||||
if (_shake_offset != shake_offset) {
|
||||
_shake_offset = shake_offset;
|
||||
_force_redraw = true;
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_Android::fillScreen(uint32 col) {
|
||||
ENTER("%u", col);
|
||||
|
||||
GLTHREADCHECK;
|
||||
|
||||
_game_texture->fillBuffer(col);
|
||||
}
|
||||
|
||||
void OSystem_Android::setFocusRectangle(const Common::Rect& rect) {
|
||||
ENTER("%d, %d, %d, %d", rect.left, rect.top, rect.right, rect.bottom);
|
||||
|
||||
if (_enable_zoning) {
|
||||
_focus_rect = rect;
|
||||
_force_redraw = true;
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_Android::clearFocusRectangle() {
|
||||
ENTER();
|
||||
|
||||
if (_enable_zoning) {
|
||||
_focus_rect = Common::Rect();
|
||||
_force_redraw = true;
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_Android::showOverlay() {
|
||||
ENTER();
|
||||
|
||||
_show_overlay = true;
|
||||
_force_redraw = true;
|
||||
|
||||
updateEventScale();
|
||||
|
||||
warpMouse(_overlay_texture->width() / 2, _overlay_texture->height() / 2);
|
||||
|
||||
GLCALL(glDisable(GL_SCISSOR_TEST));
|
||||
}
|
||||
|
||||
void OSystem_Android::hideOverlay() {
|
||||
ENTER();
|
||||
|
||||
_show_overlay = false;
|
||||
|
||||
updateEventScale();
|
||||
|
||||
warpMouse(_game_texture->width() / 2, _game_texture->height() / 2);
|
||||
|
||||
// double buffered, flip twice
|
||||
clearScreen(kClearUpdate, 2);
|
||||
|
||||
GLCALL(glEnable(GL_SCISSOR_TEST));
|
||||
}
|
||||
|
||||
void OSystem_Android::clearOverlay() {
|
||||
ENTER();
|
||||
|
||||
GLTHREADCHECK;
|
||||
|
||||
_overlay_texture->fillBuffer(0);
|
||||
}
|
||||
|
||||
void OSystem_Android::grabOverlay(void *buf, int pitch) {
|
||||
ENTER("%p, %d", buf, pitch);
|
||||
|
||||
GLTHREADCHECK;
|
||||
|
||||
const Graphics::Surface *surface = _overlay_texture->surface_const();
|
||||
assert(surface->format.bytesPerPixel == sizeof(uint16));
|
||||
|
||||
byte *dst = (byte *)buf;
|
||||
const byte *src = (const byte *)surface->getPixels();
|
||||
uint h = surface->h;
|
||||
|
||||
do {
|
||||
memcpy(dst, src, surface->w * surface->format.bytesPerPixel);
|
||||
src += surface->pitch;
|
||||
dst += pitch;
|
||||
} while (--h);
|
||||
}
|
||||
|
||||
void OSystem_Android::copyRectToOverlay(const void *buf, int pitch,
|
||||
int x, int y, int w, int h) {
|
||||
ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h);
|
||||
|
||||
GLTHREADCHECK;
|
||||
|
||||
_overlay_texture->updateBuffer(x, y, w, h, buf, pitch);
|
||||
}
|
||||
|
||||
int16 OSystem_Android::getOverlayHeight() {
|
||||
return _overlay_texture->height();
|
||||
}
|
||||
|
||||
int16 OSystem_Android::getOverlayWidth() {
|
||||
return _overlay_texture->width();
|
||||
}
|
||||
|
||||
Graphics::PixelFormat OSystem_Android::getOverlayFormat() const {
|
||||
return _overlay_texture->getPixelFormat();
|
||||
}
|
||||
|
||||
bool OSystem_Android::showMouse(bool visible) {
|
||||
ENTER("%d", visible);
|
||||
|
||||
_show_mouse = visible;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OSystem_Android::setMouseCursor(const void *buf, uint w, uint h,
|
||||
int hotspotX, int hotspotY,
|
||||
uint32 keycolor, bool dontScale,
|
||||
const Graphics::PixelFormat *format) {
|
||||
ENTER("%p, %u, %u, %d, %d, %u, %d, %p", buf, w, h, hotspotX, hotspotY,
|
||||
keycolor, dontScale, format);
|
||||
|
||||
GLTHREADCHECK;
|
||||
|
||||
#ifdef USE_RGB_COLOR
|
||||
if (format && format->bytesPerPixel > 1) {
|
||||
if (_mouse_texture != _mouse_texture_rgb) {
|
||||
LOGD("switching to rgb mouse cursor");
|
||||
|
||||
assert(!_mouse_texture_rgb);
|
||||
_mouse_texture_rgb = new GLES5551Texture();
|
||||
_mouse_texture_rgb->setLinearFilter(_graphicsMode == 1);
|
||||
}
|
||||
|
||||
_mouse_texture = _mouse_texture_rgb;
|
||||
} else {
|
||||
if (_mouse_texture != _mouse_texture_palette)
|
||||
LOGD("switching to paletted mouse cursor");
|
||||
|
||||
_mouse_texture = _mouse_texture_palette;
|
||||
|
||||
delete _mouse_texture_rgb;
|
||||
_mouse_texture_rgb = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
_mouse_texture->allocBuffer(w, h);
|
||||
|
||||
if (_mouse_texture == _mouse_texture_palette) {
|
||||
assert(keycolor < 256);
|
||||
|
||||
byte *p = _mouse_texture_palette->palette() + _mouse_keycolor * 2;
|
||||
WRITE_UINT16(p, READ_UINT16(p) | 1);
|
||||
|
||||
_mouse_keycolor = keycolor;
|
||||
|
||||
p = _mouse_texture_palette->palette() + _mouse_keycolor * 2;
|
||||
WRITE_UINT16(p, 0);
|
||||
}
|
||||
|
||||
if (w == 0 || h == 0)
|
||||
return;
|
||||
|
||||
if (_mouse_texture == _mouse_texture_palette) {
|
||||
_mouse_texture->updateBuffer(0, 0, w, h, buf, w);
|
||||
} else {
|
||||
uint16 pitch = _mouse_texture->pitch();
|
||||
|
||||
byte *tmp = new byte[pitch * h];
|
||||
|
||||
// meh, a 16bit cursor without alpha bits... this is so silly
|
||||
if (!crossBlit(tmp, (const byte *)buf, pitch, w * 2, w, h,
|
||||
_mouse_texture->getPixelFormat(),
|
||||
*format)) {
|
||||
LOGE("crossblit failed");
|
||||
|
||||
delete[] tmp;
|
||||
|
||||
_mouse_texture->allocBuffer(0, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const uint16 *s = (const uint16 *)buf;
|
||||
uint16 *d = (uint16 *)tmp;
|
||||
for (uint16 y = 0; y < h; ++y, d += pitch / 2 - w)
|
||||
for (uint16 x = 0; x < w; ++x, d++)
|
||||
if (*s++ == (keycolor & 0xffff))
|
||||
*d = 0;
|
||||
|
||||
_mouse_texture->updateBuffer(0, 0, w, h, tmp, pitch);
|
||||
|
||||
delete[] tmp;
|
||||
}
|
||||
|
||||
_mouse_hotspot = Common::Point(hotspotX, hotspotY);
|
||||
// TODO: Adapt to the new "do not scale" cursor logic.
|
||||
_mouse_targetscale = 1;
|
||||
}
|
||||
|
||||
void OSystem_Android::setCursorPaletteInternal(const byte *colors,
|
||||
uint start, uint num) {
|
||||
const Graphics::PixelFormat &pf =
|
||||
_mouse_texture_palette->getPalettePixelFormat();
|
||||
byte *p = _mouse_texture_palette->palette() + start * 2;
|
||||
|
||||
for (uint i = 0; i < num; ++i, colors += 3, p += 2)
|
||||
WRITE_UINT16(p, pf.RGBToColor(colors[0], colors[1], colors[2]));
|
||||
|
||||
p = _mouse_texture_palette->palette() + _mouse_keycolor * 2;
|
||||
WRITE_UINT16(p, 0);
|
||||
}
|
||||
|
||||
void OSystem_Android::setCursorPalette(const byte *colors,
|
||||
uint start, uint num) {
|
||||
ENTER("%p, %u, %u", colors, start, num);
|
||||
|
||||
GLTHREADCHECK;
|
||||
|
||||
if (!_mouse_texture->hasPalette()) {
|
||||
LOGD("switching to paletted mouse cursor");
|
||||
|
||||
_mouse_texture = _mouse_texture_palette;
|
||||
|
||||
delete _mouse_texture_rgb;
|
||||
_mouse_texture_rgb = 0;
|
||||
}
|
||||
|
||||
setCursorPaletteInternal(colors, start, num);
|
||||
_use_mouse_palette = true;
|
||||
}
|
||||
|
||||
void OSystem_Android::disableCursorPalette() {
|
||||
// when disabling the cursor palette, and we're running a clut8 game,
|
||||
// it expects the game palette to be used for the cursor
|
||||
if (_game_texture->hasPalette()) {
|
||||
const byte *src = _game_texture->palette_const();
|
||||
byte *dst = _mouse_texture_palette->palette();
|
||||
|
||||
const Graphics::PixelFormat &pf_src =
|
||||
_game_texture->getPalettePixelFormat();
|
||||
const Graphics::PixelFormat &pf_dst =
|
||||
_mouse_texture_palette->getPalettePixelFormat();
|
||||
|
||||
uint8 r, g, b;
|
||||
|
||||
for (uint i = 0; i < 256; ++i, src += 2, dst += 2) {
|
||||
pf_src.colorToRGB(READ_UINT16(src), r, g, b);
|
||||
WRITE_UINT16(dst, pf_dst.RGBToColor(r, g, b));
|
||||
}
|
||||
|
||||
byte *p = _mouse_texture_palette->palette() + _mouse_keycolor * 2;
|
||||
WRITE_UINT16(p, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
134
backends/platform/android/graphics.cpp
Normal file
134
backends/platform/android/graphics.cpp
Normal file
|
@ -0,0 +1,134 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
// Allow use of stuff in <time.h>
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
|
||||
|
||||
// Disable printf override in common/forbidden.h to avoid
|
||||
// clashes with log.h from the Android SDK.
|
||||
// That header file uses
|
||||
// __attribute__ ((format(printf, 3, 4)))
|
||||
// which gets messed up by our override mechanism; this could
|
||||
// be avoided by either changing the Android SDK to use the equally
|
||||
// legal and valid
|
||||
// __attribute__ ((format(printf, 3, 4)))
|
||||
// or by refining our printf override to use a varadic macro
|
||||
// (which then wouldn't be portable, though).
|
||||
// Anyway, for now we just disable the printf override globally
|
||||
// for the Android port
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_printf
|
||||
|
||||
#include "backends/platform/android/android.h"
|
||||
#include "backends/platform/android/graphics.h"
|
||||
#include "backends/platform/android/jni.h"
|
||||
|
||||
//
|
||||
// AndroidGraphicsManager
|
||||
//
|
||||
AndroidGraphicsManager::AndroidGraphicsManager() {
|
||||
ENTER();
|
||||
|
||||
// Initialize our OpenGL ES context.
|
||||
initSurface();
|
||||
|
||||
}
|
||||
|
||||
AndroidGraphicsManager::~AndroidGraphicsManager() {
|
||||
ENTER();
|
||||
|
||||
deinitSurface();
|
||||
}
|
||||
|
||||
void AndroidGraphicsManager::initSurface() {
|
||||
LOGD("initializing surface");
|
||||
|
||||
assert(!JNI::haveSurface());
|
||||
JNI::initSurface();
|
||||
|
||||
// Notify the OpenGL code about our context.
|
||||
// FIXME: Support OpenGL ES 2 contexts
|
||||
setContextType(OpenGL::kContextGLES);
|
||||
|
||||
// We default to RGB565 and RGBA5551 which is closest to the actual output
|
||||
// mode we setup.
|
||||
notifyContextCreate(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0));
|
||||
|
||||
handleResize(JNI::egl_surface_width, JNI::egl_surface_height);
|
||||
}
|
||||
|
||||
void AndroidGraphicsManager::deinitSurface() {
|
||||
if (!JNI::haveSurface())
|
||||
return;
|
||||
|
||||
LOGD("deinitializing surface");
|
||||
|
||||
notifyContextDestroy();
|
||||
|
||||
JNI::deinitSurface();
|
||||
}
|
||||
|
||||
void AndroidGraphicsManager::updateScreen() {
|
||||
//ENTER();
|
||||
|
||||
if (!JNI::haveSurface())
|
||||
return;
|
||||
|
||||
OpenGLGraphicsManager::updateScreen();
|
||||
}
|
||||
|
||||
void AndroidGraphicsManager::displayMessageOnOSD(const char *msg) {
|
||||
ENTER("%s", msg);
|
||||
|
||||
JNI::displayMessageOnOSD(msg);
|
||||
}
|
||||
|
||||
bool AndroidGraphicsManager::loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) {
|
||||
ENTER("%d, %d, %s", requestedWidth, requestedHeight, format.toString().c_str());
|
||||
|
||||
// We get this whenever a new resolution is requested. Since Android is
|
||||
// using a fixed output size we do nothing like that here.
|
||||
// TODO: Support screen rotation
|
||||
return true;
|
||||
}
|
||||
|
||||
void AndroidGraphicsManager::refreshScreen() {
|
||||
//ENTER();
|
||||
|
||||
JNI::swapBuffers();
|
||||
}
|
||||
|
||||
void *AndroidGraphicsManager::getProcAddress(const char *name) const {
|
||||
ENTER("%s", name);
|
||||
|
||||
// TODO: Support dynamically loaded OpenGL
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool AndroidGraphicsManager::notifyMousePosition(Common::Point &mouse) {
|
||||
mouse.x = CLIP<int16>(mouse.x, _activeArea.drawRect.left, _activeArea.drawRect.right);
|
||||
mouse.y = CLIP<int16>(mouse.y, _activeArea.drawRect.top, _activeArea.drawRect.bottom);
|
||||
|
||||
setMousePosition(mouse.x, mouse.y);
|
||||
mouse = convertWindowToVirtual(mouse.x, mouse.y);
|
||||
|
||||
return true;
|
||||
}
|
55
backends/platform/android/graphics.h
Normal file
55
backends/platform/android/graphics.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_GRAPHICS_H
|
||||
#define ANDROID_GRAPHICS_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "backends/graphics/opengl/opengl-graphics.h"
|
||||
|
||||
class AndroidGraphicsManager : public OpenGL::OpenGLGraphicsManager {
|
||||
public:
|
||||
AndroidGraphicsManager();
|
||||
virtual ~AndroidGraphicsManager();
|
||||
|
||||
void initSurface();
|
||||
void deinitSurface();
|
||||
|
||||
void updateScreen();
|
||||
|
||||
void displayMessageOnOSD(const char *msg);
|
||||
|
||||
bool notifyMousePosition(Common::Point &mouse);
|
||||
Common::Point getMousePosition() { return Common::Point(_cursorX, _cursorY); }
|
||||
|
||||
protected:
|
||||
void setSystemMousePosition(int x, int y) {}
|
||||
|
||||
bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format);
|
||||
|
||||
void refreshScreen();
|
||||
|
||||
void *getProcAddress(const char *name) const;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -111,8 +111,6 @@ const JNINativeMethod JNI::_natives[] = {
|
|||
(void *)JNI::main },
|
||||
{ "pushEvent", "(IIIIIII)V",
|
||||
(void *)JNI::pushEvent },
|
||||
{ "enableZoning", "(Z)V",
|
||||
(void *)JNI::enableZoning },
|
||||
{ "setPause", "(Z)V",
|
||||
(void *)JNI::setPause },
|
||||
{ "getCurrentCharset", "()Ljava/lang/String;",
|
||||
|
@ -662,12 +660,6 @@ void JNI::pushEvent(JNIEnv *env, jobject self, int type, int arg1, int arg2,
|
|||
_system->pushEvent(type, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
}
|
||||
|
||||
void JNI::enableZoning(JNIEnv *env, jobject self, jboolean enable) {
|
||||
assert(_system);
|
||||
|
||||
_system->enableZoning(enable);
|
||||
}
|
||||
|
||||
void JNI::setPause(JNIEnv *env, jobject self, jboolean value) {
|
||||
if (!_system)
|
||||
return;
|
||||
|
|
|
@ -132,8 +132,6 @@ private:
|
|||
|
||||
static void pushEvent(JNIEnv *env, jobject self, int type, int arg1,
|
||||
int arg2, int arg3, int arg4, int arg5, int arg6);
|
||||
static void enableZoning(JNIEnv *env, jobject self, jboolean enable);
|
||||
|
||||
static void setPause(JNIEnv *env, jobject self, jboolean value);
|
||||
|
||||
static jstring getCurrentCharset(JNIEnv *env, jobject self);
|
||||
|
|
|
@ -2,10 +2,9 @@ MODULE := backends/platform/android
|
|||
|
||||
MODULE_OBJS := \
|
||||
jni.o \
|
||||
texture.o \
|
||||
asset-archive.o \
|
||||
android.o \
|
||||
gfx.o \
|
||||
graphics.o \
|
||||
events.o
|
||||
|
||||
# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
|
||||
|
|
|
@ -45,7 +45,6 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
|
|||
|
||||
// pause the engine and all native threads
|
||||
final public native void setPause(boolean pause);
|
||||
final public native void enableZoning(boolean enable);
|
||||
// Feed an event to ScummVM. Safe to call from other threads.
|
||||
final public native void pushEvent(int type, int arg1, int arg2, int arg3,
|
||||
int arg4, int arg5, int arg6);
|
||||
|
|
|
@ -53,30 +53,8 @@ public class ScummVMActivity extends Activity {
|
|||
};
|
||||
|
||||
private class MyScummVM extends ScummVM {
|
||||
private boolean usingSmallScreen() {
|
||||
// Multiple screen sizes came in with Android 1.6. Have
|
||||
// to use reflection in order to continue supporting 1.5
|
||||
// devices :(
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
getWindowManager().getDefaultDisplay().getMetrics(metrics);
|
||||
|
||||
try {
|
||||
// This 'density' term is very confusing.
|
||||
int DENSITY_LOW = metrics.getClass().getField("DENSITY_LOW").getInt(null);
|
||||
int densityDpi = metrics.getClass().getField("densityDpi").getInt(metrics);
|
||||
return densityDpi <= DENSITY_LOW;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public MyScummVM(SurfaceHolder holder) {
|
||||
super(ScummVMActivity.this.getAssets(), holder);
|
||||
|
||||
// Enable ScummVM zoning on 'small' screens.
|
||||
// FIXME make this optional for the user
|
||||
// disabled for now since it crops too much
|
||||
//enableZoning(usingSmallScreen());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,476 +0,0 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
// Allow use of stuff in <time.h>
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
|
||||
|
||||
// Disable printf override in common/forbidden.h to avoid
|
||||
// clashes with log.h from the Android SDK.
|
||||
// That header file uses
|
||||
// __attribute__ ((format(printf, 3, 4)))
|
||||
// which gets messed up by our override mechanism; this could
|
||||
// be avoided by either changing the Android SDK to use the equally
|
||||
// legal and valid
|
||||
// __attribute__ ((format(printf, 3, 4)))
|
||||
// or by refining our printf override to use a varadic macro
|
||||
// (which then wouldn't be portable, though).
|
||||
// Anyway, for now we just disable the printf override globally
|
||||
// for the Android port
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_printf
|
||||
|
||||
#include "base/main.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "common/rect.h"
|
||||
#include "common/array.h"
|
||||
#include "common/util.h"
|
||||
#include "common/tokenizer.h"
|
||||
|
||||
#include "backends/platform/android/texture.h"
|
||||
#include "backends/platform/android/android.h"
|
||||
|
||||
// Supported GL extensions
|
||||
static bool npot_supported = false;
|
||||
|
||||
static inline GLfixed xdiv(int numerator, int denominator) {
|
||||
assert(numerator < (1 << 16));
|
||||
return (numerator << 16) / denominator;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static T nextHigher2(T k) {
|
||||
if (k == 0)
|
||||
return 1;
|
||||
--k;
|
||||
|
||||
for (uint i = 1; i < sizeof(T) * CHAR_BIT; i <<= 1)
|
||||
k = k | k >> i;
|
||||
|
||||
return k + 1;
|
||||
}
|
||||
|
||||
void GLESBaseTexture::initGLExtensions() {
|
||||
const char *ext_string =
|
||||
reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
|
||||
|
||||
LOGI("Extensions: %s", ext_string);
|
||||
|
||||
Common::StringTokenizer tokenizer(ext_string, " ");
|
||||
while (!tokenizer.empty()) {
|
||||
Common::String token = tokenizer.nextToken();
|
||||
|
||||
if (token == "GL_ARB_texture_non_power_of_two")
|
||||
npot_supported = true;
|
||||
}
|
||||
}
|
||||
|
||||
GLESBaseTexture::GLESBaseTexture(GLenum glFormat, GLenum glType,
|
||||
Graphics::PixelFormat pixelFormat) :
|
||||
_glFormat(glFormat),
|
||||
_glType(glType),
|
||||
_glFilter(GL_NEAREST),
|
||||
_texture_name(0),
|
||||
_surface(),
|
||||
_texture_width(0),
|
||||
_texture_height(0),
|
||||
_draw_rect(),
|
||||
_all_dirty(false),
|
||||
_dirty_rect(),
|
||||
_pixelFormat(pixelFormat),
|
||||
_palettePixelFormat()
|
||||
{
|
||||
GLCALL(glGenTextures(1, &_texture_name));
|
||||
}
|
||||
|
||||
GLESBaseTexture::~GLESBaseTexture() {
|
||||
release();
|
||||
}
|
||||
|
||||
void GLESBaseTexture::release() {
|
||||
if (_texture_name) {
|
||||
LOGD("Destroying texture %u", _texture_name);
|
||||
|
||||
GLCALL(glDeleteTextures(1, &_texture_name));
|
||||
_texture_name = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GLESBaseTexture::reinit() {
|
||||
GLCALL(glGenTextures(1, &_texture_name));
|
||||
|
||||
initSize();
|
||||
|
||||
setDirty();
|
||||
}
|
||||
|
||||
void GLESBaseTexture::initSize() {
|
||||
// Allocate room for the texture now, but pixel data gets uploaded
|
||||
// later (perhaps with multiple TexSubImage2D operations).
|
||||
GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter));
|
||||
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter));
|
||||
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, _glFormat,
|
||||
_texture_width, _texture_height,
|
||||
0, _glFormat, _glType, 0));
|
||||
}
|
||||
|
||||
void GLESBaseTexture::setLinearFilter(bool value) {
|
||||
if (value)
|
||||
_glFilter = GL_LINEAR;
|
||||
else
|
||||
_glFilter = GL_NEAREST;
|
||||
|
||||
GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
|
||||
|
||||
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter));
|
||||
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter));
|
||||
}
|
||||
|
||||
void GLESBaseTexture::allocBuffer(GLuint w, GLuint h) {
|
||||
_surface.w = w;
|
||||
_surface.h = h;
|
||||
_surface.format = _pixelFormat;
|
||||
|
||||
if (w == _texture_width && h == _texture_height)
|
||||
return;
|
||||
|
||||
if (npot_supported) {
|
||||
_texture_width = _surface.w;
|
||||
_texture_height = _surface.h;
|
||||
} else {
|
||||
_texture_width = nextHigher2(_surface.w);
|
||||
_texture_height = nextHigher2(_surface.h);
|
||||
}
|
||||
|
||||
initSize();
|
||||
}
|
||||
|
||||
void GLESBaseTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
|
||||
GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
|
||||
|
||||
const GLfixed tex_width = xdiv(_surface.w, _texture_width);
|
||||
const GLfixed tex_height = xdiv(_surface.h, _texture_height);
|
||||
const GLfixed texcoords[] = {
|
||||
0, 0,
|
||||
tex_width, 0,
|
||||
0, tex_height,
|
||||
tex_width, tex_height,
|
||||
};
|
||||
|
||||
GLCALL(glTexCoordPointer(2, GL_FIXED, 0, texcoords));
|
||||
|
||||
const GLshort vertices[] = {
|
||||
x, y,
|
||||
GLshort(x + w), y,
|
||||
x, GLshort(y + h),
|
||||
GLshort(x + w), GLshort(y + h)
|
||||
};
|
||||
|
||||
GLCALL(glVertexPointer(2, GL_SHORT, 0, vertices));
|
||||
|
||||
assert(ARRAYSIZE(vertices) == ARRAYSIZE(texcoords));
|
||||
GLCALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, ARRAYSIZE(vertices) / 2));
|
||||
|
||||
clearDirty();
|
||||
}
|
||||
|
||||
const Graphics::PixelFormat &GLESBaseTexture::getPixelFormat() const {
|
||||
return _pixelFormat;
|
||||
}
|
||||
|
||||
GLESTexture::GLESTexture(GLenum glFormat, GLenum glType,
|
||||
Graphics::PixelFormat pixelFormat) :
|
||||
GLESBaseTexture(glFormat, glType, pixelFormat),
|
||||
_pixels(0),
|
||||
_buf(0) {
|
||||
}
|
||||
|
||||
GLESTexture::~GLESTexture() {
|
||||
delete[] _buf;
|
||||
delete[] _pixels;
|
||||
}
|
||||
|
||||
void GLESTexture::allocBuffer(GLuint w, GLuint h) {
|
||||
GLuint oldw = _surface.w;
|
||||
GLuint oldh = _surface.h;
|
||||
|
||||
GLESBaseTexture::allocBuffer(w, h);
|
||||
|
||||
_surface.pitch = w * _pixelFormat.bytesPerPixel;
|
||||
|
||||
if (_surface.w == oldw && _surface.h == oldh) {
|
||||
fillBuffer(0);
|
||||
return;
|
||||
}
|
||||
|
||||
delete[] _buf;
|
||||
delete[] _pixels;
|
||||
|
||||
_pixels = new byte[w * h * _surface.format.bytesPerPixel];
|
||||
assert(_pixels);
|
||||
|
||||
_surface.setPixels(_pixels);
|
||||
|
||||
fillBuffer(0);
|
||||
|
||||
_buf = new byte[w * h * _surface.format.bytesPerPixel];
|
||||
assert(_buf);
|
||||
}
|
||||
|
||||
void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h,
|
||||
const void *buf, int pitch_buf) {
|
||||
setDirtyRect(Common::Rect(x, y, x + w, y + h));
|
||||
|
||||
const byte *src = (const byte *)buf;
|
||||
byte *dst = _pixels + y * _surface.pitch + x * _surface.format.bytesPerPixel;
|
||||
|
||||
do {
|
||||
memcpy(dst, src, w * _surface.format.bytesPerPixel);
|
||||
dst += _surface.pitch;
|
||||
src += pitch_buf;
|
||||
} while (--h);
|
||||
}
|
||||
|
||||
void GLESTexture::fillBuffer(uint32 color) {
|
||||
assert(_surface.getPixels());
|
||||
|
||||
if (_pixelFormat.bytesPerPixel == 1 ||
|
||||
(_pixelFormat.bytesPerPixel == 2 &&
|
||||
((color & 0xff) == ((color >> 8) & 0xff))))
|
||||
memset(_pixels, color & 0xff, _surface.pitch * _surface.h);
|
||||
else if (_pixelFormat.bytesPerPixel == 2)
|
||||
Common::fill((uint16 *)_pixels, (uint16 *)(_pixels + _surface.pitch * _surface.h),
|
||||
(uint16)color);
|
||||
else
|
||||
Common::fill((uint32 *)_pixels, (uint32 *)(_pixels + _surface.pitch * _surface.h),
|
||||
color);
|
||||
|
||||
setDirty();
|
||||
}
|
||||
|
||||
void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
|
||||
if (_all_dirty) {
|
||||
_dirty_rect.top = 0;
|
||||
_dirty_rect.left = 0;
|
||||
_dirty_rect.bottom = _surface.h;
|
||||
_dirty_rect.right = _surface.w;
|
||||
|
||||
_all_dirty = false;
|
||||
}
|
||||
|
||||
if (!_dirty_rect.isEmpty()) {
|
||||
byte *_tex;
|
||||
|
||||
int16 dwidth = _dirty_rect.width();
|
||||
int16 dheight = _dirty_rect.height();
|
||||
|
||||
if (dwidth == _surface.w) {
|
||||
_tex = _pixels + _dirty_rect.top * _surface.pitch;
|
||||
} else {
|
||||
_tex = _buf;
|
||||
|
||||
byte *src = _pixels + _dirty_rect.top * _surface.pitch +
|
||||
_dirty_rect.left * _surface.format.bytesPerPixel;
|
||||
byte *dst = _buf;
|
||||
|
||||
uint16 l = dwidth * _surface.format.bytesPerPixel;
|
||||
|
||||
for (uint16 i = 0; i < dheight; ++i) {
|
||||
memcpy(dst, src, l);
|
||||
src += _surface.pitch;
|
||||
dst += l;
|
||||
}
|
||||
}
|
||||
|
||||
GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||
|
||||
GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||
_dirty_rect.left, _dirty_rect.top,
|
||||
dwidth, dheight, _glFormat, _glType, _tex));
|
||||
}
|
||||
|
||||
GLESBaseTexture::drawTexture(x, y, w, h);
|
||||
}
|
||||
|
||||
GLES4444Texture::GLES4444Texture() :
|
||||
GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, pixelFormat()) {
|
||||
}
|
||||
|
||||
GLES4444Texture::~GLES4444Texture() {
|
||||
}
|
||||
|
||||
GLES5551Texture::GLES5551Texture() :
|
||||
GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, pixelFormat()) {
|
||||
}
|
||||
|
||||
GLES5551Texture::~GLES5551Texture() {
|
||||
}
|
||||
|
||||
GLES565Texture::GLES565Texture() :
|
||||
GLESTexture(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixelFormat()) {
|
||||
}
|
||||
|
||||
GLES565Texture::~GLES565Texture() {
|
||||
}
|
||||
|
||||
GLES8888Texture::GLES8888Texture() :
|
||||
GLESTexture(GL_RGBA, GL_UNSIGNED_BYTE, pixelFormat()) {
|
||||
}
|
||||
|
||||
GLES8888Texture::~GLES8888Texture() {
|
||||
}
|
||||
|
||||
GLESFakePaletteTexture::GLESFakePaletteTexture(GLenum glFormat, GLenum glType,
|
||||
Graphics::PixelFormat pixelFormat) :
|
||||
GLESBaseTexture(glFormat, glType, pixelFormat),
|
||||
_palette(0),
|
||||
_pixels(0),
|
||||
_buf(0)
|
||||
{
|
||||
_palettePixelFormat = pixelFormat;
|
||||
_fake_format = Graphics::PixelFormat::createFormatCLUT8();
|
||||
|
||||
_palette = new uint16[256];
|
||||
assert(_palette);
|
||||
|
||||
memset(_palette, 0, 256 * 2);
|
||||
}
|
||||
|
||||
GLESFakePaletteTexture::~GLESFakePaletteTexture() {
|
||||
delete[] _buf;
|
||||
delete[] _pixels;
|
||||
delete[] _palette;
|
||||
}
|
||||
|
||||
void GLESFakePaletteTexture::allocBuffer(GLuint w, GLuint h) {
|
||||
GLuint oldw = _surface.w;
|
||||
GLuint oldh = _surface.h;
|
||||
|
||||
GLESBaseTexture::allocBuffer(w, h);
|
||||
|
||||
_surface.format = Graphics::PixelFormat::createFormatCLUT8();
|
||||
_surface.pitch = w;
|
||||
|
||||
if (_surface.w == oldw && _surface.h == oldh) {
|
||||
fillBuffer(0);
|
||||
return;
|
||||
}
|
||||
|
||||
delete[] _buf;
|
||||
delete[] _pixels;
|
||||
|
||||
_pixels = new byte[w * h];
|
||||
assert(_pixels);
|
||||
|
||||
// fixup surface, for the outside this is a CLUT8 surface
|
||||
_surface.setPixels(_pixels);
|
||||
|
||||
fillBuffer(0);
|
||||
|
||||
_buf = new uint16[w * h];
|
||||
assert(_buf);
|
||||
}
|
||||
|
||||
void GLESFakePaletteTexture::fillBuffer(uint32 color) {
|
||||
assert(_surface.getPixels());
|
||||
memset(_surface.getPixels(), color & 0xff, _surface.pitch * _surface.h);
|
||||
setDirty();
|
||||
}
|
||||
|
||||
void GLESFakePaletteTexture::updateBuffer(GLuint x, GLuint y, GLuint w,
|
||||
GLuint h, const void *buf,
|
||||
int pitch_buf) {
|
||||
setDirtyRect(Common::Rect(x, y, x + w, y + h));
|
||||
|
||||
const byte *src = (const byte *)buf;
|
||||
byte *dst = _pixels + y * _surface.pitch + x;
|
||||
|
||||
do {
|
||||
memcpy(dst, src, w);
|
||||
dst += _surface.pitch;
|
||||
src += pitch_buf;
|
||||
} while (--h);
|
||||
}
|
||||
|
||||
void GLESFakePaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w,
|
||||
GLshort h) {
|
||||
if (_all_dirty) {
|
||||
_dirty_rect.top = 0;
|
||||
_dirty_rect.left = 0;
|
||||
_dirty_rect.bottom = _surface.h;
|
||||
_dirty_rect.right = _surface.w;
|
||||
|
||||
_all_dirty = false;
|
||||
}
|
||||
|
||||
if (!_dirty_rect.isEmpty()) {
|
||||
int16 dwidth = _dirty_rect.width();
|
||||
int16 dheight = _dirty_rect.height();
|
||||
|
||||
byte *src = _pixels + _dirty_rect.top * _surface.pitch +
|
||||
_dirty_rect.left;
|
||||
uint16 *dst = _buf;
|
||||
uint pitch_delta = _surface.pitch - dwidth;
|
||||
|
||||
for (uint16 j = 0; j < dheight; ++j) {
|
||||
for (uint16 i = 0; i < dwidth; ++i)
|
||||
*dst++ = _palette[*src++];
|
||||
src += pitch_delta;
|
||||
}
|
||||
|
||||
GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
|
||||
|
||||
GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||
_dirty_rect.left, _dirty_rect.top,
|
||||
dwidth, dheight, _glFormat, _glType, _buf));
|
||||
}
|
||||
|
||||
GLESBaseTexture::drawTexture(x, y, w, h);
|
||||
}
|
||||
|
||||
const Graphics::PixelFormat &GLESFakePaletteTexture::getPixelFormat() const {
|
||||
return _fake_format;
|
||||
}
|
||||
|
||||
GLESFakePalette565Texture::GLESFakePalette565Texture() :
|
||||
GLESFakePaletteTexture(GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
|
||||
GLES565Texture::pixelFormat()) {
|
||||
}
|
||||
|
||||
GLESFakePalette565Texture::~GLESFakePalette565Texture() {
|
||||
}
|
||||
|
||||
GLESFakePalette5551Texture::GLESFakePalette5551Texture() :
|
||||
GLESFakePaletteTexture(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1,
|
||||
GLES5551Texture::pixelFormat()) {
|
||||
}
|
||||
|
||||
GLESFakePalette5551Texture::~GLESFakePalette5551Texture() {
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,285 +0,0 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _ANDROID_TEXTURE_H_
|
||||
#define _ANDROID_TEXTURE_H_
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#include "graphics/surface.h"
|
||||
#include "graphics/pixelformat.h"
|
||||
|
||||
#include "common/rect.h"
|
||||
#include "common/array.h"
|
||||
|
||||
class GLESBaseTexture {
|
||||
public:
|
||||
static void initGLExtensions();
|
||||
|
||||
protected:
|
||||
GLESBaseTexture(GLenum glFormat, GLenum glType,
|
||||
Graphics::PixelFormat pixelFormat);
|
||||
|
||||
public:
|
||||
virtual ~GLESBaseTexture();
|
||||
|
||||
void release();
|
||||
void reinit();
|
||||
void initSize();
|
||||
|
||||
void setLinearFilter(bool value);
|
||||
|
||||
virtual void allocBuffer(GLuint w, GLuint h);
|
||||
|
||||
virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
|
||||
const void *buf, int pitch_buf) = 0;
|
||||
virtual void fillBuffer(uint32 color) = 0;
|
||||
|
||||
virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
|
||||
|
||||
inline void setDrawRect(const Common::Rect &rect) {
|
||||
_draw_rect = rect;
|
||||
}
|
||||
|
||||
inline void setDrawRect(int16 w, int16 h) {
|
||||
_draw_rect = Common::Rect(w, h);
|
||||
}
|
||||
|
||||
inline void setDrawRect(int16 x1, int16 y1, int16 x2, int16 y2) {
|
||||
_draw_rect = Common::Rect(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
inline const Common::Rect &getDrawRect() const {
|
||||
return _draw_rect;
|
||||
}
|
||||
|
||||
inline void drawTextureRect() {
|
||||
drawTexture(_draw_rect.left, _draw_rect.top,
|
||||
_draw_rect.width(), _draw_rect.height());
|
||||
}
|
||||
|
||||
inline void drawTextureOrigin() {
|
||||
drawTexture(0, 0, _surface.w, _surface.h);
|
||||
}
|
||||
|
||||
inline GLuint width() const {
|
||||
return _surface.w;
|
||||
}
|
||||
|
||||
inline GLuint height() const {
|
||||
return _surface.h;
|
||||
}
|
||||
|
||||
inline uint16 pitch() const {
|
||||
return _surface.pitch;
|
||||
}
|
||||
|
||||
inline bool isEmpty() const {
|
||||
return _surface.w == 0 || _surface.h == 0;
|
||||
}
|
||||
|
||||
inline const Graphics::Surface *surface_const() const {
|
||||
return &_surface;
|
||||
}
|
||||
|
||||
inline Graphics::Surface *surface() {
|
||||
setDirty();
|
||||
return &_surface;
|
||||
}
|
||||
|
||||
virtual const byte *palette_const() const {
|
||||
return 0;
|
||||
};
|
||||
|
||||
virtual byte *palette() {
|
||||
return 0;
|
||||
};
|
||||
|
||||
inline bool hasPalette() const {
|
||||
return _palettePixelFormat.bytesPerPixel > 0;
|
||||
}
|
||||
|
||||
inline bool dirty() const {
|
||||
return _all_dirty || !_dirty_rect.isEmpty();
|
||||
}
|
||||
|
||||
virtual const Graphics::PixelFormat &getPixelFormat() const;
|
||||
|
||||
inline const Graphics::PixelFormat &getPalettePixelFormat() const {
|
||||
return _palettePixelFormat;
|
||||
}
|
||||
|
||||
protected:
|
||||
inline void setDirty() {
|
||||
_all_dirty = true;
|
||||
}
|
||||
|
||||
inline void clearDirty() {
|
||||
_all_dirty = false;
|
||||
_dirty_rect.top = 0;
|
||||
_dirty_rect.left = 0;
|
||||
_dirty_rect.bottom = 0;
|
||||
_dirty_rect.right = 0;
|
||||
}
|
||||
|
||||
inline void setDirtyRect(const Common::Rect& r) {
|
||||
if (!_all_dirty) {
|
||||
if (_dirty_rect.isEmpty())
|
||||
_dirty_rect = r;
|
||||
else
|
||||
_dirty_rect.extend(r);
|
||||
}
|
||||
}
|
||||
|
||||
GLenum _glFormat;
|
||||
GLenum _glType;
|
||||
GLint _glFilter;
|
||||
|
||||
GLuint _texture_name;
|
||||
Graphics::Surface _surface;
|
||||
GLuint _texture_width;
|
||||
GLuint _texture_height;
|
||||
|
||||
Common::Rect _draw_rect;
|
||||
|
||||
bool _all_dirty;
|
||||
Common::Rect _dirty_rect;
|
||||
|
||||
Graphics::PixelFormat _pixelFormat;
|
||||
Graphics::PixelFormat _palettePixelFormat;
|
||||
};
|
||||
|
||||
class GLESTexture : public GLESBaseTexture {
|
||||
protected:
|
||||
GLESTexture(GLenum glFormat, GLenum glType,
|
||||
Graphics::PixelFormat pixelFormat);
|
||||
|
||||
public:
|
||||
virtual ~GLESTexture();
|
||||
|
||||
virtual void allocBuffer(GLuint w, GLuint h);
|
||||
|
||||
virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
|
||||
const void *buf, int pitch_buf);
|
||||
virtual void fillBuffer(uint32 color);
|
||||
|
||||
virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
|
||||
|
||||
protected:
|
||||
byte *_pixels;
|
||||
byte *_buf;
|
||||
};
|
||||
|
||||
// RGBA4444 texture
|
||||
class GLES4444Texture : public GLESTexture {
|
||||
public:
|
||||
GLES4444Texture();
|
||||
virtual ~GLES4444Texture();
|
||||
|
||||
static Graphics::PixelFormat pixelFormat() {
|
||||
return Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0);
|
||||
}
|
||||
};
|
||||
|
||||
// RGBA5551 texture
|
||||
class GLES5551Texture : public GLESTexture {
|
||||
public:
|
||||
GLES5551Texture();
|
||||
virtual ~GLES5551Texture();
|
||||
|
||||
static inline Graphics::PixelFormat pixelFormat() {
|
||||
return Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0);
|
||||
}
|
||||
};
|
||||
|
||||
// RGB565 texture
|
||||
class GLES565Texture : public GLESTexture {
|
||||
public:
|
||||
GLES565Texture();
|
||||
virtual ~GLES565Texture();
|
||||
|
||||
static inline Graphics::PixelFormat pixelFormat() {
|
||||
return Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
|
||||
}
|
||||
};
|
||||
|
||||
// RGBA8888 texture
|
||||
class GLES8888Texture : public GLESTexture {
|
||||
public:
|
||||
GLES8888Texture();
|
||||
virtual ~GLES8888Texture();
|
||||
|
||||
static inline Graphics::PixelFormat pixelFormat() {
|
||||
// We assume LE since all Android platforms are LE.
|
||||
return Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24);
|
||||
}
|
||||
};
|
||||
|
||||
class GLESFakePaletteTexture : public GLESBaseTexture {
|
||||
protected:
|
||||
GLESFakePaletteTexture(GLenum glFormat, GLenum glType,
|
||||
Graphics::PixelFormat pixelFormat);
|
||||
|
||||
public:
|
||||
virtual ~GLESFakePaletteTexture();
|
||||
|
||||
virtual void allocBuffer(GLuint w, GLuint h);
|
||||
virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
|
||||
const void *buf, int pitch_buf);
|
||||
virtual void fillBuffer(uint32 color);
|
||||
|
||||
virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
|
||||
|
||||
virtual const byte *palette_const() const {
|
||||
return (byte *)_palette;
|
||||
};
|
||||
|
||||
virtual byte *palette() {
|
||||
setDirty();
|
||||
return (byte *)_palette;
|
||||
};
|
||||
|
||||
virtual const Graphics::PixelFormat &getPixelFormat() const;
|
||||
|
||||
protected:
|
||||
Graphics::PixelFormat _fake_format;
|
||||
uint16 *_palette;
|
||||
byte *_pixels;
|
||||
uint16 *_buf;
|
||||
};
|
||||
|
||||
class GLESFakePalette565Texture : public GLESFakePaletteTexture {
|
||||
public:
|
||||
GLESFakePalette565Texture();
|
||||
virtual ~GLESFakePalette565Texture();
|
||||
};
|
||||
|
||||
class GLESFakePalette5551Texture : public GLESFakePaletteTexture {
|
||||
public:
|
||||
GLESFakePalette5551Texture();
|
||||
virtual ~GLESFakePalette5551Texture();
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
4
configure
vendored
4
configure
vendored
|
@ -5075,6 +5075,10 @@ esac
|
|||
|
||||
if test "$_opengl_mode" = auto ; then
|
||||
case $_backend in
|
||||
android)
|
||||
# Android always runs in GLES mode
|
||||
_opengl_mode=gles
|
||||
;;
|
||||
sdl)
|
||||
case $_sdlversion in
|
||||
1.2.*)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue