ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

backends/platform/android/gfx.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #if defined(__ANDROID__)
00024 
00025 // Allow use of stuff in <time.h>
00026 #define FORBIDDEN_SYMBOL_EXCEPTION_time_h
00027 
00028 // Disable printf override in common/forbidden.h to avoid
00029 // clashes with log.h from the Android SDK.
00030 // That header file uses
00031 //   __attribute__ ((format(printf, 3, 4)))
00032 // which gets messed up by our override mechanism; this could
00033 // be avoided by either changing the Android SDK to use the equally
00034 // legal and valid
00035 //   __attribute__ ((format(printf, 3, 4)))
00036 // or by refining our printf override to use a varadic macro
00037 // (which then wouldn't be portable, though).
00038 // Anyway, for now we just disable the printf override globally
00039 // for the Android port
00040 #define FORBIDDEN_SYMBOL_EXCEPTION_printf
00041 
00042 #include "common/endian.h"
00043 #include "common/tokenizer.h"
00044 #include "graphics/conversion.h"
00045 #include "graphics/opengl/shader.h"
00046 #include "graphics/opengl/context.h"
00047 
00048 #include "backends/platform/android/android.h"
00049 #include "backends/platform/android/jni.h"
00050 
00051 static inline GLfixed xdiv(int numerator, int denominator) {
00052     assert(numerator < (1 << 16));
00053     return (numerator << 16) / denominator;
00054 }
00055 
00056 // ResidualVM specific method
00057 void OSystem_Android::launcherInitSize(uint w, uint h) {
00058     setupScreen(w, h, true, true, false);
00059 }
00060 
00061 // ResidualVM specific method
00062 bool OSystem_Android::lockMouse(bool lock) {
00063     _show_mouse = lock;
00064     return true;
00065 }
00066 
00067 const OSystem::GraphicsMode *OSystem_Android::getSupportedGraphicsModes() const {
00068     static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
00069         { "default", "Default", 0 },
00070         { "filter", "Linear filtering", 1 },
00071         { 0, 0, 0 },
00072     };
00073 
00074     return s_supportedGraphicsModes;
00075 }
00076 
00077 int OSystem_Android::getDefaultGraphicsMode() const {
00078     return 0;
00079 }
00080 
00081 bool OSystem_Android::setGraphicsMode(int mode) {
00082     ENTER("%d", mode);
00083 
00084     if (_game_texture)
00085         _game_texture->setLinearFilter(mode == 1);
00086 
00087     if (_overlay_texture)
00088         _overlay_texture->setLinearFilter(mode == 1);
00089 
00090     if (_mouse_texture)
00091         _mouse_texture->setLinearFilter(mode == 1);
00092 
00093     _graphicsMode = mode;
00094 
00095     return true;
00096 }
00097 
00098 int OSystem_Android::getGraphicsMode() const {
00099     return _graphicsMode;
00100 }
00101 
00102 #ifdef USE_RGB_COLOR
00103 Graphics::PixelFormat OSystem_Android::getScreenFormat() const {
00104     return _game_texture->getPixelFormat();
00105 }
00106 
00107 Common::List<Graphics::PixelFormat> OSystem_Android::getSupportedFormats() const {
00108     Common::List<Graphics::PixelFormat> res;
00109     res.push_back(GLES565Texture::pixelFormat());
00110     res.push_back(GLES5551Texture::pixelFormat());
00111     res.push_back(GLES4444Texture::pixelFormat());
00112     res.push_back(Graphics::PixelFormat::createFormatCLUT8());
00113 
00114     return res;
00115 }
00116 
00117 void OSystem_Android::initTexture(GLESBaseTexture **texture,
00118                                     uint width, uint height,
00119                                     const Graphics::PixelFormat *format) {
00120     assert(texture);
00121     Graphics::PixelFormat format_clut8 =
00122         Graphics::PixelFormat::createFormatCLUT8();
00123     Graphics::PixelFormat format_current;
00124     Graphics::PixelFormat format_new;
00125 
00126     if (*texture)
00127         format_current = (*texture)->getPixelFormat();
00128     else
00129         format_current = Graphics::PixelFormat();
00130 
00131     if (format)
00132         format_new = *format;
00133     else
00134         format_new = format_clut8;
00135 
00136     if (format_current != format_new) {
00137         if (*texture)
00138             LOGD("switching pixel format from: %s",
00139                     (*texture)->getPixelFormat().toString().c_str());
00140 
00141         delete *texture;
00142 
00143         if (format_new == GLES565Texture::pixelFormat())
00144             *texture = new GLES565Texture();
00145         else if (format_new == GLES5551Texture::pixelFormat())
00146             *texture = new GLES5551Texture();
00147         else if (format_new == GLES4444Texture::pixelFormat())
00148             *texture = new GLES4444Texture();
00149         else {
00150             // TODO what now?
00151             if (format_new != format_clut8)
00152                 LOGE("unsupported pixel format: %s",
00153                     format_new.toString().c_str());
00154 
00155             *texture = new GLESFakePalette565Texture;
00156         }
00157 
00158         LOGD("new pixel format: %s",
00159                 (*texture)->getPixelFormat().toString().c_str());
00160     }
00161 
00162     (*texture)->allocBuffer(width, height);
00163 }
00164 #endif
00165 
00166 static void logExtensions() {
00167     const char *ext_string =
00168         reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
00169 
00170     LOGI("Extensions:");
00171 
00172     Common::String exts;
00173     Common::StringTokenizer tokenizer(ext_string, " ");
00174     while (!tokenizer.empty()) {
00175         Common::String token = tokenizer.nextToken();
00176 
00177         exts += token + " ";
00178         if (exts.size() > 100) {
00179             LOGI("\t%s", exts.c_str());
00180             exts = "";
00181         }
00182     }
00183 
00184     if (exts.size() > 0)
00185         LOGI("\t%s", exts.c_str());
00186 }
00187 
00188 void OSystem_Android::initSurface() {
00189     LOGD("initializing surface");
00190 
00191     assert(!JNI::haveSurface());
00192 
00193     _screen_changeid = JNI::surface_changeid;
00194     _egl_surface_width = JNI::egl_surface_width;
00195     _egl_surface_height = JNI::egl_surface_height;
00196 
00197     assert(_egl_surface_width > 0 && _egl_surface_height > 0);
00198 
00199     JNI::initSurface();
00200 
00201     // Initialize OpenGLES context.
00202     OpenGLContext.initialize(OpenGL::kContextGLES2);
00203     logExtensions();
00204     GLESTexture::initGL();
00205 
00206     if (_game_texture)
00207         _game_texture->reinit();
00208 
00209     if (_overlay_texture) {
00210         _overlay_texture->reinit();
00211         initOverlay();
00212     }
00213 
00214     if (_mouse_texture)
00215         _mouse_texture->reinit();
00216 }
00217 
00218 void OSystem_Android::deinitSurface() {
00219     if (!JNI::haveSurface())
00220         return;
00221 
00222     LOGD("deinitializing surface");
00223 
00224     _screen_changeid = JNI::surface_changeid;
00225     _egl_surface_width = 0;
00226     _egl_surface_height = 0;
00227 
00228     // release texture resources
00229     if (_game_texture)
00230         _game_texture->release();
00231 
00232     if (_overlay_texture)
00233         _overlay_texture->release();
00234 
00235     if (_mouse_texture)
00236         _mouse_texture->release();
00237 
00238     OpenGL::Context::destroy();
00239 
00240     JNI::deinitSurface();
00241 }
00242 
00243 void OSystem_Android::initViewport() {
00244     LOGD("initializing viewport");
00245 
00246     assert(JNI::haveSurface());
00247 
00248     GLCALL(glDisable(GL_CULL_FACE));
00249     GLCALL(glDisable(GL_DEPTH_TEST));
00250 
00251     GLCALL(glEnable(GL_BLEND));
00252     GLCALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
00253 
00254     GLCALL(glViewport(0, 0, _egl_surface_width, _egl_surface_height));
00255     LOGD("viewport size: %dx%d", _egl_surface_width, _egl_surface_height);
00256 
00257     clearFocusRectangle();
00258 }
00259 
00260 void OSystem_Android::initOverlay() {
00261     // minimum of 320x200
00262     // (surface can get smaller when opening the virtual keyboard on *QVGA*)
00263     int overlay_width = MAX(_egl_surface_width, 320);
00264     int overlay_height = MAX(_egl_surface_height, 200);
00265 
00266     // the 'normal' theme layout uses a max height of 400 pixels. if the
00267     // surface is too big we use only a quarter of the size so that the widgets
00268     // don't get too small. if the surface height has less than 800 pixels, this
00269     // enforces the 'lowres' layout, which will be scaled back up by factor 2x,
00270     // but this looks way better than the 'normal' layout scaled by some
00271     // calculated factors
00272 //  while (overlay_height > 480) {
00273 //      overlay_width /= 2;
00274 //      overlay_height /= 2;
00275 //  }
00276 
00277     LOGI("overlay size is %ux%u", overlay_width, overlay_height);
00278 
00279     _overlay_texture->allocBuffer(overlay_width, overlay_height);
00280     _overlay_texture->setDrawRect(0, 0,
00281                                     _egl_surface_width, _egl_surface_height);
00282 }
00283 
00284 void OSystem_Android::initSize(uint width, uint height,
00285                                 const Graphics::PixelFormat *format) {
00286     ENTER("%d, %d, %p", width, height, format);
00287 
00288     GLTHREADCHECK;
00289 
00290 #ifdef USE_RGB_COLOR
00291     initTexture(&_game_texture, width, height, format);
00292 #else
00293     _game_texture->allocBuffer(width, height);
00294 #endif
00295 #ifdef USE_GLES2
00296     _frame_buffer = new OpenGL::FrameBuffer(_game_texture->getTextureName(), _game_texture->width(), _game_texture->height(), _game_texture->texWidth(), _game_texture->texHeight());
00297     _frame_buffer->attach();
00298 #endif
00299 
00300     updateScreenRect();
00301     updateEventScale();
00302 
00303     // Don't know mouse size yet - it gets reallocated in
00304     // setMouseCursor.  We need the palette allocated before
00305     // setMouseCursor however, so just take a guess at the desired
00306     // size (it's small).
00307     _mouse_texture_palette->allocBuffer(20, 20);
00308 
00309     clearScreen(kClear);
00310 }
00311 
00312 void OSystem_Android::clearScreen(FixupType type, byte count) {
00313     assert(count > 0);
00314 
00315     bool sm = _show_mouse;
00316     _show_mouse = false;
00317 
00318     GLCALL(glDisable(GL_SCISSOR_TEST));
00319 
00320     for (byte i = 0; i < count; ++i) {
00321         // clear screen
00322         GLCALL(glClearColor(0, 0, 0, 1 << 16));
00323         if (_opengl) {
00324             GLCALL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
00325         } else {
00326             GLCALL(glClear(GL_COLOR_BUFFER_BIT));
00327         }
00328 
00329         switch (type) {
00330         case kClear:
00331             break;
00332 
00333         case kClearSwap:
00334             JNI::swapBuffers();
00335             break;
00336 
00337         case kClearUpdate:
00338             _force_redraw = true;
00339             updateScreen();
00340             break;
00341         }
00342     }
00343 
00344     if (!_show_overlay)
00345         GLCALL(glEnable(GL_SCISSOR_TEST));
00346 
00347     _show_mouse = sm;
00348     _force_redraw = true;
00349 }
00350 
00351 void OSystem_Android::updateScreenRect() {
00352     Common::Rect rect(0, 0, _egl_surface_width, _egl_surface_height);
00353 
00354     _overlay_texture->setDrawRect(rect);
00355 
00356     uint16 w = _game_texture->width();
00357     uint16 h = _game_texture->height();
00358 
00359     if (w && h && _ar_correction) {
00360 
00361         float dpi[2];
00362         JNI::getDPI(dpi);
00363 
00364         float screen_ar;
00365         if (dpi[0] != 0.0 && dpi[1] != 0.0) {
00366             // horizontal orientation
00367             screen_ar = (dpi[1] * _egl_surface_width) /
00368                         (dpi[0] * _egl_surface_height);
00369         } else {
00370             screen_ar = float(_egl_surface_width) / float(_egl_surface_height);
00371         }
00372 
00373         float game_ar = float(w) / float(h);
00374 
00375         if (screen_ar > game_ar) {
00376             rect.setWidth(round(_egl_surface_height * game_ar));
00377             rect.moveTo((_egl_surface_width - rect.width()) / 2, 0);
00378         } else {
00379             rect.setHeight(round(_egl_surface_width / game_ar));
00380             rect.moveTo((_egl_surface_height - rect.height()) / 2, 0);
00381         }
00382     }
00383 
00384     _game_texture->setDrawRect(rect);
00385 }
00386 
00387 int OSystem_Android::getScreenChangeID() const {
00388     return _screen_changeid;
00389 }
00390 
00391 int16 OSystem_Android::getHeight() {
00392     return _game_texture->height();
00393 }
00394 
00395 int16 OSystem_Android::getWidth() {
00396     return _game_texture->width();
00397 }
00398 
00399 void OSystem_Android::setPalette(const byte *colors, uint start, uint num) {
00400     ENTER("%p, %u, %u", colors, start, num);
00401 
00402 #ifdef USE_RGB_COLOR
00403     assert(_game_texture->hasPalette());
00404 #endif
00405 
00406     GLTHREADCHECK;
00407 
00408     if (!_use_mouse_palette)
00409         setCursorPaletteInternal(colors, start, num);
00410 
00411     const Graphics::PixelFormat &pf = _game_texture->getPalettePixelFormat();
00412     byte *p = _game_texture->palette() + start * 2;
00413 
00414     for (uint i = 0; i < num; ++i, colors += 3, p += 2)
00415         WRITE_UINT16(p, pf.RGBToColor(colors[0], colors[1], colors[2]));
00416 }
00417 
00418 void OSystem_Android::grabPalette(byte *colors, uint start, uint num) const {
00419     ENTER("%p, %u, %u", colors, start, num);
00420 
00421 #ifdef USE_RGB_COLOR
00422     assert(_game_texture->hasPalette());
00423 #endif
00424 
00425     GLTHREADCHECK;
00426 
00427     const Graphics::PixelFormat &pf = _game_texture->getPalettePixelFormat();
00428     const byte *p = _game_texture->palette_const() + start * 2;
00429 
00430     for (uint i = 0; i < num; ++i, colors += 3, p += 2)
00431         pf.colorToRGB(READ_UINT16(p), colors[0], colors[1], colors[2]);
00432 }
00433 
00434 void OSystem_Android::copyRectToScreen(const void *buf, int pitch,
00435                                         int x, int y, int w, int h) {
00436     ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h);
00437 
00438     GLTHREADCHECK;
00439 
00440     _game_texture->updateBuffer(x, y, w, h, buf, pitch);
00441 }
00442 
00443 
00444 // ResidualVM specific method
00445 void OSystem_Android::setupScreen(uint screenW, uint screenH, bool fullscreen, bool accel3d, bool isGame) {
00446     _opengl = accel3d;
00447     initViewport();
00448 
00449     _touchControls.init(this, _egl_surface_width, _egl_surface_height);
00450 
00451     if (_opengl) {
00452         // resize game texture
00453         initSize(screenW, screenH, 0);
00454         if (isGame)
00455             _game_texture->setGameTexture();
00456         // format is not used by the gfx_opengl driver, use fake format
00457         _game_pbuf.set(Graphics::PixelFormat(), 0);
00458 
00459     } else {
00460         Graphics::PixelFormat format = GLES565Texture::pixelFormat();
00461         initSize(screenW, screenH, &format);
00462         // as there is no support for the texture surface's lock/unlock mechanism in gfx_tinygl/...
00463         // do not use _game_texture->surface()->pixels directly
00464         _game_pbuf.create(_game_texture->getPixelFormat(),
00465                 _game_texture->width() * _game_texture->height(), DisposeAfterUse::YES);
00466     }
00467 
00468 }
00469 
00470 Graphics::PixelBuffer OSystem_Android::getScreenPixelBuffer() {
00471     return _game_pbuf;
00472 }
00473 
00474 void OSystem_Android::updateScreen() {
00475     //ENTER();
00476 
00477     GLTHREADCHECK;
00478 
00479     if (!JNI::haveSurface())
00480         return;
00481 
00482         if (_game_pbuf) {
00483             int pitch = _game_texture->width() * _game_texture->getPixelFormat().bytesPerPixel;
00484             _game_texture->updateBuffer(0, 0, _game_texture->width(), _game_texture->height(),
00485                     _game_pbuf.getRawBuffer(), pitch);
00486         }
00487 
00488         if (!_force_redraw &&
00489                 !_game_texture->dirty() &&
00490                 !_overlay_texture->dirty() &&
00491                 !_mouse_texture->dirty())
00492             return;
00493 
00494         _force_redraw = false;
00495 
00496         if (_frame_buffer) {
00497             _frame_buffer->detach();
00498             glViewport(0,0, _egl_surface_width, _egl_surface_height);
00499         }
00500 
00501         // clear pointer leftovers in dead areas
00502         clearScreen(kClear);
00503 
00504     // TODO this doesnt work on those sucky drivers, do it differently
00505     //  if (_show_overlay)
00506     //      GLCALL(glColor4ub(0x9f, 0x9f, 0x9f, 0x9f));
00507 
00508         if (true || _focus_rect.isEmpty()) {
00509             _game_texture->drawTextureRect();
00510             drawVirtControls();
00511         } else {
00512 // TODO what is this and do we have engines using it?
00513 #if 0
00514             GLCALL(glPushMatrix());
00515 
00516             GLCALL(glScalex(xdiv(_egl_surface_width, _focus_rect.width()),
00517                             xdiv(_egl_surface_height, _focus_rect.height()),
00518                             1 << 16));
00519             GLCALL(glTranslatex(-_focus_rect.left << 16,
00520                                 -_focus_rect.top << 16, 0));
00521             GLCALL(glScalex(xdiv(_game_texture->width(), _egl_surface_width),
00522                             xdiv(_game_texture->height(), _egl_surface_height),
00523                             1 << 16));
00524 
00525             _game_texture->drawTextureRect();
00526 
00527             GLCALL(glPopMatrix());
00528 #endif
00529         }
00530 
00531         int cs = _mouse_targetscale;
00532 
00533         if (_show_overlay) {
00534     // TODO see above
00535     //      GLCALL(glColor4ub(0xff, 0xff, 0xff, 0xff));
00536 
00537             // ugly, but the modern theme sets a wacko factor, only god knows why
00538             cs = 1;
00539 
00540             GLCALL(_overlay_texture->drawTextureRect());
00541         }
00542 
00543         if (_show_mouse && !_mouse_texture->isEmpty()) {
00544             const Common::Point &mouse = getEventManager()->getMousePos();
00545             if (_show_overlay) {
00546                 _mouse_texture->drawTexture(mouse.x * cs, mouse.y * cs, _mouse_texture->width(), _mouse_texture->height());
00547             }
00548 // TODO: Port the non-overlay code as well?
00549 #if 0
00550             if (_show_overlay) {
00551             } else {
00552                 const Common::Rect &r = _game_texture->getDrawRect();
00553 
00554                 GLCALL(glTranslatex(r.left << 16,
00555                                     r.top << 16,
00556                                     0));
00557                 GLCALL(glScalex(xdiv(r.width(), _game_texture->width()),
00558                                 xdiv(r.height(), _game_texture->height()),
00559                                 1 << 16));
00560             }
00561 
00562             GLCALL(glTranslatex((-_mouse_hotspot.x * cs) << 16,
00563                                 (-_mouse_hotspot.y * cs) << 16,
00564                                 0));
00565 
00566 #endif
00567     }
00568 
00569     if (!JNI::swapBuffers())
00570         LOGW("swapBuffers failed: 0x%x", glGetError());
00571 
00572     if (_frame_buffer)
00573         _frame_buffer->attach();
00574 }
00575 
00576 void OSystem_Android::drawVirtControls() {
00577     if (_show_overlay)
00578         return;
00579 
00580     glEnable(GL_BLEND);
00581     _touchControls.draw();
00582 }
00583 
00584 Graphics::Surface *OSystem_Android::lockScreen() {
00585     ENTER();
00586 
00587     GLTHREADCHECK;
00588 
00589     Graphics::Surface *surface = _game_texture->surface();
00590     assert(surface->getPixels());
00591 
00592     return surface;
00593 }
00594 
00595 void OSystem_Android::unlockScreen() {
00596     ENTER();
00597 
00598     GLTHREADCHECK;
00599 
00600     assert(_game_texture->dirty());
00601 }
00602 
00603 void OSystem_Android::setShakePos(int shake_offset) {
00604     /* not used in any engine */
00605 }
00606 
00607 void OSystem_Android::fillScreen(uint32 col) {
00608     ENTER("%u", col);
00609 
00610     GLTHREADCHECK;
00611 
00612     _game_texture->fillBuffer(col);
00613 }
00614 
00615 void OSystem_Android::setFocusRectangle(const Common::Rect& rect) {
00616     ENTER("%d, %d, %d, %d", rect.left, rect.top, rect.right, rect.bottom);
00617 
00618     if (_enable_zoning) {
00619         _focus_rect = rect;
00620         _force_redraw = true;
00621     }
00622 }
00623 
00624 void OSystem_Android::clearFocusRectangle() {
00625     ENTER();
00626 
00627     if (_enable_zoning) {
00628         _focus_rect = Common::Rect();
00629         _force_redraw = true;
00630     }
00631 }
00632 
00633 void OSystem_Android::showOverlay() {
00634     ENTER();
00635 
00636     _show_overlay = true;
00637     _force_redraw = true;
00638 
00639     updateEventScale();
00640 
00641     warpMouse(_overlay_texture->width() / 2, _overlay_texture->height() / 2);
00642 
00643     GLCALL(glDisable(GL_SCISSOR_TEST));
00644 }
00645 
00646 void OSystem_Android::hideOverlay() {
00647     ENTER();
00648 
00649     _show_overlay = false;
00650 
00651     updateEventScale();
00652 
00653     warpMouse(_game_texture->width() / 2, _game_texture->height() / 2);
00654 
00655     // double buffered, flip twice
00656     clearScreen(kClearUpdate, 2);
00657 
00658     GLCALL(glEnable(GL_SCISSOR_TEST));
00659 }
00660 
00661 void OSystem_Android::clearOverlay() {
00662     ENTER();
00663 
00664     GLTHREADCHECK;
00665 
00666     _overlay_texture->fillBuffer(0);
00667 }
00668 
00669 void OSystem_Android::grabOverlay(void *buf, int pitch) {
00670     ENTER("%p, %d", buf, pitch);
00671 
00672     GLTHREADCHECK;
00673 
00674     const Graphics::Surface *surface = _overlay_texture->surface_const();
00675     assert(surface->format.bytesPerPixel == sizeof(uint16));
00676 
00677     byte *dst = (byte *)buf;
00678     const byte *src = (const byte *)surface->getPixels();
00679     uint h = surface->h;
00680 
00681     do {
00682         memcpy(dst, src, surface->w * surface->format.bytesPerPixel);
00683         src += surface->pitch;
00684         dst += pitch;
00685     } while (--h);
00686 }
00687 
00688 void OSystem_Android::copyRectToOverlay(const void *buf, int pitch,
00689                                         int x, int y, int w, int h) {
00690     ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h);
00691 
00692     GLTHREADCHECK;
00693 
00694     _overlay_texture->updateBuffer(x, y, w, h, buf, pitch);
00695 }
00696 
00697 int16 OSystem_Android::getOverlayHeight() {
00698     return _overlay_texture->height();
00699 }
00700 
00701 int16 OSystem_Android::getOverlayWidth() {
00702     return _overlay_texture->width();
00703 }
00704 
00705 Graphics::PixelFormat OSystem_Android::getOverlayFormat() const {
00706     return _overlay_texture->getPixelFormat();
00707 }
00708 
00709 bool OSystem_Android::showMouse(bool visible) {
00710     ENTER("%d", visible);
00711 
00712     _show_mouse = visible;
00713 
00714     return true;
00715 }
00716 
00717 void OSystem_Android::setMouseCursor(const void *buf, uint w, uint h,
00718                                         int hotspotX, int hotspotY,
00719                                         uint32 keycolor, bool dontScale,
00720                                         const Graphics::PixelFormat *format) {
00721     ENTER("%p, %u, %u, %d, %d, %u, %d, %p", buf, w, h, hotspotX, hotspotY,
00722             keycolor, dontScale, format);
00723 
00724     GLTHREADCHECK;
00725 
00726 #ifdef USE_RGB_COLOR
00727     if (format && format->bytesPerPixel > 1) {
00728         if (_mouse_texture != _mouse_texture_rgb) {
00729             LOGD("switching to rgb mouse cursor");
00730 
00731             assert(!_mouse_texture_rgb);
00732             _mouse_texture_rgb = new GLES5551Texture();
00733             _mouse_texture_rgb->setLinearFilter(_graphicsMode == 1);
00734         }
00735 
00736         _mouse_texture = _mouse_texture_rgb;
00737     } else {
00738         if (_mouse_texture != _mouse_texture_palette)
00739             LOGD("switching to paletted mouse cursor");
00740 
00741         _mouse_texture = _mouse_texture_palette;
00742 
00743         delete _mouse_texture_rgb;
00744         _mouse_texture_rgb = 0;
00745     }
00746 #endif
00747 
00748     _mouse_texture->allocBuffer(w, h);
00749 
00750     if (_mouse_texture == _mouse_texture_palette) {
00751         assert(keycolor < 256);
00752 
00753         byte *p = _mouse_texture_palette->palette() + _mouse_keycolor * 2;
00754         WRITE_UINT16(p, READ_UINT16(p) | 1);
00755 
00756         _mouse_keycolor = keycolor;
00757 
00758         p = _mouse_texture_palette->palette() + _mouse_keycolor * 2;
00759         WRITE_UINT16(p, READ_UINT16(p) & ~1);
00760     }
00761 
00762     if (w == 0 || h == 0)
00763         return;
00764 
00765     if (_mouse_texture == _mouse_texture_palette) {
00766         _mouse_texture->updateBuffer(0, 0, w, h, buf, w);
00767     } else {
00768         uint16 pitch = _mouse_texture->pitch();
00769 
00770         byte *tmp = new byte[pitch * h];
00771 
00772         // meh, a 16bit cursor without alpha bits... this is so silly
00773         if (!crossBlit(tmp, (const byte *)buf, pitch, w * 2, w, h,
00774                         _mouse_texture->getPixelFormat(),
00775                         *format)) {
00776             LOGE("crossblit failed");
00777 
00778             delete[] tmp;
00779 
00780             _mouse_texture->allocBuffer(0, 0);
00781 
00782             return;
00783         }
00784 
00785         const uint16 *s = (const uint16 *)buf;
00786         uint16 *d = (uint16 *)tmp;
00787         for (uint16 y = 0; y < h; ++y, d += pitch / 2 - w)
00788             for (uint16 x = 0; x < w; ++x, d++)
00789                 if (*s++ == (keycolor & 0xffff))
00790                     *d = 0;
00791 
00792         _mouse_texture->updateBuffer(0, 0, w, h, tmp, pitch);
00793 
00794         delete[] tmp;
00795     }
00796 
00797     _mouse_hotspot = Common::Point(hotspotX, hotspotY);
00798     // TODO: Adapt to the new "do not scale" cursor logic.
00799     _mouse_targetscale = 1;
00800 }
00801 
00802 void OSystem_Android::setCursorPaletteInternal(const byte *colors,
00803                                                 uint start, uint num) {
00804     const Graphics::PixelFormat &pf =
00805         _mouse_texture_palette->getPalettePixelFormat();
00806     byte *p = _mouse_texture_palette->palette() + start * 2;
00807 
00808     for (uint i = 0; i < num; ++i, colors += 3, p += 2)
00809         WRITE_UINT16(p, pf.RGBToColor(colors[0], colors[1], colors[2]));
00810 
00811     p = _mouse_texture_palette->palette() + _mouse_keycolor * 2;
00812     WRITE_UINT16(p, READ_UINT16(p) & ~1);
00813 }
00814 
00815 void OSystem_Android::setCursorPalette(const byte *colors,
00816                                         uint start, uint num) {
00817     ENTER("%p, %u, %u", colors, start, num);
00818 
00819     GLTHREADCHECK;
00820 
00821     if (!_mouse_texture->hasPalette()) {
00822         LOGD("switching to paletted mouse cursor");
00823 
00824         _mouse_texture = _mouse_texture_palette;
00825 
00826         delete _mouse_texture_rgb;
00827         _mouse_texture_rgb = 0;
00828     }
00829 
00830     setCursorPaletteInternal(colors, start, num);
00831     _use_mouse_palette = true;
00832 }
00833 
00834 void OSystem_Android::disableCursorPalette() {
00835     // when disabling the cursor palette, and we're running a clut8 game,
00836     // it expects the game palette to be used for the cursor
00837     if (_game_texture->hasPalette()) {
00838         const byte *src = _game_texture->palette_const();
00839         byte *dst = _mouse_texture_palette->palette();
00840 
00841         const Graphics::PixelFormat &pf_src =
00842             _game_texture->getPalettePixelFormat();
00843         const Graphics::PixelFormat &pf_dst =
00844             _mouse_texture_palette->getPalettePixelFormat();
00845 
00846         uint8 r, g, b;
00847 
00848         for (uint i = 0; i < 256; ++i, src += 2, dst += 2) {
00849             pf_src.colorToRGB(READ_UINT16(src), r, g, b);
00850             WRITE_UINT16(dst, pf_dst.RGBToColor(r, g, b));
00851         }
00852 
00853         byte *p = _mouse_texture_palette->palette() + _mouse_keycolor * 2;
00854         WRITE_UINT16(p, READ_UINT16(p) & ~1);
00855     }
00856 }
00857 
00858 #endif


Generated on Sat May 25 2019 05:00:45 for ResidualVM by doxygen 1.7.1
curved edge   curved edge