[Scummvm-git-logs] scummvm master -> 6aea08860fa09bd8c9972a32bcd4bd9ca1698ce9

aquadran noreply at scummvm.org
Wed Dec 15 23:09:29 UTC 2021


This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
8094b77d21 ANDROID: Simplify 3D backend
35fff1ab79 ANDROID: Add cursor scaling to 3D backend
24565a5bd8 ANDROID: Rework 3D GLES textures
6aea08860f ANDROID: Chooose the best surface formats offered by the system


Commit: 8094b77d214569076fb76152a48aa96a5c9a59a4
    https://github.com/scummvm/scummvm/commit/8094b77d214569076fb76152a48aa96a5c9a59a4
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2021-12-16T00:09:25+01:00

Commit Message:
ANDROID: Simplify 3D backend

Changed paths:
    backends/graphics3d/android/android-graphics3d.cpp
    backends/graphics3d/android/android-graphics3d.h


diff --git a/backends/graphics3d/android/android-graphics3d.cpp b/backends/graphics3d/android/android-graphics3d.cpp
index e6e6025725..2e31f2f58f 100644
--- a/backends/graphics3d/android/android-graphics3d.cpp
+++ b/backends/graphics3d/android/android-graphics3d.cpp
@@ -72,8 +72,7 @@ AndroidGraphics3dManager::AndroidGraphics3dManager() :
 	_mouse_texture_rgb(0),
 	_mouse_hotspot(),
 	_mouse_keycolor(0),
-	_show_mouse(false),
-	_use_mouse_palette(false) {
+	_show_mouse(false) {
 	_game_texture = new GLESFakePalette565Texture();
 	_overlay_texture = new GLES5551Texture();
 	_overlay_background = new GLES5551Texture();
@@ -388,12 +387,6 @@ bool AndroidGraphics3dManager::hasFeature(OSystem::Feature f) const {
 
 void AndroidGraphics3dManager::setFeatureState(OSystem::Feature f, bool enable) {
 	switch (f) {
-	case OSystem::kFeatureCursorPalette:
-		_use_mouse_palette = enable;
-		if (!enable) {
-			disableCursorPalette();
-		}
-		break;
 	case OSystem::kFeatureFullscreenMode:
 		_fullscreen = enable;
 		updateScreenRect();
@@ -410,7 +403,7 @@ void AndroidGraphics3dManager::setFeatureState(OSystem::Feature f, bool enable)
 bool AndroidGraphics3dManager::getFeatureState(OSystem::Feature f) const {
 	switch (f) {
 	case OSystem::kFeatureCursorPalette:
-		return _use_mouse_palette;
+		return true;
 	case OSystem::kFeatureFullscreenMode:
 		return _fullscreen;
 	case OSystem::kFeatureAspectRatioCorrection:
@@ -539,81 +532,36 @@ int16 AndroidGraphics3dManager::getWidth() const {
 }
 
 void AndroidGraphics3dManager::setPalette(const byte *colors, uint start, uint num) {
-	ENTER("%p, %u, %u", colors, start, num);
-
-#ifdef USE_RGB_COLOR
-	assert(_game_texture->hasPalette());
-#endif
-
-	GLTHREADCHECK;
-
-	if (!_use_mouse_palette) {
-		setCursorPaletteInternal(colors, start, num);
-	}
-
-	const Graphics::PixelFormat &pf = _game_texture->getPalettePixelFormat();
-	// _game_texture is a GLESFakePalette565Texture so it's 16bits colors
-	assert(pf.bpp() == sizeof(uint16) * 8);
-	byte *p = _game_texture->palette() + start * sizeof(uint16);
-
-	for (uint i = 0; i < num; ++i, colors += 3, p += sizeof(uint16)) {
-		WRITE_UINT16(p, pf.RGBToColor(colors[0], colors[1], colors[2]));
-	}
+	// We should never end up here in 3D
+	assert(false);
 }
 
 void AndroidGraphics3dManager::grabPalette(byte *colors, uint start, uint num) const {
-	ENTER("%p, %u, %u", colors, start, num);
-
-#ifdef USE_RGB_COLOR
-	assert(_game_texture->hasPalette());
-#endif
-
-	GLTHREADCHECK;
-
-	const Graphics::PixelFormat &pf = _game_texture->getPalettePixelFormat();
-	// _game_texture is a GLESFakePalette565Texture so it's 16bits colors
-	assert(pf.bpp() == sizeof(uint16) * 8);
-	const byte *p = _game_texture->palette_const() + start * sizeof(uint16);
-
-	for (uint i = 0; i < num; ++i, colors += 3, p += sizeof(uint16)) {
-		pf.colorToRGB(READ_UINT16(p), colors[0], colors[1], colors[2]);
-	}
+	// We should never end up here in 3D
+	assert(false);
 }
 
 Graphics::Surface *AndroidGraphics3dManager::lockScreen() {
-	ENTER();
-
-	GLTHREADCHECK;
-
-	Graphics::Surface *surface = _game_texture->surface();
-	assert(surface->getPixels());
+	// We should never end up here in 3D
+	assert(false);
 
-	return surface;
+	return nullptr;
 }
 
 void AndroidGraphics3dManager::unlockScreen() {
-	ENTER();
-
-	GLTHREADCHECK;
-
-	assert(_game_texture->dirty());
+	// We should never end up here in 3D
+	assert(false);
 }
 
 void AndroidGraphics3dManager::fillScreen(uint32 col) {
-	ENTER("%u", col);
-
-	GLTHREADCHECK;
-
-	_game_texture->fillBuffer(col);
+	// We should never end up here in 3D
+	assert(false);
 }
 
 void AndroidGraphics3dManager::copyRectToScreen(const void *buf, int pitch,
         int x, int y, int w, int h) {
-	ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h);
-
-	GLTHREADCHECK;
-
-	_game_texture->updateBuffer(x, y, w, h, buf, pitch);
+	// We should never end up here in 3D
+	assert(false);
 }
 
 void AndroidGraphics3dManager::initSize(uint width, uint height,
@@ -817,34 +765,6 @@ void AndroidGraphics3dManager::setCursorPalette(const byte *colors,
 	}
 
 	setCursorPaletteInternal(colors, start, num);
-	_use_mouse_palette = true;
-}
-
-void AndroidGraphics3dManager::disableCursorPalette() {
-	// when disabling the cursor palette, and we're running a clut8 game,
-	// it expects the game palette to be used for the cursor
-	if (_game_texture->hasPalette()) {
-		// _game_texture and _mouse_texture_palette are GLESFakePalette565Texture so it's 16bits colors
-		const Graphics::PixelFormat &pf_src =
-		    _game_texture->getPalettePixelFormat();
-		const Graphics::PixelFormat &pf_dst =
-		    _mouse_texture_palette->getPalettePixelFormat();
-		assert(pf_src.bpp() == sizeof(uint16) * 8);
-		assert(pf_dst.bpp() == sizeof(uint16) * 8);
-
-		const byte *src = _game_texture->palette_const();
-		byte *dst = _mouse_texture_palette->palette();
-
-		uint8 r, g, b;
-
-		for (uint i = 0; i < 256; ++i, src += sizeof(uint16), dst += sizeof(uint16)) {
-			pf_src.colorToRGB(READ_UINT16(src), r, g, b);
-			WRITE_UINT16(dst, pf_dst.RGBToColor(r, g, b));
-		}
-
-		byte *p = _mouse_texture_palette->palette() + _mouse_keycolor * sizeof(uint16);
-		WRITE_UINT16(p, READ_UINT16(p) & ~1);
-	}
 }
 
 bool AndroidGraphics3dManager::lockMouse(bool lock) {
@@ -866,10 +786,8 @@ Graphics::PixelFormat AndroidGraphics3dManager::getScreenFormat() const {
 
 Common::List<Graphics::PixelFormat> AndroidGraphics3dManager::getSupportedFormats() const {
 	Common::List<Graphics::PixelFormat> res;
-	res.push_back(GLES565Texture::pixelFormat());
-	res.push_back(GLES5551Texture::pixelFormat());
-	res.push_back(GLES4444Texture::pixelFormat());
-	res.push_back(Graphics::PixelFormat::createFormatCLUT8());
+
+	// empty list
 
 	return res;
 }
@@ -990,14 +908,17 @@ AndroidCommonGraphics::State AndroidGraphics3dManager::getState() const {
 	state.fullscreen    = getFeatureState(OSystem::kFeatureFullscreenMode);
 	state.cursorPalette = getFeatureState(OSystem::kFeatureCursorPalette);
 #ifdef USE_RGB_COLOR
-	state.pixelFormat   = getScreenFormat();
+	state.pixelFormat   = _2d_pixel_format;
 #endif
 	return state;
 }
 
 bool AndroidGraphics3dManager::setState(const AndroidCommonGraphics::State &state) {
-	// In 3d we don't have a pixel format so we ignore it
+	// In 3d we don't have a pixel format so we ignore it but store it for when leaving 3d mode
 	initSize(state.screenWidth, state.screenHeight, nullptr);
+#ifdef USE_RGB_COLOR
+	_2d_pixel_format = state.pixelFormat;
+#endif
 	setFeatureState(OSystem::kFeatureAspectRatioCorrection, state.aspectRatio);
 	setFeatureState(OSystem::kFeatureFullscreenMode, state.fullscreen);
 	setFeatureState(OSystem::kFeatureCursorPalette, state.cursorPalette);
diff --git a/backends/graphics3d/android/android-graphics3d.h b/backends/graphics3d/android/android-graphics3d.h
index bdd1e0363f..b459f5a85f 100644
--- a/backends/graphics3d/android/android-graphics3d.h
+++ b/backends/graphics3d/android/android-graphics3d.h
@@ -132,7 +132,6 @@ protected:
 
 private:
 	void setCursorPaletteInternal(const byte *colors, uint start, uint num);
-	void disableCursorPalette();
 	void initOverlay();
 
 	enum FixupType {
@@ -154,6 +153,11 @@ private:
 	GLESBaseTexture *_game_texture;
 	OpenGL::FrameBuffer *_frame_buffer;
 
+#ifdef USE_RGB_COLOR
+	// Backup of the previous pixel format to pass it back when we leave 3d
+	Graphics::PixelFormat _2d_pixel_format;
+#endif
+
 	/**
 	 * The position of the mouse cursor, in window coordinates.
 	 */
@@ -172,7 +176,6 @@ private:
 	uint32 _mouse_keycolor;
 	int _mouse_targetscale;
 	bool _show_mouse;
-	bool _use_mouse_palette;
 };
 
 #endif


Commit: 35fff1ab79248a0f88c6b30da65564a76ac16cb4
    https://github.com/scummvm/scummvm/commit/35fff1ab79248a0f88c6b30da65564a76ac16cb4
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2021-12-16T00:09:25+01:00

Commit Message:
ANDROID: Add cursor scaling to 3D backend

Changed paths:
    backends/graphics3d/android/android-graphics3d.cpp
    backends/graphics3d/android/android-graphics3d.h


diff --git a/backends/graphics3d/android/android-graphics3d.cpp b/backends/graphics3d/android/android-graphics3d.cpp
index 2e31f2f58f..59eca9f035 100644
--- a/backends/graphics3d/android/android-graphics3d.cpp
+++ b/backends/graphics3d/android/android-graphics3d.cpp
@@ -72,6 +72,7 @@ AndroidGraphics3dManager::AndroidGraphics3dManager() :
 	_mouse_texture_rgb(0),
 	_mouse_hotspot(),
 	_mouse_keycolor(0),
+	_mouse_dont_scale(false),
 	_show_mouse(false) {
 	_game_texture = new GLESFakePalette565Texture();
 	_overlay_texture = new GLES5551Texture();
@@ -281,23 +282,15 @@ void AndroidGraphics3dManager::updateScreen() {
 		dynamic_cast<OSystem_Android *>(g_system)->getTouchControls().draw();
 	}
 
-	int cs = _mouse_targetscale;
-
 	if (_show_overlay) {
-		// ugly, but the modern theme sets a wacko factor, only god knows why
-		cs = 1;
-
 		if (_overlay_background && _overlay_background->getTextureName() != 0) {
 			GLCALL(_overlay_background->drawTextureRect());
 		}
 		GLCALL(_overlay_texture->drawTextureRect());
-	}
 
-	if (_show_mouse && !_mouse_texture->isEmpty()) {
-		const Common::Point &mouse = g_system->getEventManager()->getMousePos();
-		if (_show_overlay) {
-			_mouse_texture->drawTexture(mouse.x * cs, mouse.y * cs,
-			                            _mouse_texture->width(), _mouse_texture->height());
+		if (_show_mouse && !_mouse_texture->isEmpty()) {
+			_mouse_texture->drawTexture(_cursorX - _mouse_hotspot_scaled.x, _cursorY - _mouse_hotspot_scaled.y,
+						    _mouse_width_scaled, _mouse_width_scaled);
 		}
 	}
 
@@ -589,14 +582,14 @@ void AndroidGraphics3dManager::initSize(uint width, uint height,
 	                                        _game_texture->texWidth(), _game_texture->texHeight());
 	_frame_buffer->attach();
 
-	updateScreenRect();
-
 	// Don't know mouse size yet - it gets reallocated in
 	// setMouseCursor.  We need the palette allocated before
 	// setMouseCursor however, so just take a guess at the desired
 	// size (it's small).
 	_mouse_texture_palette->allocBuffer(20, 20);
 
+	updateScreenRect();
+
 	clearScreen(kClear);
 
 	_game_texture->setGameTexture();
@@ -630,6 +623,30 @@ void AndroidGraphics3dManager::warpMouse(int x, int y) {
 	dynamic_cast<OSystem_Android *>(g_system)->pushEvent(e);
 }
 
+void AndroidGraphics3dManager::updateCursorScaling() {
+	// By default we use the unscaled versions.
+	_mouse_hotspot_scaled = _mouse_hotspot;
+	_mouse_width_scaled = _mouse_texture->width();
+	_mouse_height_scaled = _mouse_texture->height();
+
+	// In case scaling is actually enabled we will scale the cursor according
+	// to the game screen.
+	uint16 w = _game_texture->width();
+	uint16 h = _game_texture->height();
+
+	if (!_mouse_dont_scale && w && h) {
+		const frac_t screen_scale_factor_x = intToFrac(_game_texture->getDrawRect().width()) / w;
+		const frac_t screen_scale_factor_y = intToFrac(_game_texture->getDrawRect().height()) / h;
+
+		_mouse_hotspot_scaled = Common::Point(
+			fracToInt(_mouse_hotspot_scaled.x * screen_scale_factor_x),
+			fracToInt(_mouse_hotspot_scaled.y * screen_scale_factor_y));
+
+		_mouse_width_scaled  = fracToInt(_mouse_width_scaled * screen_scale_factor_x);
+		_mouse_height_scaled = fracToInt(_mouse_height_scaled * screen_scale_factor_y);
+	}
+}
+
 void AndroidGraphics3dManager::setMouseCursor(const void *buf, uint w, uint h,
         int hotspotX, int hotspotY,
         uint32 keycolor, bool dontScale,
@@ -729,8 +746,8 @@ void AndroidGraphics3dManager::setMouseCursor(const void *buf, uint w, uint h,
 	}
 
 	_mouse_hotspot = Common::Point(hotspotX, hotspotY);
-	// TODO: Adapt to the new "do not scale" cursor logic.
-	_mouse_targetscale = 1;
+	_mouse_dont_scale = dontScale;
+	updateCursorScaling();
 }
 
 void AndroidGraphics3dManager::setCursorPaletteInternal(const byte *colors,
@@ -830,6 +847,8 @@ void AndroidGraphics3dManager::updateScreenRect() {
 	}
 
 	_game_texture->setDrawRect(rect);
+
+	updateCursorScaling();
 }
 
 const GLESBaseTexture *AndroidGraphics3dManager::getActiveTexture() const {
diff --git a/backends/graphics3d/android/android-graphics3d.h b/backends/graphics3d/android/android-graphics3d.h
index b459f5a85f..8a0e59c658 100644
--- a/backends/graphics3d/android/android-graphics3d.h
+++ b/backends/graphics3d/android/android-graphics3d.h
@@ -119,6 +119,7 @@ public:
 
 protected:
 	void updateScreenRect();
+	void updateCursorScaling();
 	const GLESBaseTexture *getActiveTexture() const;
 	void clipMouse(Common::Point &p) const;
 
@@ -174,7 +175,9 @@ private:
 	GLES5551Texture *_mouse_texture_rgb;
 	Common::Point _mouse_hotspot;
 	uint32 _mouse_keycolor;
-	int _mouse_targetscale;
+	Common::Point _mouse_hotspot_scaled;
+	int _mouse_width_scaled, _mouse_height_scaled;
+	bool _mouse_dont_scale;
 	bool _show_mouse;
 };
 


Commit: 24565a5bd8cdc9ed1f2b74d2798d8bb89d802fb4
    https://github.com/scummvm/scummvm/commit/24565a5bd8cdc9ed1f2b74d2798d8bb89d802fb4
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2021-12-16T00:09:25+01:00

Commit Message:
ANDROID: Rework 3D GLES textures

The abstraction added will allow the backend to allow surface
customization

Changed paths:
    backends/graphics3d/android/android-graphics3d.cpp
    backends/graphics3d/android/android-graphics3d.h
    backends/graphics3d/android/texture.cpp
    backends/graphics3d/android/texture.h


diff --git a/backends/graphics3d/android/android-graphics3d.cpp b/backends/graphics3d/android/android-graphics3d.cpp
index 59eca9f035..3fc2633b4b 100644
--- a/backends/graphics3d/android/android-graphics3d.cpp
+++ b/backends/graphics3d/android/android-graphics3d.cpp
@@ -71,7 +71,6 @@ AndroidGraphics3dManager::AndroidGraphics3dManager() :
 	_mouse_texture_palette(0),
 	_mouse_texture_rgb(0),
 	_mouse_hotspot(),
-	_mouse_keycolor(0),
 	_mouse_dont_scale(false),
 	_show_mouse(false) {
 	_game_texture = new GLESFakePalette565Texture();
@@ -434,9 +433,7 @@ void AndroidGraphics3dManager::showOverlay() {
 			_overlay_background->allocBuffer(_overlay_texture->width(), _overlay_texture->height());
 			_overlay_background->setDrawRect(0, 0,
 			                                 JNI::egl_surface_width, JNI::egl_surface_height);
-			Graphics::Surface *background = _overlay_background->surface();
-			GLCALL(glReadPixels(0, 0, background->w, background->h, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1,
-			             background->getPixels()));
+			_overlay_background->readPixels();
 
 			// Restore game viewport
 			GLCALL(glViewport(savedViewport[0], savedViewport[1], savedViewport[2], savedViewport[3]));
@@ -683,17 +680,7 @@ void AndroidGraphics3dManager::setMouseCursor(const void *buf, uint w, uint h,
 
 	if (_mouse_texture == _mouse_texture_palette) {
 		assert(keycolor < 256);
-
-		const Graphics::PixelFormat &pf = _mouse_texture_palette->getPalettePixelFormat();
-		// _mouse_texture_palette is a GLESFakePalette565Texture so it's 16bits colors
-		assert(pf.bpp() == sizeof(uint16) * 8);
-		byte *p = _mouse_texture_palette->palette() + _mouse_keycolor * sizeof(uint16);
-		WRITE_UINT16(p, READ_UINT16(p) | 1);
-
-		_mouse_keycolor = keycolor;
-
-		p = _mouse_texture_palette->palette() + _mouse_keycolor * sizeof(uint16);
-		WRITE_UINT16(p, READ_UINT16(p) & ~1);
+		_mouse_texture->setKeycolor(keycolor);
 	}
 
 	if (w == 0 || h == 0) {
@@ -747,23 +734,8 @@ void AndroidGraphics3dManager::setMouseCursor(const void *buf, uint w, uint h,
 
 	_mouse_hotspot = Common::Point(hotspotX, hotspotY);
 	_mouse_dont_scale = dontScale;
-	updateCursorScaling();
-}
 
-void AndroidGraphics3dManager::setCursorPaletteInternal(const byte *colors,
-        uint start, uint num) {
-	// _mouse_texture_palette is a GLESFakePalette565Texture so it's 16bits colors
-	const Graphics::PixelFormat &pf =
-		_mouse_texture_palette->getPalettePixelFormat();
-	assert(pf.bpp() == sizeof(uint16) * 8);
-	byte *p = _mouse_texture_palette->palette() + start * sizeof(uint16);
-
-	for (uint i = 0; i < num; ++i, colors += 3, p += sizeof(uint16)) {
-		WRITE_UINT16(p, pf.RGBToColor(colors[0], colors[1], colors[2]));
-	}
-
-	p = _mouse_texture_palette->palette() + _mouse_keycolor * sizeof(uint16);
-	WRITE_UINT16(p, READ_UINT16(p) & ~1);
+	updateCursorScaling();
 }
 
 void AndroidGraphics3dManager::setCursorPalette(const byte *colors,
@@ -781,7 +753,7 @@ void AndroidGraphics3dManager::setCursorPalette(const byte *colors,
 		_mouse_texture_rgb = 0;
 	}
 
-	setCursorPaletteInternal(colors, start, num);
+	_mouse_texture->setPalette(colors, start, num);
 }
 
 bool AndroidGraphics3dManager::lockMouse(bool lock) {
diff --git a/backends/graphics3d/android/android-graphics3d.h b/backends/graphics3d/android/android-graphics3d.h
index 8a0e59c658..759115f6ca 100644
--- a/backends/graphics3d/android/android-graphics3d.h
+++ b/backends/graphics3d/android/android-graphics3d.h
@@ -132,7 +132,6 @@ protected:
 	void *getProcAddress(const char *name) const;
 
 private:
-	void setCursorPaletteInternal(const byte *colors, uint start, uint num);
 	void initOverlay();
 
 	enum FixupType {
@@ -174,7 +173,6 @@ private:
 	GLESBaseTexture *_mouse_texture_palette;
 	GLES5551Texture *_mouse_texture_rgb;
 	Common::Point _mouse_hotspot;
-	uint32 _mouse_keycolor;
 	Common::Point _mouse_hotspot_scaled;
 	int _mouse_width_scaled, _mouse_height_scaled;
 	bool _mouse_dont_scale;
diff --git a/backends/graphics3d/android/texture.cpp b/backends/graphics3d/android/texture.cpp
index 1d84a9b1d0..4924e7ebe8 100644
--- a/backends/graphics3d/android/texture.cpp
+++ b/backends/graphics3d/android/texture.cpp
@@ -181,6 +181,28 @@ void GLESBaseTexture::allocBuffer(GLuint w, GLuint h) {
 
 void GLESBaseTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h,
                                   const Common::Rect &clip) {
+	if (_all_dirty) {
+		_dirty_rect.top = 0;
+		_dirty_rect.left = 0;
+		_dirty_rect.bottom = _surface.h;
+		_dirty_rect.right = _surface.w;
+
+		_all_dirty = false;
+	}
+
+	if (!_dirty_rect.isEmpty()) {
+		void *tex = prepareTextureBuffer(_dirty_rect);
+
+		GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
+		GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
+
+		GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0,
+		                       _dirty_rect.left, _dirty_rect.top,
+		                       _dirty_rect.width(), _dirty_rect.height(),
+				       _glFormat, _glType, tex));
+	}
+
+
 //	LOGD("*** Texture %p: Drawing %dx%d rect to (%d,%d)", this, w, h, x, y);
 
 	assert(_box_shader);
@@ -277,98 +299,44 @@ void GLESTexture::fillBuffer(uint32 color) {
 	setDirty();
 }
 
-void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h,
-                              const Common::Rect &clip) {
-	if (_all_dirty) {
-		_dirty_rect.top = 0;
-		_dirty_rect.left = 0;
-		_dirty_rect.bottom = _surface.h;
-		_dirty_rect.right = _surface.w;
-
-		_all_dirty = false;
-	}
-
-	if (!_dirty_rect.isEmpty()) {
-		byte *_tex;
-
-		int16 dwidth = _dirty_rect.width();
-		int16 dheight = _dirty_rect.height();
-
-		if (dwidth == _surface.w) {
-			_tex = _pixels + _dirty_rect.top * _surface.pitch;
-		} else {
-			_tex = _buf;
+void *GLESTexture::prepareTextureBuffer(const Common::Rect &rect) {
+	if (rect.width() == _surface.w) {
+		return _pixels + rect.top * _surface.pitch;
+	} else {
+		byte *tex = _buf;
 
-			byte *src = _pixels + _dirty_rect.top * _surface.pitch +
-			            _dirty_rect.left * _surface.format.bytesPerPixel;
-			byte *dst = _buf;
+		byte *src = _pixels + rect.top * _surface.pitch +
+			    rect.left * _surface.format.bytesPerPixel;
+		byte *dst = _buf;
 
-			uint16 l = dwidth * _surface.format.bytesPerPixel;
+		uint16 l = rect.width() * _surface.format.bytesPerPixel;
 
-			for (uint16 i = 0; i < dheight; ++i) {
-				memcpy(dst, src, l);
-				src += _surface.pitch;
-				dst += l;
-			}
+		for (uint16 i = rect.height(); i > 0; --i) {
+			memcpy(dst, src, l);
+			src += _surface.pitch;
+			dst += l;
 		}
 
-		GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
-		GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
-
-		GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0,
-		                       _dirty_rect.left, _dirty_rect.top,
-		                       dwidth, dheight, _glFormat, _glType, _tex));
+		return tex;
 	}
-
-	GLESBaseTexture::drawTexture(x, y, w, h, clip);
 }
 
-GLES4444Texture::GLES4444Texture() :
-	GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, pixelFormat()) {
-}
-
-GLES4444Texture::~GLES4444Texture() {
-}
-
-GLES8888Texture::GLES8888Texture() :
-	GLESTexture(GL_RGBA, GL_UNSIGNED_BYTE, pixelFormat()) {
-}
-
-GLES8888Texture::~GLES8888Texture() {
-}
-
-GLES5551Texture::GLES5551Texture() :
-	GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, pixelFormat()) {
-}
-
-GLES5551Texture::~GLES5551Texture() {
-}
-
-GLES565Texture::GLES565Texture() :
-	GLESTexture(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixelFormat()) {
-}
-
-GLES565Texture::~GLES565Texture() {
+void GLESTexture::readPixels() {
+	GLCALL(glReadPixels(0, 0, _surface.w, _surface.h, _glFormat, _glType,
+			    _pixels));
+	setDirty();
 }
 
 GLESFakePaletteTexture::GLESFakePaletteTexture(GLenum glFormat, GLenum glType,
         Graphics::PixelFormat pixelFormat) :
 	GLESBaseTexture(glFormat, glType, pixelFormat),
-	_palette(nullptr),
-	_pixels(nullptr),
-	_buf(nullptr) {
+	_pixels(nullptr) {
 	_palettePixelFormat = pixelFormat;
 	_fake_format = Graphics::PixelFormat::createFormatCLUT8();
-
-	_palette = new uint16[256];
-
-	memset(_palette, 0, 256 * 2);
 }
 
 GLESFakePaletteTexture::~GLESFakePaletteTexture() {
-	delete[] _buf;
 	delete[] _pixels;
-	delete[] _palette;
 }
 
 void GLESFakePaletteTexture::allocBuffer(GLuint w, GLuint h) {
@@ -385,8 +353,8 @@ void GLESFakePaletteTexture::allocBuffer(GLuint w, GLuint h) {
 		return;
 	}
 
-	delete[] _buf;
 	delete[] _pixels;
+	_pixels = nullptr;
 
 	_pixels = new byte[w * h];
 
@@ -394,8 +362,6 @@ void GLESFakePaletteTexture::allocBuffer(GLuint w, GLuint h) {
 	_surface.setPixels(_pixels);
 
 	fillBuffer(0);
-
-	_buf = new uint16[w * h];
 }
 
 void GLESFakePaletteTexture::fillBuffer(uint32 color) {
@@ -418,59 +384,209 @@ void GLESFakePaletteTexture::updateBuffer(GLuint x, GLuint y,
 	} while (--h);
 }
 
-void GLESFakePaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h,
-        const Common::Rect &clip) {
-	if (_all_dirty) {
-		_dirty_rect.top = 0;
-		_dirty_rect.left = 0;
-		_dirty_rect.bottom = _surface.h;
-		_dirty_rect.right = _surface.w;
+GLESFakePalette16Texture::GLESFakePalette16Texture(GLenum glFormat, GLenum glType,
+        Graphics::PixelFormat pixelFormat) :
+	GLESFakePaletteTexture(glFormat, glType, pixelFormat),
+	_palette(nullptr),
+	_buf(nullptr) {
+	_palette = new uint16[256];
+	memset(_palette, 0, sizeof(*_palette) * 256);
+}
 
-		_all_dirty = false;
-	}
+GLESFakePalette16Texture::~GLESFakePalette16Texture() {
+	delete[] _buf;
+	delete[] _palette;
+}
 
-	if (!_dirty_rect.isEmpty()) {
-		int16 dwidth = _dirty_rect.width();
-		int16 dheight = _dirty_rect.height();
-
-		byte *src = _pixels + _dirty_rect.top * _surface.pitch +
-		            _dirty_rect.left;
-		uint16 *dst = _buf;
-		uint pitch_delta = _surface.pitch - dwidth;
-
-		for (uint16 j = 0; j < dheight; ++j) {
-			for (uint16 i = 0; i < dwidth; ++i) {
-				*dst++ = _palette[*src++];
-			}
-			src += pitch_delta;
-		}
+void GLESFakePalette16Texture::allocBuffer(GLuint w, GLuint h) {
+	delete[] _buf;
+	_buf = nullptr;
 
-		GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
+	GLESFakePaletteTexture::allocBuffer(w, h);
 
-		GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0,
-		                       _dirty_rect.left, _dirty_rect.top,
-		                       dwidth, dheight, _glFormat, _glType, _buf));
+	_buf = new uint16[w * h];
+}
+
+void *GLESFakePalette16Texture::prepareTextureBuffer(const Common::Rect &rect) {
+	int16 w = rect.width();
+
+	byte *src = _pixels + rect.top * _surface.pitch +
+		    rect.left;
+	uint16 *dst = _buf;
+	uint pitch_delta = _surface.pitch - w;
+
+	for (uint16 j = rect.height(); j > 0; --j) {
+		for (uint16 i = 0; i < w; ++i) {
+			*dst++ = _palette[*src++];
+		}
+		src += pitch_delta;
 	}
 
-	GLESBaseTexture::drawTexture(x, y, w, h, clip);
+	return _buf;
 }
 
-const Graphics::PixelFormat &GLESFakePaletteTexture::getPixelFormat() const {
-	return _fake_format;
+void GLESFakePalette16Texture::setPalette(const byte *colors, uint start, uint num) {
+	uint16 *p = _palette + start;
+
+	for (uint i = 0; i < num; ++i, colors += 3, ++p) {
+		*p = _palettePixelFormat.RGBToColor(colors[0], colors[1], colors[2]);
+	}
 }
 
-GLESFakePalette565Texture::GLESFakePalette565Texture() :
-	GLESFakePaletteTexture(GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
-	                       GLES565Texture::pixelFormat()) {
+void GLESFakePalette16Texture::grabPalette(byte *colors, uint start, uint num) const {
+        const uint16 *p = _palette + start;
+
+        for (uint i = 0; i < num; ++i, colors += 3, ++p) {
+                _palettePixelFormat.colorToRGB(*p, colors[0], colors[1], colors[2]);
+        }
 }
 
-GLESFakePalette565Texture::~GLESFakePalette565Texture() {
+GLESFakePalette565Texture::GLESFakePalette565Texture() :
+	GLESFakePalette16Texture(GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
+	                         GLES565Texture::pixelFormat()) {
 }
 
 GLESFakePalette5551Texture::GLESFakePalette5551Texture() :
-	GLESFakePaletteTexture(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1,
-	                       GLES5551Texture::pixelFormat()) {
+	GLESFakePalette16Texture(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1,
+	                         GLES5551Texture::pixelFormat()),
+	_keycolor(0) {
+}
+
+void GLESFakePalette5551Texture::setKeycolor(byte color) {
+	uint16 *p = _palette + _keycolor;
+	*p |= 1;
+
+	_keycolor = color;
+
+	p = _palette + _keycolor;
+	*p &= ~1;
+}
+
+GLESFakePalette888Texture::GLESFakePalette888Texture() :
+	GLESFakePaletteTexture(GL_RGB, GL_UNSIGNED_BYTE,
+	                       GLES888Texture::pixelFormat()),
+	_palette(nullptr),
+	_buf(nullptr) {
+	_palette = new byte[256 * 3];
+	memset(_palette, 0, 256 * 3);
+}
+
+GLESFakePalette888Texture::~GLESFakePalette888Texture() {
+	delete[] _buf;
+	delete[] _palette;
+}
+
+void GLESFakePalette888Texture::allocBuffer(GLuint w, GLuint h) {
+	delete[] _buf;
+	_buf = nullptr;
+
+	GLESFakePaletteTexture::allocBuffer(w, h);
+
+	_buf = new byte[w * h * 3];
+}
+
+void *GLESFakePalette888Texture::prepareTextureBuffer(const Common::Rect &rect) {
+	int16 w = rect.width();
+
+	byte *src = _pixels + rect.top * _surface.pitch +
+		    rect.left;
+	byte *dst = _buf;
+	uint pitch_delta = _surface.pitch - w;
+
+	for (uint16 j = rect.height(); j > 0; --j) {
+		for (uint16 i = 0; i < w; ++i) {
+			byte c = *src++;
+			byte *p = _palette + c * 3;
+			*dst++ = *p++;
+			*dst++ = *p++;
+			*dst++ = *p++;
+		}
+		src += pitch_delta;
+	}
+
+	return _buf;
+}
+
+void GLESFakePalette888Texture::setPalette(const byte *colors, uint start, uint num) {
+	memcpy(_palette + start * 3, colors, num * 3);
+}
+
+void GLESFakePalette888Texture::grabPalette(byte *colors, uint start, uint num) const {
+	memcpy(colors, _palette + start * 3, num * 3);
+}
+
+GLESFakePalette8888Texture::GLESFakePalette8888Texture() :
+	GLESFakePaletteTexture(GL_RGBA, GL_UNSIGNED_BYTE,
+	                       GLES8888Texture::pixelFormat()),
+	_palette(nullptr),
+	_buf(nullptr),
+	_keycolor(0) {
+	_palette = new uint32[256];
+	memset(_palette, 0, sizeof(*_palette) * 256);
+}
+
+GLESFakePalette8888Texture::~GLESFakePalette8888Texture() {
+	delete[] _buf;
+	delete[] _palette;
+}
+
+void GLESFakePalette8888Texture::allocBuffer(GLuint w, GLuint h) {
+	delete[] _buf;
+	_buf = nullptr;
+
+	GLESFakePaletteTexture::allocBuffer(w, h);
+
+	_buf = new uint32[w * h];
+}
+
+void *GLESFakePalette8888Texture::prepareTextureBuffer(const Common::Rect &rect) {
+	int16 w = rect.width();
+
+	byte *src = _pixels + rect.top * _surface.pitch +
+		    rect.left;
+	uint32 *dst = _buf;
+	uint pitch_delta = _surface.pitch - w;
+
+	for (uint16 j = rect.height(); j > 0; --j) {
+		for (uint16 i = 0; i < w; ++i) {
+			*dst++ = _palette[*src++];
+		}
+		src += pitch_delta;
+	}
+
+	return _buf;
 }
 
-GLESFakePalette5551Texture::~GLESFakePalette5551Texture() {
+void GLESFakePalette8888Texture::setPalette(const byte *colors, uint start, uint num) {
+	// We use _palette as a uint32 to ensure proper alignment but we store bytes in a endian independent fashion
+	// because GL_UNSIGNED_BYTE is endian neutral
+	byte *p = (byte *)(_palette + start);
+
+	for (uint i = 0; i < num; ++i, colors += 3, p += 4) {
+		p[0] = colors[0];
+		p[1] = colors[1];
+		p[2] = colors[2];
+		p[3] = 255;
+	}
+}
+
+void GLESFakePalette8888Texture::setKeycolor(byte color) {
+	// _palette is endian neutral even though it's an uint32
+	byte *p = (byte *)(_palette + _keycolor);
+	p[3] = 255;
+
+	_keycolor = color;
+
+	p = (byte *)(_palette + _keycolor);
+	p[3] = 0;
+}
+
+void GLESFakePalette8888Texture::grabPalette(byte *colors, uint start, uint num) const {
+	const byte *p = (byte *)(_palette + start);
+
+        for (uint i = 0; i < num; ++i, colors += 3, p += 4) {
+		colors[0] = p[0];
+		colors[1] = p[1];
+		colors[2] = p[2];
+        }
 }
diff --git a/backends/graphics3d/android/texture.h b/backends/graphics3d/android/texture.h
index 468a891579..c416f0d279 100644
--- a/backends/graphics3d/android/texture.h
+++ b/backends/graphics3d/android/texture.h
@@ -60,11 +60,12 @@ public:
 	                          const void *buf, int pitch_buf) = 0;
 	virtual void fillBuffer(uint32 color) = 0;
 
-	virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
+	void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
 		drawTexture(x, y, w, h, Common::Rect(0, 0, width(), height()));
 	}
-	virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h, const Common::Rect &clip);
+	void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h, const Common::Rect &clip);
 
+	virtual void *prepareTextureBuffer(const Common::Rect &rect) = 0;
 
 	inline void setDrawRect(const Common::Rect &rect) {
 		_draw_rect = rect;
@@ -124,13 +125,9 @@ public:
 		return &_surface;
 	}
 
-	virtual const byte *palette_const() const {
-		return 0;
-	};
-
-	virtual byte *palette() {
-		return 0;
-	};
+	virtual void setPalette(const byte *colors, uint start, uint num) = 0;
+	virtual void setKeycolor(byte color) = 0;
+	virtual void grabPalette(byte *colors, uint start, uint num) const = 0;
 
 	inline bool hasPalette() const {
 		return _palettePixelFormat.bytesPerPixel > 0;
@@ -216,31 +213,24 @@ public:
 	                          const void *buf, int pitch_buf);
 	virtual void fillBuffer(uint32 color);
 
-	virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
-		drawTexture(x, y, w, h, Common::Rect(0, 0, width(), height()));
-	}
-	virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h, const Common::Rect &clip);
+	virtual void *prepareTextureBuffer(const Common::Rect &rect) override;
+
+	virtual void setPalette(const byte *colors, uint start, uint num) override {}
+	virtual void setKeycolor(byte color) override {};
+	virtual void grabPalette(byte *colors, uint start, uint num) const override {}
+
+	void readPixels();
 
 protected:
 	byte *_pixels;
 	byte *_buf;
 };
 
-class GLES8888Texture : public GLESTexture {
-public:
-	GLES8888Texture();
-	virtual ~GLES8888Texture();
-
-	static Graphics::PixelFormat pixelFormat() {
-		return Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
-	}
-};
-
 // RGBA4444 texture
 class GLES4444Texture : public GLESTexture {
 public:
-	GLES4444Texture();
-	virtual ~GLES4444Texture();
+	GLES4444Texture() : GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, pixelFormat()) {}
+	virtual ~GLES4444Texture() {}
 
 	static Graphics::PixelFormat pixelFormat() {
 		return Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0);
@@ -250,8 +240,8 @@ public:
 // RGBA5551 texture
 class GLES5551Texture : public GLESTexture {
 public:
-	GLES5551Texture();
-	virtual ~GLES5551Texture();
+	GLES5551Texture() : GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, pixelFormat()) {}
+	virtual ~GLES5551Texture() {}
 
 	static inline Graphics::PixelFormat pixelFormat() {
 		return Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0);
@@ -261,14 +251,42 @@ public:
 // RGB565 texture
 class GLES565Texture : public GLESTexture {
 public:
-	GLES565Texture();
-	virtual ~GLES565Texture();
+	GLES565Texture() : GLESTexture(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixelFormat()) {}
+	virtual ~GLES565Texture() {}
 
 	static inline Graphics::PixelFormat pixelFormat() {
 		return Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
 	}
 };
 
+class GLES888Texture : public GLESTexture {
+public:
+	GLES888Texture() : GLESTexture(GL_RGB, GL_UNSIGNED_BYTE, pixelFormat()) {}
+	virtual ~GLES888Texture() {}
+
+	static Graphics::PixelFormat pixelFormat() {
+#ifdef SCUMM_BIG_ENDIAN
+		return Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0);
+#else
+		return Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0);
+#endif
+	}
+};
+
+class GLES8888Texture : public GLESTexture {
+public:
+	GLES8888Texture() : GLESTexture(GL_RGBA, GL_UNSIGNED_BYTE, pixelFormat()) {}
+	virtual ~GLES8888Texture() {}
+
+	static Graphics::PixelFormat pixelFormat() {
+#ifdef SCUMM_BIG_ENDIAN
+		return Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
+#else
+		return Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24);
+#endif
+	}
+};
+
 class GLESFakePaletteTexture : public GLESBaseTexture {
 protected:
 	GLESFakePaletteTexture(GLenum glFormat, GLenum glType,
@@ -277,44 +295,90 @@ protected:
 public:
 	virtual ~GLESFakePaletteTexture();
 
-	virtual void allocBuffer(GLuint w, GLuint h);
+	virtual void allocBuffer(GLuint w, GLuint h) override;
 	virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
-	                          const void *buf, int pitch_buf);
-	virtual void fillBuffer(uint32 color);
+	                          const void *buf, int pitch_buf) override;
+	virtual void fillBuffer(uint32 color) override;
 
-	virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
-		drawTexture(x, y, w, h, Common::Rect(0, 0, width(), height()));
+	virtual const Graphics::PixelFormat &getPixelFormat() const override {
+		return _fake_format;
 	}
-	virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h, const Common::Rect &clip);
 
-	virtual const byte *palette_const() const {
-		return (byte *)_palette;
-	};
+protected:
+	Graphics::PixelFormat _fake_format;
+	byte *_pixels;
+};
 
-	virtual byte *palette() {
-		setDirty();
-		return (byte *)_palette;
-	};
+class GLESFakePalette16Texture : public GLESFakePaletteTexture {
+protected:
+	GLESFakePalette16Texture(GLenum glFormat, GLenum glType,
+	                       Graphics::PixelFormat pixelFormat);
+public:
+	virtual ~GLESFakePalette16Texture();
 
-	virtual const Graphics::PixelFormat &getPixelFormat() const;
+	virtual void allocBuffer(GLuint w, GLuint h) override;
+	virtual void *prepareTextureBuffer(const Common::Rect &rect) override;
+
+	virtual void setPalette(const byte *colors, uint start, uint num) override;
+	virtual void grabPalette(byte *colors, uint start, uint num) const override;
 
 protected:
-	Graphics::PixelFormat _fake_format;
 	uint16 *_palette;
-	byte *_pixels;
 	uint16 *_buf;
 };
 
-class GLESFakePalette565Texture : public GLESFakePaletteTexture {
+class GLESFakePalette565Texture : public GLESFakePalette16Texture {
 public:
 	GLESFakePalette565Texture();
-	virtual ~GLESFakePalette565Texture();
+	virtual ~GLESFakePalette565Texture() {}
+
+	virtual void setKeycolor(byte color) override {};
 };
 
-class GLESFakePalette5551Texture : public GLESFakePaletteTexture {
+class GLESFakePalette5551Texture : public GLESFakePalette16Texture {
 public:
 	GLESFakePalette5551Texture();
-	virtual ~GLESFakePalette5551Texture();
+	virtual ~GLESFakePalette5551Texture() {}
+
+	virtual void setKeycolor(byte color) override;
+
+protected:
+	byte _keycolor;
+};
+
+class GLESFakePalette888Texture : public GLESFakePaletteTexture {
+public:
+	GLESFakePalette888Texture();
+	virtual ~GLESFakePalette888Texture();
+
+	virtual void allocBuffer(GLuint w, GLuint h) override;
+	virtual void *prepareTextureBuffer(const Common::Rect &rect) override;
+
+	virtual void setPalette(const byte *colors, uint start, uint num) override;
+	virtual void setKeycolor(byte color) override {};
+	virtual void grabPalette(byte *colors, uint start, uint num) const override;
+
+protected:
+	byte *_palette;
+	byte *_buf;
+};
+
+class GLESFakePalette8888Texture : public GLESFakePaletteTexture {
+public:
+	GLESFakePalette8888Texture();
+	virtual ~GLESFakePalette8888Texture();
+
+	virtual void allocBuffer(GLuint w, GLuint h) override;
+	virtual void *prepareTextureBuffer(const Common::Rect &rect) override;
+
+	virtual void setPalette(const byte *colors, uint start, uint num) override;
+	virtual void setKeycolor(byte color) override;
+	virtual void grabPalette(byte *colors, uint start, uint num) const override;
+
+protected:
+	uint32 *_palette;
+	uint32 *_buf;
+	byte _keycolor;
 };
 
 #endif


Commit: 6aea08860fa09bd8c9972a32bcd4bd9ca1698ce9
    https://github.com/scummvm/scummvm/commit/6aea08860fa09bd8c9972a32bcd4bd9ca1698ce9
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2021-12-16T00:09:25+01:00

Commit Message:
ANDROID: Chooose the best surface formats offered by the system

Changed paths:
    backends/graphics/android/android-graphics.cpp
    backends/graphics3d/android/android-graphics3d.cpp
    backends/graphics3d/android/android-graphics3d.h
    backends/platform/android/jni-android.cpp
    backends/platform/android/jni-android.h
    backends/platform/android/org/scummvm/scummvm/ScummVM.java
    backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java


diff --git a/backends/graphics/android/android-graphics.cpp b/backends/graphics/android/android-graphics.cpp
index 4ca106c084..6cf4f1b783 100644
--- a/backends/graphics/android/android-graphics.cpp
+++ b/backends/graphics/android/android-graphics.cpp
@@ -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);
 }
diff --git a/backends/graphics3d/android/android-graphics3d.cpp b/backends/graphics3d/android/android-graphics3d.cpp
index 3fc2633b4b..4798503c10 100644
--- a/backends/graphics3d/android/android-graphics3d.cpp
+++ b/backends/graphics3d/android/android-graphics3d.cpp
@@ -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);
diff --git a/backends/graphics3d/android/android-graphics3d.h b/backends/graphics3d/android/android-graphics3d.h
index 759115f6ca..99aea2e2f2 100644
--- a/backends/graphics3d/android/android-graphics3d.h
+++ b/backends/graphics3d/android/android-graphics3d.h
@@ -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;
diff --git a/backends/platform/android/jni-android.cpp b/backends/platform/android/jni-android.cpp
index fa846cc0d2..fd19aef238 100644
--- a/backends/platform/android/jni-android.cpp
+++ b/backends/platform/android/jni-android.cpp
@@ -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++;
 }
 
diff --git a/backends/platform/android/jni-android.h b/backends/platform/android/jni-android.h
index 547af26cdc..b118ab7f03 100644
--- a/backends/platform/android/jni-android.h
+++ b/backends/platform/android/jni-android.h
@@ -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,
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVM.java b/backends/platform/android/org/scummvm/scummvm/ScummVM.java
index 5d6d0a5a35..d3d04fdced 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.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;
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index 9902dd5059..9b2ad2711d 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -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 {




More information about the Scummvm-git-logs mailing list