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:
Cameron Cawley 2019-09-08 19:37:48 +01:00 committed by GitHub
parent 997e15878a
commit 7a05624e1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 271 additions and 2039 deletions

View file

@ -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

View file

@ -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);

View file

@ -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();

View file

@ -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;

View file

@ -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

View 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;
}

View 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

View file

@ -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;

View file

@ -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);

View file

@ -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.

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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
View file

@ -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.*)