mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-13 21:31:53 +00:00
ANDROID: Chooose the best surface formats offered by the system
This commit is contained in:
parent
24565a5bd8
commit
6aea08860f
@ -67,9 +67,17 @@ void AndroidGraphicsManager::initSurface() {
|
||||
// Notify the OpenGL code about our context.
|
||||
setContextType(OpenGL::kContextGLES2);
|
||||
|
||||
// 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));
|
||||
if (JNI::egl_bits_per_pixel == 16) {
|
||||
// We default to RGB565 and RGBA5551 which is closest to what we setup in Java side
|
||||
notifyContextCreate(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0));
|
||||
} else {
|
||||
// If not 16, this must be 24 or 32 bpp so make use of them
|
||||
#ifdef SCUMM_BIG_ENDIAN
|
||||
notifyContextCreate(Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0), Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0));
|
||||
#else
|
||||
notifyContextCreate(Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0), Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24));
|
||||
#endif
|
||||
}
|
||||
|
||||
handleResize(JNI::egl_surface_width, JNI::egl_surface_height);
|
||||
}
|
||||
|
@ -73,10 +73,20 @@ AndroidGraphics3dManager::AndroidGraphics3dManager() :
|
||||
_mouse_hotspot(),
|
||||
_mouse_dont_scale(false),
|
||||
_show_mouse(false) {
|
||||
_game_texture = new GLESFakePalette565Texture();
|
||||
_overlay_texture = new GLES5551Texture();
|
||||
_overlay_background = new GLES5551Texture();
|
||||
_mouse_texture_palette = new GLESFakePalette5551Texture();
|
||||
|
||||
if (JNI::egl_bits_per_pixel == 16) {
|
||||
// We default to RGB565 and RGBA5551 which is closest to what we setup in Java side
|
||||
_game_texture = new GLES565Texture();
|
||||
_overlay_texture = new GLES5551Texture();
|
||||
_overlay_background = new GLES565Texture();
|
||||
_mouse_texture_palette = new GLESFakePalette5551Texture();
|
||||
} else {
|
||||
// If not 16, this must be 24 or 32 bpp so make use of them
|
||||
_game_texture = new GLES888Texture();
|
||||
_overlay_texture = new GLES8888Texture();
|
||||
_overlay_background = new GLES888Texture();
|
||||
_mouse_texture_palette = new GLESFakePalette8888Texture();
|
||||
}
|
||||
_mouse_texture = _mouse_texture_palette;
|
||||
|
||||
initSurface();
|
||||
@ -374,6 +384,9 @@ bool AndroidGraphics3dManager::hasFeature(OSystem::Feature f) const {
|
||||
f == OSystem::kFeatureAspectRatioCorrection) {
|
||||
return true;
|
||||
}
|
||||
if (f == OSystem::kFeatureOverlaySupportsAlpha) {
|
||||
return _overlay_texture->getPixelFormat().aBits() > 3;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -483,13 +496,12 @@ void AndroidGraphics3dManager::grabOverlay(Graphics::Surface &surface) const {
|
||||
|
||||
assert(surface.w >= overlaySurface->w);
|
||||
assert(surface.h >= overlaySurface->h);
|
||||
assert(surface.format.bytesPerPixel == sizeof(uint16));
|
||||
assert(overlaySurface->format.bytesPerPixel == sizeof(uint16));
|
||||
assert(surface.format.bytesPerPixel == overlaySurface->format.bytesPerPixel);
|
||||
|
||||
const byte *src = (const byte *)overlaySurface->getPixels();
|
||||
byte *dst = (byte *)surface.getPixels();
|
||||
Graphics::copyBlit(dst, src, surface.pitch, overlaySurface->pitch,
|
||||
overlaySurface->w, overlaySurface->h, sizeof(uint16));
|
||||
overlaySurface->w, overlaySurface->h, overlaySurface->format.bytesPerPixel);
|
||||
}
|
||||
|
||||
void AndroidGraphics3dManager::copyRectToOverlay(const void *buf, int pitch,
|
||||
@ -659,7 +671,11 @@ void AndroidGraphics3dManager::setMouseCursor(const void *buf, uint w, uint h,
|
||||
LOGD("switching to rgb mouse cursor");
|
||||
|
||||
assert(!_mouse_texture_rgb);
|
||||
_mouse_texture_rgb = new GLES5551Texture();
|
||||
if (JNI::egl_bits_per_pixel == 16) {
|
||||
_mouse_texture_rgb = new GLES5551Texture();
|
||||
} else {
|
||||
_mouse_texture_rgb = new GLES8888Texture();
|
||||
}
|
||||
_mouse_texture_rgb->setLinearFilter(_graphicsMode == 1);
|
||||
}
|
||||
|
||||
@ -691,6 +707,7 @@ void AndroidGraphics3dManager::setMouseCursor(const void *buf, uint w, uint h,
|
||||
_mouse_texture->updateBuffer(0, 0, w, h, buf, w);
|
||||
} else {
|
||||
uint16 pitch = _mouse_texture->pitch();
|
||||
uint16 bpp = _mouse_texture->getPixelFormat().bytesPerPixel;
|
||||
|
||||
byte *tmp = new byte[pitch * h];
|
||||
|
||||
@ -709,19 +726,19 @@ void AndroidGraphics3dManager::setMouseCursor(const void *buf, uint w, uint h,
|
||||
|
||||
if (format->bytesPerPixel == 2) {
|
||||
const uint16 *s = (const uint16 *)buf;
|
||||
uint16 *d = (uint16 *)tmp;
|
||||
byte *d = 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;
|
||||
memset(d, 0, bpp);
|
||||
}
|
||||
} else if (format->bytesPerPixel == 4) {
|
||||
const uint32 *s = (const uint32 *)buf;
|
||||
uint16 *d = (uint16 *)tmp;
|
||||
byte *d = 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;
|
||||
if (*s++ == (keycolor & 0xffffffff)) {
|
||||
memset(d, 0, bpp);
|
||||
}
|
||||
} else {
|
||||
error("AndroidGraphics3dManager::setMouseCursor: invalid bytesPerPixel %d", format->bytesPerPixel);
|
||||
|
@ -150,7 +150,7 @@ private:
|
||||
bool _force_redraw;
|
||||
|
||||
// Game layer
|
||||
GLESBaseTexture *_game_texture;
|
||||
GLESTexture *_game_texture;
|
||||
OpenGL::FrameBuffer *_frame_buffer;
|
||||
|
||||
#ifdef USE_RGB_COLOR
|
||||
@ -164,14 +164,14 @@ private:
|
||||
int _cursorX, _cursorY;
|
||||
|
||||
// Overlay layer
|
||||
GLES5551Texture *_overlay_background;
|
||||
GLES5551Texture *_overlay_texture;
|
||||
GLESTexture *_overlay_background;
|
||||
GLESTexture *_overlay_texture;
|
||||
bool _show_overlay;
|
||||
|
||||
// Mouse layer
|
||||
GLESBaseTexture *_mouse_texture;
|
||||
GLESBaseTexture *_mouse_texture_palette;
|
||||
GLES5551Texture *_mouse_texture_rgb;
|
||||
GLESFakePaletteTexture *_mouse_texture_palette;
|
||||
GLESTexture *_mouse_texture_rgb;
|
||||
Common::Point _mouse_hotspot;
|
||||
Common::Point _mouse_hotspot_scaled;
|
||||
int _mouse_width_scaled, _mouse_height_scaled;
|
||||
|
@ -72,6 +72,7 @@ sem_t JNI::pause_sem = { 0 };
|
||||
int JNI::surface_changeid = 0;
|
||||
int JNI::egl_surface_width = 0;
|
||||
int JNI::egl_surface_height = 0;
|
||||
int JNI::egl_bits_per_pixel = 0;
|
||||
bool JNI::_ready_for_events = 0;
|
||||
|
||||
jmethodID JNI::_MID_getDPI = 0;
|
||||
@ -113,7 +114,7 @@ const JNINativeMethod JNI::_natives[] = {
|
||||
(void *)JNI::create },
|
||||
{ "destroy", "()V",
|
||||
(void *)JNI::destroy },
|
||||
{ "setSurface", "(II)V",
|
||||
{ "setSurface", "(III)V",
|
||||
(void *)JNI::setSurface },
|
||||
{ "main", "([Ljava/lang/String;)I",
|
||||
(void *)JNI::main },
|
||||
@ -647,9 +648,10 @@ void JNI::destroy(JNIEnv *env, jobject self) {
|
||||
JNI::getEnv()->DeleteGlobalRef(_jobj);
|
||||
}
|
||||
|
||||
void JNI::setSurface(JNIEnv *env, jobject self, jint width, jint height) {
|
||||
void JNI::setSurface(JNIEnv *env, jobject self, jint width, jint height, jint bpp) {
|
||||
egl_surface_width = width;
|
||||
egl_surface_height = height;
|
||||
egl_bits_per_pixel = bpp;
|
||||
surface_changeid++;
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@ public:
|
||||
static int surface_changeid;
|
||||
static int egl_surface_width;
|
||||
static int egl_surface_height;
|
||||
static int egl_bits_per_pixel;
|
||||
|
||||
static jint onLoad(JavaVM *vm);
|
||||
|
||||
@ -146,7 +147,7 @@ private:
|
||||
jint audio_buffer_size);
|
||||
static void destroy(JNIEnv *env, jobject self);
|
||||
|
||||
static void setSurface(JNIEnv *env, jobject self, jint width, jint height);
|
||||
static void setSurface(JNIEnv *env, jobject self, jint width, jint height, jint bpp);
|
||||
static jint main(JNIEnv *env, jobject self, jobjectArray args);
|
||||
|
||||
static void pushEvent(JNIEnv *env, jobject self, int type, int arg1,
|
||||
|
@ -2,6 +2,7 @@ package org.scummvm.scummvm;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import android.content.res.AssetManager;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.media.AudioAttributes;
|
||||
import android.media.AudioFormat;
|
||||
import android.media.AudioManager;
|
||||
@ -33,6 +34,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
|
||||
private EGLSurface _egl_surface = EGL10.EGL_NO_SURFACE;
|
||||
|
||||
private SurfaceHolder _surface_holder;
|
||||
private int bitsPerPixel;
|
||||
private AudioTrack _audio_track;
|
||||
private int _sample_rate = 0;
|
||||
private int _buffer_size = 0;
|
||||
@ -46,7 +48,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
|
||||
int sample_rate,
|
||||
int buffer_size);
|
||||
private native void destroy();
|
||||
private native void setSurface(int width, int height);
|
||||
private native void setSurface(int width, int height, int bpp);
|
||||
private native int main(String[] args);
|
||||
|
||||
// pause the engine and all native threads
|
||||
@ -109,13 +111,17 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d(LOG_TAG, String.format(Locale.ROOT, "surfaceChanged: %dx%d (%d)",
|
||||
width, height, format));
|
||||
PixelFormat pixelFormat = new PixelFormat();
|
||||
PixelFormat.getPixelFormatInfo(format, pixelFormat);
|
||||
bitsPerPixel = pixelFormat.bitsPerPixel;
|
||||
|
||||
Log.d(LOG_TAG, String.format(Locale.ROOT, "surfaceChanged: %dx%d (%d: %dbpp)",
|
||||
width, height, format, bitsPerPixel));
|
||||
|
||||
// store values for the native code
|
||||
// make sure to do it before notifying the lock
|
||||
// as it leads to a race condition otherwise
|
||||
setSurface(width, height);
|
||||
setSurface(width, height, bitsPerPixel);
|
||||
|
||||
synchronized(_sem_surface) {
|
||||
_surface_holder = holder;
|
||||
@ -133,7 +139,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
|
||||
}
|
||||
|
||||
// clear values for the native code
|
||||
setSurface(0, 0);
|
||||
setSurface(0, 0, 0);
|
||||
}
|
||||
|
||||
final public void setArgs(String[] args) {
|
||||
@ -142,14 +148,14 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
|
||||
|
||||
final public void run() {
|
||||
try {
|
||||
initAudio();
|
||||
initEGL();
|
||||
|
||||
// wait for the surfaceChanged callback
|
||||
synchronized(_sem_surface) {
|
||||
while (_surface_holder == null)
|
||||
_sem_surface.wait();
|
||||
}
|
||||
|
||||
initAudio();
|
||||
initEGL();
|
||||
} catch (Exception e) {
|
||||
deinitEGL();
|
||||
deinitAudio();
|
||||
@ -477,15 +483,24 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
|
||||
|
||||
for (EGLConfig config : configs) {
|
||||
if (config != null) {
|
||||
boolean good = true;
|
||||
|
||||
EglAttribs attr = new EglAttribs(config);
|
||||
|
||||
// must have
|
||||
if ((attr.get(EGL10.EGL_SURFACE_TYPE) & EGL10.EGL_WINDOW_BIT) == 0)
|
||||
continue;
|
||||
good = false;
|
||||
|
||||
if (attr.get(EGL10.EGL_BUFFER_SIZE) < bitsPerPixel)
|
||||
good = false;
|
||||
|
||||
int score = attr.weight();
|
||||
|
||||
Log.d(LOG_TAG, String.format(Locale.ROOT, "%s (%d)", attr.toString(), score));
|
||||
Log.d(LOG_TAG, String.format(Locale.ROOT, "%s (%d, %s)", attr.toString(), score, good ? "OK" : "NOK"));
|
||||
|
||||
if (!good) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (score > bestScore) {
|
||||
res = config;
|
||||
|
@ -1007,7 +1007,14 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
|
||||
// so app's internal space (which would be deleted on uninstall) was set as WORLD_READABLE which is no longer supported in newer versions of Android API
|
||||
// In newer APIs we can set that path as Context.MODE_PRIVATE which is the default - but this makes the files inaccessible to other apps
|
||||
|
||||
_scummvm = new MyScummVM(_main_surface.getHolder(), new MyScummVMDestroyedCallback() {
|
||||
SurfaceHolder main_surface_holder = _main_surface.getHolder();
|
||||
|
||||
// By default Android selects RGB_565 for backward compatibility, use the best one by querying the display
|
||||
// It's deprecated on API level >= 17 and will always return RGBA_8888
|
||||
// but on older versions it could return RGB_565 which could be more efficient for the GPU
|
||||
main_surface_holder.setFormat(getDisplayPixelFormat());
|
||||
|
||||
_scummvm = new MyScummVM(main_surface_holder, new MyScummVMDestroyedCallback() {
|
||||
@Override
|
||||
public void handle(int exitResult) {
|
||||
Log.d(ScummVM.LOG_TAG, "Via callback: ScummVM native terminated with code: " + exitResult);
|
||||
@ -1385,6 +1392,13 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
|
||||
hideSystemUI();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private int getDisplayPixelFormat() {
|
||||
// Since API level 17 this always returns PixelFormat.RGBA_8888
|
||||
// so if we target more recent API levels, we could remove this function
|
||||
return getWindowManager().getDefaultDisplay().getPixelFormat();
|
||||
}
|
||||
|
||||
// Auxiliary function to overwrite a file (used for overwriting the scummvm.ini file with an existing other one)
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
private static void copyFileUsingStream(File source, File dest) throws IOException {
|
||||
|
Loading…
Reference in New Issue
Block a user