diff options
Diffstat (limited to 'backends/platform/android/gfx.cpp')
-rw-r--r-- | backends/platform/android/gfx.cpp | 814 |
1 files changed, 0 insertions, 814 deletions
diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp deleted file mode 100644 index 58c92adbdf..0000000000 --- a/backends/platform/android/gfx.cpp +++ /dev/null @@ -1,814 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#if defined(__ANDROID__) - -// Allow use of stuff in <time.h> -#define FORBIDDEN_SYMBOL_EXCEPTION_time_h - -// Disable printf override in common/forbidden.h to avoid -// clashes with log.h from the Android SDK. -// That header file uses -// __attribute__ ((format(printf, 3, 4))) -// which gets messed up by our override mechanism; this could -// be avoided by either changing the Android SDK to use the equally -// legal and valid -// __attribute__ ((format(printf, 3, 4))) -// or by refining our printf override to use a varadic macro -// (which then wouldn't be portable, though). -// Anyway, for now we just disable the printf override globally -// for the Android port -#define FORBIDDEN_SYMBOL_EXCEPTION_printf - -#include "common/endian.h" -#include "graphics/conversion.h" - -#include "backends/platform/android/android.h" -#include "backends/platform/android/jni.h" - -static inline GLfixed xdiv(int numerator, int denominator) { - assert(numerator < (1 << 16)); - return (numerator << 16) / denominator; -} - -const OSystem::GraphicsMode *OSystem_Android::getSupportedGraphicsModes() const { - static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { - { "default", "Default", 0 }, - { "filter", "Linear filtering", 1 }, - { 0, 0, 0 }, - }; - - return s_supportedGraphicsModes; -} - -int OSystem_Android::getDefaultGraphicsMode() const { - return 0; -} - -bool OSystem_Android::setGraphicsMode(int mode) { - ENTER("%d", mode); - - if (_game_texture) - _game_texture->setLinearFilter(mode == 1); - - if (_overlay_texture) - _overlay_texture->setLinearFilter(mode == 1); - - if (_mouse_texture) - _mouse_texture->setLinearFilter(mode == 1); - - _graphicsMode = mode; - - return true; -} - -int OSystem_Android::getGraphicsMode() const { - return _graphicsMode; -} - -#ifdef USE_RGB_COLOR -Graphics::PixelFormat OSystem_Android::getScreenFormat() const { - return _game_texture->getPixelFormat(); -} - -Common::List<Graphics::PixelFormat> OSystem_Android::getSupportedFormats() const { - Common::List<Graphics::PixelFormat> res; - res.push_back(GLES565Texture::pixelFormat()); - res.push_back(GLES5551Texture::pixelFormat()); - res.push_back(GLES8888Texture::pixelFormat()); - res.push_back(GLES4444Texture::pixelFormat()); - res.push_back(Graphics::PixelFormat::createFormatCLUT8()); - - return res; -} - -void OSystem_Android::initTexture(GLESBaseTexture **texture, - uint width, uint height, - const Graphics::PixelFormat *format) { - assert(texture); - Graphics::PixelFormat format_clut8 = - Graphics::PixelFormat::createFormatCLUT8(); - Graphics::PixelFormat format_current; - Graphics::PixelFormat format_new; - - if (*texture) - format_current = (*texture)->getPixelFormat(); - else - format_current = Graphics::PixelFormat(); - - if (format) - format_new = *format; - else - format_new = format_clut8; - - if (format_current != format_new) { - if (*texture) - LOGD("switching pixel format from: %s", - (*texture)->getPixelFormat().toString().c_str()); - - delete *texture; - - if (format_new == GLES565Texture::pixelFormat()) - *texture = new GLES565Texture(); - else if (format_new == GLES5551Texture::pixelFormat()) - *texture = new GLES5551Texture(); - else if (format_new == GLES8888Texture::pixelFormat()) - *texture = new GLES8888Texture(); - else if (format_new == GLES4444Texture::pixelFormat()) - *texture = new GLES4444Texture(); - else { - // TODO what now? - if (format_new != format_clut8) - LOGE("unsupported pixel format: %s", - format_new.toString().c_str()); - - *texture = new GLESFakePalette565Texture; - } - - LOGD("new pixel format: %s", - (*texture)->getPixelFormat().toString().c_str()); - } - - (*texture)->allocBuffer(width, height); -} -#endif - -void OSystem_Android::initSurface() { - LOGD("initializing surface"); - - assert(!JNI::haveSurface()); - - _screen_changeid = JNI::surface_changeid; - _egl_surface_width = JNI::egl_surface_width; - _egl_surface_height = JNI::egl_surface_height; - - assert(_egl_surface_width > 0 && _egl_surface_height > 0); - - JNI::initSurface(); - - // Initialize OpenGLES context. - GLESTexture::initGLExtensions(); - - if (_game_texture) - _game_texture->reinit(); - - if (_overlay_texture) { - _overlay_texture->reinit(); - initOverlay(); - } - - if (_mouse_texture) - _mouse_texture->reinit(); -} - -void OSystem_Android::deinitSurface() { - if (!JNI::haveSurface()) - return; - - LOGD("deinitializing surface"); - - _screen_changeid = JNI::surface_changeid; - _egl_surface_width = 0; - _egl_surface_height = 0; - - // release texture resources - if (_game_texture) - _game_texture->release(); - - if (_overlay_texture) - _overlay_texture->release(); - - if (_mouse_texture) - _mouse_texture->release(); - - JNI::deinitSurface(); -} - -void OSystem_Android::initViewport() { - LOGD("initializing viewport"); - - assert(JNI::haveSurface()); - - // Turn off anything that looks like 3D ;) - GLCALL(glDisable(GL_CULL_FACE)); - GLCALL(glDisable(GL_DEPTH_TEST)); - GLCALL(glDisable(GL_LIGHTING)); - GLCALL(glDisable(GL_FOG)); - GLCALL(glDisable(GL_DITHER)); - - GLCALL(glShadeModel(GL_FLAT)); - GLCALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)); - - GLCALL(glEnable(GL_BLEND)); - GLCALL(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); - - GLCALL(glEnableClientState(GL_VERTEX_ARRAY)); - GLCALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); - - GLCALL(glEnable(GL_TEXTURE_2D)); - - GLCALL(glViewport(0, 0, _egl_surface_width, _egl_surface_height)); - - GLCALL(glMatrixMode(GL_PROJECTION)); - GLCALL(glLoadIdentity()); - GLCALL(glOrthof(0, _egl_surface_width, _egl_surface_height, 0, -1, 1)); - GLCALL(glMatrixMode(GL_MODELVIEW)); - GLCALL(glLoadIdentity()); - - clearFocusRectangle(); -} - -void OSystem_Android::initOverlay() { - // minimum of 320x200 - // (surface can get smaller when opening the virtual keyboard on *QVGA*) - int overlay_width = MAX(_egl_surface_width, 320); - int overlay_height = MAX(_egl_surface_height, 200); - - // the 'normal' theme layout uses a max height of 400 pixels. if the - // surface is too big we use only a quarter of the size so that the widgets - // don't get too small. if the surface height has less than 800 pixels, this - // enforces the 'lowres' layout, which will be scaled back up by factor 2x, - // but this looks way better than the 'normal' layout scaled by some - // calculated factors - while (overlay_height > 480) { - overlay_width /= 2; - overlay_height /= 2; - } - - LOGI("overlay size is %ux%u", overlay_width, overlay_height); - - _overlay_texture->allocBuffer(overlay_width, overlay_height); - _overlay_texture->setDrawRect(0, 0, - _egl_surface_width, _egl_surface_height); -} - -void OSystem_Android::initSize(uint width, uint height, - const Graphics::PixelFormat *format) { - ENTER("%d, %d, %p", width, height, format); - - GLTHREADCHECK; - -#ifdef USE_RGB_COLOR - initTexture(&_game_texture, width, height, format); -#else - _game_texture->allocBuffer(width, height); -#endif - - updateScreenRect(); - updateEventScale(); - - // 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); - - clearScreen(kClear); -} - -void OSystem_Android::clearScreen(FixupType type, byte count) { - assert(count > 0); - - bool sm = _show_mouse; - _show_mouse = false; - - GLCALL(glDisable(GL_SCISSOR_TEST)); - - for (byte i = 0; i < count; ++i) { - // clear screen - GLCALL(glClearColorx(0, 0, 0, 1 << 16)); - GLCALL(glClear(GL_COLOR_BUFFER_BIT)); - - switch (type) { - case kClear: - break; - - case kClearSwap: - JNI::swapBuffers(); - break; - - case kClearUpdate: - _force_redraw = true; - updateScreen(); - break; - } - } - - if (!_show_overlay) - GLCALL(glEnable(GL_SCISSOR_TEST)); - - _show_mouse = sm; - _force_redraw = true; -} - -void OSystem_Android::updateScreenRect() { - Common::Rect rect(0, 0, _egl_surface_width, _egl_surface_height); - - _overlay_texture->setDrawRect(rect); - - uint16 w = _game_texture->width(); - uint16 h = _game_texture->height(); - - if (w && h && !_fullscreen) { - if (_ar_correction && w == 320 && h == 200) - h = 240; - - float dpi[2]; - JNI::getDPI(dpi); - - float screen_ar; - if (dpi[0] != 0.0 && dpi[1] != 0.0) { - // horizontal orientation - screen_ar = (dpi[1] * _egl_surface_width) / - (dpi[0] * _egl_surface_height); - } else { - screen_ar = float(_egl_surface_width) / float(_egl_surface_height); - } - - float game_ar = float(w) / float(h); - - if (screen_ar > game_ar) { - rect.setWidth(round(_egl_surface_height * game_ar)); - rect.moveTo((_egl_surface_width - rect.width()) / 2, 0); - } else { - rect.setHeight(round(_egl_surface_width / game_ar)); - rect.moveTo((_egl_surface_height - rect.height()) / 2, 0); - } - } - - glScissor(rect.left, rect.top, rect.width(), rect.height()); - - _game_texture->setDrawRect(rect); -} - -int OSystem_Android::getScreenChangeID() const { - return _screen_changeid; -} - -int16 OSystem_Android::getHeight() { - return _game_texture->height(); -} - -int16 OSystem_Android::getWidth() { - return _game_texture->width(); -} - -void OSystem_Android::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(); - byte *p = _game_texture->palette() + start * 2; - - for (uint i = 0; i < num; ++i, colors += 3, p += 2) - WRITE_UINT16(p, pf.RGBToColor(colors[0], colors[1], colors[2])); -} - -void OSystem_Android::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(); - const byte *p = _game_texture->palette_const() + start * 2; - - for (uint i = 0; i < num; ++i, colors += 3, p += 2) - pf.colorToRGB(READ_UINT16(p), colors[0], colors[1], colors[2]); -} - -void OSystem_Android::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); -} - -void OSystem_Android::updateScreen() { - //ENTER(); - - GLTHREADCHECK; - - if (!JNI::haveSurface()) - return; - - if (!_force_redraw && - !_game_texture->dirty() && - !_overlay_texture->dirty() && - !_mouse_texture->dirty()) - return; - - _force_redraw = false; - - // clear pointer leftovers in dead areas - // also, HTC's GLES drivers are made of fail and don't preserve the buffer - // ( http://www.khronos.org/registry/egl/specs/EGLTechNote0001.html ) - if ((_show_overlay || _htc_fail) && !_fullscreen) - clearScreen(kClear); - - GLCALL(glPushMatrix()); - - if (_shake_offset != 0 || - (!_focus_rect.isEmpty() && - !Common::Rect(_game_texture->width(), - _game_texture->height()).contains(_focus_rect))) { - // These are the only cases where _game_texture doesn't - // cover the entire screen. - clearScreen(kClear); - - // Move everything up by _shake_offset (game) pixels - GLCALL(glTranslatex(0, -_shake_offset << 16, 0)); - } - -// TODO this doesn't work on those sucky drivers, do it differently -// if (_show_overlay) -// GLCALL(glColor4ub(0x9f, 0x9f, 0x9f, 0x9f)); - - if (_focus_rect.isEmpty()) { - _game_texture->drawTextureRect(); - } else { - GLCALL(glPushMatrix()); - - GLCALL(glScalex(xdiv(_egl_surface_width, _focus_rect.width()), - xdiv(_egl_surface_height, _focus_rect.height()), - 1 << 16)); - GLCALL(glTranslatex(-_focus_rect.left << 16, - -_focus_rect.top << 16, 0)); - GLCALL(glScalex(xdiv(_game_texture->width(), _egl_surface_width), - xdiv(_game_texture->height(), _egl_surface_height), - 1 << 16)); - - _game_texture->drawTextureRect(); - - GLCALL(glPopMatrix()); - } - - int cs = _mouse_targetscale; - - if (_show_overlay) { -// TODO see above -// GLCALL(glColor4ub(0xff, 0xff, 0xff, 0xff)); - - // ugly, but the modern theme sets a wacko factor, only god knows why - cs = 1; - - GLCALL(_overlay_texture->drawTextureRect()); - } - - if (_show_mouse && !_mouse_texture->isEmpty()) { - GLCALL(glPushMatrix()); - - const Common::Point &mouse = getEventManager()->getMousePos(); - - // Scale up ScummVM -> OpenGL (pixel) coordinates - if (_show_overlay) { - GLCALL(glScalex(xdiv(_egl_surface_width, - _overlay_texture->width()), - xdiv(_egl_surface_height, - _overlay_texture->height()), - 1 << 16)); - } else { - const Common::Rect &r = _game_texture->getDrawRect(); - - GLCALL(glTranslatex(r.left << 16, - r.top << 16, - 0)); - GLCALL(glScalex(xdiv(r.width(), _game_texture->width()), - xdiv(r.height(), _game_texture->height()), - 1 << 16)); - } - - GLCALL(glTranslatex((-_mouse_hotspot.x * cs) << 16, - (-_mouse_hotspot.y * cs) << 16, - 0)); - - // Note the extra half texel to position the mouse in - // the middle of the x,y square: - GLCALL(glTranslatex((mouse.x << 16) | 1 << 15, - (mouse.y << 16) | 1 << 15, 0)); - - GLCALL(glScalex(cs << 16, cs << 16, 1 << 16)); - - _mouse_texture->drawTextureOrigin(); - - GLCALL(glPopMatrix()); - } - - GLCALL(glPopMatrix()); - - if (!JNI::swapBuffers()) - LOGW("swapBuffers failed: 0x%x", glGetError()); -} - -Graphics::Surface *OSystem_Android::lockScreen() { - ENTER(); - - GLTHREADCHECK; - - Graphics::Surface *surface = _game_texture->surface(); - assert(surface->getPixels()); - - return surface; -} - -void OSystem_Android::unlockScreen() { - ENTER(); - - GLTHREADCHECK; - - assert(_game_texture->dirty()); -} - -void OSystem_Android::setShakePos(int shake_offset) { - ENTER("%d", shake_offset); - - if (_shake_offset != shake_offset) { - _shake_offset = shake_offset; - _force_redraw = true; - } -} - -void OSystem_Android::fillScreen(uint32 col) { - ENTER("%u", col); - - GLTHREADCHECK; - - _game_texture->fillBuffer(col); -} - -void OSystem_Android::setFocusRectangle(const Common::Rect& rect) { - ENTER("%d, %d, %d, %d", rect.left, rect.top, rect.right, rect.bottom); - - if (_enable_zoning) { - _focus_rect = rect; - _force_redraw = true; - } -} - -void OSystem_Android::clearFocusRectangle() { - ENTER(); - - if (_enable_zoning) { - _focus_rect = Common::Rect(); - _force_redraw = true; - } -} - -void OSystem_Android::showOverlay() { - ENTER(); - - _show_overlay = true; - _force_redraw = true; - - updateEventScale(); - - warpMouse(_overlay_texture->width() / 2, _overlay_texture->height() / 2); - - GLCALL(glDisable(GL_SCISSOR_TEST)); -} - -void OSystem_Android::hideOverlay() { - ENTER(); - - _show_overlay = false; - - updateEventScale(); - - warpMouse(_game_texture->width() / 2, _game_texture->height() / 2); - - // double buffered, flip twice - clearScreen(kClearUpdate, 2); - - GLCALL(glEnable(GL_SCISSOR_TEST)); -} - -void OSystem_Android::clearOverlay() { - ENTER(); - - GLTHREADCHECK; - - _overlay_texture->fillBuffer(0); -} - -void OSystem_Android::grabOverlay(void *buf, int pitch) { - ENTER("%p, %d", buf, pitch); - - GLTHREADCHECK; - - const Graphics::Surface *surface = _overlay_texture->surface_const(); - assert(surface->format.bytesPerPixel == sizeof(uint16)); - - byte *dst = (byte *)buf; - const byte *src = (const byte *)surface->getPixels(); - uint h = surface->h; - - do { - memcpy(dst, src, surface->w * surface->format.bytesPerPixel); - src += surface->pitch; - dst += pitch; - } while (--h); -} - -void OSystem_Android::copyRectToOverlay(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; - - _overlay_texture->updateBuffer(x, y, w, h, buf, pitch); -} - -int16 OSystem_Android::getOverlayHeight() { - return _overlay_texture->height(); -} - -int16 OSystem_Android::getOverlayWidth() { - return _overlay_texture->width(); -} - -Graphics::PixelFormat OSystem_Android::getOverlayFormat() const { - return _overlay_texture->getPixelFormat(); -} - -bool OSystem_Android::showMouse(bool visible) { - ENTER("%d", visible); - - _show_mouse = visible; - - return true; -} - -void OSystem_Android::setMouseCursor(const void *buf, uint w, uint h, - int hotspotX, int hotspotY, - uint32 keycolor, bool dontScale, - const Graphics::PixelFormat *format) { - ENTER("%p, %u, %u, %d, %d, %u, %d, %p", buf, w, h, hotspotX, hotspotY, - keycolor, dontScale, format); - - GLTHREADCHECK; - -#ifdef USE_RGB_COLOR - if (format && format->bytesPerPixel > 1) { - if (_mouse_texture != _mouse_texture_rgb) { - LOGD("switching to rgb mouse cursor"); - - assert(!_mouse_texture_rgb); - _mouse_texture_rgb = new GLES5551Texture(); - _mouse_texture_rgb->setLinearFilter(_graphicsMode == 1); - } - - _mouse_texture = _mouse_texture_rgb; - } else { - if (_mouse_texture != _mouse_texture_palette) - LOGD("switching to paletted mouse cursor"); - - _mouse_texture = _mouse_texture_palette; - - delete _mouse_texture_rgb; - _mouse_texture_rgb = 0; - } -#endif - - _mouse_texture->allocBuffer(w, h); - - if (_mouse_texture == _mouse_texture_palette) { - assert(keycolor < 256); - - byte *p = _mouse_texture_palette->palette() + _mouse_keycolor * 2; - WRITE_UINT16(p, READ_UINT16(p) | 1); - - _mouse_keycolor = keycolor; - - p = _mouse_texture_palette->palette() + _mouse_keycolor * 2; - WRITE_UINT16(p, 0); - } - - if (w == 0 || h == 0) - return; - - if (_mouse_texture == _mouse_texture_palette) { - _mouse_texture->updateBuffer(0, 0, w, h, buf, w); - } else { - uint16 pitch = _mouse_texture->pitch(); - - byte *tmp = new byte[pitch * h]; - - // meh, a 16bit cursor without alpha bits... this is so silly - if (!crossBlit(tmp, (const byte *)buf, pitch, w * 2, w, h, - _mouse_texture->getPixelFormat(), - *format)) { - LOGE("crossblit failed"); - - delete[] tmp; - - _mouse_texture->allocBuffer(0, 0); - - return; - } - - const uint16 *s = (const uint16 *)buf; - uint16 *d = (uint16 *)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; - - _mouse_texture->updateBuffer(0, 0, w, h, tmp, pitch); - - delete[] tmp; - } - - _mouse_hotspot = Common::Point(hotspotX, hotspotY); - // TODO: Adapt to the new "do not scale" cursor logic. - _mouse_targetscale = 1; -} - -void OSystem_Android::setCursorPaletteInternal(const byte *colors, - uint start, uint num) { - const Graphics::PixelFormat &pf = - _mouse_texture_palette->getPalettePixelFormat(); - byte *p = _mouse_texture_palette->palette() + start * 2; - - for (uint i = 0; i < num; ++i, colors += 3, p += 2) - WRITE_UINT16(p, pf.RGBToColor(colors[0], colors[1], colors[2])); - - p = _mouse_texture_palette->palette() + _mouse_keycolor * 2; - WRITE_UINT16(p, 0); -} - -void OSystem_Android::setCursorPalette(const byte *colors, - uint start, uint num) { - ENTER("%p, %u, %u", colors, start, num); - - GLTHREADCHECK; - - if (!_mouse_texture->hasPalette()) { - LOGD("switching to paletted mouse cursor"); - - _mouse_texture = _mouse_texture_palette; - - delete _mouse_texture_rgb; - _mouse_texture_rgb = 0; - } - - setCursorPaletteInternal(colors, start, num); - _use_mouse_palette = true; -} - -void OSystem_Android::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()) { - const byte *src = _game_texture->palette_const(); - byte *dst = _mouse_texture_palette->palette(); - - const Graphics::PixelFormat &pf_src = - _game_texture->getPalettePixelFormat(); - const Graphics::PixelFormat &pf_dst = - _mouse_texture_palette->getPalettePixelFormat(); - - uint8 r, g, b; - - for (uint i = 0; i < 256; ++i, src += 2, dst += 2) { - 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 * 2; - WRITE_UINT16(p, 0); - } -} - -#endif |