mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-21 03:31:40 +00:00
ANDROID: Don't use compressed textures for the game screen
Some GLES drivers suck so much that uploading data to the GPU takes ages. CLUT8 games now use a faked paletted texture, which internally uses a RGB565 hardware texture (Android's native pixel format). This seems to be the only way to efficiently implement constant changing textures with GLES1 - at the cost of extra buffers. Then again, we can now use glTexSubImage2D to only update the dirty rects, which wasn't possible before because glCompressedTexSubImage2D is only usable on GLES2. This commit does exactly that. Overall, the CPU usage is massively reduced for CLUT8 games.
This commit is contained in:
parent
5b820cee64
commit
a93229cae5
@ -330,7 +330,7 @@ void OSystem_Android::initBackend() {
|
||||
initSurface();
|
||||
initViewport();
|
||||
|
||||
_game_texture = new GLESPalette565Texture();
|
||||
_game_texture = new GLESFakePalette565Texture();
|
||||
_overlay_texture = new GLES4444Texture();
|
||||
_mouse_texture_palette = new GLESPalette5551Texture();
|
||||
_mouse_texture = _mouse_texture_palette;
|
||||
|
@ -72,9 +72,9 @@ Graphics::PixelFormat OSystem_Android::getScreenFormat() const {
|
||||
|
||||
Common::List<Graphics::PixelFormat> OSystem_Android::getSupportedFormats() const {
|
||||
Common::List<Graphics::PixelFormat> res;
|
||||
res.push_back(GLES565Texture::getPixelFormat());
|
||||
res.push_back(GLES5551Texture::getPixelFormat());
|
||||
res.push_back(GLES4444Texture::getPixelFormat());
|
||||
res.push_back(GLES565Texture::pixelFormat());
|
||||
res.push_back(GLES5551Texture::pixelFormat());
|
||||
res.push_back(GLES4444Texture::pixelFormat());
|
||||
res.push_back(Graphics::PixelFormat::createFormatCLUT8());
|
||||
|
||||
return res;
|
||||
@ -123,11 +123,11 @@ void OSystem_Android::initTexture(GLESTexture **texture,
|
||||
|
||||
delete *texture;
|
||||
|
||||
if (format_new == GLES565Texture::getPixelFormat())
|
||||
if (format_new == GLES565Texture::pixelFormat())
|
||||
*texture = new GLES565Texture();
|
||||
else if (format_new == GLES5551Texture::getPixelFormat())
|
||||
else if (format_new == GLES5551Texture::pixelFormat())
|
||||
*texture = new GLES5551Texture();
|
||||
else if (format_new == GLES4444Texture::getPixelFormat())
|
||||
else if (format_new == GLES4444Texture::pixelFormat())
|
||||
*texture = new GLES4444Texture();
|
||||
else {
|
||||
// TODO what now?
|
||||
@ -135,7 +135,7 @@ void OSystem_Android::initTexture(GLESTexture **texture,
|
||||
LOGE("unsupported pixel format: %s",
|
||||
getPixelFormatName(format_new).c_str());
|
||||
|
||||
*texture = new GLESPalette565Texture;
|
||||
*texture = new GLESFakePalette565Texture;
|
||||
}
|
||||
|
||||
LOGD("new pixel format: %s",
|
||||
|
@ -279,22 +279,26 @@ void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
|
||||
clearDirty();
|
||||
}
|
||||
|
||||
const Graphics::PixelFormat &GLESTexture::getPixelFormat() const {
|
||||
return _pixelFormat;
|
||||
}
|
||||
|
||||
GLES4444Texture::GLES4444Texture() :
|
||||
GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, getPixelFormat()) {
|
||||
GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, pixelFormat()) {
|
||||
}
|
||||
|
||||
GLES4444Texture::~GLES4444Texture() {
|
||||
}
|
||||
|
||||
GLES5551Texture::GLES5551Texture() :
|
||||
GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, getPixelFormat()) {
|
||||
GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, pixelFormat()) {
|
||||
}
|
||||
|
||||
GLES5551Texture::~GLES5551Texture() {
|
||||
}
|
||||
|
||||
GLES565Texture::GLES565Texture() :
|
||||
GLESTexture(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, getPixelFormat()) {
|
||||
GLESTexture(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixelFormat()) {
|
||||
}
|
||||
|
||||
GLES565Texture::~GLES565Texture() {
|
||||
@ -409,5 +413,112 @@ GLESPalette5551Texture::GLESPalette5551Texture() :
|
||||
GLESPalette5551Texture::~GLESPalette5551Texture() {
|
||||
}
|
||||
|
||||
GLESFakePaletteTexture::GLESFakePaletteTexture(GLenum glFormat, GLenum glType,
|
||||
Graphics::PixelFormat pixelFormat) :
|
||||
GLESTexture(glFormat, glType, pixelFormat),
|
||||
_palette(0),
|
||||
_pixels(0),
|
||||
_buf(0)
|
||||
{
|
||||
_palettePixelFormat = pixelFormat;
|
||||
_fake_format = Graphics::PixelFormat::createFormatCLUT8();
|
||||
|
||||
_palette = new uint16[256];
|
||||
assert(_palette);
|
||||
}
|
||||
|
||||
GLESFakePaletteTexture::~GLESFakePaletteTexture() {
|
||||
delete[] _buf;
|
||||
delete[] _pixels;
|
||||
delete[] _palette;
|
||||
}
|
||||
|
||||
void GLESFakePaletteTexture::allocBuffer(GLuint w, GLuint h) {
|
||||
GLESTexture::allocBuffer(w, h);
|
||||
|
||||
delete[] _buf;
|
||||
delete[] _pixels;
|
||||
|
||||
_pixels = new byte[w * h];
|
||||
assert(_pixels);
|
||||
|
||||
// fixup surface, for the outside this is a CLUT8 surface
|
||||
_surface.pixels = _pixels;
|
||||
_surface.bytesPerPixel = 1;
|
||||
_surface.pitch = w;
|
||||
|
||||
_buf = new uint16[w * h];
|
||||
assert(_buf);
|
||||
}
|
||||
|
||||
void GLESFakePaletteTexture::fillBuffer(uint32 color) {
|
||||
assert(_surface.pixels);
|
||||
memset(_surface.pixels, color & 0xff, _surface.pitch * _surface.h);
|
||||
setDirty();
|
||||
}
|
||||
|
||||
void GLESFakePaletteTexture::updateBuffer(GLuint x, GLuint y, GLuint w,
|
||||
GLuint h, const void *buf,
|
||||
int pitch_buf) {
|
||||
setDirtyRect(Common::Rect(x, y, x + w, y + h));
|
||||
|
||||
const byte *src = (const byte *)buf;
|
||||
byte *dst = _pixels + y * _surface.pitch + x;
|
||||
|
||||
do {
|
||||
memcpy(dst, src, w);
|
||||
dst += _surface.pitch;
|
||||
src += pitch_buf;
|
||||
} while (--h);
|
||||
}
|
||||
|
||||
void GLESFakePaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w,
|
||||
GLshort h) {
|
||||
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()) {
|
||||
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;
|
||||
}
|
||||
|
||||
GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
|
||||
|
||||
GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||
_dirty_rect.left, _dirty_rect.top,
|
||||
dwidth, dheight, _glFormat, _glType, _buf));
|
||||
}
|
||||
|
||||
GLESTexture::drawTexture(x, y, w, h);
|
||||
}
|
||||
|
||||
const Graphics::PixelFormat &GLESFakePaletteTexture::getPixelFormat() const {
|
||||
return _fake_format;
|
||||
}
|
||||
|
||||
GLESFakePalette565Texture::GLESFakePalette565Texture() :
|
||||
GLESFakePaletteTexture(GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
|
||||
GLES565Texture::pixelFormat()) {
|
||||
}
|
||||
|
||||
GLESFakePalette565Texture::~GLESFakePalette565Texture() {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -100,9 +100,7 @@ public:
|
||||
return _all_dirty || !_dirty_rect.isEmpty();
|
||||
}
|
||||
|
||||
inline const Graphics::PixelFormat &getPixelFormat() const {
|
||||
return _pixelFormat;
|
||||
}
|
||||
virtual const Graphics::PixelFormat &getPixelFormat() const;
|
||||
|
||||
inline const Graphics::PixelFormat &getPalettePixelFormat() const {
|
||||
return _palettePixelFormat;
|
||||
@ -152,7 +150,7 @@ public:
|
||||
GLES4444Texture();
|
||||
virtual ~GLES4444Texture();
|
||||
|
||||
static inline Graphics::PixelFormat getPixelFormat() {
|
||||
static Graphics::PixelFormat pixelFormat() {
|
||||
return Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0);
|
||||
}
|
||||
};
|
||||
@ -163,7 +161,7 @@ public:
|
||||
GLES5551Texture();
|
||||
virtual ~GLES5551Texture();
|
||||
|
||||
static inline Graphics::PixelFormat getPixelFormat() {
|
||||
static inline Graphics::PixelFormat pixelFormat() {
|
||||
return Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0);
|
||||
}
|
||||
};
|
||||
@ -174,7 +172,7 @@ public:
|
||||
GLES565Texture();
|
||||
virtual ~GLES565Texture();
|
||||
|
||||
static inline Graphics::PixelFormat getPixelFormat() {
|
||||
static inline Graphics::PixelFormat pixelFormat() {
|
||||
return Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
|
||||
}
|
||||
};
|
||||
@ -247,6 +245,49 @@ public:
|
||||
virtual ~GLESPalette5551Texture();
|
||||
};
|
||||
|
||||
class GLESFakePaletteTexture : public GLESTexture {
|
||||
protected:
|
||||
GLESFakePaletteTexture(GLenum glFormat, GLenum glType,
|
||||
Graphics::PixelFormat pixelFormat);
|
||||
|
||||
public:
|
||||
virtual ~GLESFakePaletteTexture();
|
||||
|
||||
virtual void allocBuffer(GLuint width, GLuint height);
|
||||
virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
|
||||
const void *buf, int pitch_buf);
|
||||
virtual void fillBuffer(uint32 color);
|
||||
|
||||
virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
|
||||
|
||||
inline void drawTexture() {
|
||||
drawTexture(0, 0, _surface.w, _surface.h);
|
||||
}
|
||||
|
||||
virtual const byte *palette_const() const {
|
||||
return (byte *)_palette;
|
||||
};
|
||||
|
||||
virtual byte *palette() {
|
||||
setDirty();
|
||||
return (byte *)_palette;
|
||||
};
|
||||
|
||||
virtual const Graphics::PixelFormat &getPixelFormat() const;
|
||||
|
||||
protected:
|
||||
Graphics::PixelFormat _fake_format;
|
||||
uint16 *_palette;
|
||||
byte *_pixels;
|
||||
uint16 *_buf;
|
||||
};
|
||||
|
||||
class GLESFakePalette565Texture : public GLESFakePaletteTexture {
|
||||
public:
|
||||
GLESFakePalette565Texture();
|
||||
virtual ~GLESFakePalette565Texture();
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user