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.
This commit is contained in:
parent
4267011e3a
commit
79d991081d
7 changed files with 157 additions and 26 deletions
|
@ -115,6 +115,8 @@ OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) :
|
||||||
_mouse_hotspot(),
|
_mouse_hotspot(),
|
||||||
_mouse_keycolor(0),
|
_mouse_keycolor(0),
|
||||||
_use_mouse_palette(false),
|
_use_mouse_palette(false),
|
||||||
|
_fullscreen(false),
|
||||||
|
_ar_correction(false),
|
||||||
_show_mouse(false),
|
_show_mouse(false),
|
||||||
_show_overlay(false),
|
_show_overlay(false),
|
||||||
_enable_zoning(false),
|
_enable_zoning(false),
|
||||||
|
@ -302,6 +304,9 @@ void OSystem_Android::initBackend() {
|
||||||
|
|
||||||
_main_thread = pthread_self();
|
_main_thread = pthread_self();
|
||||||
|
|
||||||
|
ConfMan.registerDefault("fullscreen", true);
|
||||||
|
ConfMan.registerDefault("aspect_ratio", true);
|
||||||
|
|
||||||
ConfMan.setInt("autosave_period", 0);
|
ConfMan.setInt("autosave_period", 0);
|
||||||
ConfMan.setBool("FM_high_quality", false);
|
ConfMan.setBool("FM_high_quality", false);
|
||||||
ConfMan.setBool("FM_medium_quality", true);
|
ConfMan.setBool("FM_medium_quality", true);
|
||||||
|
@ -351,7 +356,9 @@ void OSystem_Android::addPluginDirectories(Common::FSList &dirs) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OSystem_Android::hasFeature(Feature f) {
|
bool OSystem_Android::hasFeature(Feature f) {
|
||||||
return (f == kFeatureCursorHasPalette ||
|
return (f == kFeatureFullscreenMode ||
|
||||||
|
f == kFeatureAspectRatioCorrection ||
|
||||||
|
f == kFeatureCursorHasPalette ||
|
||||||
f == kFeatureVirtualKeyboard ||
|
f == kFeatureVirtualKeyboard ||
|
||||||
f == kFeatureOverlaySupportsAlpha);
|
f == kFeatureOverlaySupportsAlpha);
|
||||||
}
|
}
|
||||||
|
@ -360,6 +367,14 @@ void OSystem_Android::setFeatureState(Feature f, bool enable) {
|
||||||
ENTER("%d, %d", f, enable);
|
ENTER("%d, %d", f, enable);
|
||||||
|
|
||||||
switch (f) {
|
switch (f) {
|
||||||
|
case kFeatureFullscreenMode:
|
||||||
|
_fullscreen = enable;
|
||||||
|
updateScreenRect();
|
||||||
|
break;
|
||||||
|
case kFeatureAspectRatioCorrection:
|
||||||
|
_ar_correction = enable;
|
||||||
|
updateScreenRect();
|
||||||
|
break;
|
||||||
case kFeatureVirtualKeyboard:
|
case kFeatureVirtualKeyboard:
|
||||||
_virtkeybd_on = enable;
|
_virtkeybd_on = enable;
|
||||||
showVirtualKeyboard(enable);
|
showVirtualKeyboard(enable);
|
||||||
|
@ -490,18 +505,29 @@ bool OSystem_Android::pollEvent(Common::Event &event) {
|
||||||
} else {
|
} else {
|
||||||
// Touchscreen events need to be converted
|
// Touchscreen events need to be converted
|
||||||
// from device to game coords first.
|
// from device to game coords first.
|
||||||
const GLESBaseTexture *tex;
|
if (_show_overlay) {
|
||||||
if (_show_overlay)
|
event.mouse.x = scalef(event.mouse.x,
|
||||||
tex = _overlay_texture;
|
_overlay_texture->width(),
|
||||||
else
|
|
||||||
tex = _game_texture;
|
|
||||||
|
|
||||||
event.mouse.x = scalef(event.mouse.x, tex->width(),
|
|
||||||
_egl_surface_width);
|
_egl_surface_width);
|
||||||
event.mouse.y = scalef(event.mouse.y, tex->height(),
|
event.mouse.y = scalef(event.mouse.y,
|
||||||
|
_overlay_texture->height(),
|
||||||
_egl_surface_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;
|
event.mouse.x -= _shake_offset;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -121,6 +121,9 @@ private:
|
||||||
bool _show_mouse;
|
bool _show_mouse;
|
||||||
bool _use_mouse_palette;
|
bool _use_mouse_palette;
|
||||||
|
|
||||||
|
bool _fullscreen;
|
||||||
|
bool _ar_correction;
|
||||||
|
|
||||||
Common::Queue<Common::Event> _event_queue;
|
Common::Queue<Common::Event> _event_queue;
|
||||||
MutexRef _event_queue_lock;
|
MutexRef _event_queue_lock;
|
||||||
|
|
||||||
|
@ -183,6 +186,8 @@ public:
|
||||||
|
|
||||||
virtual void initSize(uint width, uint height,
|
virtual void initSize(uint width, uint height,
|
||||||
const Graphics::PixelFormat *format);
|
const Graphics::PixelFormat *format);
|
||||||
|
void clearScreen(bool swapBuffers);
|
||||||
|
void updateScreenRect();
|
||||||
virtual int getScreenChangeID() const;
|
virtual int getScreenChangeID() const;
|
||||||
|
|
||||||
virtual int16 getHeight();
|
virtual int16 getHeight();
|
||||||
|
|
|
@ -267,7 +267,7 @@ void OSystem_Android::initSize(uint width, uint height,
|
||||||
_game_texture->fillBuffer(0);
|
_game_texture->fillBuffer(0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_game_texture->setDrawRect(0, 0, _egl_surface_width, _egl_surface_height);
|
updateScreenRect();
|
||||||
|
|
||||||
// Don't know mouse size yet - it gets reallocated in
|
// Don't know mouse size yet - it gets reallocated in
|
||||||
// setMouseCursor. We need the palette allocated before
|
// setMouseCursor. We need the palette allocated before
|
||||||
|
@ -275,12 +275,56 @@ void OSystem_Android::initSize(uint width, uint height,
|
||||||
// size (it's small).
|
// size (it's small).
|
||||||
_mouse_texture_palette->allocBuffer(20, 20);
|
_mouse_texture_palette->allocBuffer(20, 20);
|
||||||
|
|
||||||
|
clearScreen(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSystem_Android::clearScreen(bool swapBuffers) {
|
||||||
// clear screen
|
// clear screen
|
||||||
GLCALL(glClearColorx(0, 0, 0, 1 << 16));
|
GLCALL(glClearColorx(0, 0, 0, 1 << 16));
|
||||||
GLCALL(glClear(GL_COLOR_BUFFER_BIT));
|
GLCALL(glClear(GL_COLOR_BUFFER_BIT));
|
||||||
|
|
||||||
|
if (swapBuffers)
|
||||||
JNI::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 {
|
int OSystem_Android::getScreenChangeID() const {
|
||||||
return _screen_changeid;
|
return _screen_changeid;
|
||||||
}
|
}
|
||||||
|
@ -353,6 +397,10 @@ void OSystem_Android::updateScreen() {
|
||||||
|
|
||||||
_force_redraw = false;
|
_force_redraw = false;
|
||||||
|
|
||||||
|
// clear pointer leftovers in dead areas
|
||||||
|
if (_show_overlay && !_fullscreen)
|
||||||
|
clearScreen(false);
|
||||||
|
|
||||||
GLCALL(glPushMatrix());
|
GLCALL(glPushMatrix());
|
||||||
|
|
||||||
if (_shake_offset != 0 ||
|
if (_shake_offset != 0 ||
|
||||||
|
@ -361,8 +409,7 @@ void OSystem_Android::updateScreen() {
|
||||||
_game_texture->height()).contains(_focus_rect))) {
|
_game_texture->height()).contains(_focus_rect))) {
|
||||||
// These are the only cases where _game_texture doesn't
|
// These are the only cases where _game_texture doesn't
|
||||||
// cover the entire screen.
|
// cover the entire screen.
|
||||||
GLCALL(glClearColorx(0, 0, 0, 1 << 16));
|
clearScreen(false);
|
||||||
GLCALL(glClear(GL_COLOR_BUFFER_BIT));
|
|
||||||
|
|
||||||
// Move everything up by _shake_offset (game) pixels
|
// Move everything up by _shake_offset (game) pixels
|
||||||
GLCALL(glTranslatex(0, -_shake_offset << 16, 0));
|
GLCALL(glTranslatex(0, -_shake_offset << 16, 0));
|
||||||
|
@ -397,20 +444,25 @@ void OSystem_Android::updateScreen() {
|
||||||
if (_show_mouse) {
|
if (_show_mouse) {
|
||||||
GLCALL(glPushMatrix());
|
GLCALL(glPushMatrix());
|
||||||
|
|
||||||
|
Common::Point mouse = getEventManager()->getMousePos();
|
||||||
|
|
||||||
// Scale up ScummVM -> OpenGL (pixel) coordinates
|
// Scale up ScummVM -> OpenGL (pixel) coordinates
|
||||||
int texwidth, texheight;
|
|
||||||
|
|
||||||
if (_show_overlay) {
|
if (_show_overlay) {
|
||||||
texwidth = getOverlayWidth();
|
GLCALL(glScalex(xdiv(_egl_surface_width,
|
||||||
texheight = getOverlayHeight();
|
_overlay_texture->width()),
|
||||||
} else {
|
xdiv(_egl_surface_height,
|
||||||
texwidth = getWidth();
|
_overlay_texture->height()),
|
||||||
texheight = getHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
GLCALL(glScalex(xdiv(_egl_surface_width, texwidth),
|
|
||||||
xdiv(_egl_surface_height, texheight),
|
|
||||||
1 << 16));
|
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,
|
GLCALL(glTranslatex((-_mouse_hotspot.x * cs) << 16,
|
||||||
(-_mouse_hotspot.y * cs) << 16,
|
(-_mouse_hotspot.y * cs) << 16,
|
||||||
|
@ -418,7 +470,6 @@ void OSystem_Android::updateScreen() {
|
||||||
|
|
||||||
// Note the extra half texel to position the mouse in
|
// Note the extra half texel to position the mouse in
|
||||||
// the middle of the x,y square:
|
// the middle of the x,y square:
|
||||||
const Common::Point& mouse = getEventManager()->getMousePos();
|
|
||||||
GLCALL(glTranslatex((mouse.x << 16) | 1 << 15,
|
GLCALL(glTranslatex((mouse.x << 16) | 1 << 15,
|
||||||
(mouse.y << 16) | 1 << 15, 0));
|
(mouse.y << 16) | 1 << 15, 0));
|
||||||
|
|
||||||
|
@ -494,6 +545,8 @@ void OSystem_Android::showOverlay() {
|
||||||
|
|
||||||
_show_overlay = true;
|
_show_overlay = true;
|
||||||
_force_redraw = true;
|
_force_redraw = true;
|
||||||
|
|
||||||
|
GLCALL(glDisable(GL_SCISSOR_TEST));
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSystem_Android::hideOverlay() {
|
void OSystem_Android::hideOverlay() {
|
||||||
|
@ -501,6 +554,10 @@ void OSystem_Android::hideOverlay() {
|
||||||
|
|
||||||
_show_overlay = false;
|
_show_overlay = false;
|
||||||
_force_redraw = true;
|
_force_redraw = true;
|
||||||
|
|
||||||
|
clearScreen(false);
|
||||||
|
|
||||||
|
GLCALL(glEnable(GL_SCISSOR_TEST));
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSystem_Android::clearOverlay() {
|
void OSystem_Android::clearOverlay() {
|
||||||
|
|
|
@ -65,6 +65,7 @@ jfieldID JNI::_FID_Event_mouse_x = 0;
|
||||||
jfieldID JNI::_FID_Event_mouse_y = 0;
|
jfieldID JNI::_FID_Event_mouse_y = 0;
|
||||||
jfieldID JNI::_FID_Event_mouse_relative = 0;
|
jfieldID JNI::_FID_Event_mouse_relative = 0;
|
||||||
|
|
||||||
|
jmethodID JNI::_MID_getDPI = 0;
|
||||||
jmethodID JNI::_MID_displayMessageOnOSD = 0;
|
jmethodID JNI::_MID_displayMessageOnOSD = 0;
|
||||||
jmethodID JNI::_MID_setWindowCaption = 0;
|
jmethodID JNI::_MID_setWindowCaption = 0;
|
||||||
jmethodID JNI::_MID_showVirtualKeyboard = 0;
|
jmethodID JNI::_MID_showVirtualKeyboard = 0;
|
||||||
|
@ -214,6 +215,35 @@ void JNI::throwRuntimeException(JNIEnv *env, const char *msg) {
|
||||||
|
|
||||||
// calls to the dark side
|
// 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) {
|
void JNI::displayMessageOnOSD(const char *msg) {
|
||||||
JNIEnv *env = JNI::getEnv();
|
JNIEnv *env = JNI::getEnv();
|
||||||
jstring java_msg = env->NewStringUTF(msg);
|
jstring java_msg = env->NewStringUTF(msg);
|
||||||
|
@ -445,6 +475,7 @@ void JNI::create(JNIEnv *env, jobject self, jobject asset_manager,
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
FIND_METHOD(, setWindowCaption, "(Ljava/lang/String;)V");
|
FIND_METHOD(, setWindowCaption, "(Ljava/lang/String;)V");
|
||||||
|
FIND_METHOD(, getDPI, "([F)V");
|
||||||
FIND_METHOD(, displayMessageOnOSD, "(Ljava/lang/String;)V");
|
FIND_METHOD(, displayMessageOnOSD, "(Ljava/lang/String;)V");
|
||||||
FIND_METHOD(, showVirtualKeyboard, "(Z)V");
|
FIND_METHOD(, showVirtualKeyboard, "(Z)V");
|
||||||
FIND_METHOD(, getSysArchives, "()[Ljava/lang/String;");
|
FIND_METHOD(, getSysArchives, "()[Ljava/lang/String;");
|
||||||
|
|
|
@ -60,6 +60,7 @@ public:
|
||||||
|
|
||||||
static void getPluginDirectories(Common::FSList &dirs);
|
static void getPluginDirectories(Common::FSList &dirs);
|
||||||
static void setWindowCaption(const char *caption);
|
static void setWindowCaption(const char *caption);
|
||||||
|
static void getDPI(float *values);
|
||||||
static void displayMessageOnOSD(const char *msg);
|
static void displayMessageOnOSD(const char *msg);
|
||||||
static void showVirtualKeyboard(bool enable);
|
static void showVirtualKeyboard(bool enable);
|
||||||
static void addSysArchivesToSearchSet(Common::SearchSet &s, int priority);
|
static void addSysArchivesToSearchSet(Common::SearchSet &s, int priority);
|
||||||
|
@ -100,6 +101,7 @@ private:
|
||||||
static jfieldID _FID_Event_mouse_relative;
|
static jfieldID _FID_Event_mouse_relative;
|
||||||
static jfieldID _FID_ScummVM_nativeScummVM;
|
static jfieldID _FID_ScummVM_nativeScummVM;
|
||||||
|
|
||||||
|
static jmethodID _MID_getDPI;
|
||||||
static jmethodID _MID_displayMessageOnOSD;
|
static jmethodID _MID_displayMessageOnOSD;
|
||||||
static jmethodID _MID_setWindowCaption;
|
static jmethodID _MID_setWindowCaption;
|
||||||
static jmethodID _MID_showVirtualKeyboard;
|
static jmethodID _MID_showVirtualKeyboard;
|
||||||
|
|
|
@ -52,6 +52,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
|
||||||
final public native void pushEvent(Event e);
|
final public native void pushEvent(Event e);
|
||||||
|
|
||||||
// Callbacks from C++ peer instance
|
// Callbacks from C++ peer instance
|
||||||
|
abstract protected void getDPI(float[] values);
|
||||||
abstract protected void displayMessageOnOSD(String msg);
|
abstract protected void displayMessageOnOSD(String msg);
|
||||||
abstract protected void setWindowCaption(String caption);
|
abstract protected void setWindowCaption(String caption);
|
||||||
abstract protected String[] getPluginDirectories();
|
abstract protected String[] getPluginDirectories();
|
||||||
|
|
|
@ -58,6 +58,15 @@ public class ScummVMActivity extends Activity {
|
||||||
//enableZoning(usingSmallScreen());
|
//enableZoning(usingSmallScreen());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void getDPI(float[] values) {
|
||||||
|
DisplayMetrics metrics = new DisplayMetrics();
|
||||||
|
getWindowManager().getDefaultDisplay().getMetrics(metrics);
|
||||||
|
|
||||||
|
values[0] = metrics.xdpi;
|
||||||
|
values[1] = metrics.ydpi;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void displayMessageOnOSD(String msg) {
|
protected void displayMessageOnOSD(String msg) {
|
||||||
Log.i(LOG_TAG, "OSD: " + msg);
|
Log.i(LOG_TAG, "OSD: " + msg);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue