diff --git a/backends/platform/android/android.mk b/backends/platform/android/android.mk index 984ef506ee2..490f43e7fc3 100644 --- a/backends/platform/android/android.mk +++ b/backends/platform/android/android.mk @@ -1,8 +1,6 @@ # Android specific build targets PATH_DIST = $(srcdir)/dists/android -DIST_ANDROID_CONTROLS = $(PATH_DIST)/assets/arrows.tga - GRADLE_FILES = $(shell find $(PATH_DIST)/gradle -type f) $(PATH_DIST)/gradlew $(PATH_DIST)/build.gradle PATH_BUILD = ./android_project @@ -27,9 +25,9 @@ $(PATH_BUILD_GRADLE): $(GRADLE_FILES) | $(PATH_BUILD) $(ECHO) "android.enableJetifier=true\n" >> $(PATH_BUILD)/gradle.properties $(ECHO) "sdk.dir=$(realpath $(ANDROID_SDK_ROOT))\n" > $(PATH_BUILD)/local.properties -$(PATH_BUILD_ASSETS): $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(DIST_FILES_NETWORKING) $(DIST_FILES_VKEYBD) $(DIST_FILES_DOCS) $(DIST_ANDROID_CONTROLS) | $(PATH_BUILD) +$(PATH_BUILD_ASSETS): $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(DIST_FILES_NETWORKING) $(DIST_FILES_VKEYBD) $(DIST_FILES_DOCS) | $(PATH_BUILD) $(INSTALL) -d $(PATH_BUILD_ASSETS) - $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(DIST_FILES_NETWORKING) $(DIST_FILES_VKEYBD) $(DIST_FILES_DOCS) $(DIST_ANDROID_CONTROLS) $(PATH_BUILD_ASSETS)/ + $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(DIST_FILES_NETWORKING) $(DIST_FILES_VKEYBD) $(DIST_FILES_DOCS) $(PATH_BUILD_ASSETS)/ ifneq ($(DIST_FILES_SHADERS),) $(INSTALL) -d $(PATH_BUILD_ASSETS)/shaders $(INSTALL) -c -m 644 $(DIST_FILES_SHADERS) $(PATH_BUILD_ASSETS)/shaders diff --git a/backends/platform/android/jni-android.cpp b/backends/platform/android/jni-android.cpp index 28aa08af83e..98b00cf1d65 100644 --- a/backends/platform/android/jni-android.cpp +++ b/backends/platform/android/jni-android.cpp @@ -39,12 +39,15 @@ // for the Android port #define FORBIDDEN_SYMBOL_EXCEPTION_printf +#include + #include "base/main.h" #include "base/version.h" #include "common/config-manager.h" #include "common/error.h" #include "common/textconsole.h" #include "engines/engine.h" +#include "graphics/surface.h" #include "backends/platform/android/android.h" #include "backends/platform/android/asset-archive.h" @@ -84,6 +87,7 @@ jmethodID JNI::_MID_isConnectionLimited = 0; jmethodID JNI::_MID_setWindowCaption = 0; jmethodID JNI::_MID_showVirtualKeyboard = 0; jmethodID JNI::_MID_showKeyboardControl = 0; +jmethodID JNI::_MID_getBitmapResource = 0; jmethodID JNI::_MID_setTouch3DMode = 0; jmethodID JNI::_MID_showSAFRevokePermsControl = 0; jmethodID JNI::_MID_getSysArchives = 0; @@ -389,6 +393,71 @@ void JNI::showKeyboardControl(bool enable) { } } +Graphics::Surface *JNI::getBitmapResource(BitmapResources resource) { + JNIEnv *env = JNI::getEnv(); + + jobject bitmap = env->CallObjectMethod(_jobj, _MID_getBitmapResource, (int) resource); + + if (env->ExceptionCheck()) { + LOGE("Can't get bitmap resource"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + + return nullptr; + } + + if (bitmap == nullptr) { + LOGE("Bitmap resource was not found"); + return nullptr; + } + + AndroidBitmapInfo bitmap_info; + if (AndroidBitmap_getInfo(env, bitmap, &bitmap_info) != ANDROID_BITMAP_RESULT_SUCCESS) { + LOGE("Error reading bitmap info"); + env->DeleteLocalRef(bitmap); + return nullptr; + } + + Graphics::PixelFormat fmt; + switch(bitmap_info.format) { + case ANDROID_BITMAP_FORMAT_RGBA_8888: +#ifdef SCUMM_BIG_ENDIAN + fmt = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0); +#else + fmt = Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24); +#endif + break; + case ANDROID_BITMAP_FORMAT_RGBA_4444: + fmt = Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0); + break; + case ANDROID_BITMAP_FORMAT_RGB_565: + fmt = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0); + break; + default: + LOGE("Bitmap has unsupported format"); + env->DeleteLocalRef(bitmap); + return nullptr; + } + + void *src_pixels = nullptr; + if (AndroidBitmap_lockPixels(env, bitmap, &src_pixels) != ANDROID_BITMAP_RESULT_SUCCESS) { + LOGE("Error locking bitmap pixels"); + env->DeleteLocalRef(bitmap); + return nullptr; + } + + Graphics::Surface *ret = new Graphics::Surface(); + ret->create(bitmap_info.width, bitmap_info.height, fmt); + ret->copyRectToSurface(src_pixels, bitmap_info.stride, + 0, 0, bitmap_info.width, bitmap_info.height); + + AndroidBitmap_unlockPixels(env, bitmap); + env->DeleteLocalRef(bitmap); + + return ret; +} + void JNI::setTouch3DMode(bool touch3DMode) { JNIEnv *env = JNI::getEnv(); @@ -587,6 +656,7 @@ void JNI::create(JNIEnv *env, jobject self, jobject asset_manager, FIND_METHOD(, isConnectionLimited, "()Z"); FIND_METHOD(, showVirtualKeyboard, "(Z)V"); FIND_METHOD(, showKeyboardControl, "(Z)V"); + FIND_METHOD(, getBitmapResource, "(I)Landroid/graphics/Bitmap;"); FIND_METHOD(, setTouch3DMode, "(Z)V"); FIND_METHOD(, getSysArchives, "()[Ljava/lang/String;"); FIND_METHOD(, getAllStorageLocations, "()[Ljava/lang/String;"); diff --git a/backends/platform/android/jni-android.h b/backends/platform/android/jni-android.h index 4d8cfccbcd4..ad4c63ac7b9 100644 --- a/backends/platform/android/jni-android.h +++ b/backends/platform/android/jni-android.h @@ -33,6 +33,10 @@ #include "common/ustr.h" #include "engines/engine.h" +namespace Graphics { + struct Surface; +} + class OSystem_Android; class JNI { @@ -41,6 +45,10 @@ private: virtual ~JNI(); public: + enum struct BitmapResources { + TOUCH_ARROWS_BITMAP = 0 + }; + static bool pause; static sem_t pause_sem; @@ -68,6 +76,7 @@ public: static bool isConnectionLimited(); static void showVirtualKeyboard(bool enable); static void showKeyboardControl(bool enable); + static Graphics::Surface *getBitmapResource(BitmapResources resource); static void setTouch3DMode(bool touch3DMode); static void showSAFRevokePermsControl(bool enable); static void addSysArchivesToSearchSet(Common::SearchSet &s, int priority); @@ -115,6 +124,7 @@ private: static jmethodID _MID_setWindowCaption; static jmethodID _MID_showVirtualKeyboard; static jmethodID _MID_showKeyboardControl; + static jmethodID _MID_getBitmapResource; static jmethodID _MID_setTouch3DMode; static jmethodID _MID_showSAFRevokePermsControl; static jmethodID _MID_getSysArchives; diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVM.java b/backends/platform/android/org/scummvm/scummvm/ScummVM.java index 0cb8ac8a793..41dca1cab89 100644 --- a/backends/platform/android/org/scummvm/scummvm/ScummVM.java +++ b/backends/platform/android/org/scummvm/scummvm/ScummVM.java @@ -2,6 +2,7 @@ package org.scummvm.scummvm; import androidx.annotation.NonNull; import android.content.res.AssetManager; +import android.graphics.Bitmap; import android.graphics.PixelFormat; import android.media.AudioAttributes; import android.media.AudioFormat; @@ -72,6 +73,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable { abstract protected void setWindowCaption(String caption); abstract protected void showVirtualKeyboard(boolean enable); abstract protected void showKeyboardControl(boolean enable); + abstract protected Bitmap getBitmapResource(int resource); abstract protected void setTouch3DMode(boolean touch3DMode); abstract protected void showSAFRevokePermsControl(boolean enable); abstract protected String[] getSysArchives(); diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java index 93dffe6e4bc..963a605b715 100644 --- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java +++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java @@ -12,6 +12,8 @@ import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.res.AssetManager; import android.content.res.Configuration; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.Rect; import android.media.AudioManager; import android.net.Uri; @@ -705,6 +707,23 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis }); } + @Override + protected Bitmap getBitmapResource(int resource) { + int id; + switch(resource) { + case 0: // TOUCH_ARROWS_BITMAP + id = R.drawable.touch_arrows; + break; + default: + return null; + } + + BitmapFactory.Options opts = new BitmapFactory.Options(); + opts.inScaled = false; + + return BitmapFactory.decodeResource(getResources(), id, opts); + } + @Override protected void setTouch3DMode(final boolean touch3DMode) { runOnUiThread(new Runnable() { diff --git a/backends/platform/android/touchcontrols.cpp b/backends/platform/android/touchcontrols.cpp index 3b86a06838f..de50325610d 100644 --- a/backends/platform/android/touchcontrols.cpp +++ b/backends/platform/android/touchcontrols.cpp @@ -37,13 +37,11 @@ // for the Android port #define FORBIDDEN_SYMBOL_EXCEPTION_printf -#include "common/fs.h" -#include "common/stream.h" -#include "common/archive.h" -#include "image/tga.h" +#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() : @@ -156,26 +154,28 @@ TouchControls::FunctionBehavior TouchControls::functionBehaviors[TouchControls:: { touchToRightState, true, .8f, .5f } }; -static GLES8888Texture *loadBuiltinTexture(const char *filename) { - Common::ArchiveMemberPtr member = SearchMan.getMember(filename); - Common::SeekableReadStream *str = member->createReadStream(); - Image::TGADecoder dec; - dec.loadStream(*str); - const void *pixels = dec.getSurface()->getPixels(); +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(); - uint16 w = dec.getSurface()->w; - uint16 h = dec.getSurface()->h; - uint16 pitch = dec.getSurface()->pitch; - ret->allocBuffer(w, h); - ret->updateBuffer(0, 0, w, h, pixels, pitch); + ret->allocBuffer(src->w, src->h); + Graphics::Surface *dst = ret->surface(); - delete str; + 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("arrows.tga"); + _arrows_texture = loadBuiltinTexture(JNI::BitmapResources::TOUCH_ARROWS_BITMAP); _screen_width = width; _screen_height = height; } diff --git a/configure b/configure index 1e272971ec8..f4390f4d3aa 100755 --- a/configure +++ b/configure @@ -6097,7 +6097,7 @@ case $_host_os in # -lgcc is carefully placed here - we want to catch # all toolchain symbols in *our* libraries rather # than pick up anything unhygenic from the Android libs. - LIBS="-Wl,-Bstatic $static_libs -Wl,-Bdynamic -lgcc $system_libs -llog -landroid -lGLESv2" + LIBS="-Wl,-Bstatic $static_libs -Wl,-Bdynamic -lgcc $system_libs -llog -landroid -ljnigraphics -lGLESv2" ;; ds) # Moved -Wl,--gc-sections here to avoid it interfering with the library checks diff --git a/dists/android/assets/arrows.tga b/dists/android/assets/arrows.tga deleted file mode 100644 index 64a504fe4a6..00000000000 Binary files a/dists/android/assets/arrows.tga and /dev/null differ diff --git a/dists/android/res/drawable/touch_arrows.png b/dists/android/res/drawable/touch_arrows.png new file mode 100644 index 00000000000..816dabfd998 Binary files /dev/null and b/dists/android/res/drawable/touch_arrows.png differ