Added the Android port

This commit is contained in:
Jonathan De Wachter 2013-08-25 20:39:55 +02:00
parent 01b745185e
commit 63bbe2c91e
183 changed files with 40166 additions and 40 deletions

53
src/SFML/Android.mk Normal file
View file

@ -0,0 +1,53 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := sfml-system
LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libsfml-system.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := sfml-window
LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libsfml-window.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_EXPORT_LDLIBS := -lEGL
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := sfml-graphics
LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libsfml-graphics.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_EXPORT_LDLIBS := -lGLESv1_CM
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/extlibs/include
LOCAL_STATIC_LIBRARIES := jpeg freetype
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := sfml-audio
LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libsfml-audio.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/extlibs/include
LOCAL_WHOLE_STATIC_LIBRARIES := ogg vorbis vorbisenc flac sndfile openal
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := sfml-network
LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libsfml-network.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := sfml-main
LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libsfml-main.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
$(call import-module,sfml/extlibs)

View file

@ -31,8 +31,13 @@
#include <SFML/Config.hpp>
#include <iostream>
#include <string>
#include <al.h>
#include <alc.h>
#ifndef SFML_SYSTEM_ANDROID
#include <al.h>
#include <alc.h>
#else
#include <AL/al.h>
#include <AL/alc.h>
#endif
namespace sf

20
src/SFML/Audio/Android.mk Normal file
View file

@ -0,0 +1,20 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := sfml-audio
LOCAL_SRC_FILES := ALCheck.cpp
LOCAL_SRC_FILES += AudioDevice.cpp
LOCAL_SRC_FILES += Listener.cpp
LOCAL_SRC_FILES += Music.cpp
LOCAL_SRC_FILES += Sound.cpp
LOCAL_SRC_FILES += SoundBuffer.cpp
LOCAL_SRC_FILES += SoundBufferRecorder.cpp
LOCAL_SRC_FILES += SoundFile.cpp
LOCAL_SRC_FILES += SoundRecorder.cpp
LOCAL_SRC_FILES += SoundSource.cpp
LOCAL_SRC_FILES += SoundStream.cpp
include $(BUILD_STATIC_LIBRARY)
$(call import-module,extlibs)

View file

@ -29,7 +29,7 @@ set(SRC
${INCROOT}/SoundStream.hpp
)
source_group("" FILES ${SRC})
if(NOT ANDROID)
# let CMake know about our additional audio libraries paths (on Windows and OSX)
if(SFML_OS_WINDOWS)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/AL")
@ -45,7 +45,7 @@ find_package(Sndfile REQUIRED)
# add include paths of external libraries
include_directories(${OPENAL_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR})
endif()
# define the sfml-audio target
sfml_add_library(sfml-audio
SOURCES ${SRC}

View file

@ -28,6 +28,10 @@
#include <SFML/Audio/SoundFile.hpp>
#include <SFML/System/InputStream.hpp>
#include <SFML/System/Err.hpp>
#ifdef SFML_SYSTEM_ANDROID
#include <SFML/System/Lock.hpp>
#include <SFML/Main/activity.hpp>
#endif
#include <cstring>
#include <cctype>
@ -91,6 +95,8 @@ unsigned int SoundFile::getSampleRate() const
////////////////////////////////////////////////////////////
bool SoundFile::openRead(const std::string& filename)
{
#ifndef SFML_SYSTEM_ANDROID
// If the file is already opened, first close it
if (m_file)
sf_close(m_file);
@ -109,6 +115,44 @@ bool SoundFile::openRead(const std::string& filename)
initialize(fileInfo);
return true;
#else
priv::ActivityStates* states = priv::getActivityStates(NULL);
Lock lock(states->mutex);
// Open the file
AAsset* file = NULL;
file = AAssetManager_open(states->activity->assetManager, filename.c_str(), AASSET_MODE_UNKNOWN);
if (!file)
{
// File not found, abording...
err() << "Failed to load sound \"" << filename << "\" (couldn't find it)" << std::endl;
return false;
}
// Copy into memory
off_t size = AAsset_getLength(file);
void* data = malloc(size);
int status = AAsset_read(file, data, size);
if (status <= 0)
{
// Something went wrong while we were copying, reading error...
err() << "Failed to load sound \"" << filename << "\" (couldn't read it)" << std::endl;
return false;
}
// Load from our fresh memory
bool ret = openRead(data, size);
// Close the file
AAsset_close(file);
return ret;
#endif
}

View file

@ -44,7 +44,7 @@ add_subdirectory(Network)
add_subdirectory(Graphics)
if(NOT SFML_OS_IOS)
add_subdirectory(Audio)
endif()
if(SFML_OS_WINDOWS)
endif()
if(SFML_OS_WINDOWS OR SFML_OS_ANDROID)
add_subdirectory(Main)
endif()

View file

@ -0,0 +1,38 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := sfml-graphics
LOCAL_SRC_FILES := Color.cpp
LOCAL_SRC_FILES += GLCheck.cpp
LOCAL_SRC_FILES += GLExtensions.cpp
LOCAL_SRC_FILES += Image.cpp
LOCAL_SRC_FILES += ImageLoader.cpp
LOCAL_SRC_FILES += RenderStates.cpp
LOCAL_SRC_FILES += RenderTexture.cpp
LOCAL_SRC_FILES += RenderTarget.cpp
LOCAL_SRC_FILES += RenderWindow.cpp
LOCAL_SRC_FILES += Shader.cpp
LOCAL_SRC_FILES += Texture.cpp
LOCAL_SRC_FILES += TextureSaver.cpp
LOCAL_SRC_FILES += Transform.cpp
LOCAL_SRC_FILES += Transformable.cpp
LOCAL_SRC_FILES += View.cpp
LOCAL_SRC_FILES += Vertex.cpp
LOCAL_SRC_FILES += Shape.cpp
LOCAL_SRC_FILES += CircleShape.cpp
LOCAL_SRC_FILES += RectangleShape.cpp
LOCAL_SRC_FILES += ConvexShape.cpp
LOCAL_SRC_FILES += Sprite.cpp
LOCAL_SRC_FILES += Font.cpp
LOCAL_SRC_FILES += Text.cpp
LOCAL_SRC_FILES += VertexArray.cpp
LOCAL_SRC_FILES += RenderTextureImpl.cpp
LOCAL_SRC_FILES += RenderTextureImplFBO.cpp
LOCAL_SRC_FILES += RenderTextureImplDefault.cpp
LOCAL_CPPFLAGS := -DGL_GLEXT_PROTOTYPES -DSFML_OPENGL_ES
include $(BUILD_STATIC_LIBRARY)
$(call import-module,extlibs)

View file

@ -104,8 +104,8 @@ elseif(SFML_OS_IOS)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/ios/freetype2")
endif()
# find external libraries
if(NOT IOS)
# find external libraries
if(NOT OPENGL_ES)
find_package(OpenGL REQUIRED)
find_package(Freetype REQUIRED)
find_package(GLEW REQUIRED)
@ -121,7 +121,9 @@ if(NOT IOS)
if(SFML_OS_LINUX)
set(GRAPHICS_EXT_LIBS ${GRAPHICS_EXT_LIBS} ${X11_LIBRARIES})
endif()
else()
endif()
if(IOS)
find_host_package(JPEG REQUIRED)
find_host_package(Freetype REQUIRED)
set(GRAPHICS_EXT_INCLUDE_PATHS ${FREETYPE_INCLUDE_DIRS} ${JPEG_INCLUDE_DIR})

View file

@ -29,6 +29,10 @@
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/System/InputStream.hpp>
#include <SFML/System/Err.hpp>
#ifdef SFML_SYSTEM_ANDROID
#include <SFML/System/Lock.hpp>
#include <SFML/Main/activity.hpp>
#endif
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
@ -102,6 +106,8 @@ Font::~Font()
////////////////////////////////////////////////////////////
bool Font::loadFromFile(const std::string& filename)
{
#ifndef SFML_SYSTEM_ANDROID
// Cleanup the previous resources
cleanup();
m_refCount = new int(1);
@ -140,6 +146,44 @@ bool Font::loadFromFile(const std::string& filename)
m_info.family = face->family_name ? face->family_name : std::string();
return true;
#else
priv::ActivityStates* states = priv::getActivityStates(NULL);
Lock lock(states->mutex);
// Open the file
AAsset* file = NULL;
file = AAssetManager_open(states->activity->assetManager, filename.c_str(), AASSET_MODE_UNKNOWN);
if (!file)
{
// File not found, abording...
err() << "Failed to load font \"" << filename << "\" (couldn't find it)" << std::endl;
return false;
}
// Copy into memory
off_t size = AAsset_getLength(file);
void* data = malloc(size);
int status = AAsset_read(file, data, size);
if (status <= 0)
{
// Something went wrong while we were copying, reading error...
err() << "Failed to load font \"" << filename << "\" (couldn't read it)" << std::endl;
return false;
}
// Load from our fresh memory
bool ret = loadFromMemory(data, size);
// Close the file
AAsset_close(file);
return ret;
#endif
}

View file

@ -35,7 +35,7 @@ namespace priv
////////////////////////////////////////////////////////////
void ensureExtensionsInit()
{
#ifndef SFML_SYSTEM_IOS
#if !(defined SFML_SYSTEM_IOS || defined SFML_SYSTEM_ANDROID)
static bool initialized = false;
if (!initialized)
{

View file

@ -28,6 +28,10 @@
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/ImageLoader.hpp>
#include <SFML/System/Err.hpp>
#ifdef SFML_SYSTEM_ANDROID
#include <SFML/System/Lock.hpp>
#include <SFML/Main/activity.hpp>
#endif
#include <algorithm>
#include <cstring>
@ -102,7 +106,47 @@ void Image::create(unsigned int width, unsigned int height, const Uint8* pixels)
////////////////////////////////////////////////////////////
bool Image::loadFromFile(const std::string& filename)
{
#ifndef SFML_SYSTEM_ANDROID
return priv::ImageLoader::getInstance().loadImageFromFile(filename, m_pixels, m_size);
#else
priv::ActivityStates* states = priv::getActivityStates(NULL);
Lock lock(states->mutex);
// Open the file
AAsset* file = NULL;
file = AAssetManager_open(states->activity->assetManager, filename.c_str(), AASSET_MODE_UNKNOWN);
if (!file)
{
// File not found, abording...
err() << "Failed to load image \"" << filename << "\" (couldn't find it)" << std::endl;
return false;
}
// Copy into memory
off_t size = AAsset_getLength(file);
void* data = malloc(size);
int status = AAsset_read(file, data, size);
if (status <= 0)
{
// Something went wrong while we were copying, reading error...
err() << "Failed to load image \"" << filename << "\" (couldn't read it)" << std::endl;
return false;
}
// Load from our fresh memory
bool ret = loadFromMemory(data, size);
// Close the file
AAsset_close(file);
return ret;
#endif
}

View file

@ -166,6 +166,7 @@ void RenderTarget::draw(const Vertex* vertices, unsigned int vertexCount,
err() << "sf::Quads primitive type is not supported on OpenGL ES platforms, drawing skipped" << std::endl;
return;
}
#define GL_QUADS 0
#endif
if (activate(true))
@ -234,7 +235,7 @@ void RenderTarget::draw(const Vertex* vertices, unsigned int vertexCount,
// Find the OpenGL primitive type
static const GLenum modes[] = {GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES,
GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN};
GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS};
GLenum mode = modes[type];
// Draw the primitives
@ -468,5 +469,5 @@ void RenderTarget::applyShader(const Shader* shader)
// like matrices or textures. The only optimization that we
// do is that we avoid setting a null shader if there was
// already none for the previous draw.
//
//
////////////////////////////////////////////////////////////

7
src/SFML/Main/Android.mk Normal file
View file

@ -0,0 +1,7 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := sfml-main
LOCAL_SRC_FILES := SFML_Main.cpp
include $(BUILD_STATIC_LIBRARY)

View file

@ -5,17 +5,22 @@ set(SRC
)
source_group("" FILES ${SRC})
# define the sfml-main target
add_library(sfml-main STATIC ${SRC})
if(NOT ANDROID)
# define the sfml-main target
add_library(sfml-main STATIC ${SRC})
# set the debug suffix
set_target_properties(sfml-main PROPERTIES DEBUG_POSTFIX -d)
# set the debug suffix
set_target_properties(sfml-main PROPERTIES DEBUG_POSTFIX -d)
# insert the major version number in the output filename
set_target_properties(sfml-main PROPERTIES OUTPUT_NAME "sfml-main")
# insert the major version number in the output filename
set_target_properties(sfml-main PROPERTIES OUTPUT_NAME "sfml-main")
# set the target's folder (for IDEs that support it, e.g. Visual Studio)
set_target_properties(sfml-main PROPERTIES FOLDER "SFML")
# set the target's folder (for IDEs that support it, e.g. Visual Studio)
set_target_properties(sfml-main PROPERTIES FOLDER "SFML")
# setup the install rule
install(TARGETS sfml-main ARCHIVE DESTINATION lib${LIB_SUFFIX} COMPONENT devel)
# setup the install rule
install(TARGETS sfml-main ARCHIVE DESTINATION lib${LIB_SUFFIX} COMPONENT devel)
else()
# define the sfml-main target
sfml_add_library(sfml-main SOURCES ${SRC} DEPENDS sfml-window sfml-system)
endif()

View file

@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@ -42,3 +42,662 @@
}
#endif // _WIN32
#if defined(_WIN32)
////////////////////////////////////////////////////////////////////////////////
// Windows specific : defines the WinMain entry function,
// so that developers can use the standard main function
// even in a Win32 Application project, and keep a portable code
////////////////////////////////////////////////////////////////////////////////
#include <windows.h>
extern int main(int argc, char* argv[]);
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
{
return main(__argc, __argv);
}
#elif defined(__ANDROID__)
#include <SFML/Window/Keyboard.hpp>
#include <SFML/System/Sleep.hpp>
#include <SFML/System/Thread.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/Main/activity.hpp>
extern int main(int argc, char *argv[]);
JavaVM* javaVM;
namespace sf
{
namespace priv
{
Keyboard::Key mapAndroidKeyToSFMLKey(int32_t key)
{
switch (key)
{
case AKEYCODE_UNKNOWN :
case AKEYCODE_SOFT_LEFT :
case AKEYCODE_SOFT_RIGHT :
case AKEYCODE_HOME :
case AKEYCODE_BACK :
case AKEYCODE_CALL :
case AKEYCODE_ENDCALL : return Keyboard::Unknown;
case AKEYCODE_0 : return Keyboard::Num0;
case AKEYCODE_1 : return Keyboard::Num1;
case AKEYCODE_2 : return Keyboard::Num2;
case AKEYCODE_3 : return Keyboard::Num3;
case AKEYCODE_4 : return Keyboard::Num4;
case AKEYCODE_5 : return Keyboard::Num5;
case AKEYCODE_6 : return Keyboard::Num6;
case AKEYCODE_7 : return Keyboard::Num7;
case AKEYCODE_8 : return Keyboard::Num8;
case AKEYCODE_9 : return Keyboard::Num9;
case AKEYCODE_STAR :
case AKEYCODE_POUND :
case AKEYCODE_DPAD_UP :
case AKEYCODE_DPAD_DOWN :
case AKEYCODE_DPAD_LEFT :
case AKEYCODE_DPAD_RIGHT :
case AKEYCODE_DPAD_CENTER :
case AKEYCODE_VOLUME_UP :
case AKEYCODE_VOLUME_DOWN :
case AKEYCODE_POWER :
case AKEYCODE_CAMERA :
case AKEYCODE_CLEAR : return Keyboard::Unknown;
case AKEYCODE_A : return Keyboard::A;
case AKEYCODE_B : return Keyboard::B;
case AKEYCODE_C : return Keyboard::C;
case AKEYCODE_D : return Keyboard::D;
case AKEYCODE_E : return Keyboard::E;
case AKEYCODE_F : return Keyboard::F;
case AKEYCODE_G : return Keyboard::G;
case AKEYCODE_H : return Keyboard::H;
case AKEYCODE_I : return Keyboard::I;
case AKEYCODE_J : return Keyboard::J;
case AKEYCODE_K : return Keyboard::K;
case AKEYCODE_L : return Keyboard::L;
case AKEYCODE_M : return Keyboard::M;
case AKEYCODE_N : return Keyboard::N;
case AKEYCODE_O : return Keyboard::O;
case AKEYCODE_P : return Keyboard::P;
case AKEYCODE_Q : return Keyboard::Q;
case AKEYCODE_R : return Keyboard::R;
case AKEYCODE_S : return Keyboard::S;
case AKEYCODE_T : return Keyboard::T;
case AKEYCODE_U : return Keyboard::U;
case AKEYCODE_V : return Keyboard::V;
case AKEYCODE_W : return Keyboard::W;
case AKEYCODE_X : return Keyboard::X;
case AKEYCODE_Y : return Keyboard::Y;
case AKEYCODE_Z : return Keyboard::Z;
case AKEYCODE_COMMA : return Keyboard::Comma;
case AKEYCODE_PERIOD : return Keyboard::Period;
case AKEYCODE_ALT_LEFT : return Keyboard::LAlt;
case AKEYCODE_ALT_RIGHT : return Keyboard::RAlt;
case AKEYCODE_SHIFT_LEFT : return Keyboard::LShift;
case AKEYCODE_SHIFT_RIGHT : return Keyboard::RShift;
case AKEYCODE_TAB : return Keyboard::Tab;
case AKEYCODE_SPACE : return Keyboard::Space;
case AKEYCODE_SYM :
case AKEYCODE_EXPLORER :
case AKEYCODE_ENVELOPE : return Keyboard::Unknown;
case AKEYCODE_ENTER : return Keyboard::Return;
case AKEYCODE_DEL : return Keyboard::Delete;
case AKEYCODE_GRAVE : return Keyboard::Tilde;
case AKEYCODE_MINUS : return Keyboard::Subtract;
case AKEYCODE_EQUALS : return Keyboard::Equal;
case AKEYCODE_LEFT_BRACKET : return Keyboard::LBracket;
case AKEYCODE_RIGHT_BRACKET : return Keyboard::RBracket;
case AKEYCODE_BACKSLASH : return Keyboard::BackSlash;
case AKEYCODE_SEMICOLON : return Keyboard::SemiColon;
case AKEYCODE_APOSTROPHE : return Keyboard::Quote;
case AKEYCODE_SLASH : return Keyboard::Slash;
case AKEYCODE_AT :
case AKEYCODE_NUM :
case AKEYCODE_HEADSETHOOK :
case AKEYCODE_FOCUS : // *Camera* focus
case AKEYCODE_PLUS :
case AKEYCODE_MENU :
case AKEYCODE_NOTIFICATION :
case AKEYCODE_SEARCH :
case AKEYCODE_MEDIA_PLAY_PAUSE :
case AKEYCODE_MEDIA_STOP :
case AKEYCODE_MEDIA_NEXT :
case AKEYCODE_MEDIA_PREVIOUS :
case AKEYCODE_MEDIA_REWIND :
case AKEYCODE_MEDIA_FAST_FORWARD :
case AKEYCODE_MUTE : return Keyboard::Unknown;
case AKEYCODE_PAGE_UP : return Keyboard::PageUp;
case AKEYCODE_PAGE_DOWN : return Keyboard::PageDown;
case AKEYCODE_PICTSYMBOLS :
case AKEYCODE_SWITCH_CHARSET :
case AKEYCODE_BUTTON_A :
case AKEYCODE_BUTTON_B :
case AKEYCODE_BUTTON_C :
case AKEYCODE_BUTTON_X :
case AKEYCODE_BUTTON_Y :
case AKEYCODE_BUTTON_Z :
case AKEYCODE_BUTTON_L1 :
case AKEYCODE_BUTTON_R1 :
case AKEYCODE_BUTTON_L2 :
case AKEYCODE_BUTTON_R2 :
case AKEYCODE_BUTTON_THUMBL :
case AKEYCODE_BUTTON_THUMBR :
case AKEYCODE_BUTTON_START :
case AKEYCODE_BUTTON_SELECT :
case AKEYCODE_BUTTON_MODE : return Keyboard::Unknown;
}
}
void processEvent(ActivityStates* states)
{
// The caller must ensure states can be safely accessed!
AInputEvent* _event = NULL;
if (AInputQueue_getEvent(states->inputQueue, &_event) >= 0)
{
if (AInputQueue_preDispatchEvent(states->inputQueue, _event))
return;
int32_t handled = 0;
int32_t type = AInputEvent_getType(_event);
if (type == AINPUT_EVENT_TYPE_KEY)
{
int32_t action = AKeyEvent_getAction(_event);
if (action == AKEY_EVENT_ACTION_DOWN || action == AKEY_EVENT_ACTION_UP)
{
int32_t key = AKeyEvent_getKeyCode(_event);
int32_t metakey = AKeyEvent_getMetaState(_event);
sf::Event event;
if (action == AKEY_EVENT_ACTION_DOWN)
event.type = Event::KeyPressed;
else
event.type = Event::KeyReleased;
event.key.code = mapAndroidKeyToSFMLKey(key);
event.key.alt = metakey & AMETA_ALT_ON;
event.key.control = metakey & AMETA_SHIFT_ON;
event.key.shift = false;
states->pendingEvents.push_back(event);
}
}
else if (type == AINPUT_EVENT_TYPE_MOTION)
{
int32_t action = AMotionEvent_getAction(_event);
switch (action & AMOTION_EVENT_ACTION_MASK)
{
case AMOTION_EVENT_ACTION_MOVE:
{
int historySize = AMotionEvent_getHistorySize(_event);
int pointerCount = AMotionEvent_getPointerCount(_event);
for (int h = 0; h < historySize; h++)
{
for (int p = 0; p < pointerCount; p++)
{
int id = AMotionEvent_getPointerId(_event, p);
float x = AMotionEvent_getHistoricalX(_event, p, h);
float y = AMotionEvent_getHistoricalY(_event, p, h);
sf::Event event;
event.type = Event::MouseMoved;
event.mouseButton.button = static_cast<Mouse::Button>(id);
event.mouseButton.x = x;
event.mouseButton.y = y;
states->pendingEvents.push_back(event);
}
}
break;
}
case AMOTION_EVENT_ACTION_POINTER_DOWN:
case AMOTION_EVENT_ACTION_DOWN:
{
int index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
int id = AMotionEvent_getPointerId(_event, index);
float x = AMotionEvent_getX(_event, 0);
float y = AMotionEvent_getY(_event, 0);
sf::Event event;
event.type = Event::MouseButtonPressed;
event.mouseButton.button = static_cast<Mouse::Button>(id);
event.mouseButton.x = x;
event.mouseButton.y = y;
states->pendingEvents.push_back(event);
break;
}
case AMOTION_EVENT_ACTION_POINTER_UP:
case AMOTION_EVENT_ACTION_UP:
case AMOTION_EVENT_ACTION_CANCEL:
{
int index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
int id = AMotionEvent_getPointerId(_event, index);
float x = AMotionEvent_getX(_event, 0);
float y = AMotionEvent_getY(_event, 0);
sf::Event event;
event.type = Event::MouseButtonReleased;
event.mouseButton.button = static_cast<Mouse::Button>(id);
event.mouseButton.x = x;
event.mouseButton.y = y;
states->pendingEvents.push_back(event);
break;
}
}
}
handled = 1;
AInputQueue_finishEvent(states->inputQueue, _event, handled);
}
}
void processSensorEvents(ActivityStates* states)
{
// The caller must ensure states can be safely accessed!
ASensorEvent _event;
while (ASensorEventQueue_getEvents(states->sensorEventQueue, &_event, 1) > 0)
{
sf::Event event;
event.type = sf::Event::MouseWheelMoved;
event.mouseWheel.delta = static_cast<int>(_event.acceleration.x*1000);
event.mouseWheel.x = static_cast<int>(_event.acceleration.y*1000);
event.mouseWheel.y = static_cast<int>(_event.acceleration.z*1000);
states->pendingEvents.push_back(event);
}
}
ActivityStates* getActivityStates(ActivityStates* initializedStates)
{
static ActivityStates* states = NULL;
if (!states)
states = initializedStates;
return states;
}
ActivityStates* retrieveStates(ANativeActivity* activity)
{
// Hide the ugly cast we find in each callback function
return (sf::priv::ActivityStates*)activity->instance;
}
static void initializeMain(ActivityStates* states)
{
// Protect from concurent access
sf::Lock lock(states->mutex);
// Prepare and share the looper to be read later
ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
states->looper = looper;
// Prepare the sensor event queue
states->sensorEventQueue = ASensorManager_createEventQueue(states->sensorManager, states->looper, 2, NULL, (void*)&sf::priv::processSensorEvents);
// Get the default configuration
states->config = AConfiguration_new();
AConfiguration_fromAssetManager(states->config, states->activity->assetManager);
}
static void terminateMain(ActivityStates* states)
{
// Protect from concurent access
sf::Lock lock(states->mutex);
// The main thread is over, we must explicitly ask the activity to finish
states->mainOver = true;
ANativeActivity_finish(states->activity);
}
void* main(ActivityStates* states)
{
// Initialize the thread before giving the hand
initializeMain(states);
{
sf::Lock lock(states->mutex);
states->initialized = true;
}
sf::sleep(sf::seconds(0.5));
::main(0, NULL);
// Terminate properly the thread and Wait until it's done
terminateMain(states);
{
sf::Lock lock(states->mutex);
states->terminated = true;
}
return NULL;
}
} // namespace priv
} // namespace sf
static void onStart(ANativeActivity* activity)
{
}
static void onResume(ANativeActivity* activity)
{
// Retrieve our activity states from the activity instance
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
sf::Lock lock(states->mutex);
// Send an event to warn people the activity has been resumed
sf::Event event;
event.type = sf::Event::MouseEntered;
states->pendingEvents.push_back(event);
}
static void onPause(ANativeActivity* activity)
{
// Retrieve our activity states from the activity instance
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
sf::Lock lock(states->mutex);
// Send an event to warn people the activity has been paused
sf::Event event;
event.type = sf::Event::MouseLeft;
states->pendingEvents.push_back(event);
}
static void onStop(ANativeActivity* activity)
{
}
static void onDestroy(ANativeActivity* activity)
{
// Retrieve our activity states from the activity instance
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
// Send an event to warn people the activity is being destroyed
{
sf::Lock lock(states->mutex);
// If the main thread hasn't yet finished, send the event and wait for
// it to finish.
if (!states->mainOver)
{
sf::Event event;
event.type = sf::Event::Closed;
states->pendingEvents.push_back(event);
}
}
// Wait for the main thread to be terminated
states->mutex.lock();
while (!states->terminated)
{
states->mutex.unlock();
sf::sleep(sf::milliseconds(20));
states->mutex.lock();
}
states->mutex.unlock();
// Terminate EGL display
eglCheck(eglTerminate(states->display));
// Delete our allocated states
delete states;
// The application should now terminate
}
static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window)
{
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
sf::Lock lock(states->mutex);
// Update the activity states
states->window = window;
// Notify SFML mechanism
sf::Event event;
event.type = sf::Event::GainedFocus;
states->pendingEvents.push_back(event);
// Wait for the event to be taken into account by SFML
states->updated = false;
while(!states->updated)
{
states->mutex.unlock();
sf::sleep(sf::milliseconds(10));
states->mutex.lock();
}
}
static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window)
{
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
sf::Lock lock(states->mutex);
// Update the activity states
states->window = NULL;
// Notify SFML mechanism
sf::Event event;
event.type = sf::Event::LostFocus;
states->pendingEvents.push_back(event);
// Wait for the event to be taken into account by SFML
states->updated = false;
while(!states->updated)
{
states->mutex.unlock();
sf::sleep(sf::milliseconds(10));
states->mutex.lock();
}
}
static void onNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow* window)
{
}
static void onNativeWindowResized(ANativeActivity* activity, ANativeWindow* window)
{
}
static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue)
{
// Retrieve our activity states from the activity instance
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
// Attach the input queue
{
sf::Lock lock(states->mutex);
AInputQueue_attachLooper(queue, states->looper, 1, NULL, (void*)&sf::priv::processEvent);
states->inputQueue = queue;
}
}
static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue)
{
// Retrieve our activity states from the activity instance
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
// Detach the input queue
{
sf::Lock lock(states->mutex);
states->inputQueue = NULL;
AInputQueue_detachLooper(queue);
}
}
static void onWindowFocusChanged(ANativeActivity* activity, int focused)
{
// Retrieve our activity states from the activity instance
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
if (focused)
{
// We start monitoring the accelerometer with 60 events per second
if (states->accelerometerSensor != NULL)
{
ASensorEventQueue_enableSensor(states->sensorEventQueue, states->accelerometerSensor);
ASensorEventQueue_setEventRate(states->sensorEventQueue, states->accelerometerSensor, (1000L/60)*1000);
}
}
else
{
// We stop monitoring the accelerometer (it avoids consuming battery)
if (states->accelerometerSensor != NULL)
{
ASensorEventQueue_disableSensor(states->sensorEventQueue, states->accelerometerSensor);
}
}
}
static void onContentRectChanged(ANativeActivity* activity, const ARect* rect)
{
// Retrieve our activity states from the activity instance
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
sf::Lock lock(states->mutex);
// Send an event to warn people about the window move/resize
sf::Event event;
event.type = sf::Event::Resized;
event.size.width = ANativeWindow_getWidth(states->window);
event.size.height = ANativeWindow_getHeight(states->window);
states->pendingEvents.push_back(event);
}
static void onConfigurationChanged(ANativeActivity* activity)
{
}
static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen)
{
*outLen = 0;
return NULL;
}
static void onLowMemory(ANativeActivity* activity)
{
}
void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize)
{
// Feed OpenAL-Soft's javaVM to make so he can function
javaVM = activity->vm;
// Create an activity states (will keep us in the know, about events we care)
sf::priv::ActivityStates* states = NULL;
states = new sf::priv::ActivityStates;
// Initialize the states value
states->activity = NULL;
states->window = NULL;
states->looper = NULL;
states->inputQueue = NULL;
states->config = NULL;
states->sensorManager = ASensorManager_getInstance();
states->accelerometerSensor = ASensorManager_getDefaultSensor(states->sensorManager, ASENSOR_TYPE_ACCELEROMETER);
states->sensorEventQueue = NULL;
states->display = eglCheck(eglGetDisplay(EGL_DEFAULT_DISPLAY));
if (savedState != NULL) {
states->savedState = malloc(savedStateSize);
states->savedStateSize = savedStateSize;
memcpy(states->savedState, savedState, savedStateSize);
}
states->mainOver = false;
states->initialized = false;
states->terminated = false;
// Share it across the SFML modules
sf::priv::getActivityStates(states);
// These functions will update the activity states and therefore, will allow
// SFML to be kept in the know
activity->callbacks->onStart = onStart;
activity->callbacks->onResume = onResume;
activity->callbacks->onPause = onPause;
activity->callbacks->onStop = onStop;
activity->callbacks->onDestroy = onDestroy;
activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded;
activity->callbacks->onNativeWindowResized = onNativeWindowResized;
activity->callbacks->onInputQueueCreated = onInputQueueCreated;
activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
activity->callbacks->onContentRectChanged = onContentRectChanged;
activity->callbacks->onConfigurationChanged = onConfigurationChanged;
activity->callbacks->onSaveInstanceState = onSaveInstanceState;
activity->callbacks->onLowMemory = onLowMemory;
// Share this activity with the callback functions
states->activity = activity;
// Initialize the display
eglCheck(eglInitialize(states->display, NULL, NULL));
// Launch the main thread
sf::Thread* thread = new sf::Thread(sf::priv::main, states);
thread->launch();
// Wait for the main thread to be initialized
states->mutex.lock();
while (!states->initialized)
{
states->mutex.unlock();
sf::sleep(sf::milliseconds(20));
states->mutex.lock();
}
states->mutex.unlock();
// Share this state with the callback functions
activity->instance = states;
}
#endif

View file

@ -0,0 +1,17 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := sfml-network
LOCAL_SRC_FILES := Ftp.cpp
LOCAL_SRC_FILES += Http.cpp
LOCAL_SRC_FILES += IpAddress.cpp
LOCAL_SRC_FILES += Packet.cpp
LOCAL_SRC_FILES += Socket.cpp
LOCAL_SRC_FILES += SocketSelector.cpp
LOCAL_SRC_FILES += TcpListener.cpp
LOCAL_SRC_FILES += TcpSocket.cpp
LOCAL_SRC_FILES += UdpSocket.cpp
LOCAL_SRC_FILES += Unix/SocketImpl.cpp
include $(BUILD_STATIC_LIBRARY)

View file

@ -28,6 +28,9 @@
#include <SFML/Network/Ftp.hpp>
#include <SFML/Network/IpAddress.hpp>
#include <algorithm>
#ifdef SFML_SYSTEM_ANDROID
#include <cctype>
#endif
#include <fstream>
#include <iterator>
#include <sstream>

View file

@ -0,0 +1,21 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := sfml-system
LOCAL_SRC_FILES := Clock.cpp
LOCAL_SRC_FILES += Err.cpp
LOCAL_SRC_FILES += Lock.cpp
LOCAL_SRC_FILES += Mutex.cpp
LOCAL_SRC_FILES += Sleep.cpp
LOCAL_SRC_FILES += String.cpp
LOCAL_SRC_FILES += Thread.cpp
LOCAL_SRC_FILES += ThreadLocal.cpp
LOCAL_SRC_FILES += Time.cpp
LOCAL_SRC_FILES += Unix/ClockImpl.cpp
LOCAL_SRC_FILES += Unix/MutexImpl.cpp
LOCAL_SRC_FILES += Unix/SleepImpl.cpp
LOCAL_SRC_FILES += Unix/ThreadImpl.cpp
LOCAL_SRC_FILES += Unix/ThreadLocalImpl.cpp
include $(BUILD_STATIC_LIBRARY)

View file

@ -61,7 +61,14 @@ void ThreadImpl::wait()
void ThreadImpl::terminate()
{
if (m_isActive)
pthread_cancel(m_thread);
{
#ifndef SFML_SYSTEM_ANDROID
pthread_cancel(m_thread);
#else
// See http://stackoverflow.com/questions/4610086/pthread-cancel-al
pthread_kill(m_thread, SIGUSR1);
#endif
}
}
@ -71,8 +78,10 @@ void* ThreadImpl::entryPoint(void* userData)
// The Thread instance is stored in the user data
Thread* owner = static_cast<Thread*>(userData);
// Tell the thread to handle cancel requests immediatly
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
#ifndef SFML_SYSTEM_ANDROID
// Tell the thread to handle cancel requests immediatly
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
#endif
// Forward to the owner
owner->run();

View file

@ -28,6 +28,7 @@
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <SFML/System/NonCopyable.hpp>
#include <pthread.h>

View file

@ -0,0 +1,23 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := sfml-window
LOCAL_SRC_FILES := Context.cpp
LOCAL_SRC_FILES += GlContext.cpp
LOCAL_SRC_FILES += GlResource.cpp
LOCAL_SRC_FILES += Joystick.cpp
LOCAL_SRC_FILES += JoystickManager.cpp
LOCAL_SRC_FILES += Keyboard.cpp
LOCAL_SRC_FILES += Mouse.cpp
LOCAL_SRC_FILES += VideoMode.cpp
LOCAL_SRC_FILES += Window.cpp
LOCAL_SRC_FILES += WindowImpl.cpp
LOCAL_SRC_FILES += EGLCheck.cpp
LOCAL_SRC_FILES += Android/WindowImplAndroid.cpp
LOCAL_SRC_FILES += Android/EglContext.cpp
LOCAL_SRC_FILES += Android/VideoModeImpl.cpp
LOCAL_SRC_FILES += Android/InputImpl.cpp
LOCAL_SRC_FILES += Android/JoystickImpl.cpp
include $(BUILD_STATIC_LIBRARY)

View file

@ -0,0 +1,213 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/Android/EglContext.hpp>
#include <SFML/OpenGL.hpp>
#include <SFML/System/Err.hpp>
#include <SFML/System/Sleep.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/Main/activity.hpp>
#include <android/native_window.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
EglContext::EglContext(EglContext* shared) :
m_display (EGL_NO_DISPLAY),
m_context (EGL_NO_CONTEXT),
m_surface (EGL_NO_SURFACE)
{
// Get the activity states and protect it from concurent access
ActivityStates* states = getActivityStates(NULL);
sf::Lock lock(states->mutex);
// Get the intialized EGL display
m_display = states->display;
// Create the EGL surface
const EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
EGL_NONE
};
EGLint numConfigs;
EGLConfig config[1];
eglCheck(eglChooseConfig(m_display, attribs, &config[0], 1, &numConfigs));
// Note: The EGL specs say that attrib_list can be NULL when passed to eglCreatePbufferSurface,
// but this is resulting in a segfault. Bug in Android?
EGLint attrib_list[] = { EGL_NONE };
m_surface = eglCheck(eglCreatePbufferSurface(m_display, config[0], attrib_list));
// Create the context
createContext(shared, 0, config[0]);
}
////////////////////////////////////////////////////////////
EglContext::EglContext(EglContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel) :
m_display (EGL_NO_DISPLAY),
m_context (EGL_NO_CONTEXT),
m_surface (EGL_NO_SURFACE)
{
// Get the activity states and protect it from concurent access
ActivityStates* states = getActivityStates(NULL);
sf::Lock lock(states->mutex);
// Get the intialized EGL display
m_display = states->display;
// Create the EGL surface
const EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
EGL_NONE
};
EGLint numConfigs;
EGLConfig config[1];
eglCheck(eglChooseConfig(m_display, attribs, &config[0], 1, &numConfigs));
// Create the context
createContext(shared, 0, config[0]);
}
////////////////////////////////////////////////////////////
EglContext::EglContext(EglContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height) :
m_display (EGL_NO_DISPLAY),
m_context (EGL_NO_CONTEXT),
m_surface (EGL_NO_SURFACE)
{
}
////////////////////////////////////////////////////////////
EglContext::~EglContext()
{
// Desactive the current context
EGLContext currentContext = eglCheck(eglGetCurrentContext());
if (currentContext == m_context)
{
eglCheck(eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
}
// Destroy context
if (m_context != EGL_NO_CONTEXT)
{
eglCheck(eglDestroyContext(m_display, m_context));
}
// Destroy surface
if (m_surface != EGL_NO_SURFACE)
{
eglCheck(eglDestroySurface(m_display, m_surface));
}
}
////////////////////////////////////////////////////////////
bool EglContext::makeCurrent()
{
bool success = m_surface != EGL_NO_SURFACE && eglCheck(eglMakeCurrent(m_display, m_surface, m_surface, m_context));
return success;
}
////////////////////////////////////////////////////////////
void EglContext::display()
{
eglCheck(eglSwapBuffers(m_display, m_surface));
}
////////////////////////////////////////////////////////////
void EglContext::setVerticalSyncEnabled(bool enabled)
{
eglCheck(eglSwapInterval(m_display, enabled ? 1 : 0));
}
void EglContext::createContext(EglContext* shared, unsigned int bitsPerPixel, const EGLConfig settings)
{
EGLint contextVersion[] = { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE };
EGLContext toShared;
if (shared)
toShared = shared->m_context;
else
toShared = EGL_NO_CONTEXT;
// Create the EGL context
m_context = eglCheck(eglCreateContext(m_display, settings, toShared, contextVersion));
}
void EglContext::createSurface(ANativeWindow* window)
{
// Create the EGL surface
const EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
EGL_NONE
};
EGLint numConfigs;
EGLConfig config[1];
eglCheck(eglChooseConfig(m_display, attribs, &config[0], 1, &numConfigs));
m_surface = eglCheck(eglCreateWindowSurface(m_display, config[0], window, NULL));
}
void EglContext::destroySurface()
{
eglCheck(eglDestroySurface(m_display, m_surface));
m_surface = EGL_NO_SURFACE;
// Ensure that this context is no longer active since our surface is now destroyed
setActive(false);
}
} // namespace priv
} // namespace sf

View file

@ -0,0 +1,156 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_EGLCONTEXT_HPP
#define SFML_EGLCONTEXT_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/VideoMode.hpp>
#include <SFML/Window/ContextSettings.hpp>
#include <SFML/Window/EGLCheck.hpp>
#include <SFML/Window/GlContext.hpp>
#include <SFML/OpenGL.hpp>
namespace sf
{
namespace priv
{
class EglContext : public GlContext
{
public :
////////////////////////////////////////////////////////////
/// \brief Create a new context, not associated to a window
///
/// \param shared Context to share the new one with (can be NULL)
///
////////////////////////////////////////////////////////////
EglContext(EglContext* shared);
////////////////////////////////////////////////////////////
/// \brief Create a new context attached to a window
///
/// \param shared Context to share the new one with
/// \param settings Creation parameters
/// \param owner Pointer to the owner window
/// \param bitsPerPixel Pixel depth, in bits per pixel
///
////////////////////////////////////////////////////////////
EglContext(EglContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel);
////////////////////////////////////////////////////////////
/// \brief Create a new context that embeds its own rendering target
///
/// \param shared Context to share the new one with
/// \param settings Creation parameters
/// \param width Back buffer width, in pixels
/// \param height Back buffer height, in pixels
///
////////////////////////////////////////////////////////////
EglContext(EglContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height);
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~EglContext();
////////////////////////////////////////////////////////////
/// \brief Activate the context as the current target
/// for rendering
///
/// \return True on success, false if any error happened
///
////////////////////////////////////////////////////////////
virtual bool makeCurrent();
////////////////////////////////////////////////////////////
/// \brief Display what has been rendered to the context so far
///
////////////////////////////////////////////////////////////
virtual void display();
////////////////////////////////////////////////////////////
/// \brief Enable or disable vertical synchronization
///
/// Activating vertical synchronization will limit the number
/// of frames displayed to the refresh rate of the monitor.
/// This can avoid some visual artifacts, and limit the framerate
/// to a good value (but not constant across different computers).
///
/// \param enabled : True to enable v-sync, false to deactivate
///
////////////////////////////////////////////////////////////
virtual void setVerticalSyncEnabled(bool enabled);
////////////////////////////////////////////////////////////
/// \brief Create the context
///
/// \param shared Context to share the new one with (can be NULL)
/// \param bitsPerPixel Pixel depth, in bits per pixel
/// \param settings Creation parameters
///
////////////////////////////////////////////////////////////
void createContext(EglContext* shared, unsigned int bitsPerPixel, const EGLConfig settings);
////////////////////////////////////////////////////////////
/// \brief Create the EGL surface
///
/// This function must be called when the activity (re)start, or
/// when the orientation change.
///
/// \param window : The Android window
///
////////////////////////////////////////////////////////////
void createSurface(ANativeWindow* window);
////////////////////////////////////////////////////////////
/// \brief Destroy the EGL surface
///
/// This function must be called when the activity is stopped, or
/// when the orientation change.
///
////////////////////////////////////////////////////////////
void destroySurface();
private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
EGLDisplay m_display; ///< The internal EGL display
EGLContext m_context; ///< The internal EGL context
EGLSurface m_surface; ///< The internal EGL surface
};
} // namespace priv
} // namespace sf
#endif // SFML_EGLCONTEXT_HPP

View file

@ -0,0 +1,174 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/Android/InputImpl.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/Main/activity.hpp>
#include <jni.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
bool InputImpl::isKeyPressed(Keyboard::Key key)
{
// Not applicable
return false;
}
////////////////////////////////////////////////////////////
void InputImpl::setVirtualKeyboardVisible(bool visible)
{
// TODO: Check if the window is active
ActivityStates* states = getActivityStates(NULL);
sf::Lock lock(states->mutex);
jint lResult;
jint lFlags = 0;
JavaVM* lJavaVM = states->activity->vm;
JNIEnv* lJNIEnv = states->activity->env;
JavaVMAttachArgs lJavaVMAttachArgs;
lJavaVMAttachArgs.version = JNI_VERSION_1_6;
lJavaVMAttachArgs.name = "NativeThread";
lJavaVMAttachArgs.group = NULL;
lResult=lJavaVM->AttachCurrentThread(&lJNIEnv, &lJavaVMAttachArgs);
if (lResult == JNI_ERR) {
return;
}
// Retrieves NativeActivity.
jobject lNativeActivity = states->activity->clazz;
jclass ClassNativeActivity = lJNIEnv->GetObjectClass(lNativeActivity);
// Retrieves Context.INPUT_METHOD_SERVICE.
jclass ClassContext = lJNIEnv->FindClass("android/content/Context");
jfieldID FieldINPUT_METHOD_SERVICE =
lJNIEnv->GetStaticFieldID(ClassContext,
"INPUT_METHOD_SERVICE", "Ljava/lang/String;");
jobject INPUT_METHOD_SERVICE =
lJNIEnv->GetStaticObjectField(ClassContext,
FieldINPUT_METHOD_SERVICE);
// Runs getSystemService(Context.INPUT_METHOD_SERVICE).
jclass ClassInputMethodManager = lJNIEnv->FindClass(
"android/view/inputmethod/InputMethodManager");
jmethodID MethodGetSystemService = lJNIEnv->GetMethodID(
ClassNativeActivity, "getSystemService",
"(Ljava/lang/String;)Ljava/lang/Object;");
jobject lInputMethodManager = lJNIEnv->CallObjectMethod(
lNativeActivity, MethodGetSystemService,
INPUT_METHOD_SERVICE);
// Runs getWindow().getDecorView().
jmethodID MethodGetWindow = lJNIEnv->GetMethodID(
ClassNativeActivity, "getWindow",
"()Landroid/view/Window;");
jobject lWindow = lJNIEnv->CallObjectMethod(lNativeActivity,
MethodGetWindow);
jclass ClassWindow = lJNIEnv->FindClass(
"android/view/Window");
jmethodID MethodGetDecorView = lJNIEnv->GetMethodID(
ClassWindow, "getDecorView", "()Landroid/view/View;");
jobject lDecorView = lJNIEnv->CallObjectMethod(lWindow,
MethodGetDecorView);
if (visible)
{
// Runs lInputMethodManager.showSoftInput(...).
jmethodID MethodShowSoftInput = lJNIEnv->GetMethodID(
ClassInputMethodManager, "showSoftInput",
"(Landroid/view/View;I)Z");
jboolean lResult = lJNIEnv->CallBooleanMethod(
lInputMethodManager, MethodShowSoftInput,
lDecorView, lFlags);
}
else
{
// Runs lWindow.getViewToken()
jclass ClassView = lJNIEnv->FindClass(
"android/view/View");
jmethodID MethodGetWindowToken = lJNIEnv->GetMethodID(
ClassView, "getWindowToken", "()Landroid/os/IBinder;");
jobject lBinder = lJNIEnv->CallObjectMethod(lDecorView,
MethodGetWindowToken);
// lInputMethodManager.hideSoftInput(...).
jmethodID MethodHideSoftInput = lJNIEnv->GetMethodID(
ClassInputMethodManager, "hideSoftInputFromWindow",
"(Landroid/os/IBinder;I)Z");
jboolean lRes = lJNIEnv->CallBooleanMethod(
lInputMethodManager, MethodHideSoftInput,
lBinder, lFlags);
}
// Finished with the JVM.
lJavaVM->DetachCurrentThread();
}
////////////////////////////////////////////////////////////
bool InputImpl::isMouseButtonPressed(Mouse::Button button)
{
return false;
}
////////////////////////////////////////////////////////////
Vector2i InputImpl::getMousePosition()
{
return Vector2i(0, 0);
}
////////////////////////////////////////////////////////////
Vector2i InputImpl::getMousePosition(const Window& relativeTo)
{
return Vector2i(0, 0);
}
////////////////////////////////////////////////////////////
void InputImpl::setMousePosition(const Vector2i& position)
{
// Not applicable
}
////////////////////////////////////////////////////////////
void InputImpl::setMousePosition(const Vector2i& position, const Window& relativeTo)
{
// Not applicable
}
} // namespace priv
} // namespace sf

View file

@ -0,0 +1,131 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_INPUTIMPLANDROID_HPP
#define SFML_INPUTIMPLANDROID_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/Keyboard.hpp>
#include <SFML/Window/Mouse.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief iOS implementation of inputs (keyboard + mouse)
///
////////////////////////////////////////////////////////////
class InputImpl
{
public :
////////////////////////////////////////////////////////////
/// \brief Check if a key is pressed
///
/// \param key Key to check
///
/// \return True if the key is pressed, false otherwise
///
////////////////////////////////////////////////////////////
static bool isKeyPressed(Keyboard::Key key);
////////////////////////////////////////////////////////////
/// \brief Show or hide the virtual keyboard
///
/// \param visible True to show, false to hide
///
////////////////////////////////////////////////////////////
static void setVirtualKeyboardVisible(bool visible);
////////////////////////////////////////////////////////////
/// \brief Check if a mouse button is pressed
///
/// \param button Button to check
///
/// \return True if the button is pressed, false otherwise
///
////////////////////////////////////////////////////////////
static bool isMouseButtonPressed(Mouse::Button button);
////////////////////////////////////////////////////////////
/// \brief Get the current position of the mouse in desktop coordinates
///
/// This function returns the current position of the mouse
/// cursor, in global (desktop) coordinates.
///
/// \return Current position of the mouse
///
////////////////////////////////////////////////////////////
static Vector2i getMousePosition();
////////////////////////////////////////////////////////////
/// \brief Get the current position of the mouse in window coordinates
///
/// This function returns the current position of the mouse
/// cursor, relative to the given window.
/// If no window is used, it returns desktop coordinates.
///
/// \param relativeTo Reference window
///
/// \return Current position of the mouse
///
////////////////////////////////////////////////////////////
static Vector2i getMousePosition(const Window& relativeTo);
////////////////////////////////////////////////////////////
/// \brief Set the current position of the mouse in desktop coordinates
///
/// This function sets the current position of the mouse
/// cursor in global (desktop) coordinates.
/// If no window is used, it sets the position in desktop coordinates.
///
/// \param position New position of the mouse
///
////////////////////////////////////////////////////////////
static void setMousePosition(const Vector2i& position);
////////////////////////////////////////////////////////////
/// \brief Set the current position of the mouse in window coordinates
///
/// This function sets the current position of the mouse
/// cursor, relative to the given window.
/// If no window is used, it sets the position in desktop coordinates.
///
/// \param position New position of the mouse
/// \param relativeTo Reference window
///
////////////////////////////////////////////////////////////
static void setMousePosition(const Vector2i& position, const Window& relativeTo);
};
} // namespace priv
} // namespace sf
#endif // SFML_INPUTIMPLANDROID_HPP

View file

@ -0,0 +1,80 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/JoystickImpl.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
void JoystickImpl::initialize()
{
}
////////////////////////////////////////////////////////////
void JoystickImpl::cleanup()
{
}
////////////////////////////////////////////////////////////
bool JoystickImpl::isConnected(unsigned int index)
{
return false;
}
////////////////////////////////////////////////////////////
bool JoystickImpl::open(unsigned int index)
{
return false;
}
////////////////////////////////////////////////////////////
void JoystickImpl::close()
{
}
////////////////////////////////////////////////////////////
JoystickCaps JoystickImpl::getCapabilities() const
{
}
////////////////////////////////////////////////////////////
JoystickState JoystickImpl::JoystickImpl::update()
{
}
} // namespace priv
} // namespace sf

View file

@ -0,0 +1,108 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_JOYSTICKIMPLANDROID_HPP
#define SFML_JOYSTICKIMPLANDROID_HPP
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Android implementation of joysticks
///
////////////////////////////////////////////////////////////
class JoystickImpl
{
public :
////////////////////////////////////////////////////////////
/// \brief Perform the global initialization of the joystick module
///
////////////////////////////////////////////////////////////
static void initialize();
////////////////////////////////////////////////////////////
/// \brief Perform the global cleanup of the joystick module
///
////////////////////////////////////////////////////////////
static void cleanup();
////////////////////////////////////////////////////////////
/// \brief Check if a joystick is currently connected
///
/// \param index Index of the joystick to check
///
/// \return True if the joystick is connected, false otherwise
///
////////////////////////////////////////////////////////////
static bool isConnected(unsigned int index);
////////////////////////////////////////////////////////////
/// \brief Open the joystick
///
/// \param index Index assigned to the joystick
///
/// \return True on success, false on failure
///
////////////////////////////////////////////////////////////
bool open(unsigned int index);
////////////////////////////////////////////////////////////
/// \brief Close the joystick
///
////////////////////////////////////////////////////////////
void close();
////////////////////////////////////////////////////////////
/// \brief Get the joystick capabilities
///
/// \return Joystick capabilities
///
////////////////////////////////////////////////////////////
JoystickCaps getCapabilities() const;
////////////////////////////////////////////////////////////
/// \brief Update the joystick and get its new state
///
/// \return Joystick state
///
////////////////////////////////////////////////////////////
JoystickState update();
private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
int m_index; ///< Index of the joystick
};
} // namespace priv
} // namespace sf
#endif // SFML_JOYSTICKIMPLANDROID_HPP

View file

@ -0,0 +1,77 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/VideoModeImpl.hpp>
#include <SFML/System/Vector2.hpp>
#include <SFML/System/Sleep.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/Main/activity.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
{
VideoMode desktop = getDesktopMode();
// Return both protrait and landscape resolutions
std::vector<VideoMode> modes;
modes.push_back(desktop);
modes.push_back(VideoMode(desktop.height, desktop.width, desktop.bitsPerPixel));
return modes;
}
////////////////////////////////////////////////////////////
VideoMode VideoModeImpl::getDesktopMode()
{
// Get the activity states
priv::ActivityStates* states = priv::getActivityStates(NULL);
Lock lock(states->mutex);
// Wait for a window if there's none
while (!states->window)
{
states->mutex.unlock();
sleep(milliseconds(10));
states->mutex.lock();
}
// Get size from the window
sf::Vector2i size;
size.x = ANativeWindow_getWidth(states->window);
size.y = ANativeWindow_getHeight(states->window);
return VideoMode(size.x, size.y);
}
} // namespace priv
} // namespace sf

View file

@ -0,0 +1,167 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/WindowStyle.hpp> // important to be included first (conflict with None)
#include <SFML/Window/Android/WindowImplAndroid.hpp>
#include <SFML/Window/Event.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/Main/activity.hpp>
#include <android/log.h>
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "sfml_app", __VA_ARGS__))
////////////////////////////////////////////////////////////
// Private data
////////////////////////////////////////////////////////////
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
WindowImplAndroid::WindowImplAndroid(WindowHandle handle) :
m_context (NULL)
{
}
////////////////////////////////////////////////////////////
WindowImplAndroid::WindowImplAndroid(VideoMode mode, const std::string& title, unsigned long style, const ContextSettings& settings) :
m_context (NULL)
{
}
////////////////////////////////////////////////////////////
WindowImplAndroid::~WindowImplAndroid()
{
}
////////////////////////////////////////////////////////////
WindowHandle WindowImplAndroid::getSystemHandle() const
{
return NULL;
}
////////////////////////////////////////////////////////////
void WindowImplAndroid::processEvents()
{
ActivityStates* states = getActivityStates(NULL);
sf::Lock lock(states->mutex);
int ident, events;
void (*addEventToQueue)(ActivityStates*);
while ((ident=ALooper_pollAll(0, NULL, &events, (void**)&addEventToQueue)) >= 0)
{
addEventToQueue(states);
}
while (!states->pendingEvents.empty())
{
Event tempEvent = states->pendingEvents.back();
states->pendingEvents.pop_back();
if (tempEvent.type == sf::Event::Resized)
{
m_width = tempEvent.size.width;
m_height = tempEvent.size.height;
}
else if (tempEvent.type == Event::GainedFocus)
{
m_context->createSurface(states->window);
states->updated = true;
}
else if (tempEvent.type == Event::LostFocus)
{
m_context->destroySurface();
states->updated = true;
}
pushEvent(tempEvent);
}
}
////////////////////////////////////////////////////////////
Vector2i WindowImplAndroid::getPosition() const
{
return Vector2i(0, 0);
}
////////////////////////////////////////////////////////////
void WindowImplAndroid::setPosition(const Vector2i& position)
{
}
////////////////////////////////////////////////////////////
Vector2u WindowImplAndroid::getSize() const
{
return Vector2u(static_cast<unsigned int>(m_width), static_cast<unsigned int>(m_height));
}
////////////////////////////////////////////////////////////
void WindowImplAndroid::setSize(const Vector2u& size)
{
}
////////////////////////////////////////////////////////////
void WindowImplAndroid::setTitle(const String& title)
{
}
////////////////////////////////////////////////////////////
void WindowImplAndroid::setIcon(unsigned int width, unsigned int height, const Uint8* pixels)
{
}
////////////////////////////////////////////////////////////
void WindowImplAndroid::setVisible(bool visible)
{
}
////////////////////////////////////////////////////////////
void WindowImplAndroid::setMouseCursorVisible(bool visible)
{
}
////////////////////////////////////////////////////////////
void WindowImplAndroid::setKeyRepeatEnabled(bool enabled)
{
}
} // namespace priv
} // namespace sf

View file

@ -0,0 +1,179 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_WINDOWIMPLANDROID_HPP
#define SFML_WINDOWIMPLANDROID_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/Event.hpp>
#include <SFML/Window/WindowImpl.hpp>
#include <SFML/Window/Android/EglContext.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Android implementation of WindowImpl
///
////////////////////////////////////////////////////////////
class WindowImplAndroid : public WindowImpl
{
public :
////////////////////////////////////////////////////////////
/// \brief Construct the window implementation from an existing control
///
/// \param handle Platform-specific handle of the control
///
////////////////////////////////////////////////////////////
WindowImplAndroid(WindowHandle handle);
////////////////////////////////////////////////////////////
/// \brief Create the window implementation
///
/// \param mode Video mode to use
/// \param title Title of the window
/// \param style Window style (resizable, fixed, or fullscren)
/// \param settings Additional settings for the underlying OpenGL context
///
////////////////////////////////////////////////////////////
WindowImplAndroid(VideoMode mode, const std::string& title, unsigned long style, const ContextSettings& settings);
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~WindowImplAndroid();
////////////////////////////////////////////////////////////
/// \brief Get the OS-specific handle of the window
///
/// \return Handle of the window
///
////////////////////////////////////////////////////////////
virtual WindowHandle getSystemHandle() const;
////////////////////////////////////////////////////////////
/// \brief Get the position of the window
///
/// \return Position of the window, in pixels
///
////////////////////////////////////////////////////////////
virtual Vector2i getPosition() const;
////////////////////////////////////////////////////////////
/// \brief Change the position of the window on screen
///
/// \param position New position of the window, in pixels
///
////////////////////////////////////////////////////////////
virtual void setPosition(const Vector2i& position);
////////////////////////////////////////////////////////////
/// \brief Get the client size of the window
///
/// \return Size of the window, in pixels
///
////////////////////////////////////////////////////////////
virtual Vector2u getSize() const;
////////////////////////////////////////////////////////////
/// \brief Change the size of the rendering region of the window
///
/// \param size New size, in pixels
///
////////////////////////////////////////////////////////////
virtual void setSize(const Vector2u& size);
////////////////////////////////////////////////////////////
/// \brief Change the title of the window
///
/// \param title New title
///
////////////////////////////////////////////////////////////
virtual void setTitle(const String& title);
////////////////////////////////////////////////////////////
/// \brief Change the window's icon
///
/// \param width Icon's width, in pixels
/// \param height Icon's height, in pixels
/// \param pixels Pointer to the pixels in memory, format must be RGBA 32 bits
///
////////////////////////////////////////////////////////////
virtual void setIcon(unsigned int width, unsigned int height, const Uint8* pixels);
////////////////////////////////////////////////////////////
/// \brief Show or hide the window
///
/// \param visible True to show, false to hide
///
////////////////////////////////////////////////////////////
virtual void setVisible(bool visible);
////////////////////////////////////////////////////////////
/// \brief Show or hide the mouse cursor
///
/// \param visible True to show, false to hide
///
////////////////////////////////////////////////////////////
virtual void setMouseCursorVisible(bool visible);
////////////////////////////////////////////////////////////
/// \brief Enable or disable automatic key-repeat
///
/// \param enabled True to enable, false to disable
///
////////////////////////////////////////////////////////////
virtual void setKeyRepeatEnabled(bool enabled);
EglContext* m_context;
protected :
////////////////////////////////////////////////////////////
/// \brief Process incoming events from the operating system
///
////////////////////////////////////////////////////////////
virtual void processEvents();
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
// Cache the width and height, as calls to ANativeWindow_getWidth/Height can be slow
int m_width;
int m_height;
};
} // namespace priv
} // namespace sf
#endif // SFML_WINDOWIMPLANDROID_HPP

View file

@ -139,10 +139,23 @@ elseif(IOS)
${SRCROOT}/iOS/SFMain.mm
)
source_group("ios" FILES ${PLATFORM_SRC})
elseif(ANDROID)
set(PLATFORM_SRC
${SRCROOT}/Android/WindowImplAndroid.hpp
${SRCROOT}/Android/WindowImplAndroid.cpp
${SRCROOT}/Android/EGLContext.hpp
${SRCROOT}/Android/EGLContext.cpp
${SRCROOT}/Android/VideoModeImpl.hpp
${SRCROOT}/Android/VideoModeImpl.cpp
${SRCROOT}/Android/InputImpl.hpp
${SRCROOT}/Android/InputImpl.cpp
${SRCROOT}/Android/JoystickImpl.hpp
${SRCROOT}/Android/JoystickImpl.cpp)
source_group("android" FILES ${PLATFORM_SRC})
endif()
# find external libraries
if(NOT SFML_OS_IOS)
# find external libraries
if(NOT OPENGL_ES)
find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR})
if(SFML_OS_LINUX)

View file

@ -0,0 +1,161 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/EGLCheck.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
void eglCheckError(const char* file, unsigned int line)
{
// Obtain information about the success or failure of the most recent EGL
// function called in the current thread
EGLint errorCode = eglGetError();
if (errorCode != EGL_SUCCESS)
{
std::string fileString(file);
std::string error = "unknown error";
std::string description = "no description";
// Decode the error code returned
switch (errorCode)
{
case EGL_NOT_INITIALIZED :
{
error = "EGL_NOT_INITIALIZED";
description = "EGL is not initialized, or could not be initialized, for the specified display";
break;
}
case EGL_BAD_ACCESS :
{
error = "EGL_BAD_ACCESS";
description = "EGL cannot access a requested resource (for example, a context is bound in another thread)";
break;
}
case EGL_BAD_ALLOC :
{
error = "EGL_BAD_ALLOC";
description = "EGL failed to allocate resources for the requested operation";
break;
}
case EGL_BAD_ATTRIBUTE :
{
error = "EGL_BAD_ATTRIBUTE";
description = "an unrecognized attribute or attribute value was passed in an attribute list";
break;
}
case EGL_BAD_CONTEXT :
{
error = "EGL_BAD_CONTEXT";
description = "an EGLContext argument does not name a valid EGLContext";
break;
}
case EGL_BAD_CONFIG :
{
error = "EGL_BAD_CONFIG";
description = "an EGLConfig argument does not name a valid EGLConfig";
break;
}
case EGL_BAD_CURRENT_SURFACE :
{
error = "EGL_BAD_CURRENT_SURFACE";
description = "the current surface of the calling thread is a window, pbuffer, or pixmap that is no longer valid";
break;
}
case EGL_BAD_DISPLAY :
{
error = "EGL_BAD_DISPLAY";
description = "an EGLDisplay argument does not name a valid EGLDisplay; or, EGL is not initialized on the specified EGLDisplay";
break;
}
case EGL_BAD_SURFACE :
{
error = "EGL_BAD_SURFACE";
description = "an EGLSurface argument does not name a valid surface (window, pbuffer, or pixmap) configured for rendering";
break;
}
case EGL_BAD_MATCH :
{
error = "EGL_BAD_MATCH";
description = "arguments are inconsistent; for example, an otherwise valid context requires buffers (e.g. depth or stencil) not allocated by an otherwise valid surface";
break;
}
case EGL_BAD_PARAMETER :
{
error = "EGL_BAD_PARAMETER";
description = "one or more argument values are invalid";
break;
}
case EGL_BAD_NATIVE_PIXMAP :
{
error = "EGL_BAD_NATIVE_PIXMAP";
description = "an EGLNativePixmapType argument does not refer to a valid native pixmap";
break;
}
case EGL_BAD_NATIVE_WINDOW :
{
error = "EGL_BAD_NATIVE_WINDOW";
description = "an EGLNativeWindowType argument does not refer to a valid native window";
break;
}
case EGL_CONTEXT_LOST :
{
error = "EGL_CONTEXT_LOST";
description = "a power management event has occured. The application must destroy all contexts and reinitialise client API state and objects to continue rendering";
break;
}
}
// Log the error
err() << "An internal EGL call failed in "
<< fileString.substr(fileString.find_last_of("\\/") + 1) << " (" << line << ") : "
<< error << ", " << description
<< std::endl;
}
}
} // namespace priv
} // namespace sf

View file

@ -0,0 +1,68 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_EGLCHECK_HPP
#define SFML_EGLCHECK_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <EGL/egl.h>
#include <string>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// Let's define a macro to quickly check every EGL API call
////////////////////////////////////////////////////////////
#ifdef SFML_DEBUG
//// In debug mode, perform a test on every EGL call
#define eglCheck(x) x; sf::priv::eglCheckError(__FILE__, __LINE__);
#else
// Else, we don't add any overhead
#define eglCheck(x) (x)
#endif
////////////////////////////////////////////////////////////
/// \brief Check the last EGL error
///
/// \param file Source file where the call is located
/// \param line Line number of the source file where the call is located
///
////////////////////////////////////////////////////////////
void eglCheckError(const char* file, unsigned int line);
} // namespace priv
} // namespace sf
#endif // SFML_EGLCHECK_HPP

View file

@ -59,6 +59,11 @@
#include <SFML/Window/iOS/EaglContext.hpp>
typedef sf::priv::EaglContext ContextType;
#elif defined(SFML_SYSTEM_ANDROID)
#include <SFML/Window/Android/EglContext.hpp>
typedef sf::priv::EglContext ContextType;
#endif

View file

@ -38,6 +38,8 @@
#include <SFML/Window/OSX/InputImpl.hpp>
#elif defined(SFML_SYSTEM_IOS)
#include <SFML/Window/iOS/InputImpl.hpp>
#elif defined(SFML_SYSTEM_ANDROID)
#include <SFML/Window/Android/InputImpl.hpp>
#endif

View file

@ -88,6 +88,8 @@ struct JoystickState
#include <SFML/Window/OSX/JoystickImpl.hpp>
#elif defined(SFML_SYSTEM_IOS)
#include <SFML/Window/iOS/JoystickImpl.hpp>
#elif defined(SFML_SYSTEM_ANDROID)
#include <SFML/Window/Android/JoystickImpl.hpp>
#endif

View file

@ -30,7 +30,10 @@
#include <SFML/Window/WindowImpl.hpp>
#include <SFML/System/Sleep.hpp>
#include <SFML/System/Err.hpp>
#ifdef SFML_SYSTEM_ANDROID
#include <SFML/Window/Android/WindowImplAndroid.hpp>
#include <SFML/Window/Android/EglContext.hpp>
#endif
namespace
{
@ -119,6 +122,12 @@ void Window::create(VideoMode mode, const String& title, Uint32 style, const Con
// Recreate the context
m_context = priv::GlContext::create(settings, m_impl, mode.bitsPerPixel);
#ifdef SFML_SYSTEM_ANDROID
// On Android, the window needs its attached context to destroy/recreate
// it when the native window is created/destroyed.
static_cast<priv::WindowImplAndroid*>(m_impl)->m_context = (priv::EglContext*)m_context;
#endif
// Perform common initializations
initialize();
}

View file

@ -52,6 +52,11 @@
#include <SFML/Window/iOS/WindowImplUIKit.hpp>
typedef sf::priv::WindowImplUIKit WindowImplType;
#elif defined(SFML_SYSTEM_ANDROID)
#include <SFML/Window/Android/WindowImplAndroid.hpp>
typedef sf::priv::WindowImplAndroid WindowImplType;
#endif