ANDROID: Refactor touch controls to be graphics backend agnostic

This commit is contained in:
Le Philousophe 2021-12-25 23:25:45 +01:00
parent 325c47f954
commit b6c0a1c6c8
5 changed files with 101 additions and 54 deletions

View File

@ -53,6 +53,26 @@
#define CONTEXT_RESET_ENABLE(gl_param) if (!(saved ## gl_param)) { GLCALL(glDisable(gl_param)); }
#define CONTEXT_RESET_DISABLE(gl_param) if (saved ## gl_param) { GLCALL(glEnable(gl_param)); }
static GLES8888Texture *loadBuiltinTexture(JNI::BitmapResources resource) {
const Graphics::Surface *src = JNI::getBitmapResource(JNI::BitmapResources::TOUCH_ARROWS_BITMAP);
if (!src) {
error("Failed to fetch touch arrows bitmap");
}
GLES8888Texture *ret = new GLES8888Texture();
ret->allocBuffer(src->w, src->h);
Graphics::Surface *dst = ret->surface();
Graphics::crossBlit(
(byte *)dst->getPixels(), (const byte *)src->getPixels(),
dst->pitch, src->pitch,
src->w, src->h,
src->format, dst->format);
delete src;
return ret;
}
AndroidGraphics3dManager::AndroidGraphics3dManager() :
_screenChangeID(0),
_graphicsMode(0),
@ -66,12 +86,13 @@ AndroidGraphics3dManager::AndroidGraphics3dManager() :
_overlay_texture(0),
_overlay_background(nullptr),
_show_overlay(false),
_mouse_texture(0),
_mouse_texture_palette(0),
_mouse_texture_rgb(0),
_mouse_texture(nullptr),
_mouse_texture_palette(nullptr),
_mouse_texture_rgb(nullptr),
_mouse_hotspot(),
_mouse_dont_scale(false),
_show_mouse(false) {
_show_mouse(false),
_touchcontrols_texture(nullptr) {
if (JNI::egl_bits_per_pixel == 16) {
// We default to RGB565 and RGBA5551 which is closest to what we setup in Java side
@ -88,6 +109,8 @@ AndroidGraphics3dManager::AndroidGraphics3dManager() :
}
_mouse_texture = _mouse_texture_palette;
_touchcontrols_texture = loadBuiltinTexture(JNI::BitmapResources::TOUCH_ARROWS_BITMAP);
initSurface();
JNI::setTouch3DMode(true);
}
@ -100,6 +123,8 @@ AndroidGraphics3dManager::~AndroidGraphics3dManager() {
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glUseProgram(0);
JNI::setTouch3DMode(false);
deinitSurface();
delete _frame_buffer;
@ -108,8 +133,7 @@ AndroidGraphics3dManager::~AndroidGraphics3dManager() {
delete _overlay_background;
delete _mouse_texture_palette;
delete _mouse_texture_rgb;
JNI::setTouch3DMode(false);
delete _touchcontrols_texture;
}
static void logExtensions() {
@ -176,12 +200,15 @@ void AndroidGraphics3dManager::initSurface() {
_mouse_texture->reinit();
}
if (_touchcontrols_texture) {
_touchcontrols_texture->reinit();
}
dynamic_cast<OSystem_Android *>(g_system)->getTouchControls().init(
this, JNI::egl_surface_width, JNI::egl_surface_height);
updateScreenRect();
// double buffered, flip twice
clearScreen(kClearUpdate, 2);
dynamic_cast<OSystem_Android *>(g_system)->getTouchControls().init(
JNI::egl_surface_width, JNI::egl_surface_height);
}
void AndroidGraphics3dManager::deinitSurface() {
@ -210,6 +237,12 @@ void AndroidGraphics3dManager::deinitSurface() {
_mouse_texture->release();
}
dynamic_cast<OSystem_Android *>(g_system)->getTouchControls().init(
nullptr, 0, 0);
if (_touchcontrols_texture) {
_touchcontrols_texture->release();
}
OpenGL::ContextGL::destroy();
JNI::deinitSurface();
@ -286,9 +319,6 @@ void AndroidGraphics3dManager::updateScreen() {
clearScreen(kClear);
_game_texture->drawTextureRect();
if (!_show_overlay) {
dynamic_cast<OSystem_Android *>(g_system)->getTouchControls().draw();
}
if (_show_overlay) {
if (_overlay_background && _overlay_background->getTextureName() != 0) {
@ -302,6 +332,8 @@ void AndroidGraphics3dManager::updateScreen() {
}
}
dynamic_cast<OSystem_Android *>(g_system)->getTouchControls().draw();
if (!JNI::swapBuffers()) {
LOGW("swapBuffers failed: 0x%x", glGetError());
}
@ -932,3 +964,12 @@ bool AndroidGraphics3dManager::setState(const AndroidCommonGraphics::State &stat
return true;
}
void AndroidGraphics3dManager::touchControlNotifyChanged() {
// Make sure we redraw the screen
_force_redraw = true;
}
void AndroidGraphics3dManager::touchControlDraw(int16 x, int16 y, int16 w, int16 h, const Common::Rect &clip) {
_touchcontrols_texture->drawTexture(x, y, w, h, clip);
}

View File

@ -29,7 +29,10 @@
#include "backends/graphics/android/android-graphics.h"
#include "backends/graphics3d/android/texture.h"
class AndroidGraphics3dManager : public GraphicsManager, public AndroidCommonGraphics {
#include "backends/platform/android/touchcontrols.h"
class AndroidGraphics3dManager :
public GraphicsManager, public AndroidCommonGraphics, public TouchControlsDrawer {
public:
AndroidGraphics3dManager();
virtual ~AndroidGraphics3dManager();
@ -116,6 +119,9 @@ public:
virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const override;
#endif
void touchControlNotifyChanged() override;
void touchControlDraw(int16 x, int16 y, int16 w, int16 h, const Common::Rect &clip) override;
protected:
void updateScreenRect();
void updateCursorScaling();
@ -176,6 +182,9 @@ private:
int _mouse_width_scaled, _mouse_height_scaled;
bool _mouse_dont_scale;
bool _show_mouse;
// Touch controls layer
GLESTexture *_touchcontrols_texture;
};
#endif

View File

@ -180,6 +180,9 @@ OSystem_Android::~OSystem_Android() {
delete _savefileManager;
_savefileManager = 0;
// Uninitialize surface now to avoid it to be done later when touch controls are destroyed
dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->deinitSurface();
}
void *OSystem_Android::timerThreadFunc(void *arg) {

View File

@ -37,27 +37,21 @@
// for the Android port
#define FORBIDDEN_SYMBOL_EXCEPTION_printf
#include "graphics/conversion.h"
#include "backends/graphics3d/android/texture.h"
#include "backends/platform/android/android.h"
#include "backends/platform/android/jni-android.h"
#include "backends/platform/android/touchcontrols.h"
TouchControls::TouchControls() :
_arrows_texture(nullptr),
_drawer(nullptr),
_screen_width(0),
_screen_height(0) {
}
TouchControls::~TouchControls() {
if (_arrows_texture) {
delete _arrows_texture;
_arrows_texture = 0;
}
}
TouchControls::Function TouchControls::getFunction(int x, int y) {
if (_screen_width == 0) {
// Avoid divide by 0 error
return kFunctionNone;
}
float xPercent = float(x) / _screen_width;
if (xPercent < 0.3) {
@ -154,28 +148,8 @@ TouchControls::FunctionBehavior TouchControls::functionBehaviors[TouchControls::
{ touchToRightState, true, .8f, .5f }
};
static GLES8888Texture *loadBuiltinTexture(JNI::BitmapResources resource) {
const Graphics::Surface *src = JNI::getBitmapResource(JNI::BitmapResources::TOUCH_ARROWS_BITMAP);
if (!src) {
error("Failed to fetch touch arrows bitmap");
}
GLES8888Texture *ret = new GLES8888Texture();
ret->allocBuffer(src->w, src->h);
Graphics::Surface *dst = ret->surface();
Graphics::crossBlit(
(byte *)dst->getPixels(), (const byte *)src->getPixels(),
dst->pitch, src->pitch,
src->w, src->h,
src->format, dst->format);
delete src;
return ret;
}
void TouchControls::init(int width, int height) {
_arrows_texture = loadBuiltinTexture(JNI::BitmapResources::TOUCH_ARROWS_BITMAP);
void TouchControls::init(TouchControlsDrawer *drawer, int width, int height) {
_drawer = drawer;
_screen_width = width;
_screen_height = height;
}
@ -214,6 +188,8 @@ TouchControls::Pointer *TouchControls::findPointerFromFunction(Function function
}
void TouchControls::draw() {
assert(_drawer != nullptr);
for (uint i = 0; i < kFunctionMax + 1; i++) {
FunctionState &state = _functionStates[i];
FunctionBehavior behavior = functionBehaviors[i];
@ -221,7 +197,7 @@ void TouchControls::draw() {
if (state.clip.isEmpty()) {
continue;
}
_arrows_texture->drawTexture(_screen_width * behavior.xRatio, _screen_height * behavior.yRatio,
_drawer->touchControlDraw(_screen_width * behavior.xRatio, _screen_height * behavior.yRatio,
64, 64, state.clip);
}
@ -238,6 +214,10 @@ void TouchControls::update(Action action, int ptrId, int x, int y) {
// ptrId is active no matter what
ptr->active = true;
if (function == kFunctionNone) {
// No function for this finger
return;
}
if (findPointerFromFunction(function)) {
// Some finger is already using this function: don't do anything
return;
@ -280,6 +260,9 @@ void TouchControls::update(Action action, int ptrId, int x, int y) {
}
}
oldState = newState;
if (_drawer) {
_drawer->touchControlNotifyChanged();
}
} else if (action == JACTION_UP) {
Pointer *ptr = getPointerFromId(ptrId, false);
if (!ptr || ptr->function == kFunctionNone) {
@ -307,6 +290,9 @@ void TouchControls::update(Action action, int ptrId, int x, int y) {
functionState.reset();
ptr->active = false;
if (_drawer) {
_drawer->touchControlNotifyChanged();
}
} else if (action == JACTION_CANCEL) {
for (uint i = 0; i < kNumPointers; i++) {
Pointer &ptr = _pointers[i];
@ -325,6 +311,9 @@ void TouchControls::update(Action action, int ptrId, int x, int y) {
functionState.reset();
}
if (_drawer) {
_drawer->touchControlNotifyChanged();
}
}
}

View File

@ -24,7 +24,14 @@
#include "common/events.h"
#include "backends/graphics3d/android/texture.h"
class TouchControlsDrawer {
public:
virtual void touchControlNotifyChanged() = 0;
virtual void touchControlDraw(int16 x, int16 y, int16 w, int16 h, const Common::Rect &clip) = 0;
protected:
~TouchControlsDrawer() {}
};
class TouchControls {
public:
@ -37,13 +44,14 @@ public:
};
TouchControls();
~TouchControls();
void init(int width, int height);
void init(TouchControlsDrawer *drawer, int width, int height);
void draw();
void update(Action action, int ptr, int x, int y);
private:
TouchControlsDrawer *_drawer;
int _screen_width, _screen_height;
enum Function {
@ -95,7 +103,6 @@ private:
FunctionState _functionStates[kFunctionMax + 1];
GLESTexture *_arrows_texture;
void buttonDown(Common::JoystickButton jb);
void buttonUp(Common::JoystickButton jb);
void buttonPress(Common::JoystickButton jb);
@ -112,8 +119,6 @@ private:
static void touchToJoystickState(int dX, int dY, FunctionState &state);
static void touchToCenterState(int dX, int dY, FunctionState &state);
static void touchToRightState(int dX, int dY, FunctionState &state);
};
#endif