diff options
| author | Ryan Houdek <Sonicadvance1@gmail.com> | 2013-04-14 23:36:00 -0500 |
|---|---|---|
| committer | Ryan Houdek <Sonicadvance1@gmail.com> | 2013-04-14 23:36:00 -0500 |
| commit | 7772f0d071cd8f1c6b44036207b4e6f9da4d9bf7 (patch) | |
| tree | 6dbe1cff255abe6e35f51910df73daf5eecbec88 /Source/Core | |
| parent | 8a9fcd3014a4aee23b6fb7008a02679f8bf96200 (diff) | |
| parent | 44bbb54a62a58be4ad39caf6ba55ff98244223d5 (diff) | |
Merge branch 'Android-trash' since it is no longer quite so trashy.
Diffstat (limited to 'Source/Core')
23 files changed, 1558 insertions, 126 deletions
diff --git a/Source/Core/Common/Src/CommonPaths.h b/Source/Core/Common/Src/CommonPaths.h index 1628cd4dd8..c5bcb8d2e7 100644 --- a/Source/Core/Common/Src/CommonPaths.h +++ b/Source/Core/Common/Src/CommonPaths.h @@ -57,6 +57,7 @@ DIR_SEP USERDATA_DIR DIR_SEP #elif defined ANDROID #define SYSDATA_DIR "/sdcard/dolphin-emu" + #define SHARED_USER_DIR SYSDATA_DIR #else #ifdef DATA_DIR #define SYSDATA_DIR DATA_DIR "sys" diff --git a/Source/Core/Common/Src/MemArena.cpp b/Source/Core/Common/Src/MemArena.cpp index 26ce81f578..76f2e48548 100644 --- a/Source/Core/Common/Src/MemArena.cpp +++ b/Source/Core/Common/Src/MemArena.cpp @@ -153,7 +153,12 @@ u8* MemArena::Find4GBBase() } return base; #else - void* base = mmap(0, 0x31000000, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0); +#ifdef ANDROID + const u32 MemSize = 0x04000000; +#else + const u32 MemSize = 0x31000000; +#endif + void* base = mmap(0, MemSize, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0); if (base == MAP_FAILED) { PanicAlert("Failed to map 1 GB of memory space: %s", strerror(errno)); return 0; diff --git a/Source/Core/Common/Src/StringUtil.cpp b/Source/Core/Common/Src/StringUtil.cpp index 43c4aebf12..855a8c2e30 100644 --- a/Source/Core/Common/Src/StringUtil.cpp +++ b/Source/Core/Common/Src/StringUtil.cpp @@ -437,8 +437,7 @@ std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& input) std::string result; #if defined(ANDROID) - result = "Not implemented on Android!"; - + result = (char*)input.c_str(); #else iconv_t const conv_desc = iconv_open("UTF-8", fromcode); if ((iconv_t)-1 == conv_desc) diff --git a/Source/Core/Core/Src/ConfigManager.cpp b/Source/Core/Core/Src/ConfigManager.cpp index ab0fef3498..e2f01150b2 100644 --- a/Source/Core/Core/Src/ConfigManager.cpp +++ b/Source/Core/Core/Src/ConfigManager.cpp @@ -426,6 +426,8 @@ void SConfig::LoadSettings() ini.Get("DSP", "Backend", &sBackend, BACKEND_COREAUDIO); #elif defined _WIN32 ini.Get("DSP", "Backend", &sBackend, BACKEND_DIRECTSOUND); + #elif defined ANDROID + ini.Get("DSP", "Backend", &sBackend, BACKEND_OPENSLES); #else ini.Get("DSP", "Backend", &sBackend, BACKEND_NULLSOUND); #endif diff --git a/Source/Core/Core/Src/HW/GCPad.cpp b/Source/Core/Core/Src/HW/GCPad.cpp index bf0ea2dcbe..d764fcdf8a 100644 --- a/Source/Core/Core/Src/HW/GCPad.cpp +++ b/Source/Core/Core/Src/HW/GCPad.cpp @@ -23,6 +23,7 @@ #include "../ConfigManager.h" #include "../../InputCommon/Src/InputConfig.h" +#include "Host.h" namespace Pad { diff --git a/Source/Core/DolphinWX/CMakeLists.txt b/Source/Core/DolphinWX/CMakeLists.txt index 1256890eb5..9508f75a36 100644 --- a/Source/Core/DolphinWX/CMakeLists.txt +++ b/Source/Core/DolphinWX/CMakeLists.txt @@ -7,10 +7,19 @@ set(LIBS core audiocommon z sfml-network - ${GTK2_LIBRARIES} - ${XRANDR_LIBRARIES} - ${X11_LIBRARIES}) + ${GTK2_LIBRARIES}) if(NOT ANDROID) + if(USE_X11) + set(LIBS ${LIBS} ${X11_LIBRARIES} + ${XRANDR_LIBRARIES}) + endif() + if(USE_WAYLAND) + set(LIBS ${LIBS} ${WAYLAND_LIBRARIES} + ${XKBCOMMON_LIBRARIES}) + endif() + + link_directories(${CMAKE_PREFIX_PATH}/lib) + if(SDL2_FOUND) # Using shared SDL2 set(LIBS ${LIBS} ${SDL2_LIBRARY}) @@ -23,6 +32,8 @@ if(NOT ANDROID) set(LIBS ${LIBS} SDL) endif() endif() +else() + set(LIBS ${LIBS} png) endif() if(LIBAV_FOUND) @@ -80,20 +91,25 @@ if(wxWidgets_FOUND) set(WXLIBS ${wxWidgets_LIBRARIES}) else() if(ANDROID) - set(SRCS Src/MainAndroid.cpp) + set(SRCS Src/Android/TextureLoader.cpp + Src/MainAndroid.cpp) else() set(SRCS Src/MainNoGUI.cpp) endif() endif() if(USE_EGL) - if(NOT ANDROID) - set(SRCS ${SRCS} Src/GLInterface/EGL_X11.cpp - Src/GLInterface/X11_Util.cpp) + set(SRCS ${SRCS} Src/GLInterface/Platform.cpp + Src/GLInterface/EGL.cpp) + if(USE_WAYLAND) + set(SRCS ${SRCS} Src/GLInterface/Wayland_Util.cpp) + endif() + if(USE_X11) + set(SRCS ${SRCS} Src/GLInterface/X11_Util.cpp) endif() else() if(WIN32) - set(SRCS ${SRCS} Src/GLInterface/GLW.cpp) + set(SRCS ${SRCS} Src/GLInterface/WGL.cpp) elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(SRCS ${SRCS} Src/GLInterface/AGL.cpp) else() @@ -127,10 +143,8 @@ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") list(APPEND SRCS ${RESOURCES}) set_source_files_properties(${RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) -else() - if(NOT ANDROID) - set(SRCS ${SRCS} Src/X11Utils.cpp) - endif() +elseif(USE_X11) + set(SRCS ${SRCS} Src/X11Utils.cpp) endif() if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" OR diff --git a/Source/Core/DolphinWX/Src/Android/TextureLoader.cpp b/Source/Core/DolphinWX/Src/Android/TextureLoader.cpp new file mode 100644 index 0000000000..077cf32a1a --- /dev/null +++ b/Source/Core/DolphinWX/Src/Android/TextureLoader.cpp @@ -0,0 +1,179 @@ +// Copyright (C) 2003 Dolphin Project. + +// 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, version 2.0. + +// 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 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "GLInterface.h" +#include <png.h> + +GLuint LoadPNG(const char *filename) +{ + FILE *infile; /* PNG file pointer */ + png_structp png_ptr; /* internally used by libpng */ + png_infop info_ptr; /* user requested transforms */ + + char *image_data; /* raw png image data */ + char sig[8]; /* PNG signature array */ + /*char **row_pointers; */ + + int bit_depth; + int color_type; + + png_uint_32 width; /* PNG image width in pixels */ + png_uint_32 height; /* PNG image height in pixels */ + unsigned int rowbytes; /* raw bytes at row n in image */ + + image_data = NULL; + unsigned int i; + png_bytepp row_pointers = NULL; + + /* Open the file. */ + infile = fopen(filename, "rb"); + if (!infile) + return 0; + + /* + * 13.3 readpng_init() + */ + + /* Check for the 8-byte signature */ + fread(sig, 1, 8, infile); + + if (!png_check_sig((unsigned char *) sig, 8)) { + fclose(infile); + return 0; + } + + /* + * Set up the PNG structs + */ + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) { + fclose(infile); + return 4; /* out of memory */ + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); + fclose(infile); + return 4; /* out of memory */ + } + + + /* + * block to handle libpng errors, + * then check whether the PNG file had a bKGD chunk + */ + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(infile); + return 0; + } + + /* + * takes our file stream pointer (infile) and + * stores it in the png_ptr struct for later use. + */ + /* png_ptr->io_ptr = (png_voidp)infile;*/ + png_init_io(png_ptr, infile); + + /* + * lets libpng know that we already checked the 8 + * signature bytes, so it should not expect to find + * them at the current file pointer location + */ + png_set_sig_bytes(png_ptr, 8); + + /* Read the image */ + + /* + * reads and processes not only the PNG file's IHDR chunk + * but also any other chunks up to the first IDAT + * (i.e., everything before the image data). + */ + + /* read all the info up to the image data */ + png_read_info(png_ptr, info_ptr); + + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, + &color_type, NULL, NULL, NULL); + + /* Set up some transforms. */ + if (bit_depth > 8) + png_set_strip_16(png_ptr); + + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(png_ptr); + + /* Update the png info struct.*/ + png_read_update_info(png_ptr, info_ptr); + + /* Rowsize in bytes. */ + rowbytes = png_get_rowbytes(png_ptr, info_ptr); + + + /* Allocate the image_data buffer. */ + if ((image_data = (char *) malloc(rowbytes * height))==NULL) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return 4; + } + + if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + free(image_data); + image_data = NULL; + return 4; + } + + + /* set the individual row_pointers to point at the correct offsets */ + + for (i = 0; i < height; ++i) + row_pointers[i] = (png_byte*)(image_data + i*rowbytes); + + + /* now we can go ahead and just read the whole image */ + png_read_image(png_ptr, row_pointers); + + /* and we're done! (png_read_end() can be omitted if no processing of + * post-IDAT text/time/etc. is desired) */ + + /* Clean up. */ + free(row_pointers); + + /* Clean up. */ + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(infile); + + GLuint Texture = 0; + glGenTextures(1, &Texture); + + /* create a new texture object + * and bind it to texname (unsigned integer > 0) + */ + glBindTexture(GL_TEXTURE_2D, Texture); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, image_data); + return Texture; +} diff --git a/Source/Core/DolphinWX/Src/Android/TextureLoader.h b/Source/Core/DolphinWX/Src/Android/TextureLoader.h new file mode 100644 index 0000000000..69575807e6 --- /dev/null +++ b/Source/Core/DolphinWX/Src/Android/TextureLoader.h @@ -0,0 +1,21 @@ +// Copyright (C) 2003 Dolphin Project. + +// 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, version 2.0. + +// 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 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "GLInterface.h" + +GLuint LoadPNG(const char *filename); + diff --git a/Source/Core/DolphinWX/Src/GLInterface.h b/Source/Core/DolphinWX/Src/GLInterface.h index 2923ff7bf4..da74646f1b 100644 --- a/Source/Core/DolphinWX/Src/GLInterface.h +++ b/Source/Core/DolphinWX/Src/GLInterface.h @@ -17,12 +17,18 @@ #ifndef _GLINTERFACE_H_ #define _GLINTERFACE_H_ +#if USE_EGL +#include "GLInterface/Platform.h" +#else + #include "Thread.h" #ifdef ANDROID #include <GLES2/gl2.h> -#include <GLInterface/InterfaceBase.h> +#include <GLES2/gl2ext.h> +#include <EGL/egl.h> +#include "GLInterface/EGL.h" #elif defined(USE_EGL) && USE_EGL -#include "GLInterface/EGL_X11.h" +#include "GLInterface/EGL.h" #elif defined(__APPLE__) #include "GLInterface/AGL.h" #elif defined(_WIN32) @@ -34,19 +40,11 @@ #endif typedef struct { -#ifdef ANDROID -#elif defined(USE_EGL) && USE_EGL // This is currently a X11/EGL implementation for desktop +#if defined(USE_EGL) && USE_EGL // This is currently a X11/EGL implementation for desktop int screen; - Display *dpy; - Display *evdpy; - Window win; - Window parent; EGLSurface egl_surf; EGLContext egl_ctx; EGLDisplay egl_dpy; - XVisualInfo *vi; - XSetWindowAttributes attr; - std::thread xEventThread; int x, y; unsigned int width, height; #elif defined(__APPLE__) @@ -72,3 +70,4 @@ extern cInterfaceBase *GLInterface; extern GLWindow GLWin; #endif +#endif diff --git a/Source/Core/DolphinWX/Src/GLInterface/EGL_X11.cpp b/Source/Core/DolphinWX/Src/GLInterface/EGL.cpp index ccb2fc04b8..a419a2d7dc 100644 --- a/Source/Core/DolphinWX/Src/GLInterface/EGL_X11.cpp +++ b/Source/Core/DolphinWX/Src/GLInterface/EGL.cpp @@ -19,59 +19,30 @@ #include "RenderBase.h" #include "../GLInterface.h" -#include "EGL_X11.h" +#include "EGL.h" // Show the current FPS void cInterfaceEGL::UpdateFPSDisplay(const char *text) { - XStoreName(GLWin.dpy, GLWin.win, text); + Platform.UpdateFPSDisplay(text); } - -void cInterfaceEGL::SwapInterval(int Interval) -{ - eglSwapInterval(GLWin.egl_dpy, Interval); -} - void cInterfaceEGL::Swap() { eglSwapBuffers(GLWin.egl_dpy, GLWin.egl_surf); } +void cInterfaceEGL::SwapInterval(int Interval) +{ + eglSwapInterval(GLWin.egl_dpy, Interval); +} // Create rendering window. // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() bool cInterfaceEGL::Create(void *&window_handle) { - int _tx, _ty, _twidth, _theight; - Host_GetRenderWindowSize(_tx, _ty, _twidth, _theight); - - // Control window size and picture scaling - s_backbuffer_width = _twidth; - s_backbuffer_height = _theight; - + const char *s; EGLint egl_major, egl_minor; - - GLWin.dpy = XOpenDisplay(NULL); - - if (!GLWin.dpy) { - ERROR_LOG(VIDEO, "Error: couldn't open display\n"); - return false; - } - - GLWin.egl_dpy = eglGetDisplay(GLWin.dpy); - if (!GLWin.egl_dpy) { - ERROR_LOG(VIDEO, "Error: eglGetDisplay() failed\n"); - return false; - } - - if (!eglInitialize(GLWin.egl_dpy, &egl_major, &egl_minor)) { - ERROR_LOG(VIDEO, "Error: eglInitialize() failed\n"); - return false; - } - - INFO_LOG(VIDEO, "EGL_VERSION = %s\n", eglQueryString(GLWin.egl_dpy, EGL_VERSION)); - INFO_LOG(VIDEO, "EGL_VENDOR = %s\n", eglQueryString(GLWin.egl_dpy, EGL_VENDOR)); - INFO_LOG(VIDEO, "EGL_EXTENSIONS = %s\n", eglQueryString(GLWin.egl_dpy, EGL_EXTENSIONS)); - INFO_LOG(VIDEO, "EGL_CLIENT_APIS = %s\n", eglQueryString(GLWin.egl_dpy, EGL_CLIENT_APIS)); + EGLConfig config; + EGLint num_configs; // attributes for a visual in RGBA format with at least // 8 bits per color and a 24 bit depth buffer @@ -93,70 +64,79 @@ bool cInterfaceEGL::Create(void *&window_handle) #endif EGL_NONE }; - - GLWin.evdpy = XOpenDisplay(NULL); - GLWin.parent = (Window)window_handle; - GLWin.screen = DefaultScreen(GLWin.dpy); - if (GLWin.parent == 0) - GLWin.parent = RootWindow(GLWin.dpy, GLWin.screen); - - XVisualInfo visTemplate; - int num_visuals; - EGLConfig config; - EGLint num_configs; - EGLint vid; - if (!eglChooseConfig( GLWin.egl_dpy, attribs, &config, 1, &num_configs)) { - ERROR_LOG(VIDEO, "Error: couldn't get an EGL visual config\n"); + if(!Platform.SelectDisplay()) return false; - } - if (!eglGetConfigAttrib(GLWin.egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) { - ERROR_LOG(VIDEO, "Error: eglGetConfigAttrib() failed\n"); + GLWin.egl_dpy = Platform.EGLGetDisplay(); + + if (!GLWin.egl_dpy) { + printf("Error: eglGetDisplay() failed\n"); return false; } - /* The X window visual must match the EGL config */ - visTemplate.visualid = vid; - GLWin.vi = XGetVisualInfo(GLWin.dpy, VisualIDMask, &visTemplate, &num_visuals); - if (!GLWin.vi) { - ERROR_LOG(VIDEO, "Error: couldn't get X visual\n"); + GLWin.platform = Platform.platform; + + if (!eglInitialize(GLWin.egl_dpy, &egl_major, &egl_minor)) { + printf("Error: eglInitialize() failed\n"); return false; } - - GLWin.x = _tx; - GLWin.y = _ty; - GLWin.width = _twidth; - GLWin.height = _theight; - XWindow.CreateXWindow(); #ifdef USE_GLES eglBindAPI(EGL_OPENGL_ES_API); #else eglBindAPI(EGL_OPENGL_API); #endif + + if (!eglChooseConfig( GLWin.egl_dpy, attribs, &config, 1, &num_configs)) { + printf("Error: couldn't get an EGL visual config\n"); + exit(1); + } + + if (!Platform.Init(config)) + return false; + + s = eglQueryString(GLWin.egl_dpy, EGL_VERSION); + printf("EGL_VERSION = %s\n", s); + + s = eglQueryString(GLWin.egl_dpy, EGL_VENDOR); + printf("EGL_VENDOR = %s\n", s); + + s = eglQueryString(GLWin.egl_dpy, EGL_EXTENSIONS); + printf("EGL_EXTENSIONS = %s\n", s); + + s = eglQueryString(GLWin.egl_dpy, EGL_CLIENT_APIS); + printf("EGL_CLIENT_APIS = %s\n", s); + GLWin.egl_ctx = eglCreateContext(GLWin.egl_dpy, config, EGL_NO_CONTEXT, ctx_attribs ); if (!GLWin.egl_ctx) { - ERROR_LOG(VIDEO, "Error: eglCreateContext failed\n"); - return false; + printf("Error: eglCreateContext failed\n"); + exit(1); } - GLWin.egl_surf = eglCreateWindowSurface(GLWin.egl_dpy, config, (NativeWindowType)GLWin.win, NULL); + GLWin.native_window = Platform.CreateWindow(); + + GLWin.egl_surf = eglCreateWindowSurface(GLWin.egl_dpy, config, + GLWin.native_window, NULL); if (!GLWin.egl_surf) { - ERROR_LOG(VIDEO, "Error: eglCreateWindowSurface failed\n"); - return false; + printf("Error: eglCreateWindowSurface failed\n"); + exit(1); } if (!eglMakeCurrent(GLWin.egl_dpy, GLWin.egl_surf, GLWin.egl_surf, GLWin.egl_ctx)) { - ERROR_LOG(VIDEO, "Error: eglMakeCurrent() failed\n"); + + printf("Error: eglMakeCurrent() failed\n"); return false; } - - INFO_LOG(VIDEO, "GL_VENDOR: %s\n", glGetString(GL_VENDOR)); - INFO_LOG(VIDEO, "GL_RENDERER: %s\n", glGetString(GL_RENDERER)); - INFO_LOG(VIDEO, "GL_VERSION: %s\n", glGetString(GL_VERSION)); - INFO_LOG(VIDEO, "GL_EXTENSIONS: %s\n", glGetString(GL_EXTENSIONS)); - window_handle = (void *)GLWin.win; + + printf("GL_VENDOR: %s\n", glGetString(GL_VENDOR)); + printf("GL_RENDERER: %s\n", glGetString(GL_RENDERER)); + printf("GL_VERSION: %s\n", glGetString(GL_VERSION)); + printf("GL_EXTENSIONS: %s\n", glGetString(GL_EXTENSIONS)); + + Platform.ToggleFullscreen(SConfig::GetInstance().m_LocalCoreStartupParameter.bFullscreen); + + window_handle = (void *)GLWin.native_window; return true; } @@ -167,7 +147,7 @@ bool cInterfaceEGL::MakeCurrent() // Close backend void cInterfaceEGL::Shutdown() { - XWindow.DestroyXWindow(); + Platform.DestroyWindow(); if (GLWin.egl_ctx && !eglMakeCurrent(GLWin.egl_dpy, GLWin.egl_surf, GLWin.egl_surf, GLWin.egl_ctx)) NOTICE_LOG(VIDEO, "Could not release drawing context."); if (GLWin.egl_ctx) @@ -178,4 +158,3 @@ void cInterfaceEGL::Shutdown() GLWin.egl_ctx = NULL; } } - diff --git a/Source/Core/DolphinWX/Src/GLInterface/EGL_X11.h b/Source/Core/DolphinWX/Src/GLInterface/EGL.h index e47573e4d8..cf218ad760 100644 --- a/Source/Core/DolphinWX/Src/GLInterface/EGL_X11.h +++ b/Source/Core/DolphinWX/Src/GLInterface/EGL.h @@ -17,24 +17,23 @@ #ifndef _INTERFACEEGL_H_ #define _INTERFACEEGL_H_ -#include <EGL/egl.h> -#ifdef USE_GLES +#if USE_GLES #include <GLES2/gl2.h> -#include <X11/Xutil.h> #else #include <GL/glxew.h> #include <GL/gl.h> #endif -#include "X11_Util.h" #include "InterfaceBase.h" +class cPlatform; + class cInterfaceEGL : public cInterfaceBase { private: - cX11Window XWindow; + cPlatform Platform; public: - friend class cX11Window; + friend class cPlatform; void SwapInterval(int Interval); void Swap(); void UpdateFPSDisplay(const char *Text); diff --git a/Source/Core/DolphinWX/Src/GLInterface/Platform.cpp b/Source/Core/DolphinWX/Src/GLInterface/Platform.cpp new file mode 100644 index 0000000000..83f064615c --- /dev/null +++ b/Source/Core/DolphinWX/Src/GLInterface/Platform.cpp @@ -0,0 +1,218 @@ +// Copyright (C) 2013 Scott Moreau <oreaus@gmail.com> + +// 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, version 2.0. + +// 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 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Host.h" +#include "Platform.h" + +bool cPlatform::SelectDisplay(void) +{ + enum egl_platform selected_platform = EGL_PLATFORM_NONE; + enum egl_platform desired_platform = EGL_PLATFORM_NONE; + char *platform_env = getenv("DOLPHIN_EGL_PLATFORM"); + + if (platform_env) + platform_env = strdup(platform_env); + + if (!platform_env) + printf("Running automatic platform detection\n"); + + // Try to select the platform set in the environment variable first +#if HAVE_WAYLAND + bool wayland_possible = WaylandInterface.ServerConnect(); + + if (platform_env && !strcmp(platform_env, "wayland")) + { + desired_platform = EGL_PLATFORM_WAYLAND; + if (wayland_possible) + selected_platform = EGL_PLATFORM_WAYLAND; + else + printf("Wayland display server connection failed\n"); + } +#endif + +#if HAVE_X11 + bool x11_possible = XInterface.ServerConnect(); + + if (platform_env && !strcmp(platform_env, "x11")) + { + desired_platform = EGL_PLATFORM_X11; + if ((selected_platform != EGL_PLATFORM_WAYLAND) && x11_possible) + selected_platform = EGL_PLATFORM_X11; + else + printf("X11 display server connection failed\n"); + } +#endif + // Fall back to automatic detection + if (selected_platform == EGL_PLATFORM_NONE) + { + if (platform_env && (desired_platform == EGL_PLATFORM_NONE)) { + printf("DOLPHIN_EGL_PLATFORM set to unrecognized platform \"%s\".\n" +#if HAVE_WAYLAND && !HAVE_X11 + "Note: Valid value is \"wayland\" (built without x11 support)\n", +#endif +#if HAVE_X11 && !HAVE_WAYLAND + "Note: Valid values is \"x11\" (built without wayland support)\n", +#endif +#if HAVE_WAYLAND && HAVE_X11 + "Note: Valid values are \"wayland\" and \"x11\"\n", +#endif +#if !HAVE_WAYLAND && !HAVE_X11 + "Note: No Valid platform. Must be Android\n", +#endif + platform_env); + free(platform_env); + platform_env = NULL; + } +#if HAVE_WAYLAND + if (wayland_possible) + { + selected_platform = EGL_PLATFORM_WAYLAND; + platform_env = strdup("wayland"); + } +#endif +#if HAVE_X11 + if ((selected_platform != EGL_PLATFORM_WAYLAND) && x11_possible) + { + selected_platform = EGL_PLATFORM_X11; + platform_env = strdup("x11"); + } +#endif +#ifdef ANDROID + selected_platform = EGL_PLATFORM_ANDROID; +#endif + if (selected_platform == EGL_PLATFORM_NONE) + { + printf("FATAL: Failed to find suitable platform for display connection\n"); + goto out; + } + } + + printf("Using EGL Native Display Platform: %s\n", platform_env); +out: + cPlatform::platform = selected_platform; + free(platform_env); +#if HAVE_WAYLAND + if (selected_platform != EGL_PLATFORM_WAYLAND) { + if (GLWin.wl_display) + wl_display_disconnect(GLWin.wl_display); + } + +#endif +#if HAVE_X11 + if (selected_platform != EGL_PLATFORM_X11) { + if (GLWin.dpy) + XCloseDisplay(GLWin.dpy); + } +#endif + if (selected_platform == EGL_PLATFORM_NONE) + return false; + + return true; +} + +bool cPlatform::Init(EGLConfig config) +{ +#if HAVE_WAYLAND + if (cPlatform::platform == EGL_PLATFORM_WAYLAND) + if (!WaylandInterface.Initialize(config)) + return false; +#endif +#if HAVE_X11 + if (cPlatform::platform == EGL_PLATFORM_X11) + if (!XInterface.Initialize(config)) + return false; +#endif +#ifdef ANDROID + EGLint format; + eglGetConfigAttrib(GLWin.egl_dpy, config, EGL_NATIVE_VISUAL_ID, &format); + ANativeWindow_setBuffersGeometry((EGLNativeWindowType)Host_GetRenderHandle(), 0, 0, format); + int none, width, height; + Host_GetRenderWindowSize(none, none, width, height); + GLWin.width = width; + GLWin.height = height; + GLInterface->SetBackBufferDimensions(width, height); +#endif + return true; +} + +EGLDisplay cPlatform::EGLGetDisplay(void) +{ +#if HAVE_WAYLAND + if (cPlatform::platform == EGL_PLATFORM_WAYLAND) + return (EGLDisplay) WaylandInterface.EGLGetDisplay(); +#endif +#if HAVE_X11 + if (cPlatform::platform == EGL_PLATFORM_X11) + return (EGLDisplay) XInterface.EGLGetDisplay(); +#endif +#ifdef ANDROID + return eglGetDisplay(EGL_DEFAULT_DISPLAY); +#endif + return NULL; +} + +EGLNativeWindowType cPlatform::CreateWindow(void) +{ +#if HAVE_WAYLAND + if (cPlatform::platform == EGL_PLATFORM_WAYLAND) + return (EGLNativeWindowType) WaylandInterface.CreateWindow(); +#endif +#if HAVE_X11 + if (cPlatform::platform == EGL_PLATFORM_X11) + return (EGLNativeWindowType) XInterface.CreateWindow(); +#endif +#ifdef ANDROID + return (EGLNativeWindowType)Host_GetRenderHandle(); +#endif + return 0; +} + +void cPlatform::DestroyWindow(void) +{ +#if HAVE_WAYLAND + if (cPlatform::platform == EGL_PLATFORM_WAYLAND) + WaylandInterface.DestroyWindow(); +#endif +#if HAVE_X11 + if (cPlatform::platform == EGL_PLATFORM_X11) + XInterface.DestroyWindow(); +#endif +} + +void cPlatform::UpdateFPSDisplay(const char *text) +{ +#if HAVE_WAYLAND + if (cPlatform::platform == EGL_PLATFORM_WAYLAND) + WaylandInterface.UpdateFPSDisplay(text); +#endif +#if HAVE_X11 + if (cPlatform::platform == EGL_PLATFORM_X11) + XInterface.UpdateFPSDisplay(text); +#endif +} + +void +cPlatform::ToggleFullscreen(bool fullscreen) +{ +#if HAVE_WAYLAND + if (cPlatform::platform == EGL_PLATFORM_WAYLAND) + WaylandInterface.ToggleFullscreen(fullscreen); +#endif +#if HAVE_X11 + // Only wayland uses this function +#endif +} diff --git a/Source/Core/DolphinWX/Src/GLInterface/Platform.h b/Source/Core/DolphinWX/Src/GLInterface/Platform.h new file mode 100644 index 0000000000..a6b9d59cff --- /dev/null +++ b/Source/Core/DolphinWX/Src/GLInterface/Platform.h @@ -0,0 +1,161 @@ +// Copyright (C) 2013 Scott Moreau <oreaus@gmail.com> + +// 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, version 2.0. + +// 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 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +#ifndef _EGLPLATFORM_H_ +#define _EGLPLATFORM_H_ + +#include "Thread.h" +#include "ConfigManager.h" + +#if USE_EGL +// We must include wayland-egl.h before egl.h so our +// native types are defined as wayland native types +#if HAVE_WAYLAND && !HAVE_X11 +#include <wayland-egl.h> +#endif +#include <EGL/egl.h> +#endif + +#if HAVE_X11 +#include "X11_Util.h" +#endif +#if HAVE_WAYLAND +#include "Wayland_Util.h" +#endif + +#if USE_EGL +// There may be multiple EGL platforms +enum egl_platform { + EGL_PLATFORM_NONE, + EGL_PLATFORM_WAYLAND, + EGL_PLATFORM_X11, + EGL_PLATFORM_ANDROID +}; + +class cPlatform +{ +private: +#if HAVE_X11 + cXInterface XInterface; +#endif +#if HAVE_WAYLAND + cWaylandInterface WaylandInterface; +#endif +public: + enum egl_platform platform; + bool SelectDisplay(void); + bool Init(EGLConfig config); + EGLDisplay EGLGetDisplay(void); + EGLNativeWindowType CreateWindow(void); + void DestroyWindow(void); + void UpdateFPSDisplay(const char *text); + void ToggleFullscreen(bool fullscreen); +}; + +#include "GLInterface/EGL.h" + +#if HAVE_WAYLAND +#include <wayland-egl.h> +#endif +#elif defined(__APPLE__) +#include "GLInterface/AGL.h" +#elif defined(_WIN32) +#include "GLInterface/WGL.h" +#elif HAVE_X11 +#include "GLInterface/GLX.h" +#endif + +#if HAVE_WAYLAND +struct geometry { + int width; + int height; +}; + +struct xkb { + struct xkb_context *context; + struct xkb_keymap *keymap; + struct xkb_state *state; + xkb_mod_mask_t control_mask; + xkb_mod_mask_t alt_mask; + xkb_mod_mask_t shift_mask; +}; +#endif + +typedef struct { +// Currently Wayland/EGL and X11/EGL platforms are supported. +// The platform may be spelected at run time by setting the +// environment variable DOLPHIN_EGL_PLATFORM to "wayland" or "x11". +#if USE_EGL + EGLSurface egl_surf; + EGLContext egl_ctx; + EGLDisplay egl_dpy; + enum egl_platform platform; +#endif + EGLNativeWindowType native_window; +#if HAVE_WAYLAND + struct wl_display *wl_display; + struct wl_registry *wl_registry; + struct wl_compositor *wl_compositor; + struct wl_shell *wl_shell; + struct wl_seat *wl_seat; + struct { + struct wl_pointer *wl_pointer; + uint32_t serial; + } pointer; + struct { + struct wl_keyboard *wl_keyboard; + struct xkb xkb; + uint32_t modifiers; + } keyboard; + struct wl_shm *wl_shm; + struct wl_cursor_theme *wl_cursor_theme; + struct wl_cursor *wl_cursor; + struct wl_surface *wl_cursor_surface; + struct geometry geometry, window_size; + struct wl_egl_window *wl_egl_native; + struct wl_surface *wl_surface; + struct wl_shell_surface *wl_shell_surface; + struct wl_callback *wl_callback; + bool fullscreen, configured, frame_drawn, swap_complete, running; +#endif +#if HAVE_X11 + int screen; + // dpy used for egl/glx stuff, evdpy for window events etc. + // evdpy is to be used by XEventThread only + Display *dpy; + Display *evdpy; +#if !USE_EGL + GLXContext ctx; +#endif + Window win; + Window parent; + XVisualInfo *vi; + XSetWindowAttributes attr; + std::thread xEventThread; + int x, y; + unsigned int width, height; +#elif defined(ANDROID) + unsigned int width, height; +#elif defined(__APPLE__) + NSWindow *cocoaWin; + NSOpenGLContext *cocoaCtx; +#endif +} GLWindow; + +extern cInterfaceBase *GLInterface; +extern GLWindow GLWin; + +#endif diff --git a/Source/Core/DolphinWX/Src/GLInterface/Wayland_Util.cpp b/Source/Core/DolphinWX/Src/GLInterface/Wayland_Util.cpp new file mode 100644 index 0000000000..aa15917344 --- /dev/null +++ b/Source/Core/DolphinWX/Src/GLInterface/Wayland_Util.cpp @@ -0,0 +1,472 @@ +// Copyright (C) 2013 Scott Moreau <oreaus@gmail.com> + +// 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, version 2.0. + +// 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 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Core.h" +#include "State.h" +#include "../GLInterface.h" +#include <linux/input.h> +#include <sys/mman.h> + + +static void +redraw(void *data, struct wl_callback *callback, uint32_t time); + +static const struct wl_callback_listener frame_listener = { + redraw +}; + +static void +redraw(void *data, struct wl_callback *callback, uint32_t time) +{ + if (GLWin.wl_callback != callback) { + printf("Got wrong callback from wayland server\n"); + exit(-1); + } + + GLWin.wl_callback = NULL; + + if (callback) + wl_callback_destroy(callback); + + if (!GLWin.configured) + return; + + // Reset the frame callback + GLWin.wl_callback = wl_surface_frame(GLWin.wl_surface); + wl_callback_add_listener(GLWin.wl_callback, &frame_listener, 0); + + // Present rendered buffer on screen + //eglSwapBuffers(GLWin.egl_dpy, GLWin.egl_surf); +} + +static void +hide_cursor(void) +{ + if (!GLWin.pointer.wl_pointer) + return; + + wl_pointer_set_cursor(GLWin.pointer.wl_pointer, + GLWin.pointer.serial, NULL, 0, 0); +} + +static void +configure_callback(void *data, struct wl_callback *callback, uint32_t time) +{ + wl_callback_destroy(callback); + + GLWin.configured = true; + + if (GLWin.wl_callback == NULL) + redraw(data, NULL, time); +} + +static struct wl_callback_listener configure_callback_listener = { + configure_callback, +}; + +static void +handle_ping(void *data, struct wl_shell_surface *wl_shell_surface, + uint32_t serial) +{ + wl_shell_surface_pong(wl_shell_surface, serial); +} + +static void +handle_configure(void *data, struct wl_shell_surface *wl_shell_surface, + uint32_t edges, int32_t width, int32_t height) +{ + + if (GLWin.wl_egl_native) + wl_egl_window_resize(GLWin.wl_egl_native, width, height, 0, 0); + + GLWin.geometry.width = width; + GLWin.geometry.height = height; + + GLInterface->SetBackBufferDimensions(width, height); + + if (!GLWin.fullscreen) + GLWin.window_size = GLWin.geometry; +} + +static void +handle_popup_done(void *data, struct wl_shell_surface *wl_shell_surface) +{ +} + +static const struct wl_shell_surface_listener shell_surface_listener = { + handle_ping, + handle_configure, + handle_popup_done +}; + +static void +pointer_handle_enter(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface, + wl_fixed_t sx, wl_fixed_t sy) +{ + GLWin.pointer.serial = serial; + + if (GLWin.fullscreen) + hide_cursor(); +} + +static void +pointer_handle_leave(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface) +{ +} + +static void +pointer_handle_motion(void *data, struct wl_pointer *pointer, + uint32_t time, wl_fixed_t sx, wl_fixed_t sy) +{ +} + +static void +pointer_handle_button(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, uint32_t time, uint32_t button, + uint32_t state) +{ +} + +static void +pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) +{ +} + +static const struct wl_pointer_listener pointer_listener = { + pointer_handle_enter, + pointer_handle_leave, + pointer_handle_motion, + pointer_handle_button, + pointer_handle_axis, +}; + +void setup_callback_listener() +{ + struct wl_callback *callback; + + callback = wl_display_sync(GLWin.wl_display); + wl_callback_add_listener(callback, &configure_callback_listener, 0); +} + +static void +toggle_fullscreen(bool fullscreen) +{ + GLWin.fullscreen = fullscreen; + GLWin.configured = false; + + if (fullscreen) { + wl_shell_surface_set_fullscreen(GLWin.wl_shell_surface, + WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, + 0, NULL); + } else { + wl_shell_surface_set_toplevel(GLWin.wl_shell_surface); + handle_configure(NULL, GLWin.wl_shell_surface, 0, + GLWin.window_size.width, + GLWin.window_size.height); + } + + setup_callback_listener(); +} + +static void +keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, + uint32_t format, int fd, uint32_t size) +{ + char *map_str; + + if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { + close(fd); + return; + } + + map_str = (char *) mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (map_str == MAP_FAILED) { + close(fd); + return; + } + + GLWin.keyboard.xkb.keymap = xkb_map_new_from_string(GLWin.keyboard.xkb.context, + map_str, + XKB_KEYMAP_FORMAT_TEXT_V1, + (xkb_keymap_compile_flags) 0); + munmap(map_str, size); + close(fd); + + if (!GLWin.keyboard.xkb.keymap) { + fprintf(stderr, "failed to compile keymap\n"); + return; + } + + GLWin.keyboard.xkb.state = xkb_state_new(GLWin.keyboard.xkb.keymap); + if (!GLWin.keyboard.xkb.state) { + fprintf(stderr, "failed to create XKB state\n"); + xkb_map_unref(GLWin.keyboard.xkb.keymap); + GLWin.keyboard.xkb.keymap = NULL; + return; + } + + GLWin.keyboard.xkb.control_mask = + 1 << xkb_map_mod_get_index(GLWin.keyboard.xkb.keymap, "Control"); + GLWin.keyboard.xkb.alt_mask = + 1 << xkb_map_mod_get_index(GLWin.keyboard.xkb.keymap, "Mod1"); + GLWin.keyboard.xkb.shift_mask = + 1 << xkb_map_mod_get_index(GLWin.keyboard.xkb.keymap, "Shift"); +} + +static void +keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, + uint32_t serial, struct wl_surface *surface, + struct wl_array *keys) +{ +} + +static void +keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, + uint32_t serial, struct wl_surface *surface) +{ +} + +static void +keyboard_handle_key(void *data, struct wl_keyboard *keyboard, + uint32_t serial, uint32_t time, uint32_t key, + uint32_t state) +{ + if (state == WL_KEYBOARD_KEY_STATE_RELEASED) + return; + + if (key == KEY_ESC) + GLWin.running = false; + else if ((key == KEY_P) || + ((key == KEY_ENTER) && (GLWin.keyboard.modifiers == 0))) + Core::SetState((Core::GetState() == Core::CORE_RUN) ? + Core::CORE_PAUSE : Core::CORE_RUN); + else if (key == KEY_F) + toggle_fullscreen(!GLWin.fullscreen); + else if ((key == KEY_ENTER) && (GLWin.keyboard.modifiers == MOD_ALT_MASK)) + toggle_fullscreen(!GLWin.fullscreen); + else if (key >= KEY_F1 && key <= KEY_F8) { + int slot_number = key - KEY_F1 + 1; + if (GLWin.keyboard.modifiers == MOD_SHIFT_MASK) + State::Save(slot_number); + else + State::Load(slot_number); + } + else if (key == KEY_F9) + Core::SaveScreenShot(); + else if (key == KEY_F11) + State::LoadLastSaved(); + else if (key == KEY_F12) { + if (GLWin.keyboard.modifiers == MOD_SHIFT_MASK) + State::UndoLoadState(); + else + State::UndoSaveState(); + } +} + +static void +keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, + uint32_t serial, uint32_t mods_depressed, + uint32_t mods_latched, uint32_t mods_locked, + uint32_t group) +{ + xkb_mod_mask_t mask; + + xkb_state_update_mask(GLWin.keyboard.xkb.state, mods_depressed, mods_latched, + mods_locked, 0, 0, group); + mask = xkb_state_serialize_mods(GLWin.keyboard.xkb.state, + (xkb_state_component) + (XKB_STATE_DEPRESSED | + XKB_STATE_LATCHED)); + GLWin.keyboard.modifiers = 0; + if (mask & GLWin.keyboard.xkb.control_mask) + GLWin.keyboard.modifiers |= MOD_CONTROL_MASK; + if (mask & GLWin.keyboard.xkb.alt_mask) + GLWin.keyboard.modifiers |= MOD_ALT_MASK; + if (mask & GLWin.keyboard.xkb.shift_mask) + GLWin.keyboard.modifiers |= MOD_SHIFT_MASK; +} + +static const struct wl_keyboard_listener keyboard_listener = { + keyboard_handle_keymap, + keyboard_handle_enter, + keyboard_handle_leave, + keyboard_handle_key, + keyboard_handle_modifiers, +}; + +static void +seat_handle_capabilities(void *data, struct wl_seat *seat, + uint32_t caps) +{ + struct wl_pointer *wl_pointer = NULL; + struct wl_keyboard *wl_keyboard = NULL; + + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !wl_pointer) { + wl_pointer = wl_seat_get_pointer(seat); + wl_pointer_add_listener(wl_pointer, &pointer_listener, 0); + } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && wl_pointer) { + wl_pointer_destroy(wl_pointer); + wl_pointer = NULL; + } + + GLWin.pointer.wl_pointer = wl_pointer; + + if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !wl_keyboard) { + wl_keyboard = wl_seat_get_keyboard(seat); + wl_keyboard_add_listener(wl_keyboard, &keyboard_listener, 0); + } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && wl_keyboard) { + wl_keyboard_destroy(wl_keyboard); + wl_keyboard = NULL; + } + + GLWin.keyboard.wl_keyboard = wl_keyboard; +} + +static const struct wl_seat_listener seat_listener = { + seat_handle_capabilities, +}; + +static void +registry_handle_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) +{ + if (strcmp(interface, "wl_compositor") == 0) { + GLWin.wl_compositor = (wl_compositor *) + wl_registry_bind(registry, name, + &wl_compositor_interface, 1); + } else if (strcmp(interface, "wl_shell") == 0) { + GLWin.wl_shell = (wl_shell *) wl_registry_bind(registry, name, + &wl_shell_interface, 1); + } else if (strcmp(interface, "wl_seat") == 0) { + GLWin.wl_seat = (wl_seat *) wl_registry_bind(registry, name, + &wl_seat_interface, 1); + wl_seat_add_listener(GLWin.wl_seat, &seat_listener, 0); + } else if (strcmp(interface, "wl_shm") == 0) { + GLWin.wl_shm = (wl_shm *) wl_registry_bind(registry, name, + &wl_shm_interface, 1); + GLWin.wl_cursor_theme = (wl_cursor_theme *) wl_cursor_theme_load(NULL, 32, GLWin.wl_shm); + GLWin.wl_cursor = (wl_cursor *) + wl_cursor_theme_get_cursor(GLWin.wl_cursor_theme, "left_ptr"); + } +} + +static void +registry_handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) +{ +} + +static const struct wl_registry_listener registry_listener = { + registry_handle_global, + registry_handle_global_remove +}; + +bool cWaylandInterface::ServerConnect(void) +{ + GLWin.wl_display = wl_display_connect(NULL); + + if (!GLWin.wl_display) + return false; + + return true; +} + +bool cWaylandInterface::Initialize(void *config) +{ + if (!GLWin.wl_display) { + printf("Error: couldn't open wayland display\n"); + return false; + } + + GLWin.pointer.wl_pointer = NULL; + GLWin.keyboard.wl_keyboard = NULL; + + GLWin.keyboard.xkb.context = xkb_context_new((xkb_context_flags) 0); + if (GLWin.keyboard.xkb.context == NULL) { + fprintf(stderr, "Failed to create XKB context\n"); + return NULL; + } + + GLWin.wl_registry = wl_display_get_registry(GLWin.wl_display); + wl_registry_add_listener(GLWin.wl_registry, + ®istry_listener, NULL); + + wl_display_dispatch(GLWin.wl_display); + + GLWin.wl_cursor_surface = + wl_compositor_create_surface(GLWin.wl_compositor); + + return true; +} + +void *cWaylandInterface::EGLGetDisplay(void) +{ +#if HAVE_X11 + return eglGetDisplay((_XDisplay *) GLWin.wl_display); +#else + return eglGetDisplay(GLWin.wl_display); +#endif +} + +void *cWaylandInterface::CreateWindow(void) +{ + GLWin.window_size.width = 640; + GLWin.window_size.height = 480; + GLWin.fullscreen = true; + GLWin.frame_drawn = false; + GLWin.swap_complete = false; + + GLWin.wl_surface = wl_compositor_create_surface(GLWin.wl_compositor); + GLWin.wl_shell_surface = wl_shell_get_shell_surface(GLWin.wl_shell, + GLWin.wl_surface); + + wl_shell_surface_add_listener(GLWin.wl_shell_surface, + &shell_surface_listener, 0); + + GLWin.wl_egl_native = wl_egl_window_create(GLWin.wl_surface, + GLWin.window_size.width, + GLWin.window_size.height); +#if HAVE_X11 + return GLWin.wl_egl_native; +#else + return GLWin.wl_egl_native; +#endif +} + +void cWaylandInterface::DestroyWindow(void) +{ + wl_egl_window_destroy(GLWin.wl_egl_native); + + wl_shell_surface_destroy(GLWin.wl_shell_surface); + wl_surface_destroy(GLWin.wl_surface); + + if (GLWin.wl_callback) + wl_callback_destroy(GLWin.wl_callback); +} + +void cWaylandInterface::UpdateFPSDisplay(const char *text) +{ + wl_shell_surface_set_title(GLWin.wl_shell_surface, text); +} + +void cWaylandInterface::ToggleFullscreen(bool fullscreen) +{ + toggle_fullscreen(GLWin.fullscreen); +} diff --git a/Source/Core/DolphinWX/Src/GLInterface/Wayland_Util.h b/Source/Core/DolphinWX/Src/GLInterface/Wayland_Util.h new file mode 100644 index 0000000000..db5504878a --- /dev/null +++ b/Source/Core/DolphinWX/Src/GLInterface/Wayland_Util.h @@ -0,0 +1,42 @@ +// Copyright (C) 2013 Scott Moreau <oreaus@gmail.com> + +// 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, version 2.0. + +// 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 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +#ifndef _WAYLAND_UTIL_H_ +#define _WAYLAND_UTIL_H_ + +#include <wayland-client.h> +#include <wayland-egl.h> +#include <wayland-cursor.h> +#include <xkbcommon/xkbcommon.h> + +#define MOD_SHIFT_MASK 0x01 +#define MOD_ALT_MASK 0x02 +#define MOD_CONTROL_MASK 0x04 + + +class cWaylandInterface +{ +public: + bool ServerConnect(void); + bool Initialize(void *config); + void *EGLGetDisplay(void); + void *CreateWindow(void); + void DestroyWindow(void); + void UpdateFPSDisplay(const char *text); + void ToggleFullscreen(bool fullscreen); +}; + +#endif diff --git a/Source/Core/DolphinWX/Src/MainAndroid.cpp b/Source/Core/DolphinWX/Src/MainAndroid.cpp index ca2119921d..1745517dcc 100644 --- a/Source/Core/DolphinWX/Src/MainAndroid.cpp +++ b/Source/Core/DolphinWX/Src/MainAndroid.cpp @@ -33,14 +33,17 @@ #include "ConfigManager.h" #include "LogManager.h" #include "BootManager.h" +#include "OnScreenDisplay.h" + +#include "Android/ButtonManager.h" #include <jni.h> #include <android/log.h> +#include <android/native_window_jni.h> +ANativeWindow* surf; +int g_width, g_height; #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "Dolphinemu", __VA_ARGS__)) -bool rendererHasFocus = true; -bool running = true; - void Host_NotifyMapLoaded() {} void Host_RefreshDSPDebuggerWindow() {} @@ -53,7 +56,7 @@ void Host_Message(int Id) void* Host_GetRenderHandle() { - return NULL; + return surf; } void* Host_GetInstance() { return NULL; } @@ -79,8 +82,8 @@ void Host_GetRenderWindowSize(int& x, int& y, int& width, int& height) { x = SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowXPos; y = SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowYPos; - width = SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowWidth; - height = SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowHeight; + width = g_width; + height = g_height; } void Host_RequestRenderWindowSize(int width, int height) {} @@ -118,25 +121,69 @@ void Host_SysMessage(const char *fmt, ...) void Host_SetWiiMoteConnectionState(int _State) {} +void OSDCallbacks(u32 UserData) +{ + switch(UserData) + { + case 0: // Init + ButtonManager::Init(); + break; + case 1: // Draw + ButtonManager::DrawButtons(); + break; + case 2: // Shutdown + ButtonManager::Shutdown(); + break; + default: + WARN_LOG(COMMON, "Error, wrong OSD type"); + break; + } +} + #ifdef __cplusplus extern "C" { #endif -JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_dolphinemuactivity_main(JNIEnv *env, jobject obj) +JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeGLSurfaceView_UnPauseEmulation(JNIEnv *env, jobject obj) +{ + PowerPC::Start(); +} +JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeGLSurfaceView_PauseEmulation(JNIEnv *env, jobject obj) +{ + PowerPC::Pause(); +} + +JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeGLSurfaceView_StopEmulation(JNIEnv *env, jobject obj) +{ + PowerPC::Stop(); +} +JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_DolphinEmulator_onTouchEvent(JNIEnv *env, jobject obj, jint Action, jfloat X, jfloat Y) +{ + ButtonManager::TouchEvent(Action, X, Y); +} + +JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeGLSurfaceView_main(JNIEnv *env, jobject obj, jstring jFile, jobject _surf, jint _width, jint _height) { + surf = ANativeWindow_fromSurface(env, _surf); + g_width = (int)_width; + g_height = (int)_height; + + // Install our callbacks + OSD::AddCallback(OSD::OSD_INIT, OSDCallbacks, 0); + OSD::AddCallback(OSD::OSD_ONFRAME, OSDCallbacks, 1); + OSD::AddCallback(OSD::OSD_SHUTDOWN, OSDCallbacks, 2); + LogManager::Init(); SConfig::Init(); VideoBackend::PopulateList(); - VideoBackend::ActivateBackend(SConfig::GetInstance(). - m_LocalCoreStartupParameter.m_strVideoBackend); + VideoBackend::ActivateBackend(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strVideoBackend); WiimoteReal::LoadSettings(); - + + const char *File = env->GetStringUTFChars(jFile, NULL); // No use running the loop when booting fails - if (BootManager::BootCore("")) - { + if ( BootManager::BootCore( File ) ) while (PowerPC::GetState() != PowerPC::CPU_POWERDOWN) updateMainFrameEvent.Wait(); - } WiimoteReal::Shutdown(); VideoBackend::ClearList(); diff --git a/Source/Core/InputCommon/CMakeLists.txt b/Source/Core/InputCommon/CMakeLists.txt index 3a8ea1e7a2..8fc2a344c7 100644 --- a/Source/Core/InputCommon/CMakeLists.txt +++ b/Source/Core/InputCommon/CMakeLists.txt @@ -21,6 +21,10 @@ elseif(X11_FOUND) set(SRCS ${SRCS} Src/ControllerInterface/SDL/SDL.cpp Src/ControllerInterface/Xlib/Xlib.cpp) +elseif(ANDROID) + set(SRCS ${SRCS} + Src/ControllerInterface/Android/Android.cpp + Src/Android/ButtonManager.cpp) endif() add_library(inputcommon ${SRCS}) diff --git a/Source/Core/InputCommon/Src/Android/ButtonManager.cpp b/Source/Core/InputCommon/Src/Android/ButtonManager.cpp new file mode 100644 index 0000000000..947f7b0081 --- /dev/null +++ b/Source/Core/InputCommon/Src/Android/ButtonManager.cpp @@ -0,0 +1,90 @@ +// Copyright (C) 2003 Dolphin Project. + +// 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, version 2.0. + +// 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 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include <vector> +#include "GLInterface.h" +#include "Android/TextureLoader.h" +#include "Android/ButtonManager.h" + +extern void DrawButton(GLuint tex, float *coords); + +namespace ButtonManager +{ + std::vector<Button*> m_buttons; + + // XXX: This needs to not be here so we can load the locations from file + // This will allow customizable button locations in the future + // These are the OpenGL on screen coordinates + float m_coords[][8] = { // X, Y, X, EY, EX, EY, EX, Y + {0.75f, -1.0f, 0.75f, -0.75f, 1.0f, -0.75f, 1.0f, -1.0f}, // A + {0.50f, -1.0f, 0.50f, -0.75f, 0.75f, -0.75f, 0.75f, -1.0f}, // B + {-0.10f, -1.0f, -0.10f, -0.80f, 0.10f, -0.80f, 0.10f, -1.0f}, // Start + }; + + void Init() + { + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + // Initialize our buttons + m_buttons.push_back(new Button("ButtonA.png", BUTTON_A, m_coords[0])); + m_buttons.push_back(new Button("ButtonB.png", BUTTON_B, m_coords[1])); + m_buttons.push_back(new Button("ButtonStart.png", BUTTON_START, m_coords[2])); + } + bool GetButtonPressed(ButtonType button) + { + for (auto it = m_buttons.begin(); it != m_buttons.end(); ++it) + if ((*it)->GetButtonType() == button) + return (*it)->Pressed(); + return false; + } + void TouchEvent(int action, float x, float y) + { + // Actions + // 0 is press + // 1 is let go + // 2 is move + for (auto it = m_buttons.begin(); it != m_buttons.end(); ++it) + { + float *coords = (*it)->GetCoords(); + if ( x >= coords[0] && + x <= coords[4] && + y >= coords[1] && + y <= coords[3]) + { + if (action == 0) + (*it)->SetState(BUTTON_PRESSED); + if (action == 1) + (*it)->SetState(BUTTON_RELEASED); + if (action == 2) + ; // XXX: Be used later for analog stick + } + } + } + void Shutdown() + { + for(auto it = m_buttons.begin(); it != m_buttons.end(); ++it) + delete *it; + } + + void DrawButtons() + { + for(auto it = m_buttons.begin(); it != m_buttons.end(); ++it) + DrawButton((*it)->GetTexture(), (*it)->GetCoords()); + } + +} diff --git a/Source/Core/InputCommon/Src/Android/ButtonManager.h b/Source/Core/InputCommon/Src/Android/ButtonManager.h new file mode 100644 index 0000000000..f21ceedd98 --- /dev/null +++ b/Source/Core/InputCommon/Src/Android/ButtonManager.h @@ -0,0 +1,63 @@ +// Copyright (C) 2003 Dolphin Project. + +// 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, version 2.0. + +// 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 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include <string> +#include "CommonPaths.h" +#include "Android/TextureLoader.h" + +namespace ButtonManager +{ + enum ButtonType + { + BUTTON_A = 0, + BUTTON_B, + BUTTON_START, + }; + enum ButtonState + { + BUTTON_RELEASED = 0, + BUTTON_PRESSED = 1 + }; + class Button + { + private: + GLuint m_tex; + ButtonType m_button; + ButtonState m_state; + float m_coords[8]; + public: + Button(std::string filename, ButtonType button, float *coords) + { + m_tex = LoadPNG((std::string(DOLPHIN_DATA_DIR "/") + filename).c_str()); + m_button = button; + memcpy(m_coords, coords, sizeof(float) * 8); + m_state = BUTTON_RELEASED; + } + void SetState(ButtonState state) { m_state = state; } + bool Pressed() { return m_state == BUTTON_PRESSED; } + ButtonType GetButtonType() { return m_button; } + GLuint GetTexture() { return m_tex; } + float *GetCoords() { return m_coords; } + + ~Button() { glDeleteTextures(1, &m_tex); } + }; + void Init(); + void DrawButtons(); + bool GetButtonPressed(ButtonType button); + void TouchEvent(int action, float x, float y); + void Shutdown(); +} diff --git a/Source/Core/InputCommon/Src/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/Src/ControllerInterface/Android/Android.cpp new file mode 100644 index 0000000000..2d01d38f23 --- /dev/null +++ b/Source/Core/InputCommon/Src/ControllerInterface/Android/Android.cpp @@ -0,0 +1,67 @@ +// Copyright (C) 2003 Dolphin Project. + +// 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, version 2.0. + +// 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 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Android.h" + +namespace ciface +{ + +namespace Android +{ + +void Init( std::vector<ControllerInterface::Device*>& devices ) +{ + devices.push_back(new Touchscreen()); +} + +// Touchscreens and stuff +std::string Touchscreen::GetName() const +{ + return "Touchscreen"; +} + +std::string Touchscreen::GetSource() const +{ + return "Android"; +} + +int Touchscreen::GetId() const +{ + return 0; +} +Touchscreen::Touchscreen() +{ + AddInput(new Button(ButtonManager::BUTTON_A)); + AddInput(new Button(ButtonManager::BUTTON_B)); + AddInput(new Button(ButtonManager::BUTTON_START)); +} +// Buttons and stuff + +std::string Touchscreen::Button::GetName() const +{ + std::ostringstream ss; + ss << "Button " << (int)m_index; + return ss.str(); +} + +ControlState Touchscreen::Button::GetState() const +{ + return ButtonManager::GetButtonPressed(m_index); +} + +} +} diff --git a/Source/Core/InputCommon/Src/ControllerInterface/Android/Android.h b/Source/Core/InputCommon/Src/ControllerInterface/Android/Android.h new file mode 100644 index 0000000000..9bdb52a61d --- /dev/null +++ b/Source/Core/InputCommon/Src/ControllerInterface/Android/Android.h @@ -0,0 +1,57 @@ +// Copyright (C) 2003 Dolphin Project. + +// 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, version 2.0. + +// 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 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +#ifndef _CIFACE_ANDROID_H_ +#define _CIFACE_ANDROID_H_ + +#include "../ControllerInterface.h" +#include "Android/ButtonManager.h" + +namespace ciface +{ +namespace Android +{ + +void Init( std::vector<ControllerInterface::Device*>& devices ); +class Touchscreen : public ControllerInterface::Device +{ +private: + class Button : public Input + { + public: + std::string GetName() const; + Button(ButtonManager::ButtonType index) : m_index(index) {} + ControlState GetState() const; + private: + const ButtonManager::ButtonType m_index; + }; + +public: + bool UpdateInput() { return true; } + bool UpdateOutput() { return true; } + + Touchscreen(); + ~Touchscreen() {} + + std::string GetName() const; + int GetId() const; + std::string GetSource() const; +}; + +} +} + +#endif diff --git a/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.cpp index 6a1427406d..6db79605a7 100644 --- a/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.cpp @@ -15,6 +15,9 @@ #ifdef CIFACE_USE_SDL #include "SDL/SDL.h" #endif +#ifdef CIFACE_USE_ANDROID + #include "Android/Android.h" +#endif #include "Thread.h" @@ -50,6 +53,9 @@ void ControllerInterface::Initialize() #ifdef CIFACE_USE_SDL ciface::SDL::Init(m_devices); #endif +#ifdef CIFACE_USE_ANDROID + ciface::Android::Init(m_devices); +#endif m_is_init = true; } @@ -100,6 +106,9 @@ void ControllerInterface::Shutdown() // TODO: there seems to be some sort of memory leak with SDL, quit isn't freeing everything up SDL_Quit(); #endif +#ifdef CIFACE_USE_ANDROID + // nothing needed +#endif m_is_init = false; } diff --git a/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.h b/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.h index b846bb56e8..59bc49ac51 100644 --- a/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.h +++ b/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.h @@ -29,7 +29,10 @@ #if defined(__APPLE__) #define CIFACE_USE_OSX #endif - +#ifdef ANDROID + #define CIFACE_USE_ANDROID +#endif + // idk in case i wanted to change it to double or somethin, idk what's best typedef float ControlState; |
