diff options
author | dhewg | 2011-03-13 22:31:28 +0100 |
---|---|---|
committer | dhewg | 2011-03-13 23:30:16 +0100 |
commit | 79d991081dbeaddd0294c6bbf01675d1ec1fbb72 (patch) | |
tree | e7c712df278ba9b984f460842fb0f9d0234e83ba | |
parent | 4267011e3a42b3f633f86e3df6af12c456aa0f60 (diff) | |
download | scummvm-rg350-79d991081dbeaddd0294c6bbf01675d1ec1fbb72.tar.gz scummvm-rg350-79d991081dbeaddd0294c6bbf01675d1ec1fbb72.tar.bz2 scummvm-rg350-79d991081dbeaddd0294c6bbf01675d1ec1fbb72.zip |
ANDROID: Add support for video feature flags
kFeatureFullscreenMode and kFeatureAspectRatioCorrection are supported
now. The former prevents scaling to the full display - it scales one
axis and keeps the game AR.
-rw-r--r-- | backends/platform/android/android.cpp | 50 | ||||
-rw-r--r-- | backends/platform/android/android.h | 5 | ||||
-rw-r--r-- | backends/platform/android/gfx.cpp | 87 | ||||
-rw-r--r-- | backends/platform/android/jni.cpp | 31 | ||||
-rw-r--r-- | backends/platform/android/jni.h | 2 | ||||
-rw-r--r-- | backends/platform/android/org/inodes/gus/scummvm/ScummVM.java | 1 | ||||
-rw-r--r-- | backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java | 9 |
7 files changed, 158 insertions, 27 deletions
diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp index 4391cf50db..ba574564b4 100644 --- a/backends/platform/android/android.cpp +++ b/backends/platform/android/android.cpp @@ -115,6 +115,8 @@ OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) : _mouse_hotspot(), _mouse_keycolor(0), _use_mouse_palette(false), + _fullscreen(false), + _ar_correction(false), _show_mouse(false), _show_overlay(false), _enable_zoning(false), @@ -302,6 +304,9 @@ void OSystem_Android::initBackend() { _main_thread = pthread_self(); + ConfMan.registerDefault("fullscreen", true); + ConfMan.registerDefault("aspect_ratio", true); + ConfMan.setInt("autosave_period", 0); ConfMan.setBool("FM_high_quality", false); ConfMan.setBool("FM_medium_quality", true); @@ -351,7 +356,9 @@ void OSystem_Android::addPluginDirectories(Common::FSList &dirs) const { } bool OSystem_Android::hasFeature(Feature f) { - return (f == kFeatureCursorHasPalette || + return (f == kFeatureFullscreenMode || + f == kFeatureAspectRatioCorrection || + f == kFeatureCursorHasPalette || f == kFeatureVirtualKeyboard || f == kFeatureOverlaySupportsAlpha); } @@ -360,6 +367,14 @@ 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); @@ -490,17 +505,28 @@ bool OSystem_Android::pollEvent(Common::Event &event) { } else { // Touchscreen events need to be converted // from device to game coords first. - const GLESBaseTexture *tex; - if (_show_overlay) - tex = _overlay_texture; - else - tex = _game_texture; - - event.mouse.x = scalef(event.mouse.x, tex->width(), - _egl_surface_width); - event.mouse.y = scalef(event.mouse.y, tex->height(), - _egl_surface_height); - event.mouse.x -= _shake_offset; + if (_show_overlay) { + event.mouse.x = scalef(event.mouse.x, + _overlay_texture->width(), + _egl_surface_width); + event.mouse.y = scalef(event.mouse.y, + _overlay_texture->height(), + _egl_surface_height); + } else { + const Common::Rect &r = _game_texture->getDrawRect(); + + event.mouse.x -= r.left; + event.mouse.y -= r.top; + + event.mouse.x = scalef(event.mouse.x, + _game_texture->width(), + r.width()); + event.mouse.y = scalef(event.mouse.y, + _game_texture->height(), + r.height()); + + event.mouse.x -= _shake_offset; + } } break; } diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h index 11a24a5f57..26245e6a50 100644 --- a/backends/platform/android/android.h +++ b/backends/platform/android/android.h @@ -121,6 +121,9 @@ private: bool _show_mouse; bool _use_mouse_palette; + bool _fullscreen; + bool _ar_correction; + Common::Queue<Common::Event> _event_queue; MutexRef _event_queue_lock; @@ -183,6 +186,8 @@ public: virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format); + void clearScreen(bool swapBuffers); + void updateScreenRect(); virtual int getScreenChangeID() const; virtual int16 getHeight(); diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp index 2543ac7a3e..20534331bc 100644 --- a/backends/platform/android/gfx.cpp +++ b/backends/platform/android/gfx.cpp @@ -267,7 +267,7 @@ void OSystem_Android::initSize(uint width, uint height, _game_texture->fillBuffer(0); #endif - _game_texture->setDrawRect(0, 0, _egl_surface_width, _egl_surface_height); + updateScreenRect(); // Don't know mouse size yet - it gets reallocated in // setMouseCursor. We need the palette allocated before @@ -275,10 +275,54 @@ void OSystem_Android::initSize(uint width, uint height, // size (it's small). _mouse_texture_palette->allocBuffer(20, 20); + clearScreen(true); +} + +void OSystem_Android::clearScreen(bool swapBuffers) { // clear screen GLCALL(glClearColorx(0, 0, 0, 1 << 16)); GLCALL(glClear(GL_COLOR_BUFFER_BIT)); - JNI::swapBuffers(); + + if (swapBuffers) + JNI::swapBuffers(); +} + +void OSystem_Android::updateScreenRect() { + uint16 w = _game_texture->width(); + uint16 h = _game_texture->height(); + + Common::Rect rect(0, 0, _egl_surface_width, _egl_surface_height); + + if (!_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 { @@ -353,6 +397,10 @@ void OSystem_Android::updateScreen() { _force_redraw = false; + // clear pointer leftovers in dead areas + if (_show_overlay && !_fullscreen) + clearScreen(false); + GLCALL(glPushMatrix()); if (_shake_offset != 0 || @@ -361,8 +409,7 @@ void OSystem_Android::updateScreen() { _game_texture->height()).contains(_focus_rect))) { // These are the only cases where _game_texture doesn't // cover the entire screen. - GLCALL(glClearColorx(0, 0, 0, 1 << 16)); - GLCALL(glClear(GL_COLOR_BUFFER_BIT)); + clearScreen(false); // Move everything up by _shake_offset (game) pixels GLCALL(glTranslatex(0, -_shake_offset << 16, 0)); @@ -397,28 +444,32 @@ void OSystem_Android::updateScreen() { if (_show_mouse) { GLCALL(glPushMatrix()); - // Scale up ScummVM -> OpenGL (pixel) coordinates - int texwidth, texheight; + Common::Point mouse = getEventManager()->getMousePos(); + // Scale up ScummVM -> OpenGL (pixel) coordinates if (_show_overlay) { - texwidth = getOverlayWidth(); - texheight = getOverlayHeight(); + GLCALL(glScalex(xdiv(_egl_surface_width, + _overlay_texture->width()), + xdiv(_egl_surface_height, + _overlay_texture->height()), + 1 << 16)); } else { - texwidth = getWidth(); - texheight = getHeight(); + 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(glScalex(xdiv(_egl_surface_width, texwidth), - xdiv(_egl_surface_height, texheight), - 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: - const Common::Point& mouse = getEventManager()->getMousePos(); GLCALL(glTranslatex((mouse.x << 16) | 1 << 15, (mouse.y << 16) | 1 << 15, 0)); @@ -494,6 +545,8 @@ void OSystem_Android::showOverlay() { _show_overlay = true; _force_redraw = true; + + GLCALL(glDisable(GL_SCISSOR_TEST)); } void OSystem_Android::hideOverlay() { @@ -501,6 +554,10 @@ void OSystem_Android::hideOverlay() { _show_overlay = false; _force_redraw = true; + + clearScreen(false); + + GLCALL(glEnable(GL_SCISSOR_TEST)); } void OSystem_Android::clearOverlay() { diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp index 6bfe9c2095..0628d92a2f 100644 --- a/backends/platform/android/jni.cpp +++ b/backends/platform/android/jni.cpp @@ -65,6 +65,7 @@ jfieldID JNI::_FID_Event_mouse_x = 0; jfieldID JNI::_FID_Event_mouse_y = 0; jfieldID JNI::_FID_Event_mouse_relative = 0; +jmethodID JNI::_MID_getDPI = 0; jmethodID JNI::_MID_displayMessageOnOSD = 0; jmethodID JNI::_MID_setWindowCaption = 0; jmethodID JNI::_MID_showVirtualKeyboard = 0; @@ -214,6 +215,35 @@ void JNI::throwRuntimeException(JNIEnv *env, const char *msg) { // calls to the dark side +void JNI::getDPI(float *values) { + values[0] = 0.0; + values[1] = 0.0; + + JNIEnv *env = JNI::getEnv(); + + jfloatArray array = env->NewFloatArray(2); + + env->CallVoidMethod(_jobj, _MID_getDPI, array); + + if (env->ExceptionCheck()) { + LOGE("Failed to get DPIs"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + } else { + jfloat *res = env->GetFloatArrayElements(array, 0); + + if (res) { + values[0] = res[0]; + values[1] = res[1]; + + env->ReleaseFloatArrayElements(array, res, 0); + } + } + + env->DeleteLocalRef(array); +} + void JNI::displayMessageOnOSD(const char *msg) { JNIEnv *env = JNI::getEnv(); jstring java_msg = env->NewStringUTF(msg); @@ -445,6 +475,7 @@ void JNI::create(JNIEnv *env, jobject self, jobject asset_manager, } while (0) FIND_METHOD(, setWindowCaption, "(Ljava/lang/String;)V"); + FIND_METHOD(, getDPI, "([F)V"); FIND_METHOD(, displayMessageOnOSD, "(Ljava/lang/String;)V"); FIND_METHOD(, showVirtualKeyboard, "(Z)V"); FIND_METHOD(, getSysArchives, "()[Ljava/lang/String;"); diff --git a/backends/platform/android/jni.h b/backends/platform/android/jni.h index 146938636d..5746c01afd 100644 --- a/backends/platform/android/jni.h +++ b/backends/platform/android/jni.h @@ -60,6 +60,7 @@ public: static void getPluginDirectories(Common::FSList &dirs); static void setWindowCaption(const char *caption); + static void getDPI(float *values); static void displayMessageOnOSD(const char *msg); static void showVirtualKeyboard(bool enable); static void addSysArchivesToSearchSet(Common::SearchSet &s, int priority); @@ -100,6 +101,7 @@ private: static jfieldID _FID_Event_mouse_relative; static jfieldID _FID_ScummVM_nativeScummVM; + static jmethodID _MID_getDPI; static jmethodID _MID_displayMessageOnOSD; static jmethodID _MID_setWindowCaption; static jmethodID _MID_showVirtualKeyboard; diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java index f263b89015..0bc5f3ce4c 100644 --- a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java +++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java @@ -52,6 +52,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable { final public native void pushEvent(Event e); // Callbacks from C++ peer instance + abstract protected void getDPI(float[] values); abstract protected void displayMessageOnOSD(String msg); abstract protected void setWindowCaption(String caption); abstract protected String[] getPluginDirectories(); diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java index 8cb3d80063..2cf6f58941 100644 --- a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java +++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java @@ -59,6 +59,15 @@ public class ScummVMActivity extends Activity { } @Override + protected void getDPI(float[] values) { + DisplayMetrics metrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(metrics); + + values[0] = metrics.xdpi; + values[1] = metrics.ydpi; + } + + @Override protected void displayMessageOnOSD(String msg) { Log.i(LOG_TAG, "OSD: " + msg); Toast.makeText(ScummVMActivity.this, msg, Toast.LENGTH_LONG).show(); |