From 471e4748b31219a3ae7c67e817e81ba4279c00fe Mon Sep 17 00:00:00 2001 From: Dries Harnie Date: Fri, 24 May 2013 01:40:23 +0200 Subject: [PATCH] ANDROID: Support swipe-based virtcontrols Touching and holding the left side of the screen functions as a joystick. Swiping the middle side allows fine control over arrow keys (eg. dialogues), tapping it sends an enter key. Swiping the right side up/down sends pageup/pagedown. --- backends/platform/android/android.cpp | 11 ++- backends/platform/android/android.h | 25 +++--- backends/platform/android/android.mk | 5 +- backends/platform/android/events.cpp | 91 +++++++++++----------- backends/platform/android/gfx.cpp | 104 +++++++++++++++---------- backends/platform/android/texture.cpp | 27 ++++--- backends/platform/android/texture.h | 26 ++++++- dists/android/assets/arrows.tga | Bin 0 -> 262162 bytes graphics/module.mk | 1 + graphics/opengles2/control_shaders.cpp | 65 ++++++++++++++++ graphics/opengles2/shader.h | 7 +- 11 files changed, 243 insertions(+), 119 deletions(-) create mode 100644 dists/android/assets/arrows.tga create mode 100644 graphics/opengles2/control_shaders.cpp diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp index 940f92b451f..b217c117a66 100644 --- a/backends/platform/android/android.cpp +++ b/backends/platform/android/android.cpp @@ -150,7 +150,9 @@ OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) : _touchpad_scale(66), _dpad_scale(4), _fingersDown(0), - _trackball_scale(2) { + _trackball_scale(2), + _joystickPressing(Common::KEYCODE_INVALID), + _arrows_texture(0) { _fsFactory = new POSIXFilesystemFactory(); @@ -180,8 +182,6 @@ OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) : for (int i = 0; i < 4; ++i) _activePointers[i] = -1; - - _joystickPressing = Common::KEYCODE_INVALID; } OSystem_Android::~OSystem_Android() { @@ -194,6 +194,11 @@ OSystem_Android::~OSystem_Android() { delete _timerManager; _timerManager = 0; + if (_arrows_texture) { + delete _arrows_texture; + _arrows_texture = 0; + } + deleteMutex(_event_queue_lock); } diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h index abf10ee57ae..314f066766b 100644 --- a/backends/platform/android/android.h +++ b/backends/platform/android/android.h @@ -252,18 +252,10 @@ private: kTouchAreaCenter = 0xfffe, kTouchAreaRight = 0xfffd, kTouchAreaNone = 0xfffc, - }; uint16 getTouchArea(int x, int y); - struct VirtControl { - int x, y; - bool sticky; - Common::KeyCode keyCode; - bool active; - }; - struct Pointer { uint16 startX, startY; uint16 currentX, currentY; @@ -271,16 +263,27 @@ private: bool active; }; + struct CardinalSwipe { + CardinalSwipe(int dX, int dY); + uint16 distance; + enum Direction { + kDirectionLeft, + kDirectionUp, + kDirectionRight, + kDirectionDown + } direction; + }; + enum { kNumPointers = 5 }; - static int _virt_numControls; - static VirtControl _virtcontrols[]; - int _virt_numDivisions; Pointer _pointers[kNumPointers]; int _activePointers[4]; Common::KeyCode _joystickPressing; int &pointerFor(TouchArea ta); + const Common::Rect clipFor(const CardinalSwipe &cs); + void initVirtControls(); void drawVirtControls(); + GLESTexture *_arrows_texture; protected: // PaletteManager API diff --git a/backends/platform/android/android.mk b/backends/platform/android/android.mk index 7d798a9b087..ddf057422c6 100644 --- a/backends/platform/android/android.mk +++ b/backends/platform/android/android.mk @@ -23,6 +23,7 @@ PATH_DIST = $(srcdir)/dists/android PATH_RESOURCES = $(PATH_DIST)/res PORT_DISTFILES = $(PATH_DIST)/README.Android +DIST_ANDROID_CONTROLS = $(PATH_DIST)/assets/arrows.tga RESOURCES = \ $(PATH_RESOURCES)/values/strings.xml \ @@ -121,9 +122,9 @@ $(PATH_STAGE_PREFIX).%/res/drawable/residualvm.png: $(PATH_RESOURCES)/drawable/r @$(MKDIR) -p $(@D) $(CP) $< $@ -$(FILE_RESOURCES_MAIN): $(FILE_MANIFEST) $(RESOURCES) $(ANDROID_JAR) $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) +$(FILE_RESOURCES_MAIN): $(FILE_MANIFEST) $(RESOURCES) $(ANDROID_JAR) $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(DIST_ANDROID_CONTROLS) $(INSTALL) -d $(PATH_BUILD_ASSETS) - $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(PATH_BUILD_ASSETS)/ + $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(DIST_ANDROID_CONTROLS) $(PATH_BUILD_ASSETS)/ work_dir=`pwd`; \ for i in $(PATH_BUILD_ASSETS)/*.zip; do \ echo "recompress $$i"; \ diff --git a/backends/platform/android/events.cpp b/backends/platform/android/events.cpp index 3df1073e07f..cc929cdf64f 100644 --- a/backends/platform/android/events.cpp +++ b/backends/platform/android/events.cpp @@ -235,6 +235,25 @@ static Common::KeyCode determineKey(int dX, int dY) { return Common::KEYCODE_INVALID; } +OSystem_Android::CardinalSwipe::CardinalSwipe(int dX, int dY) { + if (abs(dX) > abs(dY)) { + if (dX > 0) { + distance = dX; + direction = kDirectionRight; + } else { + distance = abs(dX); + direction = kDirectionLeft; + } + } else { + if (dY > 0) { + distance = dY; + direction = kDirectionDown; + } else { + distance = abs(dY); + direction = kDirectionUp; + } + } +} static const int kQueuedInputEventDelay = 50; @@ -328,28 +347,7 @@ void OSystem_Android::updateEventScale() { _eventScaleX = 100 * 640 / tex->width(); } -int OSystem_Android::_virt_numControls = 6; -OSystem_Android::VirtControl OSystem_Android::_virtcontrols[] = { - {-2, 1, false, Common::KEYCODE_u, false}, - {-3, 1, false, Common::KEYCODE_p, false}, - {-1, 5, false, Common::KEYCODE_i, false}, - {-1, 0, false, Common::KEYCODE_PAGEDOWN, false}, - {-1, 1, false, Common::KEYCODE_KP_ENTER, false}, - {-1, 2, false, Common::KEYCODE_PAGEUP, false}, -}; - - uint16 OSystem_Android::getTouchArea(int x, int y) { - int scaledX = _virt_numDivisions * x / _egl_surface_width; - int scaledY = _virt_numDivisions * (_egl_surface_height - y) / _egl_surface_height; - for (uint16 i = 0; i < _virt_numControls; ++i) { - int testX = _virtcontrols[i].x < 0 - ? (_virtcontrols[i].x + _virt_numDivisions) - : _virtcontrols[i].x; - if (scaledX == testX && scaledY == _virtcontrols[i].y) - return i; - } - float xPercent = float(x) / _egl_surface_width; if (xPercent < 0.3) @@ -707,8 +705,6 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3, if (idx == kTouchAreaCenter) { e.kbd.keycode = Common::KEYCODE_RETURN; e.kbd.ascii = Common::ASCII_RETURN; - } else { - e.kbd.keycode = _virtcontrols[idx].keyCode; } lockMutex(_event_queue_lock); @@ -813,9 +809,6 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3, _pointers[arg1].startX = _pointers[arg1].currentX = arg3; _pointers[arg1].startY = _pointers[arg1].currentY = arg4; } - - if (touchArea == kTouchAreaJoystick) - LOGW("Started joystick move at (%d,%d)", arg3, arg4); } return; @@ -839,7 +832,6 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3, _joystickPressing = newPressing; } - LOGW("Joystick moved to (%d,%d)", arg3, arg4); } } return; @@ -880,34 +872,36 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3, unlockMutex(_event_queue_lock); } else { - _pointers[arg1].active = false; int dX = _pointers[arg1].currentX - _pointers[arg1].startX; int dY = _pointers[arg1].currentY - _pointers[arg1].startY; + struct CardinalSwipe cs(dX, dY); switch (_pointers[arg1].function) { case kTouchAreaCenter: { pointerFor(kTouchAreaCenter) = -1; - if (abs(dX) < 100 && abs(dY) < 100) { - sendKey(Common::KEYCODE_u); - } else if (abs(dX) > abs(dY)) { - if (dX > 0) { - sendKey(Common::KEYCODE_RIGHT); - } else { - sendKey(Common::KEYCODE_LEFT); - } - } else { - if (dY > 0) { - sendKey(Common::KEYCODE_DOWN); - } else { - sendKey(Common::KEYCODE_UP); - } + if (cs.distance < 100) { + sendKey(Common::KEYCODE_RETURN); + break; + } + switch (cs.direction) { + case CardinalSwipe::kDirectionLeft: + sendKey(Common::KEYCODE_LEFT); + break; + case CardinalSwipe::kDirectionUp: + sendKey(Common::KEYCODE_UP); + break; + case CardinalSwipe::kDirectionRight: + sendKey(Common::KEYCODE_RIGHT); + break; + case CardinalSwipe::kDirectionDown: + sendKey(Common::KEYCODE_DOWN); + break; } break; } case kTouchAreaJoystick: pointerFor(kTouchAreaJoystick) = -1; - LOGW("Joystick move ended at (%d,%d)", arg3, arg4); if (_joystickPressing != Common::KEYCODE_INVALID) { lockMutex(_event_queue_lock); e.kbd.keycode = _joystickPressing; @@ -919,13 +913,15 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3, case kTouchAreaRight: pointerFor(kTouchAreaRight) = -1; - if (abs(dX) > 50 || abs(dY) < 100) { + if ( cs.direction == CardinalSwipe::kDirectionLeft + || cs.direction == CardinalSwipe::kDirectionRight + || cs.distance < 100) { sendKey(Common::KEYCODE_i); } else { - if (dY > 0) { - sendKey(Common::KEYCODE_PAGEDOWN); - } else { + if (cs.direction == CardinalSwipe::kDirectionUp) { sendKey(Common::KEYCODE_PAGEUP); + } else { + sendKey(Common::KEYCODE_PAGEDOWN); } } break; @@ -934,6 +930,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3, default: break; } + _pointers[arg1].active = false; _pointers[arg1].function = kTouchAreaNone; } return; diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp index 0f327a29b22..c7c6e4ba228 100644 --- a/backends/platform/android/gfx.cpp +++ b/backends/platform/android/gfx.cpp @@ -41,6 +41,7 @@ #include "common/endian.h" #include "graphics/conversion.h" +#include "graphics/decoders/tga.h" #include "graphics/opengles2/shader.h" #include "backends/platform/android/android.h" @@ -569,57 +570,82 @@ void OSystem_Android::updateScreen() { } -static Graphics::Shader *_virtcontrols_shader = NULL; -static const char *_virtVertex = - "#version 100\n" - "attribute vec2 position;\n" - "uniform vec2 offsetXY;\n" - "uniform vec2 sizeWH;\n" - "void main() {\n" - "vec2 pos = offsetXY + position * sizeWH;\n" - "pos.x = pos.x * 2.0 - 1.0;\n" - "pos.y = pos.y * 2.0 - 1.0;\n" - "gl_Position = vec4(pos, 0.0, 1.0);\n" - "}\n"; +static GLES8888Texture *loadBuiltinTexture(const char *filename) { + Common::ArchiveMemberPtr member = SearchMan.getMember(filename); + Common::SeekableReadStream *str = member->createReadStream(); + Graphics::TGADecoder dec; + dec.loadStream(*str); + void *pixels = dec.getSurface()->pixels; -static const char *_virtFragment = - "#version 100\n" - "precision mediump float;\n" - "uniform bool active;\n" - "void main() {\n" - "gl_FragColor = vec4(1.0, 1.0, 1.0, active ? 0.8 : 0.3);\n" - "}\n"; + GLES8888Texture *ret = new GLES8888Texture(); + uint16 w = dec.getSurface()->w; + uint16 h = dec.getSurface()->h; + uint16 pitch = dec.getSurface()->pitch; + ret->allocBuffer(w, h); + ret->updateBuffer(0, 0, w, h, pixels, pitch); + + delete str; + return ret; +} void OSystem_Android::initVirtControls() { - if (_virtcontrols_shader) - return; + if (!_arrows_texture) + _arrows_texture = loadBuiltinTexture("arrows.tga"); +} - const char* attributes[] = { "position", NULL }; - _virtcontrols_shader = Graphics::Shader::fromStrings("key", _virtVertex, _virtFragment, attributes); - _virtcontrols_shader->enableVertexAttribute("position", g_verticesVBO, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0); - _virt_numDivisions = _egl_surface_width > 800 ? 12 : 8; +const Common::Rect OSystem_Android::clipFor(const CardinalSwipe &cs) { + switch (cs.direction) { + case CardinalSwipe::kDirectionLeft: + return Common::Rect(0, 128, 128, 256); + case CardinalSwipe::kDirectionUp: + return Common::Rect(0, 0, 128, 128); + case CardinalSwipe::kDirectionRight: + return Common::Rect(128, 128, 256, 256); + case CardinalSwipe::kDirectionDown: + return Common::Rect(128, 0, 256, 128); + default: // unreachable + return Common::Rect(0, 0, 1, 1); + } } void OSystem_Android::drawVirtControls() { if (_show_overlay) return; - _virtcontrols_shader->use(); - float div = 1.0 / _virt_numDivisions; - float divX = div; - float divY = div; - _virtcontrols_shader->setUniform("sizeWH", 0.9 * Math::Vector2d(divX, divY)); - glEnable(GL_BLEND); + int joyPtr = pointerFor(kTouchAreaJoystick); + if (joyPtr != -1) { + Pointer &joy = _pointers[joyPtr]; + CardinalSwipe cs(joy.currentX - joy.startX, joy.currentY - joy.startY); - for (int control = 0; control < _virt_numControls; ++control) { - float offsetX = (_virtcontrols[control].x + 0.1) * divX; - float offsetY = (_virtcontrols[control].y + 0.1) * divY; - if (offsetX < 0) - offsetX += 1.0; + if (cs.distance >= 50) { + Common::Rect clip = clipFor(cs); + _arrows_texture->drawTexture(2 * _egl_surface_width / 10, _egl_surface_height / 2, 64, 64, clip); + } + } - _virtcontrols_shader->setUniform("offsetXY", Math::Vector2d(offsetX, offsetY)); - _virtcontrols_shader->setUniform("active", _virtcontrols[control].active); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + int centerPtr = pointerFor(kTouchAreaCenter); + if (centerPtr != -1) { + Pointer ¢er = _pointers[centerPtr]; + CardinalSwipe cs(center.currentX - center.startX, center.currentY - center.startY); + + if (cs.distance >= 100) { + Common::Rect clip = clipFor(cs); + _arrows_texture->drawTexture(_egl_surface_width / 2, _egl_surface_height / 2, 64, 64, clip); + } + } + + int rightPtr = pointerFor(kTouchAreaRight); + if (rightPtr != -1) { + Pointer &right = _pointers[rightPtr]; + CardinalSwipe cs(right.currentX - right.startX, right.currentY - right.startY); + + if (cs.distance >= 100) { + if ( cs.direction == CardinalSwipe::kDirectionDown + || cs.direction == CardinalSwipe::kDirectionUp) { + Common::Rect clip = clipFor(cs); + _arrows_texture->drawTexture( 8 * _egl_surface_width / 10, _egl_surface_height / 2, 64, 64, clip); + } + } } } diff --git a/backends/platform/android/texture.cpp b/backends/platform/android/texture.cpp index 14143136f6b..05d10c56594 100644 --- a/backends/platform/android/texture.cpp +++ b/backends/platform/android/texture.cpp @@ -97,7 +97,7 @@ void GLESBaseTexture::initGL() { } const char* attributes[] = { "position", "texcoord", NULL }; - g_box_shader = Graphics::Shader::fromStrings("box", Graphics::BuiltinShaders::boxVertex, Graphics::BuiltinShaders::boxFragment, attributes); + g_box_shader = Graphics::Shader::fromStrings("control", Graphics::BuiltinShaders::controlVertex, Graphics::BuiltinShaders::controlFragment, attributes); g_verticesVBO = Graphics::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(vertices), vertices); g_box_shader->enableVertexAttribute("position", g_verticesVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0); g_box_shader->enableVertexAttribute("texcoord", g_verticesVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0); @@ -186,7 +186,7 @@ void GLESBaseTexture::allocBuffer(GLuint w, GLuint h) { initSize(); } -void GLESBaseTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) { +void GLESBaseTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h, const Common::Rect &clip) { // LOGD("*** Texture %p: Drawing %dx%d rect to (%d,%d)", this, w, h, x, y); assert(g_box_shader); @@ -197,13 +197,14 @@ void GLESBaseTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) { const GLfloat offsetY = float(y) / float(JNI::egl_surface_height); const GLfloat sizeW = float(w) / float(JNI::egl_surface_width); const GLfloat sizeH = float(h) / float(JNI::egl_surface_height); - const GLfloat tex_width = float(_surface.w) / float(_texture_width); - const GLfloat tex_height = float(_surface.h) / float(_texture_height); + Math::Vector4d clipV = Math::Vector4d(clip.left, clip.top, clip.right, clip.bottom); + clipV.x() /= _texture_width; clipV.y() /= _texture_height; + clipV.z() /= _texture_width; clipV.w() /= _texture_height; // LOGD("*** Drawing at (%f,%f) , size %f x %f", float(x) / float(_surface.w), float(y) / float(_surface.h), tex_width, tex_height); g_box_shader->setUniform("offsetXY", Math::Vector2d(offsetX, offsetY)); g_box_shader->setUniform("sizeWH", Math::Vector2d(sizeW, sizeH)); - g_box_shader->setUniform("texcrop", Math::Vector2d(tex_width, tex_height)); + g_box_shader->setUniform("clip", clipV); g_box_shader->setUniform("flipY", !_is_game_texture); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); @@ -281,7 +282,7 @@ void GLESTexture::fillBuffer(uint32 color) { setDirty(); } -void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) { +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; @@ -323,7 +324,7 @@ void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) { dwidth, dheight, _glFormat, _glType, _tex)); } - GLESBaseTexture::drawTexture(x, y, w, h); + GLESBaseTexture::drawTexture(x, y, w, h, clip); } GLES4444Texture::GLES4444Texture() : @@ -333,6 +334,13 @@ GLES4444Texture::GLES4444Texture() : 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()) { } @@ -419,8 +427,7 @@ void GLESFakePaletteTexture::updateBuffer(GLuint x, GLuint y, GLuint w, } while (--h); } -void GLESFakePaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w, - GLshort 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; @@ -452,7 +459,7 @@ void GLESFakePaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w, dwidth, dheight, _glFormat, _glType, _buf)); } - GLESBaseTexture::drawTexture(x, y, w, h); + GLESBaseTexture::drawTexture(x, y, w, h, clip); } const Graphics::PixelFormat &GLESFakePaletteTexture::getPixelFormat() const { diff --git a/backends/platform/android/texture.h b/backends/platform/android/texture.h index e71bbf6682e..3fd37a559f6 100644 --- a/backends/platform/android/texture.h +++ b/backends/platform/android/texture.h @@ -57,7 +57,11 @@ 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); + 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); + inline void setDrawRect(const Common::Rect &rect) { _draw_rect = rect; @@ -203,13 +207,26 @@ public: const void *buf, int pitch_buf); virtual void fillBuffer(uint32 color); - virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h); + 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); 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: @@ -256,7 +273,10 @@ public: const void *buf, int pitch_buf); virtual void fillBuffer(uint32 color); - virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h); + 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 const byte *palette_const() const { return (byte *)_palette; diff --git a/dists/android/assets/arrows.tga b/dists/android/assets/arrows.tga new file mode 100644 index 0000000000000000000000000000000000000000..05d5e140981886aa041e8975669f4a764e086bf8 GIT binary patch literal 262162 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 literal 0 HcmV?d00001 diff --git a/graphics/module.mk b/graphics/module.mk index 95e3d537f9b..61b60f02b22 100644 --- a/graphics/module.mk +++ b/graphics/module.mk @@ -23,6 +23,7 @@ MODULE_OBJS := \ pixelbuffer.o \ opengles2/shader.o \ opengles2/box_shaders.o \ + opengles2/control_shaders.o \ opengles2/compat_shaders.o \ tinygl/api.o \ tinygl/arrays.o \ diff --git a/graphics/opengles2/control_shaders.cpp b/graphics/opengles2/control_shaders.cpp new file mode 100644 index 00000000000..180dd998d9c --- /dev/null +++ b/graphics/opengles2/control_shaders.cpp @@ -0,0 +1,65 @@ +/* ResidualVM - A 3D game interpreter + * + * ResidualVM 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. + * + */ + +#include "common/scummsys.h" + +#ifdef USE_GLES2 + +namespace Graphics { +namespace BuiltinShaders { + +const char *controlVertex = + "#version 100\n" + "attribute vec2 position;\n" + "attribute vec2 texcoord;\n" + "uniform vec2 offsetXY;\n" + "uniform vec2 sizeWH;\n" + "uniform vec4 clip;\n" + "uniform bool flipY;\n" + "varying vec2 Texcoord;\n" + "void main() {\n" + "Texcoord = clip.xy + texcoord * (clip.zw - clip.xy);\n" + "vec2 pos = offsetXY + position * sizeWH;\n" + "pos.x = pos.x * 2.0 - 1.0;\n" + "pos.y = pos.y * 2.0 - 1.0;\n" + "if (flipY)\n" + "pos.y *= -1.0;\n" + "gl_Position = vec4(pos, 0.0, 1.0);\n" + "}\n"; + +const char *controlFragment = + "#version 100\n" + "#ifdef GL_FRAGMENT_PRECISION_HIGH\n" + "precision highp float;\n" + "#else\n" + "precision mediump float;\n" + "#endif\n" + "varying vec2 Texcoord;\n" + "uniform sampler2D tex;\n" + "void main() {\n" + "gl_FragColor = texture2D(tex, Texcoord);\n" + "}\n"; + +} +} + +#endif diff --git a/graphics/opengles2/shader.h b/graphics/opengles2/shader.h index 8b2f51fd68b..06cc91510b9 100644 --- a/graphics/opengles2/shader.h +++ b/graphics/opengles2/shader.h @@ -34,10 +34,9 @@ namespace Graphics { namespace BuiltinShaders { - extern const char *boxVertex; - extern const char *boxFragment; - extern const char *compatVertex; - extern const char *compatFragment; + extern const char *boxVertex, *boxFragment; + extern const char *compatVertex, *compatFragment; + extern const char *controlVertex, *controlFragment; } struct VertexAttrib {