mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-14 16:07:39 +00:00
Merge pull request #731 from Botje/android-tinygl
Basic support for Android
This commit is contained in:
commit
1f3ad19a38
@ -133,7 +133,7 @@ OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) :
|
||||
_ar_correction(true),
|
||||
_show_mouse(false),
|
||||
_show_overlay(false),
|
||||
_virt_arrowkeys_pressed(false),
|
||||
_virtcontrols_on(false),
|
||||
_enable_zoning(false),
|
||||
_mixer(0),
|
||||
_shake_offset(0),
|
||||
@ -149,7 +149,8 @@ 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)
|
||||
{
|
||||
|
||||
_fsFactory = new POSIXFilesystemFactory();
|
||||
|
||||
@ -347,7 +348,7 @@ void OSystem_Android::initBackend() {
|
||||
|
||||
_main_thread = pthread_self();
|
||||
|
||||
ConfMan.registerDefault("fullscreen", true);
|
||||
ConfMan.set("fullscreen", "true");
|
||||
ConfMan.registerDefault("aspect_ratio", true);
|
||||
|
||||
ConfMan.setInt("autosave_period", 0);
|
||||
@ -409,6 +410,7 @@ bool OSystem_Android::hasFeature(Feature f) {
|
||||
f == kFeatureAspectRatioCorrection ||
|
||||
f == kFeatureCursorPalette ||
|
||||
f == kFeatureVirtualKeyboard ||
|
||||
f == kFeatureVirtControls ||
|
||||
#ifdef USE_OPENGL
|
||||
f == kFeatureOpenGL ||
|
||||
#endif
|
||||
@ -431,6 +433,9 @@ void OSystem_Android::setFeatureState(Feature f, bool enable) {
|
||||
_virtkeybd_on = enable;
|
||||
showVirtualKeyboard(enable);
|
||||
break;
|
||||
case kFeatureVirtControls:
|
||||
_virtcontrols_on = enable;
|
||||
break;
|
||||
case kFeatureCursorPalette:
|
||||
_use_mouse_palette = enable;
|
||||
if (!enable)
|
||||
@ -449,6 +454,8 @@ bool OSystem_Android::getFeatureState(Feature f) {
|
||||
return _ar_correction;
|
||||
case kFeatureVirtualKeyboard:
|
||||
return _virtkeybd_on;
|
||||
case kFeatureVirtControls:
|
||||
return _virtcontrols_on;
|
||||
case kFeatureCursorPalette:
|
||||
return _use_mouse_palette;
|
||||
default:
|
||||
|
@ -35,7 +35,9 @@
|
||||
#include "backends/plugins/posix/posix-provider.h"
|
||||
#include "backends/fs/posix/posix-fs-factory.h"
|
||||
|
||||
#include "backends/platform/android/events.h"
|
||||
#include "backends/platform/android/texture.h"
|
||||
#include "backends/platform/android/touchcontrols.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
@ -104,7 +106,7 @@ protected:
|
||||
};
|
||||
#endif
|
||||
|
||||
class OSystem_Android : public EventsBaseBackend, public PaletteManager {
|
||||
class OSystem_Android : public EventsBaseBackend, public PaletteManager, public KeyReceiver {
|
||||
private:
|
||||
// passed from the dark side
|
||||
int _audio_sample_rate;
|
||||
@ -140,7 +142,7 @@ private:
|
||||
bool _show_mouse;
|
||||
bool _use_mouse_palette;
|
||||
|
||||
int _virt_arrowkeys_pressed;
|
||||
bool _virtcontrols_on;
|
||||
|
||||
int _graphicsMode;
|
||||
bool _fullscreen;
|
||||
@ -224,6 +226,7 @@ public:
|
||||
|
||||
public:
|
||||
void pushEvent(int type, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6);
|
||||
void keyPress(const Common::KeyCode keycode, const KeyReceiver::KeyPressType type);
|
||||
|
||||
private:
|
||||
Common::Queue<Common::Event> _event_queue;
|
||||
@ -245,10 +248,9 @@ private:
|
||||
void updateEventScale();
|
||||
void disableCursorPalette();
|
||||
|
||||
void updateVirtArrowKeys(int keys);
|
||||
int getTouchArea(int x, int y);
|
||||
int checkVirtArrowKeys(int action, int x, int y);
|
||||
void checkVirtArrowKeys(int pointer, int action, int x0, int y0, int x1, int y1);
|
||||
TouchControls _touchControls;
|
||||
|
||||
void drawVirtControls();
|
||||
|
||||
protected:
|
||||
// PaletteManager API
|
||||
@ -310,7 +312,10 @@ public:
|
||||
// ResidualVM specific method
|
||||
virtual void launcherInitSize(uint w, uint h);
|
||||
bool lockMouse(bool lock);
|
||||
Graphics::PixelBuffer setupScreen(int screenW, int screenH, bool fullscreen, bool accel3d);
|
||||
Graphics::PixelBuffer setupScreen(int screenW, int screenH, bool fullscreen, bool accel3d) {
|
||||
return setupScreen(screenW, screenH, fullscreen, accel3d, true);
|
||||
}
|
||||
Graphics::PixelBuffer setupScreen(int screenW, int screenH, bool fullscreen, bool accel3d, bool isGame);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -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 \
|
||||
@ -47,13 +48,7 @@ APKBUILDER = $(ANDROID_SDK)/tools/apkbuilder
|
||||
JAVAC ?= javac
|
||||
JAVACFLAGS = -source 1.5 -target 1.5
|
||||
|
||||
# This is a bit silly. I want to compile against the 2.1 android.jar,
|
||||
# to make the compiler check that I don't use something that requires
|
||||
# a newer Android. However, in order to use android:installLocation,
|
||||
# we need to give aapt a version >=8 android.jar - even though the
|
||||
# result will work ok on 2.0+.
|
||||
ANDROID_JAR = $(ANDROID_SDK)/platforms/android-7/android.jar
|
||||
ANDROID_JAR8 = $(ANDROID_SDK)/platforms/android-8/android.jar
|
||||
ANDROID_JAR = $(ANDROID_SDK)/platforms/android-8/android.jar
|
||||
|
||||
PATH_BUILD = build.tmp
|
||||
PATH_BUILD_ASSETS = $(PATH_BUILD)/assets
|
||||
@ -92,9 +87,9 @@ $(FILE_MANIFEST): $(FILE_MANIFEST_SRC)
|
||||
@$(MKDIR) -p $(@D)
|
||||
sed "s/@ANDROID_VERSIONCODE@/$(ANDROID_VERSIONCODE)/" < $< > $@
|
||||
|
||||
$(SRC_GEN): $(FILE_MANIFEST) $(filter %.xml,$(RESOURCES)) $(ANDROID_JAR8)
|
||||
$(SRC_GEN): $(FILE_MANIFEST) $(filter %.xml,$(RESOURCES)) $(ANDROID_JAR)
|
||||
@$(MKDIR) -p $(PATH_GEN_TOP)
|
||||
$(AAPT) package -m -J $(PATH_GEN_TOP) -M $< -S $(PATH_RESOURCES) -I $(ANDROID_JAR8)
|
||||
$(AAPT) package -m -J $(PATH_GEN_TOP) -M $< -S $(PATH_RESOURCES) -I $(ANDROID_JAR)
|
||||
|
||||
$(PATH_CLASSES_MAIN)/%.class: $(PATH_GEN)/%.java $(SRC_GEN)
|
||||
@$(MKDIR) -p $(@D)
|
||||
@ -127,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_JAR8) $(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"; \
|
||||
@ -141,25 +136,21 @@ $(FILE_RESOURCES_MAIN): $(FILE_MANIFEST) $(RESOURCES) $(ANDROID_JAR8) $(DIST_FIL
|
||||
zip -r ../`basename $$i` *; \
|
||||
done
|
||||
@$(RM) -rf $(PATH_BUILD_ASSETS)/tmp
|
||||
$(AAPT) package -f -0 zip -M $< -S $(PATH_RESOURCES) -A $(PATH_BUILD_ASSETS) -I $(ANDROID_JAR8) -F $@
|
||||
$(AAPT) package -f -0 "" -M $< -S $(PATH_RESOURCES) -A $(PATH_BUILD_ASSETS) -I $(ANDROID_JAR) -F $@
|
||||
|
||||
$(PATH_BUILD)/%/$(FILE_RESOURCES): $(PATH_BUILD)/%/AndroidManifest.xml $(PATH_STAGE_PREFIX).%/res/values/strings.xml $(PATH_STAGE_PREFIX).%/res/drawable/residualvm.png plugins/lib%.so $(ANDROID_JAR8)
|
||||
$(AAPT) package -f -M $< -S $(PATH_STAGE_PREFIX).$*/res -I $(ANDROID_JAR8) -F $@
|
||||
$(PATH_BUILD)/%/$(FILE_RESOURCES): $(PATH_BUILD)/%/AndroidManifest.xml $(PATH_STAGE_PREFIX).%/res/values/strings.xml $(PATH_STAGE_PREFIX).%/res/drawable/residualvm.png plugins/lib%.so $(ANDROID_JAR)
|
||||
$(AAPT) package -f -M $< -S $(PATH_STAGE_PREFIX).$*/res -I $(ANDROID_JAR) -F $@
|
||||
|
||||
# Package installer won't delete old libresidualvm.so on upgrade so
|
||||
# replace it with a zero size file
|
||||
$(APK_MAIN): $(EXECUTABLE) $(FILE_RESOURCES_MAIN) $(FILE_DEX)
|
||||
$(INSTALL) -d $(PATH_STAGE_MAIN)/common/lib/armeabi
|
||||
touch $(PATH_STAGE_MAIN)/common/lib/armeabi/libresidualvm.so
|
||||
$(INSTALL) -d $(PATH_STAGE_MAIN)/common/mylib/armeabi
|
||||
$(INSTALL) -c -m 644 libresidualvm.so $(PATH_STAGE_MAIN)/common/mylib/armeabi/
|
||||
$(STRIP) $(PATH_STAGE_MAIN)/common/mylib/armeabi/libresidualvm.so
|
||||
$(INSTALL) -c -m 644 libresidualvm.so $(PATH_STAGE_MAIN)/common/lib/armeabi/
|
||||
$(STRIP) $(PATH_STAGE_MAIN)/common/lib/armeabi/libresidualvm.so
|
||||
$(APKBUILDER) $@ -z $(FILE_RESOURCES_MAIN) -f $(FILE_DEX) -rf $(PATH_STAGE_MAIN)/common || { $(RM) $@; exit 1; }
|
||||
|
||||
residualvm-engine-%.apk: plugins/lib%.so $(PATH_BUILD)/%/$(FILE_RESOURCES) $(FILE_DEX_PLUGIN)
|
||||
$(INSTALL) -d $(PATH_STAGE_PREFIX).$*/apk/mylib/armeabi/
|
||||
$(INSTALL) -c -m 644 plugins/lib$*.so $(PATH_STAGE_PREFIX).$*/apk/mylib/armeabi/
|
||||
$(STRIP) $(PATH_STAGE_PREFIX).$*/apk/mylib/armeabi/lib$*.so
|
||||
$(INSTALL) -d $(PATH_STAGE_PREFIX).$*/apk/lib/armeabi/
|
||||
$(INSTALL) -c -m 644 plugins/lib$*.so $(PATH_STAGE_PREFIX).$*/apk/lib/armeabi/
|
||||
$(STRIP) $(PATH_STAGE_PREFIX).$*/apk/lib/armeabi/lib$*.so
|
||||
$(APKBUILDER) $@ -z $(PATH_BUILD)/$*/$(FILE_RESOURCES) -f $(FILE_DEX_PLUGIN) -rf $(PATH_STAGE_PREFIX).$*/apk || { $(RM) $@; exit 1; }
|
||||
|
||||
all: $(APK_MAIN) $(APK_PLUGINS)
|
||||
|
@ -313,6 +313,7 @@ AssetFdReadStream::AssetFdReadStream(JNIEnv *env, jobject assetfd) :
|
||||
assert(FID_descriptor);
|
||||
|
||||
_fd = env->GetIntField(javafd, FID_descriptor);
|
||||
seek(0, SEEK_SET);
|
||||
}
|
||||
|
||||
AssetFdReadStream::~AssetFdReadStream() {
|
||||
|
@ -39,180 +39,10 @@
|
||||
// for the Android port
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_printf
|
||||
|
||||
#include "common/events.h"
|
||||
|
||||
#include "backends/platform/android/android.h"
|
||||
#include "backends/platform/android/events.h"
|
||||
#include "backends/platform/android/jni.h"
|
||||
|
||||
// $ANDROID_NDK/platforms/android-9/arch-arm/usr/include/android/keycodes.h
|
||||
// http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=libs/ui/Input.cpp
|
||||
// http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/java/android/view/KeyEvent.java
|
||||
|
||||
// event type
|
||||
enum {
|
||||
JE_SYS_KEY = 0,
|
||||
JE_KEY = 1,
|
||||
JE_DPAD = 2,
|
||||
JE_DOWN = 3,
|
||||
JE_SCROLL = 4,
|
||||
JE_TAP = 5,
|
||||
JE_DOUBLE_TAP = 6,
|
||||
JE_MULTI = 7,
|
||||
JE_BALL = 8,
|
||||
JE_TOUCH = 9,
|
||||
JE_LONG = 10,
|
||||
JE_FLING = 11,
|
||||
JE_QUIT = 0x1000
|
||||
};
|
||||
|
||||
// action type
|
||||
enum {
|
||||
JACTION_DOWN = 0,
|
||||
JACTION_UP = 1,
|
||||
JACTION_MULTIPLE = 2,
|
||||
JACTION_POINTER_DOWN = 5,
|
||||
JACTION_POINTER_UP = 6
|
||||
};
|
||||
|
||||
// system keys
|
||||
enum {
|
||||
JKEYCODE_SOFT_RIGHT = 2,
|
||||
JKEYCODE_HOME = 3,
|
||||
JKEYCODE_BACK = 4,
|
||||
JKEYCODE_CALL = 5,
|
||||
JKEYCODE_ENDCALL = 6,
|
||||
JKEYCODE_VOLUME_UP = 24,
|
||||
JKEYCODE_VOLUME_DOWN = 25,
|
||||
JKEYCODE_POWER = 26,
|
||||
JKEYCODE_CAMERA = 27,
|
||||
JKEYCODE_HEADSETHOOK = 79,
|
||||
JKEYCODE_FOCUS = 80,
|
||||
JKEYCODE_MENU = 82,
|
||||
JKEYCODE_SEARCH = 84,
|
||||
JKEYCODE_MUTE = 91,
|
||||
JKEYCODE_MEDIA_PLAY_PAUSE = 85,
|
||||
JKEYCODE_MEDIA_STOP = 86,
|
||||
JKEYCODE_MEDIA_NEXT = 87,
|
||||
JKEYCODE_MEDIA_PREVIOUS = 88,
|
||||
JKEYCODE_MEDIA_REWIND = 89,
|
||||
JKEYCODE_MEDIA_FAST_FORWARD = 90
|
||||
};
|
||||
|
||||
// five-way navigation control
|
||||
enum {
|
||||
JKEYCODE_DPAD_UP = 19,
|
||||
JKEYCODE_DPAD_DOWN = 20,
|
||||
JKEYCODE_DPAD_LEFT = 21,
|
||||
JKEYCODE_DPAD_RIGHT = 22,
|
||||
JKEYCODE_DPAD_CENTER = 23
|
||||
};
|
||||
|
||||
// meta modifier
|
||||
enum {
|
||||
JMETA_SHIFT = 0x01,
|
||||
JMETA_ALT = 0x02,
|
||||
JMETA_SYM = 0x04,
|
||||
JMETA_CTRL = 0x1000
|
||||
};
|
||||
|
||||
// map android key codes to our kbd codes
|
||||
static const Common::KeyCode jkeymap[] = {
|
||||
Common::KEYCODE_INVALID, // KEYCODE_UNKNOWN
|
||||
Common::KEYCODE_INVALID, // KEYCODE_SOFT_LEFT
|
||||
Common::KEYCODE_INVALID, // KEYCODE_SOFT_RIGHT
|
||||
Common::KEYCODE_INVALID, // KEYCODE_HOME
|
||||
Common::KEYCODE_INVALID, // KEYCODE_BACK
|
||||
Common::KEYCODE_INVALID, // KEYCODE_CALL
|
||||
Common::KEYCODE_INVALID, // KEYCODE_ENDCALL
|
||||
Common::KEYCODE_0, // KEYCODE_0
|
||||
Common::KEYCODE_1, // KEYCODE_1
|
||||
Common::KEYCODE_2, // KEYCODE_2
|
||||
Common::KEYCODE_3, // KEYCODE_3
|
||||
Common::KEYCODE_4, // KEYCODE_4
|
||||
Common::KEYCODE_5, // KEYCODE_5
|
||||
Common::KEYCODE_6, // KEYCODE_6
|
||||
Common::KEYCODE_7, // KEYCODE_7
|
||||
Common::KEYCODE_8, // KEYCODE_8
|
||||
Common::KEYCODE_9, // KEYCODE_9
|
||||
Common::KEYCODE_ASTERISK, // KEYCODE_STAR
|
||||
Common::KEYCODE_HASH, // KEYCODE_POUND
|
||||
Common::KEYCODE_INVALID, // KEYCODE_DPAD_UP
|
||||
Common::KEYCODE_INVALID, // KEYCODE_DPAD_DOWN
|
||||
Common::KEYCODE_INVALID, // KEYCODE_DPAD_LEFT
|
||||
Common::KEYCODE_INVALID, // KEYCODE_DPAD_RIGHT
|
||||
Common::KEYCODE_INVALID, // KEYCODE_DPAD_CENTER
|
||||
Common::KEYCODE_INVALID, // KEYCODE_VOLUME_UP
|
||||
Common::KEYCODE_INVALID, // KEYCODE_VOLUME_DOWN
|
||||
Common::KEYCODE_INVALID, // KEYCODE_POWER
|
||||
Common::KEYCODE_INVALID, // KEYCODE_CAMERA
|
||||
Common::KEYCODE_INVALID, // KEYCODE_CLEAR
|
||||
Common::KEYCODE_a, // KEYCODE_A
|
||||
Common::KEYCODE_b, // KEYCODE_B
|
||||
Common::KEYCODE_c, // KEYCODE_C
|
||||
Common::KEYCODE_d, // KEYCODE_D
|
||||
Common::KEYCODE_e, // KEYCODE_E
|
||||
Common::KEYCODE_f, // KEYCODE_F
|
||||
Common::KEYCODE_g, // KEYCODE_G
|
||||
Common::KEYCODE_h, // KEYCODE_H
|
||||
Common::KEYCODE_i, // KEYCODE_I
|
||||
Common::KEYCODE_j, // KEYCODE_J
|
||||
Common::KEYCODE_k, // KEYCODE_K
|
||||
Common::KEYCODE_l, // KEYCODE_L
|
||||
Common::KEYCODE_m, // KEYCODE_M
|
||||
Common::KEYCODE_n, // KEYCODE_N
|
||||
Common::KEYCODE_o, // KEYCODE_O
|
||||
Common::KEYCODE_p, // KEYCODE_P
|
||||
Common::KEYCODE_q, // KEYCODE_Q
|
||||
Common::KEYCODE_r, // KEYCODE_R
|
||||
Common::KEYCODE_s, // KEYCODE_S
|
||||
Common::KEYCODE_t, // KEYCODE_T
|
||||
Common::KEYCODE_u, // KEYCODE_U
|
||||
Common::KEYCODE_v, // KEYCODE_V
|
||||
Common::KEYCODE_w, // KEYCODE_W
|
||||
Common::KEYCODE_x, // KEYCODE_X
|
||||
Common::KEYCODE_y, // KEYCODE_Y
|
||||
Common::KEYCODE_z, // KEYCODE_Z
|
||||
Common::KEYCODE_COMMA, // KEYCODE_COMMA
|
||||
Common::KEYCODE_PERIOD, // KEYCODE_PERIOD
|
||||
Common::KEYCODE_LALT, // KEYCODE_ALT_LEFT
|
||||
Common::KEYCODE_RALT, // KEYCODE_ALT_RIGHT
|
||||
Common::KEYCODE_LSHIFT, // KEYCODE_SHIFT_LEFT
|
||||
Common::KEYCODE_RSHIFT, // KEYCODE_SHIFT_RIGHT
|
||||
Common::KEYCODE_TAB, // KEYCODE_TAB
|
||||
Common::KEYCODE_SPACE, // KEYCODE_SPACE
|
||||
Common::KEYCODE_LCTRL, // KEYCODE_SYM
|
||||
Common::KEYCODE_INVALID, // KEYCODE_EXPLORER
|
||||
Common::KEYCODE_INVALID, // KEYCODE_ENVELOPE
|
||||
Common::KEYCODE_RETURN, // KEYCODE_ENTER
|
||||
Common::KEYCODE_BACKSPACE, // KEYCODE_DEL
|
||||
Common::KEYCODE_BACKQUOTE, // KEYCODE_GRAVE
|
||||
Common::KEYCODE_MINUS, // KEYCODE_MINUS
|
||||
Common::KEYCODE_EQUALS, // KEYCODE_EQUALS
|
||||
Common::KEYCODE_LEFTPAREN, // KEYCODE_LEFT_BRACKET
|
||||
Common::KEYCODE_RIGHTPAREN, // KEYCODE_RIGHT_BRACKET
|
||||
Common::KEYCODE_BACKSLASH, // KEYCODE_BACKSLASH
|
||||
Common::KEYCODE_SEMICOLON, // KEYCODE_SEMICOLON
|
||||
Common::KEYCODE_QUOTE, // KEYCODE_APOSTROPHE
|
||||
Common::KEYCODE_SLASH, // KEYCODE_SLASH
|
||||
Common::KEYCODE_AT, // KEYCODE_AT
|
||||
Common::KEYCODE_INVALID, // KEYCODE_NUM
|
||||
Common::KEYCODE_INVALID, // KEYCODE_HEADSETHOOK
|
||||
Common::KEYCODE_INVALID, // KEYCODE_FOCUS
|
||||
Common::KEYCODE_PLUS, // KEYCODE_PLUS
|
||||
Common::KEYCODE_INVALID, // KEYCODE_MENU
|
||||
Common::KEYCODE_INVALID, // KEYCODE_NOTIFICATION
|
||||
Common::KEYCODE_INVALID, // KEYCODE_SEARCH
|
||||
Common::KEYCODE_INVALID, // KEYCODE_MEDIA_PLAY_PAUSE
|
||||
Common::KEYCODE_INVALID, // KEYCODE_MEDIA_STOP
|
||||
Common::KEYCODE_INVALID, // KEYCODE_MEDIA_NEXT
|
||||
Common::KEYCODE_INVALID, // KEYCODE_MEDIA_PREVIOUS
|
||||
Common::KEYCODE_INVALID, // KEYCODE_MEDIA_REWIND
|
||||
Common::KEYCODE_INVALID, // KEYCODE_MEDIA_FAST_FORWARD
|
||||
Common::KEYCODE_INVALID, // KEYCODE_MUTE
|
||||
Common::KEYCODE_PAGEUP, // KEYCODE_PAGE_UP
|
||||
Common::KEYCODE_PAGEDOWN // KEYCODE_PAGE_DOWN
|
||||
};
|
||||
|
||||
// floating point. use sparingly
|
||||
template<class T>
|
||||
static inline T scalef(T in, float numerator, float denominator) {
|
||||
@ -311,108 +141,6 @@ void OSystem_Android::updateEventScale() {
|
||||
_eventScaleX = 100 * 640 / tex->width();
|
||||
}
|
||||
|
||||
enum TouchArea {
|
||||
kTouchAreaCenter = 1,
|
||||
kTouchAreaTop = 2,
|
||||
kTouchAreaBottom = 4,
|
||||
kTouchAreaLeft = 8,
|
||||
kTouchAreaRight = 16
|
||||
};
|
||||
|
||||
enum VirtArrowKey {
|
||||
kVirtArrowKeyUp = 1,
|
||||
kVirtArrowKeyDown = 2,
|
||||
kVirtArrowKeyLeft = 4,
|
||||
kVirtArrowKeyRight = 8,
|
||||
kVirtArrowKeyRun = 16
|
||||
};
|
||||
|
||||
void OSystem_Android::updateVirtArrowKeys(int keys) {
|
||||
Common::Event e;
|
||||
|
||||
#if 0
|
||||
if (keys != _virt_arrowkeys_pressed) {
|
||||
debug("keys: %d%d%d%d%d / %d%d%d%d%d",
|
||||
(_virt_arrowkeys_pressed >> 0) & 1, (_virt_arrowkeys_pressed >> 1) & 1,
|
||||
(_virt_arrowkeys_pressed >> 2) & 1, (_virt_arrowkeys_pressed >> 3) & 1,
|
||||
(_virt_arrowkeys_pressed >> 4) & 1,
|
||||
(keys >> 0) & 1, (keys >> 1) & 1,
|
||||
(keys >> 2) & 1, (keys >> 3) & 1,
|
||||
(keys >> 4) & 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
Common::KeyCode keymap[] = {
|
||||
Common::KEYCODE_UP, Common::KEYCODE_DOWN,
|
||||
Common::KEYCODE_LEFT, Common::KEYCODE_RIGHT,
|
||||
Common::KEYCODE_LSHIFT
|
||||
};
|
||||
|
||||
lockMutex(_event_queue_lock);
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
int mask = (1 << i);
|
||||
if ((_virt_arrowkeys_pressed & mask) && !(keys & mask)) {
|
||||
e.type = Common::EVENT_KEYUP;
|
||||
e.kbd.keycode = keymap[i];
|
||||
_event_queue.push(e);
|
||||
} else if (!(_virt_arrowkeys_pressed & mask) && (keys & mask)) {
|
||||
e.type = Common::EVENT_KEYDOWN;
|
||||
e.kbd.keycode = keymap[i];
|
||||
_event_queue.push(e);
|
||||
}
|
||||
}
|
||||
unlockMutex(_event_queue_lock);
|
||||
|
||||
_virt_arrowkeys_pressed = keys;
|
||||
}
|
||||
|
||||
int OSystem_Android::getTouchArea(int x, int y) {
|
||||
int xScaled = x * 100 / _egl_surface_width;
|
||||
int yScaled = y * 100 / _egl_surface_height;
|
||||
|
||||
if (xScaled >= 35 && xScaled <= 65 && yScaled >= 35 && yScaled <= 65)
|
||||
return kTouchAreaCenter;
|
||||
|
||||
int res = 0;
|
||||
if (xScaled >= 0 && xScaled <= 20)
|
||||
res |= kTouchAreaLeft;
|
||||
else if (xScaled >= 80 && xScaled <= 100)
|
||||
res |= kTouchAreaRight;
|
||||
if (yScaled >= 0 && yScaled <= 20)
|
||||
res |= kTouchAreaTop;
|
||||
else if (yScaled >= 80 && yScaled <= 100)
|
||||
res |= kTouchAreaBottom;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int OSystem_Android::checkVirtArrowKeys(int action, int x, int y) {
|
||||
int res = 0;
|
||||
|
||||
int touchArea = getTouchArea(x, y);
|
||||
if (touchArea & kTouchAreaLeft) {
|
||||
res |= kVirtArrowKeyLeft;
|
||||
} else if (touchArea & kTouchAreaRight) {
|
||||
res |= kVirtArrowKeyRight;
|
||||
}
|
||||
if (touchArea & kTouchAreaTop) {
|
||||
res |= kVirtArrowKeyUp;
|
||||
} else if (touchArea & kTouchAreaBottom) {
|
||||
res |= kVirtArrowKeyDown;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void OSystem_Android::checkVirtArrowKeys(int pointer, int action, int x0, int y0, int x1, int y1) {
|
||||
int virtArrowkey = _virt_arrowkeys_pressed & kVirtArrowKeyRun;
|
||||
if (!(action == JACTION_POINTER_UP && pointer == 0))
|
||||
virtArrowkey |= checkVirtArrowKeys(action, x0, y0);
|
||||
if (!(action == JACTION_POINTER_UP && pointer == 1) && x1 != -1)
|
||||
virtArrowkey |= checkVirtArrowKeys(action, x1, y1);
|
||||
updateVirtArrowKeys(virtArrowkey);
|
||||
}
|
||||
|
||||
void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
||||
int arg4, int arg5, int arg6) {
|
||||
Common::Event e;
|
||||
@ -709,46 +437,13 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
||||
|
||||
return;
|
||||
|
||||
case JE_LONG:
|
||||
if (!_show_mouse &&
|
||||
getTouchArea(arg1, arg2) == kTouchAreaCenter)
|
||||
{
|
||||
e.kbd.keycode = Common::KEYCODE_i;
|
||||
e.kbd.ascii = 'i';
|
||||
|
||||
lockMutex(_event_queue_lock);
|
||||
e.type = Common::EVENT_KEYDOWN;
|
||||
_event_queue.push(e);
|
||||
e.type = Common::EVENT_KEYUP;
|
||||
_event_queue.push(e);
|
||||
unlockMutex(_event_queue_lock);
|
||||
}
|
||||
break;
|
||||
|
||||
case JE_FLING:
|
||||
if (!_show_mouse &&
|
||||
(getTouchArea(arg1, arg2) == kTouchAreaCenter ||
|
||||
getTouchArea(arg3, arg4) == kTouchAreaCenter))
|
||||
{
|
||||
e.kbd.keycode = Common::KEYCODE_PERIOD;
|
||||
e.kbd.ascii = '.';
|
||||
|
||||
lockMutex(_event_queue_lock);
|
||||
e.type = Common::EVENT_KEYDOWN;
|
||||
_event_queue.push(e);
|
||||
e.type = Common::EVENT_KEYUP;
|
||||
_event_queue.push(e);
|
||||
unlockMutex(_event_queue_lock);
|
||||
}
|
||||
break;
|
||||
|
||||
case JE_TAP:
|
||||
if (_fingersDown > 0) {
|
||||
_fingersDown = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_show_mouse) {
|
||||
if (!_virtcontrols_on) {
|
||||
e.type = Common::EVENT_MOUSEMOVE;
|
||||
|
||||
if (_touchpad_mode) {
|
||||
@ -789,17 +484,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
||||
|
||||
unlockMutex(_event_queue_lock);
|
||||
} else {
|
||||
if (getTouchArea(arg1, arg2) == kTouchAreaCenter) {
|
||||
e.kbd.keycode = Common::KEYCODE_RETURN;
|
||||
e.kbd.ascii = Common::ASCII_RETURN;
|
||||
|
||||
lockMutex(_event_queue_lock);
|
||||
e.type = Common::EVENT_KEYDOWN;
|
||||
_event_queue.push(e);
|
||||
e.type = Common::EVENT_KEYUP;
|
||||
_event_queue.push(e);
|
||||
unlockMutex(_event_queue_lock);
|
||||
}
|
||||
keyPress(Common::KEYCODE_RETURN, KeyReceiver::PRESS);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -828,7 +513,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
||||
dptype = Common::EVENT_LBUTTONUP;
|
||||
break;
|
||||
// held and moved
|
||||
case JACTION_MULTIPLE:
|
||||
case JACTION_MOVE:
|
||||
if (_touch_pt_dt.x == -1 && _touch_pt_dt.y == -1) {
|
||||
_touch_pt_dt.x = arg1;
|
||||
_touch_pt_dt.y = arg2;
|
||||
@ -858,53 +543,34 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
||||
unlockMutex(_event_queue_lock);
|
||||
}
|
||||
} else {
|
||||
int touchArea = getTouchArea(arg1, arg2);
|
||||
if (touchArea && touchArea != kTouchAreaCenter) {
|
||||
updateVirtArrowKeys(_virt_arrowkeys_pressed | kVirtArrowKeyRun);
|
||||
} else if (touchArea == kTouchAreaCenter) {
|
||||
e.kbd.keycode = Common::KEYCODE_u;
|
||||
e.kbd.ascii = 'u';
|
||||
|
||||
lockMutex(_event_queue_lock);
|
||||
e.type = Common::EVENT_KEYDOWN;
|
||||
_event_queue.push(e);
|
||||
e.type = Common::EVENT_KEYUP;
|
||||
_event_queue.push(e);
|
||||
unlockMutex(_event_queue_lock);
|
||||
}
|
||||
keyPress(Common::KEYCODE_u, KeyReceiver::PRESS);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
|
||||
case JE_TOUCH:
|
||||
case JE_MULTI:
|
||||
{
|
||||
if (!_show_mouse) {
|
||||
_touchControls.update(arg1, arg2, arg3, arg4);
|
||||
return;
|
||||
}
|
||||
switch (arg2) {
|
||||
case JACTION_DOWN:
|
||||
case JACTION_MULTIPLE:
|
||||
if (!_show_mouse) {
|
||||
checkVirtArrowKeys(arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
}
|
||||
return;
|
||||
|
||||
case JACTION_UP:
|
||||
updateVirtArrowKeys(0);
|
||||
return;
|
||||
|
||||
case JACTION_POINTER_DOWN:
|
||||
if (arg1 > _fingersDown)
|
||||
_fingersDown = arg1;
|
||||
/* no break */
|
||||
|
||||
if (!_show_mouse) {
|
||||
checkVirtArrowKeys(arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
}
|
||||
|
||||
case JACTION_DOWN:
|
||||
case JACTION_MOVE:
|
||||
return;
|
||||
|
||||
case JACTION_POINTER_UP:
|
||||
if (arg1 != _fingersDown)
|
||||
return;
|
||||
|
||||
case JACTION_UP:
|
||||
case JACTION_POINTER_UP: {
|
||||
if (_show_mouse) {
|
||||
if (arg1 != _fingersDown)
|
||||
return;
|
||||
Common::EventType up;
|
||||
|
||||
switch (_fingersDown) {
|
||||
@ -935,13 +601,13 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
||||
_queuedEventTime = getMillis() + kQueuedInputEventDelay;
|
||||
|
||||
unlockMutex(_event_queue_lock);
|
||||
} else {
|
||||
checkVirtArrowKeys(arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case JE_BALL:
|
||||
e.mouse = getEventManager()->getMousePos();
|
||||
@ -953,7 +619,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
||||
case JACTION_UP:
|
||||
e.type = Common::EVENT_LBUTTONUP;
|
||||
break;
|
||||
case JACTION_MULTIPLE:
|
||||
case JACTION_MOVE:
|
||||
e.type = Common::EVENT_MOUSEMOVE;
|
||||
|
||||
// already multiplied by 100
|
||||
@ -1052,4 +718,19 @@ bool OSystem_Android::pollEvent(Common::Event &event) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void OSystem_Android::keyPress(const Common::KeyCode keycode, const KeyReceiver::KeyPressType type) {
|
||||
Common::Event e;
|
||||
e.kbd.keycode = keycode;
|
||||
lockMutex(_event_queue_lock);
|
||||
if (type == KeyReceiver::DOWN || type == KeyReceiver::PRESS) {
|
||||
e.type = Common::EVENT_KEYDOWN;
|
||||
_event_queue.push(e);
|
||||
}
|
||||
if (type == KeyReceiver::UP || type == KeyReceiver::PRESS) {
|
||||
e.type = Common::EVENT_KEYUP;
|
||||
_event_queue.push(e);
|
||||
}
|
||||
unlockMutex(_event_queue_lock);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
204
backends/platform/android/events.h
Normal file
204
backends/platform/android/events.h
Normal file
@ -0,0 +1,204 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_EVENTS_H
|
||||
#define ANDROID_EVENTS_H
|
||||
|
||||
#include "common/events.h"
|
||||
|
||||
class KeyReceiver {
|
||||
public:
|
||||
enum KeyPressType { DOWN, UP, PRESS };
|
||||
virtual void keyPress(const Common::KeyCode code, const KeyPressType type = PRESS) = 0;
|
||||
virtual ~KeyReceiver() {};
|
||||
};
|
||||
|
||||
// $ANDROID_NDK/platforms/android-9/arch-arm/usr/include/android/keycodes.h
|
||||
// http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=libs/ui/Input.cpp
|
||||
// http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/java/android/view/KeyEvent.java
|
||||
|
||||
// event type
|
||||
enum {
|
||||
JE_SYS_KEY = 0,
|
||||
JE_KEY = 1,
|
||||
JE_DPAD = 2,
|
||||
JE_DOWN = 3,
|
||||
JE_SCROLL = 4,
|
||||
JE_TAP = 5,
|
||||
JE_DOUBLE_TAP = 6,
|
||||
JE_MULTI = 7,
|
||||
JE_BALL = 8,
|
||||
JE_TOUCH = 9,
|
||||
JE_LONG = 10,
|
||||
JE_FLING = 11,
|
||||
JE_QUIT = 0x1000
|
||||
};
|
||||
|
||||
// action type
|
||||
enum {
|
||||
JACTION_DOWN = 0,
|
||||
JACTION_UP = 1,
|
||||
JACTION_MOVE = 2,
|
||||
JACTION_POINTER_DOWN = 5,
|
||||
JACTION_POINTER_UP = 6
|
||||
};
|
||||
|
||||
// system keys
|
||||
enum {
|
||||
JKEYCODE_SOFT_RIGHT = 2,
|
||||
JKEYCODE_HOME = 3,
|
||||
JKEYCODE_BACK = 4,
|
||||
JKEYCODE_CALL = 5,
|
||||
JKEYCODE_ENDCALL = 6,
|
||||
JKEYCODE_VOLUME_UP = 24,
|
||||
JKEYCODE_VOLUME_DOWN = 25,
|
||||
JKEYCODE_POWER = 26,
|
||||
JKEYCODE_CAMERA = 27,
|
||||
JKEYCODE_HEADSETHOOK = 79,
|
||||
JKEYCODE_FOCUS = 80,
|
||||
JKEYCODE_MENU = 82,
|
||||
JKEYCODE_SEARCH = 84,
|
||||
JKEYCODE_MUTE = 91,
|
||||
JKEYCODE_MEDIA_PLAY_PAUSE = 85,
|
||||
JKEYCODE_MEDIA_STOP = 86,
|
||||
JKEYCODE_MEDIA_NEXT = 87,
|
||||
JKEYCODE_MEDIA_PREVIOUS = 88,
|
||||
JKEYCODE_MEDIA_REWIND = 89,
|
||||
JKEYCODE_MEDIA_FAST_FORWARD = 90
|
||||
};
|
||||
|
||||
// five-way navigation control
|
||||
enum {
|
||||
JKEYCODE_DPAD_UP = 19,
|
||||
JKEYCODE_DPAD_DOWN = 20,
|
||||
JKEYCODE_DPAD_LEFT = 21,
|
||||
JKEYCODE_DPAD_RIGHT = 22,
|
||||
JKEYCODE_DPAD_CENTER = 23
|
||||
};
|
||||
|
||||
// meta modifier
|
||||
enum {
|
||||
JMETA_SHIFT = 0x01,
|
||||
JMETA_ALT = 0x02,
|
||||
JMETA_SYM = 0x04,
|
||||
JMETA_CTRL = 0x1000
|
||||
};
|
||||
|
||||
// map android key codes to our kbd codes
|
||||
static const Common::KeyCode jkeymap[] = {
|
||||
Common::KEYCODE_INVALID, // KEYCODE_UNKNOWN
|
||||
Common::KEYCODE_INVALID, // KEYCODE_SOFT_LEFT
|
||||
Common::KEYCODE_INVALID, // KEYCODE_SOFT_RIGHT
|
||||
Common::KEYCODE_INVALID, // KEYCODE_HOME
|
||||
Common::KEYCODE_INVALID, // KEYCODE_BACK
|
||||
Common::KEYCODE_INVALID, // KEYCODE_CALL
|
||||
Common::KEYCODE_INVALID, // KEYCODE_ENDCALL
|
||||
Common::KEYCODE_0, // KEYCODE_0
|
||||
Common::KEYCODE_1, // KEYCODE_1
|
||||
Common::KEYCODE_2, // KEYCODE_2
|
||||
Common::KEYCODE_3, // KEYCODE_3
|
||||
Common::KEYCODE_4, // KEYCODE_4
|
||||
Common::KEYCODE_5, // KEYCODE_5
|
||||
Common::KEYCODE_6, // KEYCODE_6
|
||||
Common::KEYCODE_7, // KEYCODE_7
|
||||
Common::KEYCODE_8, // KEYCODE_8
|
||||
Common::KEYCODE_9, // KEYCODE_9
|
||||
Common::KEYCODE_ASTERISK, // KEYCODE_STAR
|
||||
Common::KEYCODE_HASH, // KEYCODE_POUND
|
||||
Common::KEYCODE_INVALID, // KEYCODE_DPAD_UP
|
||||
Common::KEYCODE_INVALID, // KEYCODE_DPAD_DOWN
|
||||
Common::KEYCODE_INVALID, // KEYCODE_DPAD_LEFT
|
||||
Common::KEYCODE_INVALID, // KEYCODE_DPAD_RIGHT
|
||||
Common::KEYCODE_INVALID, // KEYCODE_DPAD_CENTER
|
||||
Common::KEYCODE_INVALID, // KEYCODE_VOLUME_UP
|
||||
Common::KEYCODE_INVALID, // KEYCODE_VOLUME_DOWN
|
||||
Common::KEYCODE_INVALID, // KEYCODE_POWER
|
||||
Common::KEYCODE_INVALID, // KEYCODE_CAMERA
|
||||
Common::KEYCODE_INVALID, // KEYCODE_CLEAR
|
||||
Common::KEYCODE_a, // KEYCODE_A
|
||||
Common::KEYCODE_b, // KEYCODE_B
|
||||
Common::KEYCODE_c, // KEYCODE_C
|
||||
Common::KEYCODE_d, // KEYCODE_D
|
||||
Common::KEYCODE_e, // KEYCODE_E
|
||||
Common::KEYCODE_f, // KEYCODE_F
|
||||
Common::KEYCODE_g, // KEYCODE_G
|
||||
Common::KEYCODE_h, // KEYCODE_H
|
||||
Common::KEYCODE_i, // KEYCODE_I
|
||||
Common::KEYCODE_j, // KEYCODE_J
|
||||
Common::KEYCODE_k, // KEYCODE_K
|
||||
Common::KEYCODE_l, // KEYCODE_L
|
||||
Common::KEYCODE_m, // KEYCODE_M
|
||||
Common::KEYCODE_n, // KEYCODE_N
|
||||
Common::KEYCODE_o, // KEYCODE_O
|
||||
Common::KEYCODE_p, // KEYCODE_P
|
||||
Common::KEYCODE_q, // KEYCODE_Q
|
||||
Common::KEYCODE_r, // KEYCODE_R
|
||||
Common::KEYCODE_s, // KEYCODE_S
|
||||
Common::KEYCODE_t, // KEYCODE_T
|
||||
Common::KEYCODE_u, // KEYCODE_U
|
||||
Common::KEYCODE_v, // KEYCODE_V
|
||||
Common::KEYCODE_w, // KEYCODE_W
|
||||
Common::KEYCODE_x, // KEYCODE_X
|
||||
Common::KEYCODE_y, // KEYCODE_Y
|
||||
Common::KEYCODE_z, // KEYCODE_Z
|
||||
Common::KEYCODE_COMMA, // KEYCODE_COMMA
|
||||
Common::KEYCODE_PERIOD, // KEYCODE_PERIOD
|
||||
Common::KEYCODE_LALT, // KEYCODE_ALT_LEFT
|
||||
Common::KEYCODE_RALT, // KEYCODE_ALT_RIGHT
|
||||
Common::KEYCODE_LSHIFT, // KEYCODE_SHIFT_LEFT
|
||||
Common::KEYCODE_RSHIFT, // KEYCODE_SHIFT_RIGHT
|
||||
Common::KEYCODE_TAB, // KEYCODE_TAB
|
||||
Common::KEYCODE_SPACE, // KEYCODE_SPACE
|
||||
Common::KEYCODE_LCTRL, // KEYCODE_SYM
|
||||
Common::KEYCODE_INVALID, // KEYCODE_EXPLORER
|
||||
Common::KEYCODE_INVALID, // KEYCODE_ENVELOPE
|
||||
Common::KEYCODE_RETURN, // KEYCODE_ENTER
|
||||
Common::KEYCODE_BACKSPACE, // KEYCODE_DEL
|
||||
Common::KEYCODE_BACKQUOTE, // KEYCODE_GRAVE
|
||||
Common::KEYCODE_MINUS, // KEYCODE_MINUS
|
||||
Common::KEYCODE_EQUALS, // KEYCODE_EQUALS
|
||||
Common::KEYCODE_LEFTPAREN, // KEYCODE_LEFT_BRACKET
|
||||
Common::KEYCODE_RIGHTPAREN, // KEYCODE_RIGHT_BRACKET
|
||||
Common::KEYCODE_BACKSLASH, // KEYCODE_BACKSLASH
|
||||
Common::KEYCODE_SEMICOLON, // KEYCODE_SEMICOLON
|
||||
Common::KEYCODE_QUOTE, // KEYCODE_APOSTROPHE
|
||||
Common::KEYCODE_SLASH, // KEYCODE_SLASH
|
||||
Common::KEYCODE_AT, // KEYCODE_AT
|
||||
Common::KEYCODE_INVALID, // KEYCODE_NUM
|
||||
Common::KEYCODE_INVALID, // KEYCODE_HEADSETHOOK
|
||||
Common::KEYCODE_INVALID, // KEYCODE_FOCUS
|
||||
Common::KEYCODE_PLUS, // KEYCODE_PLUS
|
||||
Common::KEYCODE_INVALID, // KEYCODE_MENU
|
||||
Common::KEYCODE_INVALID, // KEYCODE_NOTIFICATION
|
||||
Common::KEYCODE_INVALID, // KEYCODE_SEARCH
|
||||
Common::KEYCODE_INVALID, // KEYCODE_MEDIA_PLAY_PAUSE
|
||||
Common::KEYCODE_INVALID, // KEYCODE_MEDIA_STOP
|
||||
Common::KEYCODE_INVALID, // KEYCODE_MEDIA_NEXT
|
||||
Common::KEYCODE_INVALID, // KEYCODE_MEDIA_PREVIOUS
|
||||
Common::KEYCODE_INVALID, // KEYCODE_MEDIA_REWIND
|
||||
Common::KEYCODE_INVALID, // KEYCODE_MEDIA_FAST_FORWARD
|
||||
Common::KEYCODE_INVALID, // KEYCODE_MUTE
|
||||
Common::KEYCODE_PAGEUP, // KEYCODE_PAGE_UP
|
||||
Common::KEYCODE_PAGEDOWN // KEYCODE_PAGE_DOWN
|
||||
};
|
||||
|
||||
#endif
|
@ -41,6 +41,7 @@
|
||||
|
||||
#include "common/endian.h"
|
||||
#include "graphics/conversion.h"
|
||||
#include "graphics/opengles2/shader.h"
|
||||
|
||||
#include "backends/platform/android/android.h"
|
||||
#include "backends/platform/android/jni.h"
|
||||
@ -52,7 +53,7 @@ static inline GLfixed xdiv(int numerator, int denominator) {
|
||||
|
||||
// ResidualVM specific method
|
||||
void OSystem_Android::launcherInitSize(uint w, uint h) {
|
||||
//setupScreen(w, h, true, false);
|
||||
setupScreen(w, h, true, true, false);
|
||||
}
|
||||
|
||||
// ResidualVM specific method
|
||||
@ -191,7 +192,7 @@ void OSystem_Android::initSurface() {
|
||||
JNI::initSurface();
|
||||
|
||||
// Initialize OpenGLES context.
|
||||
GLESTexture::initGLExtensions();
|
||||
GLESTexture::initGL();
|
||||
|
||||
if (_game_texture)
|
||||
_game_texture->reinit();
|
||||
@ -233,44 +234,14 @@ void OSystem_Android::initViewport() {
|
||||
|
||||
assert(JNI::haveSurface());
|
||||
|
||||
if (_opengl) {
|
||||
GLCALL(glEnable(GL_DITHER));
|
||||
GLCALL(glShadeModel(GL_SMOOTH));
|
||||
|
||||
GLCALL(glDisableClientState(GL_VERTEX_ARRAY));
|
||||
GLCALL(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
|
||||
|
||||
GLCALL(glDisable(GL_TEXTURE_2D));
|
||||
|
||||
GLCALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST));
|
||||
} else {
|
||||
// Turn off anything that looks like 3D ;)
|
||||
GLCALL(glDisable(GL_DITHER));
|
||||
GLCALL(glShadeModel(GL_FLAT));
|
||||
|
||||
GLCALL(glEnableClientState(GL_VERTEX_ARRAY));
|
||||
GLCALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
|
||||
|
||||
GLCALL(glEnable(GL_TEXTURE_2D));
|
||||
|
||||
GLCALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST));
|
||||
}
|
||||
|
||||
GLCALL(glDisable(GL_CULL_FACE));
|
||||
GLCALL(glDisable(GL_DEPTH_TEST));
|
||||
GLCALL(glDisable(GL_LIGHTING));
|
||||
GLCALL(glDisable(GL_FOG));
|
||||
|
||||
GLCALL(glEnable(GL_BLEND));
|
||||
GLCALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
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());
|
||||
LOGD("viewport size: %dx%d", _egl_surface_width, _egl_surface_height);
|
||||
|
||||
clearFocusRectangle();
|
||||
}
|
||||
@ -287,10 +258,10 @@ void OSystem_Android::initOverlay() {
|
||||
// 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;
|
||||
}
|
||||
// while (overlay_height > 480) {
|
||||
// overlay_width /= 2;
|
||||
// overlay_height /= 2;
|
||||
// }
|
||||
|
||||
LOGI("overlay size is %ux%u", overlay_width, overlay_height);
|
||||
|
||||
@ -333,7 +304,7 @@ void OSystem_Android::clearScreen(FixupType type, byte count) {
|
||||
|
||||
for (byte i = 0; i < count; ++i) {
|
||||
// clear screen
|
||||
GLCALL(glClearColorx(0, 0, 0, 1 << 16));
|
||||
GLCALL(glClearColor(0, 0, 0, 1 << 16));
|
||||
if (_opengl) {
|
||||
GLCALL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
|
||||
} else {
|
||||
@ -460,15 +431,20 @@ void OSystem_Android::copyRectToScreen(const void *buf, int pitch,
|
||||
|
||||
|
||||
// ResidualVM specific method
|
||||
Graphics::PixelBuffer OSystem_Android::setupScreen(int screenW, int screenH, bool fullscreen, bool accel3d) {
|
||||
Graphics::PixelBuffer OSystem_Android::setupScreen(int screenW, int screenH, bool fullscreen, bool accel3d, bool isGame) {
|
||||
_opengl = accel3d;
|
||||
initViewport();
|
||||
|
||||
_touchControls.init(this, _egl_surface_width, _egl_surface_height);
|
||||
|
||||
if (_opengl) {
|
||||
// resize game texture
|
||||
initSize(screenW, screenH, 0);
|
||||
if (isGame)
|
||||
_game_texture->setGameTexture();
|
||||
// format is not used by the gfx_opengl driver, use fake format
|
||||
_game_pbuf.set(Graphics::PixelFormat(), 0);
|
||||
|
||||
} else {
|
||||
Graphics::PixelFormat format = GLES565Texture::pixelFormat();
|
||||
initSize(screenW, screenH, &format);
|
||||
@ -488,7 +464,6 @@ void OSystem_Android::updateScreen() {
|
||||
if (!JNI::haveSurface())
|
||||
return;
|
||||
|
||||
if (!_opengl) {
|
||||
if (_game_pbuf) {
|
||||
int pitch = _game_texture->width() * _game_texture->getPixelFormat().bytesPerPixel;
|
||||
_game_texture->updateBuffer(0, 0, _game_texture->width(), _game_texture->height(),
|
||||
@ -509,8 +484,8 @@ void OSystem_Android::updateScreen() {
|
||||
if ((_show_overlay || _htc_fail) && !_fullscreen)
|
||||
clearScreen(kClear);
|
||||
|
||||
GLCALL(glPushMatrix());
|
||||
|
||||
// TODO: Do we have engines that use this?
|
||||
#if 0
|
||||
if (_shake_offset != 0 ||
|
||||
(!_focus_rect.isEmpty() &&
|
||||
!Common::Rect(_game_texture->width(),
|
||||
@ -522,14 +497,18 @@ void OSystem_Android::updateScreen() {
|
||||
// Move everything up by _shake_offset (game) pixels
|
||||
GLCALL(glTranslatex(0, -_shake_offset << 16, 0));
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO this doesnt work on those sucky drivers, do it differently
|
||||
// if (_show_overlay)
|
||||
// GLCALL(glColor4ub(0x9f, 0x9f, 0x9f, 0x9f));
|
||||
|
||||
if (_focus_rect.isEmpty()) {
|
||||
if (true || _focus_rect.isEmpty()) {
|
||||
_game_texture->drawTextureRect();
|
||||
drawVirtControls();
|
||||
} else {
|
||||
// TODO what is this and do we have engines using it?
|
||||
#if 0
|
||||
GLCALL(glPushMatrix());
|
||||
|
||||
GLCALL(glScalex(xdiv(_egl_surface_width, _focus_rect.width()),
|
||||
@ -544,6 +523,7 @@ void OSystem_Android::updateScreen() {
|
||||
_game_texture->drawTextureRect();
|
||||
|
||||
GLCALL(glPopMatrix());
|
||||
#endif
|
||||
}
|
||||
|
||||
int cs = _mouse_targetscale;
|
||||
@ -559,17 +539,13 @@ void OSystem_Android::updateScreen() {
|
||||
}
|
||||
|
||||
if (_show_mouse && !_mouse_texture->isEmpty()) {
|
||||
GLCALL(glPushMatrix());
|
||||
|
||||
const Common::Point &mouse = getEventManager()->getMousePos();
|
||||
|
||||
// Scale up ResidualVM -> OpenGL (pixel) coordinates
|
||||
if (_show_overlay) {
|
||||
GLCALL(glScalex(xdiv(_egl_surface_width,
|
||||
_overlay_texture->width()),
|
||||
xdiv(_egl_surface_height,
|
||||
_overlay_texture->height()),
|
||||
1 << 16));
|
||||
_mouse_texture->drawTexture(mouse.x * cs, mouse.y * cs, _mouse_texture->width(), _mouse_texture->height());
|
||||
}
|
||||
// TODO: Port the non-overlay code as well?
|
||||
#if 0
|
||||
if (_show_overlay) {
|
||||
} else {
|
||||
const Common::Rect &r = _game_texture->getDrawRect();
|
||||
|
||||
@ -585,23 +561,20 @@ void OSystem_Android::updateScreen() {
|
||||
(-_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());
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!JNI::swapBuffers())
|
||||
LOGW("swapBuffers failed: 0x%x", glGetError());
|
||||
|
||||
}
|
||||
|
||||
void OSystem_Android::drawVirtControls() {
|
||||
if (_show_overlay)
|
||||
return;
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
_touchControls.draw();
|
||||
}
|
||||
|
||||
Graphics::Surface *OSystem_Android::lockScreen() {
|
||||
|
@ -6,7 +6,8 @@ MODULE_OBJS := \
|
||||
asset-archive.o \
|
||||
android.o \
|
||||
gfx.o \
|
||||
events.o
|
||||
events.o \
|
||||
touchcontrols.o
|
||||
|
||||
# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
|
||||
MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
|
||||
|
@ -151,7 +151,14 @@ public abstract class ResidualVM implements SurfaceHolder.Callback, Runnable {
|
||||
_egl.eglInitialize(_egl_display, version);
|
||||
|
||||
int[] num_config = new int[1];
|
||||
_egl.eglGetConfigs(_egl_display, null, 0, num_config);
|
||||
int[] config_attrib_list = {
|
||||
EGL10.EGL_RENDERABLE_TYPE, 4, // ES2
|
||||
EGL10.EGL_RED_SIZE, 5,
|
||||
EGL10.EGL_GREEN_SIZE, 6,
|
||||
EGL10.EGL_BLUE_SIZE, 5,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
_egl.eglChooseConfig(_egl_display, config_attrib_list, null, 0, num_config);
|
||||
|
||||
final int numConfigs = num_config[0];
|
||||
|
||||
@ -159,14 +166,14 @@ public abstract class ResidualVM implements SurfaceHolder.Callback, Runnable {
|
||||
throw new IllegalArgumentException("No EGL configs");
|
||||
|
||||
EGLConfig[] configs = new EGLConfig[numConfigs];
|
||||
_egl.eglGetConfigs(_egl_display, configs, numConfigs, num_config);
|
||||
_egl.eglChooseConfig(_egl_display, config_attrib_list, configs, numConfigs, num_config);
|
||||
|
||||
// Android's eglChooseConfig is busted in several versions and
|
||||
// devices so we have to filter/rank the configs ourselves.
|
||||
_egl_config = chooseEglConfig(configs);
|
||||
|
||||
int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
|
||||
int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL10.EGL_NONE };
|
||||
_egl_context = _egl.eglCreateContext(_egl_display, _egl_config,
|
||||
EGL10.EGL_NO_CONTEXT, null);
|
||||
EGL10.EGL_NO_CONTEXT, attrib_list);
|
||||
|
||||
if (_egl_context == EGL10.EGL_NO_CONTEXT)
|
||||
throw new Exception(String.format("Failed to create context: 0x%x",
|
||||
|
@ -8,6 +8,10 @@ import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.KeyCharacterMap;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.MotionEvent;
|
||||
@ -158,6 +162,21 @@ public class ResidualVMActivity extends Activity {
|
||||
_residualvm_thread = new Thread(_residualvm, "ResidualVM");
|
||||
_residualvm_thread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.game_menu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.show_menu:
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
|
@ -2,6 +2,7 @@ package org.residualvm.residualvm;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.content.Context;
|
||||
import android.view.KeyEvent;
|
||||
@ -30,11 +31,15 @@ public class ResidualVMEvents implements
|
||||
public static final int JE_LONG = 10;
|
||||
public static final int JE_FLING = 11;
|
||||
public static final int JE_QUIT = 0x1000;
|
||||
|
||||
private final int REL_SWIPE_MIN_DISTANCE;
|
||||
private final int REL_SWIPE_THRESHOLD_VELOCITY;
|
||||
|
||||
final protected Context _context;
|
||||
final protected ResidualVM _residualvm;
|
||||
final protected GestureDetector _gd;
|
||||
final protected int _longPress;
|
||||
final protected int _width;
|
||||
|
||||
public ResidualVMEvents(Context context, ResidualVM residualvm) {
|
||||
_context = context;
|
||||
@ -45,6 +50,11 @@ public class ResidualVMEvents implements
|
||||
//_gd.setIsLongpressEnabled(false);
|
||||
|
||||
_longPress = ViewConfiguration.getLongPressTimeout();
|
||||
|
||||
DisplayMetrics dm = context.getResources().getDisplayMetrics();
|
||||
REL_SWIPE_MIN_DISTANCE = (int)(120 * dm.densityDpi / 160.0f);
|
||||
REL_SWIPE_THRESHOLD_VELOCITY = (int)(100 * dm.densityDpi / 160.0f);
|
||||
_width = dm.widthPixels;
|
||||
}
|
||||
|
||||
final public void sendQuitEvent() {
|
||||
@ -74,6 +84,7 @@ public class ResidualVMEvents implements
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// OnKeyListener
|
||||
final public boolean onKey(View v, int keyCode, KeyEvent e) {
|
||||
final int action = e.getAction();
|
||||
@ -162,26 +173,33 @@ public class ResidualVMEvents implements
|
||||
}
|
||||
|
||||
final public boolean onTouchEvent(MotionEvent e) {
|
||||
final int action = e.getAction();
|
||||
|
||||
_gd.onTouchEvent(e);
|
||||
|
||||
final int action = e.getActionMasked();
|
||||
|
||||
// constants from APIv5:
|
||||
// (action & ACTION_POINTER_INDEX_MASK) >> ACTION_POINTER_INDEX_SHIFT
|
||||
final int pointer = (action & 0xff00) >> 8;
|
||||
|
||||
final int x0 = (int)e.getX();
|
||||
final int y0 = (int)e.getY();
|
||||
final int x1 = (e.getPointerCount() > 1 ? (int)e.getX(1) : -1);
|
||||
final int y1 = (e.getPointerCount() > 1 ? (int)e.getY(1) : -1);
|
||||
|
||||
if (pointer > 0) {
|
||||
_residualvm.pushEvent(JE_MULTI, pointer, action & 0xff, // ACTION_MASK
|
||||
x0, y0, x1, y1);
|
||||
// ACTION_MOVE always returns the first pointer as the "active" one.
|
||||
if (action == MotionEvent.ACTION_MOVE) {
|
||||
for (int idx = 0; idx < e.getPointerCount(); ++idx) {
|
||||
final int pointer = e.getPointerId(idx);
|
||||
|
||||
final int x = (int)e.getX(idx);
|
||||
final int y = (int)e.getY(idx);
|
||||
|
||||
_residualvm.pushEvent(JE_TOUCH, pointer, action, x, y, 0, 0);
|
||||
}
|
||||
} else {
|
||||
_residualvm.pushEvent(JE_TOUCH, pointer, action & 0xff, // ACTION_MASK
|
||||
x0, y0, x1, y1);
|
||||
final int idx = e.getActionIndex();
|
||||
final int pointer = e.getPointerId(idx);
|
||||
|
||||
final int x = (int)e.getX(idx);
|
||||
final int y = (int)e.getY(idx);
|
||||
|
||||
_residualvm.pushEvent(JE_TOUCH, pointer, action, x, y, 0, 0);
|
||||
}
|
||||
|
||||
return _gd.onTouchEvent(e);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// OnGestureListener
|
||||
@ -192,9 +210,16 @@ public class ResidualVMEvents implements
|
||||
|
||||
final public boolean onFling(MotionEvent e1, MotionEvent e2,
|
||||
float velocityX, float velocityY) {
|
||||
_residualvm.pushEvent(JE_FLING, (int)e1.getX(), (int)e1.getY(),
|
||||
(int)e2.getX(), (int)e2.getY(), 0, 0);
|
||||
return true;
|
||||
return false;
|
||||
// if (e1.getX() < 0.4 * _width
|
||||
// || Math.abs(e1.getX() - e2.getX()) < REL_SWIPE_MIN_DISTANCE
|
||||
// || velocityX < REL_SWIPE_THRESHOLD_VELOCITY
|
||||
// || Math.abs(e1.getY() - e2.getY()) < REL_SWIPE_MIN_DISTANCE
|
||||
// || velocityY < REL_SWIPE_THRESHOLD_VELOCITY)
|
||||
// return false;
|
||||
//
|
||||
// _residualvm.pushEvent(JE_FLING, (int)e1.getX(), (int)e1.getY(),
|
||||
// (int)e2.getX(), (int)e2.getY(), 0, 0);
|
||||
}
|
||||
|
||||
final public void onLongPress(MotionEvent e) {
|
||||
|
@ -271,7 +271,7 @@ public class Unpacker extends Activity {
|
||||
unpack_libs.add(new Uri.Builder()
|
||||
.scheme("plugin")
|
||||
.authority(getPackageName())
|
||||
.path("mylib/armeabi/libresidualvm.so")
|
||||
.path("lib/armeabi/libresidualvm.so")
|
||||
.toString());
|
||||
extras.putStringArrayList(ResidualVMApplication.EXTRA_UNPACK_LIBS,
|
||||
unpack_libs);
|
||||
|
@ -41,6 +41,7 @@
|
||||
|
||||
#include "base/main.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "graphics/opengles2/shader.h"
|
||||
|
||||
#include "common/rect.h"
|
||||
#include "common/array.h"
|
||||
@ -49,12 +50,13 @@
|
||||
|
||||
#include "backends/platform/android/texture.h"
|
||||
#include "backends/platform/android/android.h"
|
||||
#include "backends/platform/android/jni.h"
|
||||
|
||||
// Supported GL extensions
|
||||
static bool npot_supported = false;
|
||||
#ifdef GL_OES_draw_texture
|
||||
static bool draw_tex_supported = false;
|
||||
#endif
|
||||
|
||||
Graphics::Shader * g_box_shader;
|
||||
GLuint g_verticesVBO;
|
||||
|
||||
static inline GLfixed xdiv(int numerator, int denominator) {
|
||||
assert(numerator < (1 << 16));
|
||||
@ -73,7 +75,14 @@ static T nextHigher2(T k) {
|
||||
return k + 1;
|
||||
}
|
||||
|
||||
void GLESBaseTexture::initGLExtensions() {
|
||||
const GLfloat vertices[] = {
|
||||
0.0, 0.0,
|
||||
1.0, 0.0,
|
||||
0.0, 1.0,
|
||||
1.0, 1.0,
|
||||
};
|
||||
|
||||
void GLESBaseTexture::initGL() {
|
||||
const char *ext_string =
|
||||
reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
|
||||
|
||||
@ -85,12 +94,13 @@ void GLESBaseTexture::initGLExtensions() {
|
||||
|
||||
if (token == "GL_ARB_texture_non_power_of_two")
|
||||
npot_supported = true;
|
||||
|
||||
#ifdef GL_OES_draw_texture
|
||||
if (token == "GL_OES_draw_texture")
|
||||
draw_tex_supported = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* attributes[] = { "position", "texcoord", NULL };
|
||||
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);
|
||||
}
|
||||
|
||||
GLESBaseTexture::GLESBaseTexture(GLenum glFormat, GLenum glType,
|
||||
@ -106,7 +116,8 @@ GLESBaseTexture::GLESBaseTexture(GLenum glFormat, GLenum glType,
|
||||
_all_dirty(false),
|
||||
_dirty_rect(),
|
||||
_pixelFormat(pixelFormat),
|
||||
_palettePixelFormat()
|
||||
_palettePixelFormat(),
|
||||
_is_game_texture(false)
|
||||
{
|
||||
GLCALL(glGenTextures(1, &_texture_name));
|
||||
}
|
||||
@ -117,8 +128,6 @@ GLESBaseTexture::~GLESBaseTexture() {
|
||||
|
||||
void GLESBaseTexture::release() {
|
||||
if (_texture_name) {
|
||||
LOGD("Destroying texture %u", _texture_name);
|
||||
|
||||
GLCALL(glDeleteTextures(1, &_texture_name));
|
||||
_texture_name = 0;
|
||||
}
|
||||
@ -177,48 +186,28 @@ 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);
|
||||
g_box_shader->use();
|
||||
|
||||
GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
|
||||
const GLfloat offsetX = float(x) / float(JNI::egl_surface_width);
|
||||
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);
|
||||
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);
|
||||
|
||||
#ifdef GL_OES_draw_texture
|
||||
// Great extension, but only works under specific conditions.
|
||||
// Still a work-in-progress - disabled for now.
|
||||
if (false && draw_tex_supported && !hasPalette()) {
|
||||
//GLCALL(glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE));
|
||||
const GLint crop[4] = { 0, _surface.h, _surface.w, -_surface.h };
|
||||
g_box_shader->setUniform("offsetXY", Math::Vector2d(offsetX, offsetY));
|
||||
g_box_shader->setUniform("sizeWH", Math::Vector2d(sizeW, sizeH));
|
||||
g_box_shader->setUniform("clip", clipV);
|
||||
g_box_shader->setUniform("flipY", !_is_game_texture);
|
||||
|
||||
GLCALL(glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop));
|
||||
|
||||
// Android GLES bug?
|
||||
GLCALL(glColor4ub(0xff, 0xff, 0xff, 0xff));
|
||||
|
||||
GLCALL(glDrawTexiOES(x, y, 0, w, h));
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
const GLfixed tex_width = xdiv(_surface.w, _texture_width);
|
||||
const GLfixed tex_height = xdiv(_surface.h, _texture_height);
|
||||
const GLfixed texcoords[] = {
|
||||
0, 0,
|
||||
tex_width, 0,
|
||||
0, tex_height,
|
||||
tex_width, tex_height,
|
||||
};
|
||||
|
||||
GLCALL(glTexCoordPointer(2, GL_FIXED, 0, texcoords));
|
||||
|
||||
const GLshort vertices[] = {
|
||||
x, y,
|
||||
x + w, y,
|
||||
x, y + h,
|
||||
x + w, y + h,
|
||||
};
|
||||
|
||||
GLCALL(glVertexPointer(2, GL_SHORT, 0, vertices));
|
||||
|
||||
assert(ARRAYSIZE(vertices) == ARRAYSIZE(texcoords));
|
||||
GLCALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, ARRAYSIZE(vertices) / 2));
|
||||
}
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
clearDirty();
|
||||
}
|
||||
@ -293,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;
|
||||
@ -335,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() :
|
||||
@ -345,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()) {
|
||||
}
|
||||
@ -431,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;
|
||||
@ -464,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 {
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
class GLESBaseTexture {
|
||||
public:
|
||||
static void initGLExtensions();
|
||||
static void initGL();
|
||||
|
||||
protected:
|
||||
GLESBaseTexture(GLenum glFormat, GLenum glType,
|
||||
@ -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;
|
||||
@ -92,6 +96,14 @@ public:
|
||||
return _surface.h;
|
||||
}
|
||||
|
||||
inline GLuint texWidth() const {
|
||||
return _texture_width;
|
||||
}
|
||||
|
||||
inline GLuint texHeight() const {
|
||||
return _texture_height;
|
||||
}
|
||||
|
||||
inline uint16 pitch() const {
|
||||
return _surface.pitch;
|
||||
}
|
||||
@ -131,6 +143,14 @@ public:
|
||||
return _palettePixelFormat;
|
||||
}
|
||||
|
||||
GLuint getTextureName() const {
|
||||
return _texture_name;
|
||||
}
|
||||
|
||||
void setGameTexture() {
|
||||
_is_game_texture = true;
|
||||
}
|
||||
|
||||
protected:
|
||||
inline void setDirty() {
|
||||
_all_dirty = true;
|
||||
@ -169,6 +189,8 @@ protected:
|
||||
|
||||
Graphics::PixelFormat _pixelFormat;
|
||||
Graphics::PixelFormat _palettePixelFormat;
|
||||
|
||||
bool _is_game_texture;
|
||||
};
|
||||
|
||||
class GLESTexture : public GLESBaseTexture {
|
||||
@ -185,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:
|
||||
@ -238,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;
|
||||
|
264
backends/platform/android/touchcontrols.cpp
Normal file
264
backends/platform/android/touchcontrols.cpp
Normal file
@ -0,0 +1,264 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
#include "common/fs.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/archive.h"
|
||||
#include "graphics/decoders/tga.h"
|
||||
|
||||
#include "backends/platform/android/events.h"
|
||||
#include "backends/platform/android/texture.h"
|
||||
#include "backends/platform/android/touchcontrols.h"
|
||||
|
||||
static Common::Rect clipFor(const Common::KeyCode &cs) {
|
||||
switch (cs) {
|
||||
case Common::KEYCODE_UP:
|
||||
case Common::KEYCODE_PAGEUP:
|
||||
return Common::Rect(0, 0, 128, 128);
|
||||
case Common::KEYCODE_RIGHT:
|
||||
return Common::Rect(128, 0, 256, 128);
|
||||
case Common::KEYCODE_DOWN:
|
||||
case Common::KEYCODE_PAGEDOWN:
|
||||
return Common::Rect(256, 0, 384, 128);
|
||||
case Common::KEYCODE_LEFT:
|
||||
return Common::Rect(384, 0, 512, 128);
|
||||
case Common::KEYCODE_i:
|
||||
return Common::Rect(0, 128, 128, 256);
|
||||
case Common::KEYCODE_p:
|
||||
return Common::Rect(128, 128, 256, 256);
|
||||
case Common::KEYCODE_u:
|
||||
return Common::Rect(256, 128, 384, 256);
|
||||
case Common::KEYCODE_e:
|
||||
case Common::KEYCODE_l:
|
||||
return Common::Rect(384, 128, 512, 256);
|
||||
default: // unreachable
|
||||
return Common::Rect(0, 0, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
TouchControls::TouchControls() :
|
||||
_arrows_texture(NULL),
|
||||
_joystickPressing(Common::KEYCODE_INVALID),
|
||||
_centerPressing(Common::KEYCODE_INVALID),
|
||||
_rightPressing(Common::KEYCODE_INVALID),
|
||||
_key_receiver(NULL),
|
||||
_screen_width(0),
|
||||
_screen_height(0) {
|
||||
|
||||
for (int p = 0; p < kNumPointers; ++p) {
|
||||
Pointer &pp = _pointers[p];
|
||||
pp.currentX = pp.currentY = pp.startX = pp.startY = 0;
|
||||
pp.active = false;
|
||||
pp.function = kTouchAreaNone;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
_activePointers[i] = -1;
|
||||
}
|
||||
|
||||
TouchControls::~TouchControls() {
|
||||
if (_arrows_texture) {
|
||||
delete _arrows_texture;
|
||||
_arrows_texture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint16 TouchControls::getTouchArea(int x, int y) {
|
||||
float xPercent = float(x) / _screen_width;
|
||||
|
||||
if (xPercent < 0.3)
|
||||
return kTouchAreaJoystick;
|
||||
else if (xPercent < 0.8)
|
||||
return kTouchAreaCenter;
|
||||
else
|
||||
return kTouchAreaRight;
|
||||
}
|
||||
|
||||
static Common::KeyCode determineKey(int dX, int dY, Common::KeyCode def = Common::KEYCODE_INVALID) {
|
||||
if (dX * dX + dY * dY < 50 * 50)
|
||||
return def;
|
||||
|
||||
if (dY > abs(dX))
|
||||
return Common::KEYCODE_DOWN;
|
||||
if (dX > abs(dY))
|
||||
return Common::KEYCODE_RIGHT;
|
||||
if (-dY > abs(dX))
|
||||
return Common::KEYCODE_UP;
|
||||
if (-dX > abs(dY))
|
||||
return Common::KEYCODE_LEFT;
|
||||
|
||||
return Common::KEYCODE_INVALID;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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 TouchControls::init(KeyReceiver *kr, int width, int height) {
|
||||
_arrows_texture = loadBuiltinTexture("arrows.tga");
|
||||
_screen_width = width;
|
||||
_screen_height = height;
|
||||
_key_receiver = kr;
|
||||
}
|
||||
|
||||
const uint _numRightKeycodes = 4;
|
||||
const Common::KeyCode _rightKeycodes[] = { Common::KEYCODE_i, Common::KEYCODE_p, Common::KEYCODE_u, Common::KEYCODE_e };
|
||||
|
||||
void TouchControls::draw() {
|
||||
if (_joystickPressing != Common::KEYCODE_INVALID) {
|
||||
Common::Rect clip = clipFor(_joystickPressing);
|
||||
_arrows_texture->drawTexture(2 * _screen_width / 10, _screen_height / 2, 64, 64, clip);
|
||||
}
|
||||
|
||||
if (_centerPressing != Common::KEYCODE_INVALID) {
|
||||
Common::Rect clip = clipFor(_centerPressing);
|
||||
_arrows_texture->drawTexture(_screen_width / 2, _screen_height / 2, 64, 64, clip);
|
||||
}
|
||||
|
||||
if (_rightPressing != Common::KEYCODE_INVALID) {
|
||||
Common::Rect clip = clipFor(_rightPressing);
|
||||
_arrows_texture->drawTexture( 8 * _screen_width / 10, _screen_height / 2, 64, 64, clip);
|
||||
}
|
||||
}
|
||||
|
||||
void TouchControls::update(int ptr, int action, int x, int y) {
|
||||
if (ptr > kNumPointers)
|
||||
return;
|
||||
|
||||
TouchArea touchArea = (TouchArea) getTouchArea(x, y);
|
||||
|
||||
switch (action) {
|
||||
case JACTION_POINTER_DOWN:
|
||||
case JACTION_DOWN:
|
||||
if (touchArea > kTouchAreaNone && -1 == pointerFor(touchArea)) {
|
||||
pointerFor(touchArea) = ptr;
|
||||
_pointers[ptr].active = true;
|
||||
_pointers[ptr].function = touchArea;
|
||||
_pointers[ptr].startX = _pointers[ptr].currentX = x;
|
||||
_pointers[ptr].startY = _pointers[ptr].currentY = y;
|
||||
// fall through to move case to initialize _{joy,center,right}Pressing
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
case JACTION_MOVE: {
|
||||
_pointers[ptr].currentX = x;
|
||||
_pointers[ptr].currentY = y;
|
||||
int dX = x - _pointers[ptr].startX;
|
||||
int dY = y - _pointers[ptr].startY;
|
||||
|
||||
switch (_pointers[ptr].function) {
|
||||
case kTouchAreaJoystick: {
|
||||
Common::KeyCode newPressing = determineKey(dX, dY);
|
||||
if (newPressing != _joystickPressing) {
|
||||
_key_receiver->keyPress(_joystickPressing, KeyReceiver::UP);
|
||||
_key_receiver->keyPress(newPressing, KeyReceiver::DOWN);
|
||||
_joystickPressing = newPressing;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case kTouchAreaCenter:
|
||||
_centerPressing = determineKey(dX, dY, Common::KEYCODE_RETURN);
|
||||
return;
|
||||
|
||||
case kTouchAreaRight:
|
||||
_rightPressing = determineKey(dX, dY, Common::KEYCODE_i);
|
||||
switch (_rightPressing) {
|
||||
case Common::KEYCODE_LEFT:
|
||||
case Common::KEYCODE_RIGHT:
|
||||
_rightPressing = _rightKeycodes[abs(dX / 100) % _numRightKeycodes];
|
||||
break;
|
||||
|
||||
case Common::KEYCODE_UP:
|
||||
_rightPressing = Common::KEYCODE_PAGEUP;
|
||||
break;
|
||||
|
||||
case Common::KEYCODE_DOWN:
|
||||
_rightPressing = Common::KEYCODE_PAGEDOWN;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case JACTION_UP:
|
||||
case JACTION_POINTER_UP: {
|
||||
switch (_pointers[ptr].function) {
|
||||
case kTouchAreaJoystick:
|
||||
pointerFor(kTouchAreaJoystick) = -1;
|
||||
if (_joystickPressing != Common::KEYCODE_INVALID) {
|
||||
_key_receiver->keyPress(_joystickPressing, KeyReceiver::UP);
|
||||
_joystickPressing = Common::KEYCODE_INVALID;
|
||||
}
|
||||
break;
|
||||
|
||||
case kTouchAreaCenter:
|
||||
pointerFor(kTouchAreaCenter) = -1;
|
||||
_key_receiver->keyPress(_centerPressing);
|
||||
_centerPressing = Common::KEYCODE_INVALID;
|
||||
break;
|
||||
|
||||
case kTouchAreaRight:
|
||||
pointerFor(kTouchAreaRight) = -1;
|
||||
_key_receiver->keyPress(_rightPressing);
|
||||
_rightPressing = Common::KEYCODE_INVALID;
|
||||
break;
|
||||
|
||||
case kTouchAreaNone:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
_pointers[ptr].active = false;
|
||||
_pointers[ptr].function = kTouchAreaNone;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int &TouchControls::pointerFor(TouchArea ta) {
|
||||
return _activePointers[ta - kTouchAreaNone];
|
||||
}
|
||||
|
||||
#endif
|
73
backends/platform/android/touchcontrols.h
Normal file
73
backends/platform/android/touchcontrols.h
Normal file
@ -0,0 +1,73 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_TOUCHCONTROLS_H_
|
||||
#define ANDROID_TOUCHCONTROLS_H_
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
#include "common/events.h"
|
||||
|
||||
#include "backends/platform/android/events.h"
|
||||
#include "backends/platform/android/texture.h"
|
||||
|
||||
class TouchControls {
|
||||
public:
|
||||
TouchControls();
|
||||
~TouchControls();
|
||||
|
||||
void init(KeyReceiver *kr, int width, int height);
|
||||
void draw();
|
||||
void update(int ptr, int action, int x, int y);
|
||||
|
||||
private:
|
||||
int _screen_width, _screen_height;
|
||||
KeyReceiver *_key_receiver;
|
||||
|
||||
enum TouchArea{
|
||||
kTouchAreaJoystick = 0xffff,
|
||||
kTouchAreaCenter = 0xfffe,
|
||||
kTouchAreaRight = 0xfffd,
|
||||
kTouchAreaNone = 0xfffc,
|
||||
};
|
||||
|
||||
uint16 getTouchArea(int x, int y);
|
||||
|
||||
struct Pointer {
|
||||
uint16 startX, startY;
|
||||
uint16 currentX, currentY;
|
||||
TouchArea function;
|
||||
bool active;
|
||||
};
|
||||
|
||||
enum { kNumPointers = 5 };
|
||||
Pointer _pointers[kNumPointers];
|
||||
int _activePointers[4];
|
||||
Common::KeyCode _joystickPressing, _centerPressing, _rightPressing;
|
||||
int &pointerFor(TouchArea ta);
|
||||
GLESTexture *_arrows_texture;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -312,6 +312,7 @@ public:
|
||||
|
||||
//ResidualVM specific
|
||||
kFeatureOpenGL,
|
||||
kFeatureVirtControls,
|
||||
|
||||
/**
|
||||
* The presence of this feature indicates whether the displayLogFile()
|
||||
|
36
configure
vendored
36
configure
vendored
@ -104,7 +104,7 @@ _srcdir=`dirname $0`
|
||||
#
|
||||
#ResidualVM defaults: mpeg2=auto, faad=no, opengles=no, vorbis=no, tremor=no
|
||||
# mt32emu=no, translation=no, flac=no, seq_midi=no, snd_io=no, timidity=no, png=no
|
||||
# theoradec=no, fluidsynth=no
|
||||
# theoradec=no, fluidsynth=no, opengles2=no
|
||||
#
|
||||
# Default lib behaviour yes/no/auto
|
||||
_vorbis=no
|
||||
@ -125,6 +125,7 @@ _faad=no
|
||||
_fluidsynth=no
|
||||
_opengl=auto
|
||||
_opengles=no
|
||||
_opengles2=no
|
||||
_readline=auto
|
||||
_freetype2=auto
|
||||
_taskbar=yes
|
||||
@ -178,6 +179,8 @@ _nasmpath="$PATH"
|
||||
NASMFLAGS=""
|
||||
NASM=""
|
||||
_tainted_build=no
|
||||
# residualvm specific
|
||||
_android_sysroot_path=""
|
||||
# The following variables are automatically detected, and should not
|
||||
# be modified otherwise. Consider them read-only.
|
||||
_posix=no
|
||||
@ -1478,6 +1481,15 @@ android)
|
||||
echo "Please set ANDROID_NDK in your environment. export ANDROID_NDK=<path to Android NDK>"
|
||||
exit 1
|
||||
fi
|
||||
# residualvm specific
|
||||
if test ! -d android-toolchain; then
|
||||
echo "Installing Android toolchain to build directory..."
|
||||
"$ANDROID_NDK/build/tools/make-standalone-toolchain.sh" --platform=android-8 --install-dir=android-toolchain
|
||||
else
|
||||
echo "Android toolchain already installed."
|
||||
fi
|
||||
PATH="android-toolchain/bin:$PATH"
|
||||
_android_sysroot_path="android-toolchain/bin:"
|
||||
;;
|
||||
bada)
|
||||
if test -z "$BADA_SDK"; then
|
||||
@ -1990,7 +2002,7 @@ case $_host_os in
|
||||
;;
|
||||
esac
|
||||
# ResidualVM use newer NDK
|
||||
CXXFLAGS="$CXXFLAGS --sysroot=$ANDROID_NDK/platforms/android-5/arch-arm"
|
||||
CXXFLAGS="$CXXFLAGS --sysroot=$ANDROID_NDK/platforms/android-8/arch-arm"
|
||||
CXXFLAGS="$CXXFLAGS -fpic"
|
||||
CXXFLAGS="$CXXFLAGS -ffunction-sections"
|
||||
CXXFLAGS="$CXXFLAGS -funwind-tables"
|
||||
@ -2012,7 +2024,7 @@ case $_host_os in
|
||||
# supress 'mangling of 'va_list' has changed in GCC 4.4'
|
||||
CXXFLAGS="$CXXFLAGS -Wno-psabi"
|
||||
# ResidualVM use newer NDK
|
||||
LDFLAGS="$LDFLAGS --sysroot=$ANDROID_NDK/platforms/android-5/arch-arm"
|
||||
LDFLAGS="$LDFLAGS --sysroot=$ANDROID_NDK/platforms/android-8/arch-arm"
|
||||
LDFLAGS="$LDFLAGS -mthumb-interwork"
|
||||
add_line_to_config_mk "ANDROID_SDK = $ANDROID_SDK"
|
||||
_seq_midi=no
|
||||
@ -2656,6 +2668,8 @@ case $_backend in
|
||||
CXXFLAGS="$CXXFLAGS -Wa,--noexecstack"
|
||||
LDFLAGS="$LDFLAGS -Wl,-z,noexecstack"
|
||||
INCLUDES="$INCLUDES -I$ANDROID_NDK/sources/cxx-stl/system/include"
|
||||
DEFINES="$DEFINES -DANDROID_BACKEND"
|
||||
add_line_to_config_mk "ANDROID_BACKEND = 1"
|
||||
;;
|
||||
bada)
|
||||
# dirent.h not available. NONSTANDARD_PORT==ensure portdefs.h is included
|
||||
@ -3701,6 +3715,8 @@ EOF
|
||||
break
|
||||
fi
|
||||
done
|
||||
elif test "$_opengles2" = "yes" ; then
|
||||
OPENGL_LIBS="$OPENGL_LIBS -lGLESv2"
|
||||
else
|
||||
case $_host_os in
|
||||
darwin*)
|
||||
@ -3732,16 +3748,24 @@ case $_host_os in
|
||||
_opengl=yes
|
||||
_opengles=yes
|
||||
;;
|
||||
android)
|
||||
_opengles2=yes
|
||||
LDFLAGS="$LDFLAGS -Landroid-toolchain/sysroot/usr/lib"
|
||||
LDFLAGS="$LDFLAGS -lGLESv2"
|
||||
;;
|
||||
esac
|
||||
|
||||
if test "$_opengles" = "yes" ; then
|
||||
echo "yes (OpenGL ES)"
|
||||
elif test "$_opengles2" = "yes" ; then
|
||||
echo "yes (OpenGL ES2)"
|
||||
else
|
||||
echo "$_opengl"
|
||||
fi
|
||||
|
||||
define_in_config_if_yes "$_opengl" "USE_OPENGL"
|
||||
define_in_config_if_yes "$_opengles" "USE_GLES"
|
||||
define_in_config_if_yes "$_opengles2" "USE_GLES2"
|
||||
|
||||
|
||||
#
|
||||
@ -4016,7 +4040,10 @@ case $_backend in
|
||||
# -lgcc is carefully placed here - we want to catch
|
||||
# all toolchain symbols in *our* libraries rather
|
||||
# than pick up anything unhygenic from the Android libs.
|
||||
LIBS="-Wl,-Bstatic $static_libs -Wl,-Bdynamic -lgcc $system_libs -llog -lGLESv1_CM"
|
||||
LIBS="-Wl,-Bstatic $static_libs -Wl,-Bdynamic -lgcc $system_libs -llog"
|
||||
if test "$_opengles2" != "yes" ; then
|
||||
LIBS="$LIBS -lGLESv1_CM"
|
||||
fi
|
||||
;;
|
||||
n64)
|
||||
# Move some libs down here, otherwise some symbols requires by libvorbis aren't found
|
||||
@ -4212,6 +4239,7 @@ STAGINGPATH=$_stagingpath
|
||||
WIN32PATH=$_win32path
|
||||
AOS4PATH=$_aos4path
|
||||
STATICLIBPATH=$_staticlibpath
|
||||
PATH := ${_android_sysroot_path}\$(PATH)
|
||||
|
||||
BACKEND := $_backend
|
||||
MODULES += $MODULES
|
||||
|
@ -3,14 +3,12 @@
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.residualvm.residualvm"
|
||||
android:versionCode="@ANDROID_VERSIONCODE@"
|
||||
android:versionCode="1000"
|
||||
android:versionName="0.2.0git"
|
||||
android:installLocation="preferExternal"
|
||||
android:sharedUserId="org.residualvm.residualvm">
|
||||
|
||||
<!-- This version works on Android 1.5 (SDK 3) and newer, but we
|
||||
want Android 2.2 (SDK 8) defaults and features. -->
|
||||
<uses-sdk android:minSdkVersion="5"
|
||||
<uses-sdk android:minSdkVersion="8"
|
||||
android:targetSdkVersion="8"/>
|
||||
|
||||
<application android:name=".ResidualVMApplication"
|
||||
@ -47,6 +45,7 @@
|
||||
android:protectionLevel="signature"/>
|
||||
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<!-- Always needs some sort of qwerty keyboard.
|
||||
Can work with a D-pad / trackball -->
|
||||
@ -59,4 +58,6 @@
|
||||
|
||||
<uses-configuration android:reqTouchScreen="stylus"
|
||||
android:reqKeyboardType="qwerty"/>
|
||||
|
||||
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
|
||||
</manifest>
|
||||
|
@ -8,14 +8,13 @@
|
||||
android:installLocation="preferExternal"
|
||||
android:sharedUserId="org.residualvm.residualvm">
|
||||
|
||||
<!-- This version works on Android 1.5 (SDK 3) and newer, but we
|
||||
want Android 2.2 (SDK 8) defaults and features. -->
|
||||
<uses-sdk android:minSdkVersion="5"
|
||||
<uses-sdk android:minSdkVersion="8"
|
||||
android:targetSdkVersion="8"/>
|
||||
|
||||
<application android:name=".ResidualVMApplication"
|
||||
android:label="@string/app_name"
|
||||
android:description="@string/app_desc"
|
||||
android:debuggable="true"
|
||||
android:icon="@drawable/residualvm">
|
||||
<activity android:name=".ResidualVMActivity"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
||||
@ -47,6 +46,8 @@
|
||||
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
|
||||
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
|
||||
|
||||
<!-- Always needs some sort of qwerty keyboard.
|
||||
Can work with a D-pad / trackball -->
|
||||
<uses-configuration android:reqFiveWayNav="true"
|
||||
|
BIN
dists/android/assets/arrows.tga
Normal file
BIN
dists/android/assets/arrows.tga
Normal file
Binary file not shown.
After Width: | Height: | Size: 512 KiB |
114
dists/android/build.xml
Normal file
114
dists/android/build.xml
Normal file
@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="ResidualVM" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- The project.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
|
||||
This contains project specific properties such as project target, and library
|
||||
dependencies. Lower level build properties are stored in ant.properties
|
||||
(or in .classpath for Eclipse projects).
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var"
|
||||
unless="sdk.dir"
|
||||
/>
|
||||
|
||||
|
||||
<!-- extension targets. Uncomment the ones where you want to do custom work
|
||||
in between standard targets -->
|
||||
<!--
|
||||
<target name="-pre-build">
|
||||
</target>
|
||||
<target name="-pre-compile">
|
||||
</target>
|
||||
|
||||
/* This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir} */
|
||||
<target name="-post-compile">
|
||||
</target>
|
||||
-->
|
||||
|
||||
<!-- Override the built-in aapt task, don't compress assets. -->
|
||||
<target name="-package-resources" depends="-crunch">
|
||||
<!-- only package resources if *not* a library project -->
|
||||
<do-only-if-not-library elseText="Library project: do not package resources..." >
|
||||
<aapt executable="${aapt}"
|
||||
command="package"
|
||||
versioncode="${version.code}"
|
||||
versionname="${version.name}"
|
||||
debug="${build.is.packaging.debug}"
|
||||
manifest="${out.manifest.abs.file}"
|
||||
assets="${asset.absolute.dir}"
|
||||
androidjar="${project.target.android.jar}"
|
||||
apkfolder="${out.absolute.dir}"
|
||||
nocrunch="${build.packaging.nocrunch}"
|
||||
resourcefilename="${resource.package.file.name}"
|
||||
resourcefilter="${aapt.resource.filter}"
|
||||
libraryResFolderPathRefid="project.library.res.folder.path"
|
||||
libraryPackagesRefid="project.library.packages"
|
||||
libraryRFileRefid="project.library.bin.r.file.path"
|
||||
previousBuildType="${build.last.target}"
|
||||
buildType="${build.target}"
|
||||
ignoreAssets="${aapt.ignore.assets}">
|
||||
<res path="${out.res.absolute.dir}" />
|
||||
<res path="${resource.absolute.dir}" />
|
||||
<nocompress /> <!-- forces no compression on any files in assets or res/raw -->
|
||||
</aapt>
|
||||
</do-only-if-not-library>
|
||||
</target>
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<!-- version-tag: custom -->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
</project>
|
9
dists/android/jni/Android.mk
Normal file
9
dists/android/jni/Android.mk
Normal file
@ -0,0 +1,9 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
APP_ABI := armeabi
|
||||
LOCAL_MODULE := residualvm
|
||||
LOCAL_SRC_FILES := ../libresidualvm.so
|
||||
|
||||
include $(PREBUILT_SHARED_LIBRARY)
|
20
dists/android/proguard-project.txt
Normal file
20
dists/android/proguard-project.txt
Normal file
@ -0,0 +1,20 @@
|
||||
# To enable ProGuard in your project, edit project.properties
|
||||
# to define the proguard.config property as described in that file.
|
||||
#
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in ${sdk.dir}/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the ProGuard
|
||||
# include property in project.properties.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
40
dists/android/proguard.cfg
Normal file
40
dists/android/proguard.cfg
Normal file
@ -0,0 +1,40 @@
|
||||
-optimizationpasses 5
|
||||
-dontusemixedcaseclassnames
|
||||
-dontskipnonpubliclibraryclasses
|
||||
-dontpreverify
|
||||
-verbose
|
||||
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||
|
||||
-keep public class * extends android.app.Activity
|
||||
-keep public class * extends android.app.Application
|
||||
-keep public class * extends android.app.Service
|
||||
-keep public class * extends android.content.BroadcastReceiver
|
||||
-keep public class * extends android.content.ContentProvider
|
||||
-keep public class * extends android.app.backup.BackupAgentHelper
|
||||
-keep public class * extends android.preference.Preference
|
||||
-keep public class com.android.vending.licensing.ILicensingService
|
||||
|
||||
-keepclasseswithmembernames class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
}
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
}
|
||||
|
||||
-keepclassmembers class * extends android.app.Activity {
|
||||
public void *(android.view.View);
|
||||
}
|
||||
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
-keep class * implements android.os.Parcelable {
|
||||
public static final android.os.Parcelable$Creator *;
|
||||
}
|
11
dists/android/project.properties
Normal file
11
dists/android/project.properties
Normal file
@ -0,0 +1,11 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system use,
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
|
||||
# Project target.
|
||||
target=android-8
|
6
dists/android/res/menu/game_menu.xml
Normal file
6
dists/android/res/menu/game_menu.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item android:id="@+id/show_menu" android:titleCondensed="Menu" android:title="Show menu..."></item>
|
||||
|
||||
|
||||
</menu>
|
@ -21,6 +21,10 @@ MODULE_OBJS := \
|
||||
decoders/jpeg.o \
|
||||
decoders/tga.o \
|
||||
pixelbuffer.o \
|
||||
opengles2/shader.o \
|
||||
opengles2/box_shaders.o \
|
||||
opengles2/control_shaders.o \
|
||||
opengles2/compat_shaders.o \
|
||||
tinygl/api.o \
|
||||
tinygl/arrays.o \
|
||||
tinygl/clear.o \
|
||||
|
65
graphics/opengles2/box_shaders.cpp
Normal file
65
graphics/opengles2/box_shaders.cpp
Normal file
@ -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 *boxVertex =
|
||||
"#version 100\n"
|
||||
"attribute vec2 position;\n"
|
||||
"attribute vec2 texcoord;\n"
|
||||
"uniform vec2 offsetXY;\n"
|
||||
"uniform vec2 sizeWH;\n"
|
||||
"uniform vec2 texcrop;\n"
|
||||
"uniform bool flipY;\n"
|
||||
"varying vec2 Texcoord;\n"
|
||||
"void main() {\n"
|
||||
"Texcoord = texcoord * texcrop;\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 *boxFragment =
|
||||
"#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
|
57
graphics/opengles2/compat_shaders.cpp
Normal file
57
graphics/opengles2/compat_shaders.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
/* 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 *compatVertex =
|
||||
"#ifdef GL_ES\n"
|
||||
"mediump float round(in mediump float x) {\n"
|
||||
" return sign(x) * floor(abs(x) + .5);\n"
|
||||
"}\n"
|
||||
"#define in attribute\n"
|
||||
"#define out varying\n"
|
||||
"#endif\n";
|
||||
|
||||
const char *compatFragment =
|
||||
"#ifdef GL_ES\n"
|
||||
"#define in varying\n"
|
||||
"#ifdef GL_FRAGMENT_PRECISION_HIGH\n"
|
||||
"precision highp float;\n"
|
||||
"#else\n"
|
||||
"precision mediump float;\n"
|
||||
"#endif\n"
|
||||
"#define OUTPUT\n"
|
||||
"#define outColor gl_FragColor\n"
|
||||
"#define texture texture2D\n"
|
||||
"#else\n"
|
||||
"#define OUTPUT out vec4 outColor;\n"
|
||||
"#endif\n";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
65
graphics/opengles2/control_shaders.cpp
Normal file
65
graphics/opengles2/control_shaders.cpp
Normal file
@ -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
|
201
graphics/opengles2/shader.cpp
Normal file
201
graphics/opengles2/shader.cpp
Normal file
@ -0,0 +1,201 @@
|
||||
/* 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
|
||||
|
||||
#include "graphics/opengles2/shader.h"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
static const GLchar *readFile(const Common::String &filename) {
|
||||
Common::File file;
|
||||
file.open(Common::String("shaders/") + filename);
|
||||
if (!file.isOpen())
|
||||
error("Could not open shader %s!", filename.c_str());
|
||||
|
||||
const int32 size = file.size();
|
||||
GLchar *shaderSource = new GLchar[size + 1];
|
||||
|
||||
file.read(shaderSource, size);
|
||||
file.close();
|
||||
shaderSource[size] = '\0';
|
||||
return shaderSource;
|
||||
}
|
||||
|
||||
static GLuint createDirectShader(const char *shaderSource, GLenum shaderType, const Common::String &name) {
|
||||
GLuint shader = glCreateShader(shaderType);
|
||||
glShaderSource(shader, 1, &shaderSource, NULL);
|
||||
glCompileShader(shader);
|
||||
|
||||
GLint status;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
||||
if (status != GL_TRUE) {
|
||||
char buffer[512];
|
||||
glGetShaderInfoLog(shader, 512, NULL, buffer);
|
||||
error("Could not compile shader %s: %s", name.c_str(), buffer);
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
static GLuint createCompatShader(const char *shaderSource, GLenum shaderType, const Common::String &name) {
|
||||
const GLchar *compatSource =
|
||||
shaderType == GL_VERTEX_SHADER ? Graphics::BuiltinShaders::compatVertex : Graphics::BuiltinShaders::compatFragment;
|
||||
const GLchar *shaderSources[] = {
|
||||
"#version 100\n",
|
||||
compatSource,
|
||||
shaderSource
|
||||
};
|
||||
|
||||
GLuint shader = glCreateShader(shaderType);
|
||||
glShaderSource(shader, 3, shaderSources, NULL);
|
||||
glCompileShader(shader);
|
||||
|
||||
GLint status;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
||||
if (status != GL_TRUE) {
|
||||
char buffer[512];
|
||||
glGetShaderInfoLog(shader, 512, NULL, buffer);
|
||||
error("Could not compile shader %s: %s", name.c_str(), buffer);
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
static GLuint loadShaderFromFile(const char *base, const char *extension, GLenum shaderType) {
|
||||
const Common::String filename = Common::String(base) + "." + extension;
|
||||
const GLchar *shaderSource = readFile(filename);
|
||||
|
||||
GLuint shader = createCompatShader(shaderSource, shaderType, filename);
|
||||
|
||||
delete[] shaderSource;
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
Shader::Shader(const Common::String &name, GLuint vertexShader, GLuint fragmentShader, const char **attributes)
|
||||
: _name(name) {
|
||||
assert(attributes);
|
||||
GLuint shaderProgram = glCreateProgram();
|
||||
glAttachShader(shaderProgram, vertexShader);
|
||||
glAttachShader(shaderProgram, fragmentShader);
|
||||
|
||||
for (int idx = 0; attributes[idx]; ++idx) {
|
||||
glBindAttribLocation(shaderProgram, idx, attributes[idx]);
|
||||
_attributes.push_back(VertexAttrib(idx, attributes[idx]));
|
||||
}
|
||||
glLinkProgram(shaderProgram);
|
||||
|
||||
_shaderNo = shaderProgram;
|
||||
_uniforms = new Common::HashMap<Common::String, GLint>();
|
||||
}
|
||||
|
||||
Shader *Shader::fromStrings(const Common::String &name, const char *vertex, const char *fragment, const char **attributes) {
|
||||
GLuint vertexShader = createDirectShader(vertex, GL_VERTEX_SHADER, name + ".vertex");
|
||||
GLuint fragmentShader = createDirectShader(fragment, GL_FRAGMENT_SHADER, name + ".fragment");
|
||||
return new Shader(name, vertexShader, fragmentShader, attributes);
|
||||
}
|
||||
|
||||
|
||||
Shader *Shader::fromFiles(const char *vertex, const char *fragment, const char **attributes) {
|
||||
GLuint vertexShader = loadShaderFromFile(vertex, "vertex", GL_VERTEX_SHADER);
|
||||
GLuint fragmentShader = loadShaderFromFile(fragment, "fragment", GL_FRAGMENT_SHADER);
|
||||
|
||||
Common::String name = Common::String::format("%s/%s", vertex, fragment);
|
||||
return new Shader(name, vertexShader, fragmentShader, attributes);
|
||||
}
|
||||
|
||||
void Shader::use() {
|
||||
static Shader *previousShader = NULL;
|
||||
if (this == previousShader)
|
||||
return;
|
||||
previousShader = this;
|
||||
|
||||
glUseProgram(_shaderNo);
|
||||
for (uint32 i = 0; i < _attributes.size(); ++i) {
|
||||
Graphics::VertexAttrib &attrib = _attributes[i];
|
||||
if (attrib._enabled) {
|
||||
glEnableVertexAttribArray(i);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, attrib._vbo);
|
||||
glVertexAttribPointer(i, attrib._size, attrib._type, attrib._normalized, attrib._stride, attrib._offset);
|
||||
} else {
|
||||
glDisableVertexAttribArray(i);
|
||||
switch (attrib._size) {
|
||||
case 2:
|
||||
glVertexAttrib2fv(i, attrib._const);
|
||||
break;
|
||||
case 3:
|
||||
glVertexAttrib3fv(i, attrib._const);
|
||||
break;
|
||||
case 4:
|
||||
glVertexAttrib4fv(i, attrib._const);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GLuint Shader::createBuffer(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) {
|
||||
GLuint vbo;
|
||||
glGenBuffers(1, &vbo);
|
||||
glBindBuffer(target, vbo);
|
||||
glBufferData(target, size, data, usage);
|
||||
return vbo;
|
||||
}
|
||||
|
||||
VertexAttrib &Shader::getAttributeAt(uint32 idx) {
|
||||
assert(idx < _attributes.size());
|
||||
return _attributes[idx];
|
||||
}
|
||||
|
||||
VertexAttrib &Shader::getAttribute(const char *attrib) {
|
||||
for (uint32 i = 0; i < _attributes.size(); ++i)
|
||||
if (_attributes[i]._name.equals(attrib))
|
||||
return _attributes[i];
|
||||
error("Could not find attribute %s in shader %s", attrib, _name.c_str());
|
||||
return _attributes[0];
|
||||
}
|
||||
|
||||
void Shader::enableVertexAttribute(const char *attrib, GLuint vbo, GLint size, GLenum type, GLboolean normalized, GLsizei stride, uint32 offset) {
|
||||
VertexAttrib &va = getAttribute(attrib);
|
||||
va._enabled = true;
|
||||
va._vbo = vbo;
|
||||
va._size = size;
|
||||
va._type = type;
|
||||
va._normalized = normalized;
|
||||
va._stride = stride;
|
||||
va._offset = (const GLvoid *) offset;
|
||||
}
|
||||
|
||||
void Shader::disableVertexAttribute(const char *attrib, int size, const float *data) {
|
||||
VertexAttrib &va = getAttribute(attrib);
|
||||
va._enabled = false;
|
||||
va._size = size;
|
||||
for (int i = 0; i < size; ++i)
|
||||
va._const[i] = data[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
148
graphics/opengles2/shader.h
Normal file
148
graphics/opengles2/shader.h
Normal file
@ -0,0 +1,148 @@
|
||||
/* 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/file.h"
|
||||
#include "common/array.h"
|
||||
|
||||
#include "math/matrix3.h"
|
||||
#include "math/matrix4.h"
|
||||
#include "math/vector2d.h"
|
||||
#include "math/vector3d.h"
|
||||
#include "math/vector4d.h"
|
||||
|
||||
#include "graphics/opengles2/system_headers.h"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
namespace BuiltinShaders {
|
||||
extern const char *boxVertex, *boxFragment;
|
||||
extern const char *compatVertex, *compatFragment;
|
||||
extern const char *controlVertex, *controlFragment;
|
||||
}
|
||||
|
||||
struct VertexAttrib {
|
||||
VertexAttrib(uint32 idx, const char *name) : _enabled(false), _idx(idx), _name(name), _vbo(0), _size(0), _type(GL_FLOAT), _normalized(false), _stride(0), _offset(NULL) {}
|
||||
bool _enabled;
|
||||
uint32 _idx;
|
||||
Common::String _name;
|
||||
GLuint _vbo;
|
||||
GLint _size;
|
||||
GLenum _type;
|
||||
bool _normalized;
|
||||
GLsizei _stride;
|
||||
const GLvoid *_offset;
|
||||
float _const[4];
|
||||
};
|
||||
|
||||
class Shader {
|
||||
typedef Common::HashMap<Common::String, GLint> UniformsMap;
|
||||
|
||||
public:
|
||||
Shader* clone() {
|
||||
return new Shader(*this);
|
||||
}
|
||||
|
||||
void use();
|
||||
|
||||
void setUniform(const char *uniform, const Math::Matrix4 &m) {
|
||||
GLint pos = getUniformLocation(uniform);
|
||||
if (pos != -1)
|
||||
glUniformMatrix4fv(pos, 1, GL_FALSE, m.getData());
|
||||
}
|
||||
|
||||
void setUniform(const char* uniform, const Math::Matrix3 &m) {
|
||||
GLint pos = getUniformLocation(uniform);
|
||||
if (pos != -1)
|
||||
glUniformMatrix3fv(pos, 1, GL_FALSE, m.getData());
|
||||
}
|
||||
|
||||
void setUniform(const char *uniform, const Math::Vector4d &v) {
|
||||
GLint pos = getUniformLocation(uniform);
|
||||
if (pos != -1)
|
||||
glUniform4fv(pos, 1, v.getData());
|
||||
}
|
||||
|
||||
void setUniform(const char *uniform, const Math::Vector3d &v) {
|
||||
GLint pos = getUniformLocation(uniform);
|
||||
if (pos != -1)
|
||||
glUniform3fv(pos, 1, v.getData());
|
||||
}
|
||||
|
||||
void setUniform(const char *uniform, const Math::Vector2d &v) {
|
||||
GLint pos = getUniformLocation(uniform);
|
||||
if (pos != -1)
|
||||
glUniform2fv(pos, 1, v.getData());
|
||||
}
|
||||
|
||||
void setUniform(const char *uniform, unsigned int x) {
|
||||
GLint pos = getUniformLocation(uniform);
|
||||
if (pos != -1)
|
||||
glUniform1i(pos, x);
|
||||
}
|
||||
|
||||
// Different name to avoid overload ambiguity
|
||||
void setUniform1f(const char *uniform, float f) {
|
||||
GLint pos = getUniformLocation(uniform);
|
||||
if (pos != -1)
|
||||
glUniform1f(pos, f);
|
||||
}
|
||||
|
||||
|
||||
GLint getUniformLocation(const char *uniform) const {
|
||||
UniformsMap::iterator kv = _uniforms->find(uniform);
|
||||
if (kv == _uniforms->end()) {
|
||||
GLint ret = glGetUniformLocation(_shaderNo, uniform);
|
||||
_uniforms->setVal(uniform, ret);
|
||||
return ret;
|
||||
} else {
|
||||
return kv->_value;
|
||||
}
|
||||
}
|
||||
|
||||
void enableVertexAttribute(const char *attrib, GLuint vbo, GLint size, GLenum type, GLboolean normalized, GLsizei stride, uint32 offset);
|
||||
void disableVertexAttribute(const char *attrib, int size, const float *data);
|
||||
template <int r>
|
||||
void disableVertexAttribute(const char *attrib, const Math::Matrix<r,1> &m) {
|
||||
disableVertexAttribute(attrib, r, m.getData());
|
||||
}
|
||||
VertexAttrib & getAttributeAt(uint32 idx);
|
||||
VertexAttrib & getAttribute(const char *attrib);
|
||||
|
||||
static GLuint createBuffer(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage = GL_STATIC_DRAW);
|
||||
|
||||
static Shader* fromFiles(const char *vertex, const char *fragment, const char **attributes);
|
||||
static Shader* fromFiles(const char *shared, const char **attributes) {
|
||||
return fromFiles(shared, shared, attributes);
|
||||
}
|
||||
|
||||
static Shader* fromStrings(const Common::String &name, const char *vertex, const char *fragment, const char **attributes);
|
||||
|
||||
private:
|
||||
Shader(const Common::String &name, GLuint vertexShader, GLuint fragmentShader, const char **attributes);
|
||||
GLuint _shaderNo;
|
||||
Common::String _name;
|
||||
|
||||
Common::Array<VertexAttrib> _attributes;
|
||||
UniformsMap *_uniforms;
|
||||
};
|
||||
|
||||
}
|
52
graphics/opengles2/system_headers.h
Normal file
52
graphics/opengles2/system_headers.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRAPHICS_SYSTEM_HEADERS_H
|
||||
#define GRAPHICS_SYSTEM_HEADERS_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#ifdef USE_GLES2
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#ifdef IPHONE
|
||||
#include <OpenGLES/ES2/gl.h>
|
||||
#include <OpenGLES/ES2/glext.h>
|
||||
#else
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
#endif
|
||||
#undef GL_GLEXT_PROTOTYPES
|
||||
|
||||
#define glMapBuffer glMapBufferOES
|
||||
#define glUnmapBuffer glUnmapBufferOES
|
||||
#define GL_WRITE_ONLY GL_WRITE_ONLY_OES
|
||||
|
||||
#ifndef GL_BGRA
|
||||
# define GL_BGRA GL_BGRA_EXT
|
||||
#endif
|
||||
|
||||
#else
|
||||
#include <GL/glew.h>
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user