Wayland support

Based on the original port to Wayland by: Joel Teichroeb, Benjamin Franzke, Scott Moreau, et al.

Additional changes in this commit, done by me:

* Wayland uses the common EGL framework
* EGL can now create a desktop OpenGL context
* testgl2 loads GL functions dynamically, no need to link to libGL anymore
* Assorted fixes to the Wayland backend

Tested on the Weston Compositor (v1.0.5) that ships with Ubuntu 13.10,
running Weston under X. Tests ran: testrendercopyex (all backends), testgl2, testgles2,testintersections
This commit is contained in:
Gabriel Jacobo 2013-12-14 20:18:43 -03:00
parent 4a8c296712
commit ec1cb49eab
25 changed files with 2035 additions and 129 deletions

View File

@ -218,6 +218,7 @@ set_option(RPATH "Use an rpath when linking SDL" ${UNIX_SYS})
set_option(CLOCK_GETTIME "Use clock_gettime() instead of gettimeofday()" OFF)
set_option(INPUT_TSLIB "Use the Touchscreen library for input" ${UNIX_SYS})
set_option(VIDEO_X11 "Use X11 video driver" ${UNIX_SYS})
set_option(VIDEO_WAYLAND "Use Wayland video driver" ${UNIX_SYS})
dep_option(X11_SHARED "Dynamically load X11 support" ON "VIDEO_X11" OFF)
set(SDL_X11_OPTIONS Xcursor Xinerama XInput Xrandr Xscrnsaver XShape Xvm)
foreach(_SUB ${SDL_X11_OPTIONS})
@ -641,6 +642,7 @@ if(UNIX AND NOT APPLE)
CheckDirectFB()
CheckOpenGLX11()
CheckOpenGLESX11()
CheckWayland()
endif(SDL_VIDEO)
if(LINUX)

View File

@ -7,7 +7,10 @@ This is a list of major changes in SDL's version history.
General:
* Added an API to load a database of Game Controller mappings from a file:
SDL_GameControllerAddMappingsFromFile
* EGL can now create/manage OpenGL and OpenGL ES 1.x/2.x contexts, and share
them using SDL_GL_SHARE_WITH_CURRENT_CONTEXT
* Added testgles2. testgl2 does not need to link with libGL anymore.
Windows:
* Support for OpenGL ES 2.x contexts using either WGL or EGL (natively via
the driver or emulated through ANGLE)
@ -20,7 +23,7 @@ Android:
Linux:
* Fixed fullscreen and focused behavior when receiving NotifyGrab events
* Wayland support
---------------------------------------------------------------------------
2.0.1:

View File

@ -505,6 +505,29 @@ macro(CheckX11)
endif(VIDEO_X11)
endmacro(CheckX11)
# Requires:
# - EGL
macro(CheckWayland)
if(VIDEO_WAYLAND)
pkg_check_modules(WAYLAND wayland-client wayland-cursor wayland-egl egl xkbcommon)
if(WAYLAND_FOUND)
link_directories(
${WAYLAND_LIBRARY_DIRS}
)
include_directories(
${WAYLAND_INCLUDE_DIRS}
)
set(EXTRA_LIBS ${WAYLAND_LIBRARIES} ${EXTRA_LIBS})
set(HAVE_VIDEO_WAYLAND TRUE)
set(HAVE_SDL_VIDEO TRUE)
file(GLOB WAYLAND_SOURCES ${SDL2_SOURCE_DIR}/src/video/wayland/*.c)
set(SOURCE_FILES ${SOURCE_FILES} ${WAYLAND_SOURCES})
set(SDL_VIDEO_DRIVER_WAYLAND 1)
endif(WAYLAND_FOUND)
endif(VIDEO_WAYLAND)
endmacro(CheckWayland)
# Requires:
# - n/a
#

79
configure vendored
View File

@ -817,6 +817,7 @@ enable_sndio
enable_sndio_shared
enable_diskaudio
enable_dummyaudio
enable_video_wayland
enable_video_x11
with_x
enable_x11_shared
@ -1532,6 +1533,7 @@ Optional Features:
--enable-sndio-shared dynamically load sndio audio support [[default=yes]]
--enable-diskaudio support the disk writer audio driver [[default=yes]]
--enable-dummyaudio support the dummy audio driver [[default=yes]]
--enable-video-wayland use Wayland video driver [[default=yes]]
--enable-video-x11 use X11 video driver [[default=yes]]
--enable-x11-shared dynamically load X11 support [[default=maybe]]
--enable-video-x11-xcursor
@ -18633,6 +18635,82 @@ $as_echo "$need_gcc_Wno_multichar" >&6; }
fi
}
CheckWayland()
{
# Check whether --enable-video-wayland was given.
if test "${enable_video_wayland+set}" = set; then :
enableval=$enable_video_wayland;
else
enable_video_wayland=yes
fi
if test x$enable_video = xyes -a x$enable_video_wayland = xyes; then
# Extract the first word of "pkg-config", so it can be a program name with args.
set dummy pkg-config; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_PKG_CONFIG+:} false; then :
$as_echo_n "(cached) " >&6
else
case $PKG_CONFIG in
[\\/]* | ?:[\\/]*)
ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no"
;;
esac
fi
PKG_CONFIG=$ac_cv_path_PKG_CONFIG
if test -n "$PKG_CONFIG"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
$as_echo "$PKG_CONFIG" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Wayland support" >&5
$as_echo_n "checking for Wayland support... " >&6; }
video_wayland=no
if test x$PKG_CONFIG != xno; then
if $PKG_CONFIG --exists wayland-client wayland-egl wayland-cursor egl xkbcommon ; then
WAYLAND_CFLAGS=`$PKG_CONFIG --cflags wayland-client wayland-egl wayland-cursor egl xkbcommon`
WAYLAND_LIBS=`$PKG_CONFIG --libs wayland-client wayland-egl wayland-cursor egl xkbcommon`
video_wayland=yes
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $video_wayland" >&5
$as_echo "$video_wayland" >&6; }
if test x$video_wayland = xyes; then
$as_echo "#define SDL_VIDEO_DRIVER_WAYLAND 1" >>confdefs.h
SOURCES="$SOURCES $srcdir/src/video/wayland/*.c"
EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS"
EXTRA_LDFLAGS="$EXTRA_LDFLAGS $WAYLAND_LIBS"
have_video=yes
fi
fi
}
CheckX11()
{
@ -22220,6 +22298,7 @@ case "$host" in
CheckNAS
CheckSNDIO
CheckX11
CheckWayland
CheckDirectFB
CheckFusionSound
CheckOpenGLX11

View File

@ -1115,6 +1115,36 @@ CheckWarnAll()
fi
}
dnl Check for Wayland
CheckWayland()
{
AC_ARG_ENABLE(video-wayland,
AC_HELP_STRING([--enable-video-wayland], [use Wayland video driver [[default=yes]]]),
,enable_video_wayland=yes)
if test x$enable_video = xyes -a x$enable_video_wayland = xyes; then
AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
AC_MSG_CHECKING(for Wayland support)
video_wayland=no
if test x$PKG_CONFIG != xno; then
if $PKG_CONFIG --exists wayland-client wayland-egl wayland-cursor egl xkbcommon ; then
WAYLAND_CFLAGS=`$PKG_CONFIG --cflags wayland-client wayland-egl wayland-cursor egl xkbcommon`
WAYLAND_LIBS=`$PKG_CONFIG --libs wayland-client wayland-egl wayland-cursor egl xkbcommon`
video_wayland=yes
fi
fi
AC_MSG_RESULT($video_wayland)
if test x$video_wayland = xyes; then
AC_DEFINE(SDL_VIDEO_DRIVER_WAYLAND, 1, [ ])
SOURCES="$SOURCES $srcdir/src/video/wayland/*.c"
EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS"
dnl FIXME do dynamic loading code here.
EXTRA_LDFLAGS="$EXTRA_LDFLAGS $WAYLAND_LIBS"
have_video=yes
fi
fi
}
dnl Find the X11 include and library directories
CheckX11()
@ -2449,6 +2479,7 @@ case "$host" in
CheckNAS
CheckSNDIO
CheckX11
CheckWayland
CheckDirectFB
CheckFusionSound
CheckOpenGLX11

View File

@ -259,6 +259,7 @@
#cmakedefine SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC @SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC@
#cmakedefine SDL_VIDEO_DRIVER_DUMMY @SDL_VIDEO_DRIVER_DUMMY@
#cmakedefine SDL_VIDEO_DRIVER_WINDOWS @SDL_VIDEO_DRIVER_WINDOWS@
#cmakedefine SDL_VIDEO_DRIVER_WAYLAND @SDL_VIDEO_DRIVER_WAYLAND@
#cmakedefine SDL_VIDEO_DRIVER_X11 @SDL_VIDEO_DRIVER_X11@
#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC @SDL_VIDEO_DRIVER_X11_DYNAMIC@
#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT @SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT@

View File

@ -260,6 +260,7 @@
#undef SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC
#undef SDL_VIDEO_DRIVER_DUMMY
#undef SDL_VIDEO_DRIVER_WINDOWS
#undef SDL_VIDEO_DRIVER_WAYLAND
#undef SDL_VIDEO_DRIVER_X11
#undef SDL_VIDEO_DRIVER_RPI
#undef SDL_VIDEO_DRIVER_X11_DYNAMIC

View File

@ -101,6 +101,7 @@ typedef enum
SDL_SYSWM_UNKNOWN,
SDL_SYSWM_WINDOWS,
SDL_SYSWM_X11,
SDL_SYSWM_WAYLAND,
SDL_SYSWM_DIRECTFB,
SDL_SYSWM_COCOA,
SDL_SYSWM_UIKIT,
@ -175,6 +176,14 @@ struct SDL_SysWMinfo
Window window; /**< The X11 window */
} x11;
#endif
#if defined(SDL_VIDEO_DRIVER_WAYLAND)
struct
{
struct wl_display *display; /**< Wayland display */
struct wl_surface *surface; /**< Wayland surface */
struct wl_shell_surface *shell_surface; /**< Wayland shell_surface (window manager handle) */
} wl;
#endif
#if defined(SDL_VIDEO_DRIVER_DIRECTFB)
struct
{

View File

@ -30,7 +30,7 @@ SDL_PROC_UNUSED(void, glColor3bv, (const GLbyte *))
SDL_PROC_UNUSED(void, glColor3d, (GLdouble, GLdouble, GLdouble))
SDL_PROC_UNUSED(void, glColor3dv, (const GLdouble *))
SDL_PROC_UNUSED(void, glColor3f, (GLfloat, GLfloat, GLfloat))
SDL_PROC_UNUSED(void, glColor3fv, (const GLfloat *))
SDL_PROC(void, glColor3fv, (const GLfloat *))
SDL_PROC_UNUSED(void, glColor3i, (GLint, GLint, GLint))
SDL_PROC_UNUSED(void, glColor3iv, (const GLint *))
SDL_PROC_UNUSED(void, glColor3s, (GLshort, GLshort, GLshort))
@ -85,7 +85,7 @@ SDL_PROC_UNUSED(void, glCopyTexSubImage2D,
SDL_PROC_UNUSED(void, glCullFace, (GLenum mode))
SDL_PROC_UNUSED(void, glDeleteLists, (GLuint list, GLsizei range))
SDL_PROC(void, glDeleteTextures, (GLsizei n, const GLuint * textures))
SDL_PROC_UNUSED(void, glDepthFunc, (GLenum func))
SDL_PROC(void, glDepthFunc, (GLenum func))
SDL_PROC_UNUSED(void, glDepthMask, (GLboolean flag))
SDL_PROC_UNUSED(void, glDepthRange, (GLclampd zNear, GLclampd zFar))
SDL_PROC(void, glDisable, (GLenum cap))
@ -334,13 +334,13 @@ SDL_PROC_UNUSED(void, glRectsv, (const GLshort * v1, const GLshort * v2))
SDL_PROC_UNUSED(GLint, glRenderMode, (GLenum mode))
SDL_PROC(void, glRotated,
(GLdouble angle, GLdouble x, GLdouble y, GLdouble z))
SDL_PROC_UNUSED(void, glRotatef,
SDL_PROC(void, glRotatef,
(GLfloat angle, GLfloat x, GLfloat y, GLfloat z))
SDL_PROC_UNUSED(void, glScaled, (GLdouble x, GLdouble y, GLdouble z))
SDL_PROC_UNUSED(void, glScalef, (GLfloat x, GLfloat y, GLfloat z))
SDL_PROC(void, glScissor, (GLint x, GLint y, GLsizei width, GLsizei height))
SDL_PROC_UNUSED(void, glSelectBuffer, (GLsizei size, GLuint * buffer))
SDL_PROC_UNUSED(void, glShadeModel, (GLenum mode))
SDL_PROC(void, glShadeModel, (GLenum mode))
SDL_PROC_UNUSED(void, glStencilFunc, (GLenum func, GLint ref, GLuint mask))
SDL_PROC_UNUSED(void, glStencilMask, (GLuint mask))
SDL_PROC_UNUSED(void, glStencilOp, (GLenum fail, GLenum zfail, GLenum zpass))
@ -432,7 +432,7 @@ SDL_PROC_UNUSED(void, glVertex2sv, (const GLshort * v))
SDL_PROC_UNUSED(void, glVertex3d, (GLdouble x, GLdouble y, GLdouble z))
SDL_PROC_UNUSED(void, glVertex3dv, (const GLdouble * v))
SDL_PROC_UNUSED(void, glVertex3f, (GLfloat x, GLfloat y, GLfloat z))
SDL_PROC_UNUSED(void, glVertex3fv, (const GLfloat * v))
SDL_PROC(void, glVertex3fv, (const GLfloat * v))
SDL_PROC_UNUSED(void, glVertex3i, (GLint x, GLint y, GLint z))
SDL_PROC_UNUSED(void, glVertex3iv, (const GLint * v))
SDL_PROC_UNUSED(void, glVertex3s, (GLshort x, GLshort y, GLshort z))

View File

@ -50,6 +50,7 @@
#else
/* Desktop Linux */
#define DEFAULT_OGL "libGL.so.1"
#define DEFAULT_EGL "libEGL.so.1"
#define DEFAULT_OGL_ES2 "libGLESv2.so.2"
#define DEFAULT_OGL_ES_PVR "libGLES_CM.so.1"
@ -149,23 +150,31 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa
}
if (egl_dll_handle == NULL) {
if (_this->gl_config.major_version > 1) {
path = DEFAULT_OGL_ES2;
egl_dll_handle = SDL_LoadObject(path);
}
else {
path = DEFAULT_OGL_ES;
egl_dll_handle = SDL_LoadObject(path);
if (egl_dll_handle == NULL) {
path = DEFAULT_OGL_ES_PVR;
if(_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
if (_this->gl_config.major_version > 1) {
path = DEFAULT_OGL_ES2;
egl_dll_handle = SDL_LoadObject(path);
}
else {
path = DEFAULT_OGL_ES;
egl_dll_handle = SDL_LoadObject(path);
if (egl_dll_handle == NULL) {
path = DEFAULT_OGL_ES_PVR;
egl_dll_handle = SDL_LoadObject(path);
}
}
}
#ifdef DEFAULT_OGL
else {
path = DEFAULT_OGL;
egl_dll_handle = SDL_LoadObject(path);
}
#endif
}
_this->egl_data->egl_dll_handle = egl_dll_handle;
if (egl_dll_handle == NULL) {
return SDL_SetError("Could not initialize OpenGL ES library");
return SDL_SetError("Could not initialize OpenGL / GLES library");
}
/* Loading libGL* in the previous step took care of loading libEGL.so, but we future proof by double checking */
@ -205,6 +214,7 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa
LOAD_FUNC(eglSwapInterval);
LOAD_FUNC(eglWaitNative);
LOAD_FUNC(eglWaitGL);
LOAD_FUNC(eglBindAPI);
_this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display);
if (!_this->egl_data->egl_display) {
@ -281,14 +291,21 @@ SDL_EGL_ChooseConfig(_THIS)
}
attribs[i++] = EGL_RENDERABLE_TYPE;
if (_this->gl_config.major_version == 2) {
attribs[i++] = EGL_OPENGL_ES2_BIT;
} else {
attribs[i++] = EGL_OPENGL_ES_BIT;
if(_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
if (_this->gl_config.major_version == 2) {
attribs[i++] = EGL_OPENGL_ES2_BIT;
} else {
attribs[i++] = EGL_OPENGL_ES_BIT;
}
_this->egl_data->eglBindAPI(EGL_OPENGL_ES_API);
}
else {
attribs[i++] = EGL_OPENGL_BIT;
_this->egl_data->eglBindAPI(EGL_OPENGL_API);
}
attribs[i++] = EGL_NONE;
if (_this->egl_data->eglChooseConfig(_this->egl_data->egl_display,
attribs,
configs, SDL_arraysize(configs),
@ -347,18 +364,27 @@ SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface)
return NULL;
}
if (_this->gl_config.major_version) {
context_attrib_list[1] = _this->gl_config.major_version;
}
if (_this->gl_config.share_with_current_context) {
share_context = (EGLContext)SDL_GL_GetCurrentContext();
}
/* Bind the API */
if(_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
_this->egl_data->eglBindAPI(EGL_OPENGL_ES_API);
if (_this->gl_config.major_version) {
context_attrib_list[1] = _this->gl_config.major_version;
}
egl_context =
_this->egl_data->eglCreateContext(_this->egl_data->egl_display,
_this->egl_data->egl_config,
share_context, context_attrib_list);
egl_context = _this->egl_data->eglCreateContext(_this->egl_data->egl_display,
_this->egl_data->egl_config,
share_context, context_attrib_list);
}
else {
_this->egl_data->eglBindAPI(EGL_OPENGL_API);
egl_context = _this->egl_data->eglCreateContext(_this->egl_data->egl_display,
_this->egl_data->egl_config,
share_context, NULL);
}
if (egl_context == EGL_NO_CONTEXT) {
SDL_SetError("Could not create EGL context");

View File

@ -76,6 +76,9 @@ typedef struct SDL_EGL_VideoData
EGLBoolean(EGLAPIENTRY *eglWaitNative) (EGLint engine);
EGLBoolean(EGLAPIENTRY *eglWaitGL)(void);
EGLBoolean(EGLAPIENTRY *eglBindAPI)(EGLenum);
} SDL_EGL_VideoData;
/* OpenGLES functions */

View File

@ -369,6 +369,9 @@ extern VideoBootStrap RPI_bootstrap;
#if SDL_VIDEO_DRIVER_DUMMY
extern VideoBootStrap DUMMY_bootstrap;
#endif
#if SDL_VIDEO_DRIVER_WAYLAND
extern VideoBootStrap Wayland_bootstrap;
#endif
extern SDL_VideoDevice *SDL_GetVideoDevice(void);
extern int SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode);

View File

@ -85,6 +85,9 @@ static VideoBootStrap *bootstrap[] = {
#endif
#if SDL_VIDEO_DRIVER_DUMMY
&DUMMY_bootstrap,
#endif
#if SDL_VIDEO_DRIVER_WAYLAND
&Wayland_bootstrap,
#endif
NULL
};

View File

@ -0,0 +1,381 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
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.
*/
#include "SDL_config.h"
#include "SDL_stdinc.h"
#include "SDL_assert.h"
#include "../../events/SDL_sysevents.h"
#include "../../events/SDL_events_c.h"
#include "../../events/scancodes_xfree86.h"
#include "SDL_waylandvideo.h"
#include "SDL_waylandevents_c.h"
#include "SDL_waylandwindow.h"
#include <linux/input.h>
#include <sys/select.h>
#include <sys/mman.h>
#include <poll.h>
#include <errno.h>
#include <unistd.h>
#include <xkbcommon/xkbcommon.h>
struct SDL_WaylandInput {
SDL_VideoData *display;
struct wl_seat *seat;
struct wl_pointer *pointer;
struct wl_keyboard *keyboard;
SDL_WindowData *pointer_focus;
SDL_WindowData *keyboard_focus;
struct {
struct xkb_keymap *keymap;
struct xkb_state *state;
} xkb;
};
void
Wayland_PumpEvents(_THIS)
{
SDL_VideoData *d = _this->driverdata;
struct pollfd pfd[1];
pfd[0].fd = wl_display_get_fd(d->display);
pfd[0].events = POLLIN;
poll(pfd, 1, 0);
if (pfd[0].revents & POLLIN)
wl_display_dispatch(d->display);
else
wl_display_dispatch_pending(d->display);
}
static void
pointer_handle_enter(void *data, struct wl_pointer *pointer,
uint32_t serial, struct wl_surface *surface,
wl_fixed_t sx_w, wl_fixed_t sy_w)
{
struct SDL_WaylandInput *input = data;
SDL_WindowData *window;
if (!surface) {
/* enter event for a window we've just destroyed */
return;
}
input->pointer_focus = wl_surface_get_user_data(surface);
window = input->pointer_focus;
SDL_SetMouseFocus(window->sdlwindow);
}
static void
pointer_handle_leave(void *data, struct wl_pointer *pointer,
uint32_t serial, struct wl_surface *surface)
{
struct SDL_WaylandInput *input = data;
SDL_SetMouseFocus(NULL);
input->pointer_focus = NULL;
}
static void
pointer_handle_motion(void *data, struct wl_pointer *pointer,
uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w)
{
struct SDL_WaylandInput *input = data;
SDL_WindowData *window = input->pointer_focus;
int sx = wl_fixed_to_int(sx_w);
int sy = wl_fixed_to_int(sy_w);
SDL_SendMouseMotion(window->sdlwindow, 0, 0, sx, sy);
}
static void
pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
uint32_t time, uint32_t button, uint32_t state_w)
{
struct SDL_WaylandInput *input = data;
SDL_WindowData *window = input->pointer_focus;
enum wl_pointer_button_state state = state_w;
uint32_t sdl_button;
switch (button) {
case BTN_LEFT:
sdl_button = SDL_BUTTON_LEFT;
break;
case BTN_MIDDLE:
sdl_button = SDL_BUTTON_MIDDLE;
break;
case BTN_RIGHT:
sdl_button = SDL_BUTTON_RIGHT;
break;
case BTN_SIDE:
sdl_button = SDL_BUTTON_X1;
break;
case BTN_EXTRA:
sdl_button = SDL_BUTTON_X2;
break;
default:
return;
}
SDL_SendMouseButton(window->sdlwindow, 0,
state ? SDL_PRESSED : SDL_RELEASED, sdl_button);
}
static void
pointer_handle_axis(void *data, struct wl_pointer *pointer,
uint32_t time, uint32_t axis, wl_fixed_t value)
{
struct SDL_WaylandInput *input = data;
SDL_WindowData *window = input->pointer_focus;
enum wl_pointer_axis a = axis;
int x, y;
switch (a) {
case WL_POINTER_AXIS_VERTICAL_SCROLL:
x = 0;
y = wl_fixed_to_int(value);
break;
case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
x = wl_fixed_to_int(value);
y = 0;
break;
default:
return;
}
SDL_SendMouseWheel(window->sdlwindow, 0, x, y);
}
static const struct wl_pointer_listener pointer_listener = {
pointer_handle_enter,
pointer_handle_leave,
pointer_handle_motion,
pointer_handle_button,
pointer_handle_axis,
};
static void
keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
uint32_t format, int fd, uint32_t size)
{
struct SDL_WaylandInput *input = data;
char *map_str;
if (!data) {
close(fd);
return;
}
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
close(fd);
return;
}
map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
if (map_str == MAP_FAILED) {
close(fd);
return;
}
input->xkb.keymap = xkb_map_new_from_string(input->display->xkb_context,
map_str,
XKB_KEYMAP_FORMAT_TEXT_V1,
0);
munmap(map_str, size);
close(fd);
if (!input->xkb.keymap) {
fprintf(stderr, "failed to compile keymap\n");
return;
}
input->xkb.state = xkb_state_new(input->xkb.keymap);
if (!input->xkb.state) {
fprintf(stderr, "failed to create XKB state\n");
xkb_map_unref(input->xkb.keymap);
input->xkb.keymap = NULL;
return;
}
}
static void
keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
uint32_t serial, struct wl_surface *surface,
struct wl_array *keys)
{
struct SDL_WaylandInput *input = data;
SDL_WindowData *window = wl_surface_get_user_data(surface);
input->keyboard_focus = window;
window->keyboard_device = input;
SDL_SetKeyboardFocus(window->sdlwindow);
}
static void
keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
uint32_t serial, struct wl_surface *surface)
{
SDL_SetKeyboardFocus(NULL);
}
static void
keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
uint32_t serial, uint32_t time, uint32_t key,
uint32_t state_w)
{
struct SDL_WaylandInput *input = data;
SDL_WindowData *window = input->keyboard_focus;
enum wl_keyboard_key_state state = state_w;
const xkb_keysym_t *syms;
uint32_t scancode;
char text[8];
int size;
if (key < SDL_arraysize(xfree86_scancode_table2)) {
scancode = xfree86_scancode_table2[key];
// TODO when do we get WL_KEYBOARD_KEY_STATE_REPEAT?
if (scancode != SDL_SCANCODE_UNKNOWN)
SDL_SendKeyboardKey(state == WL_KEYBOARD_KEY_STATE_PRESSED ?
SDL_PRESSED : SDL_RELEASED, scancode);
}
if (!window || window->keyboard_device != input || !input->xkb.state)
return;
// TODO can this happen?
if (xkb_key_get_syms(input->xkb.state, key + 8, &syms) != 1)
return;
if (state) {
size = xkb_keysym_to_utf8(syms[0], text, sizeof text);
if (size > 0) {
text[size] = 0;
SDL_SendKeyboardText(text);
}
}
}
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)
{
struct SDL_WaylandInput *input = data;
xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched,
mods_locked, 0, 0, group);
}
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,
enum wl_seat_capability caps)
{
struct SDL_WaylandInput *input = data;
if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) {
input->pointer = wl_seat_get_pointer(seat);
input->display->pointer = input->pointer;
wl_pointer_set_user_data(input->pointer, input);
wl_pointer_add_listener(input->pointer, &pointer_listener,
input);
} else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) {
wl_pointer_destroy(input->pointer);
input->pointer = NULL;
}
if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard) {
input->keyboard = wl_seat_get_keyboard(seat);
wl_keyboard_set_user_data(input->keyboard, input);
wl_keyboard_add_listener(input->keyboard, &keyboard_listener,
input);
} else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) {
wl_keyboard_destroy(input->keyboard);
input->keyboard = NULL;
}
}
static const struct wl_seat_listener seat_listener = {
seat_handle_capabilities,
};
void
Wayland_display_add_input(SDL_VideoData *d, uint32_t id)
{
struct SDL_WaylandInput *input;
input = malloc(sizeof *input);
if (input == NULL)
return;
memset(input, 0, sizeof *input);
input->display = d;
input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, 1);
d->input = input;
wl_seat_add_listener(input->seat, &seat_listener, input);
wl_seat_set_user_data(input->seat, input);
wayland_schedule_write(d);
}
void Wayland_display_destroy_input(SDL_VideoData *d)
{
struct SDL_WaylandInput *input = d->input;
if (!input)
return;
if (input->keyboard)
wl_keyboard_destroy(input->keyboard);
if (input->pointer)
wl_pointer_destroy(input->pointer);
if (input->seat)
wl_seat_destroy(input->seat);
if (input->xkb.state)
xkb_state_unref(input->xkb.state);
if (input->xkb.keymap)
xkb_map_unref(input->xkb.keymap);
free(input);
d->input = NULL;
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -0,0 +1,37 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
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.
*/
#include "SDL_config.h"
#ifndef _SDL_waylandevents_h
#define _SDL_waylandevents_h
#include "SDL_waylandvideo.h"
#include "SDL_waylandwindow.h"
extern void Wayland_PumpEvents(_THIS);
extern void Wayland_display_add_input(SDL_VideoData *d, uint32_t id);
extern void Wayland_display_destroy_input(SDL_VideoData *d);
#endif /* _SDL_waylandevents_h */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -0,0 +1,407 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
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 _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <errno.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <limits.h>
#include "../SDL_sysvideo.h"
#include "SDL_config.h"
#include "SDL_mouse.h"
#include "../../events/SDL_mouse_c.h"
#include "SDL_waylandvideo.h"
#include "SDL_waylandevents_c.h"
#include "SDL_assert.h"
#if SDL_VIDEO_DRIVER_WAYLAND
typedef struct {
struct wl_buffer *buffer;
struct wl_surface *surface;
int hot_x, hot_y;
/* Either a preloaded cursor, or one we created ourselves */
struct wl_cursor *cursor;
void *shm_data;
} Wayland_CursorData;
static int
wayland_create_tmp_file(off_t size)
{
static const char template[] = "/sdl-shared-XXXXXX";
char *xdg_path;
char tmp_path[PATH_MAX];
int fd;
xdg_path = SDL_getenv("XDG_RUNTIME_DIR");
if (!xdg_path) {
errno = ENOENT;
return -1;
}
SDL_strlcpy(tmp_path, xdg_path, PATH_MAX);
SDL_strlcat(tmp_path, template, PATH_MAX);
fd = mkostemp(tmp_path, O_CLOEXEC);
if (fd < 0)
return -1;
if (ftruncate(fd, size) < 0) {
close(fd);
return -1;
}
return fd;
}
static void
mouse_buffer_release(void *data, struct wl_buffer *buffer)
{
}
static const struct wl_buffer_listener mouse_buffer_listener = {
mouse_buffer_release
};
static int
create_buffer_from_shm(Wayland_CursorData *d,
int width,
int height,
uint32_t format)
{
SDL_VideoDevice *vd = SDL_GetVideoDevice();
SDL_VideoData *data = (SDL_VideoData *) vd->driverdata;
int stride = width * 4;
int size = stride * height;
int shm_fd;
shm_fd = wayland_create_tmp_file(size);
if (shm_fd < 0)
{
fprintf(stderr, "creating mouse cursor buffer failed!\n");
return -1;
}
d->shm_data = mmap(NULL,
size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
shm_fd,
0);
if (data == MAP_FAILED) {
d->shm_data = NULL;
fprintf (stderr, "mmap () failed\n");
close (shm_fd);
}
struct wl_shm_pool *shm_pool = wl_shm_create_pool(data->shm,
shm_fd,
size);
d->buffer = wl_shm_pool_create_buffer(shm_pool,
0,
width,
height,
stride,
format);
wl_buffer_add_listener(d->buffer,
&mouse_buffer_listener,
d);
wl_shm_pool_destroy (shm_pool);
close (shm_fd);
return 0;
}
static SDL_Cursor *
Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
{
SDL_Cursor *cursor;
cursor = calloc(1, sizeof (*cursor));
if (cursor) {
SDL_VideoDevice *vd = SDL_GetVideoDevice ();
SDL_VideoData *wd = (SDL_VideoData *) vd->driverdata;
Wayland_CursorData *data = calloc (1, sizeof (Wayland_CursorData));
cursor->driverdata = (void *) data;
/* Assume ARGB8888 */
SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888);
SDL_assert(surface->pitch == surface->w * 4);
/* Allocate shared memory buffer for this cursor */
if (create_buffer_from_shm (data,
surface->w,
surface->h,
WL_SHM_FORMAT_XRGB8888) < 0)
{
free (cursor->driverdata);
free (cursor);
return NULL;
}
SDL_memcpy(data->shm_data,
surface->pixels,
surface->h * surface->pitch);
data->surface = wl_compositor_create_surface(wd->compositor);
wl_surface_attach(data->surface,
data->buffer,
0,
0);
wl_surface_damage(data->surface,
0,
0,
surface->w,
surface->h);
wl_surface_commit(data->surface);
data->hot_x = hot_x;
data->hot_y = hot_y;
}
return cursor;
}
static SDL_Cursor *
CreateCursorFromWlCursor(SDL_VideoData *d, struct wl_cursor *wlcursor)
{
SDL_Cursor *cursor;
cursor = calloc(1, sizeof (*cursor));
if (cursor) {
Wayland_CursorData *data = calloc (1, sizeof (Wayland_CursorData));
cursor->driverdata = (void *) data;
/* The wl_buffer here will be destroyed from wl_cursor_theme_destroy
* if we are fetching this from a wl_cursor_theme, so don't store a
* reference to it here */
data->buffer = NULL;
data->surface = wl_compositor_create_surface(d->compositor);
wl_surface_attach(data->surface,
wl_cursor_image_get_buffer(wlcursor->images[0]),
0,
0);
wl_surface_damage(data->surface,
0,
0,
wlcursor->images[0]->width,
wlcursor->images[0]->height);
wl_surface_commit(data->surface);
data->hot_x = wlcursor->images[0]->hotspot_x;
data->hot_y = wlcursor->images[0]->hotspot_y;
data->cursor= wlcursor;
} else {
SDL_OutOfMemory ();
}
return cursor;
}
static SDL_Cursor *
Wayland_CreateDefaultCursor()
{
SDL_VideoDevice *device = SDL_GetVideoDevice();
SDL_VideoData *data = device->driverdata;
return CreateCursorFromWlCursor (data,
wl_cursor_theme_get_cursor(data->cursor_theme,
"left_ptr"));
}
static SDL_Cursor *
Wayland_CreateSystemCursor(SDL_SystemCursor id)
{
SDL_VideoDevice *vd = SDL_GetVideoDevice();
SDL_VideoData *d = vd->driverdata;
struct wl_cursor *cursor = NULL;
switch(id)
{
default:
SDL_assert(0);
return NULL;
case SDL_SYSTEM_CURSOR_ARROW:
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "left_ptr");
break;
case SDL_SYSTEM_CURSOR_IBEAM:
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "xterm");
break;
case SDL_SYSTEM_CURSOR_WAIT:
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "wait");
break;
case SDL_SYSTEM_CURSOR_CROSSHAIR:
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
break;
case SDL_SYSTEM_CURSOR_WAITARROW:
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "wait");
break;
case SDL_SYSTEM_CURSOR_SIZENWSE:
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
break;
case SDL_SYSTEM_CURSOR_SIZENESW:
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
break;
case SDL_SYSTEM_CURSOR_SIZEWE:
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
break;
case SDL_SYSTEM_CURSOR_SIZENS:
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
break;
case SDL_SYSTEM_CURSOR_SIZEALL:
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
break;
case SDL_SYSTEM_CURSOR_NO:
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "xterm");
break;
case SDL_SYSTEM_CURSOR_HAND:
cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "hand1");
break;
}
SDL_Cursor *sdl_cursor = CreateCursorFromWlCursor (d, cursor);
return sdl_cursor;
}
static void
Wayland_FreeCursor(SDL_Cursor *cursor)
{
if (!cursor)
return;
Wayland_CursorData *d = cursor->driverdata;
/* Probably not a cursor we own */
if (!d)
return;
if (d->buffer)
wl_buffer_destroy(d->buffer);
if (d->surface)
wl_surface_destroy(d->surface);
/* Not sure what's meant to happen to shm_data */
free (cursor->driverdata);
SDL_free(cursor);
}
static int
Wayland_ShowCursor(SDL_Cursor *cursor)
{
SDL_VideoDevice *vd = SDL_GetVideoDevice();
SDL_VideoData *d = vd->driverdata;
struct wl_pointer *pointer = d->pointer;
if (!pointer)
return -1;
if (cursor)
{
Wayland_CursorData *data = cursor->driverdata;
wl_pointer_set_cursor (pointer, 0,
data->surface,
data->hot_x,
data->hot_y);
}
else
{
wl_pointer_set_cursor (pointer, 0,
NULL,
0,
0);
}
return 0;
}
static void
Wayland_WarpMouse(SDL_Window *window, int x, int y)
{
SDL_Unsupported();
return;
}
static int
Wayland_SetRelativeMouseMode(SDL_bool enabled)
{
SDL_Unsupported();
return -1;
}
void
Wayland_InitMouse(void)
{
SDL_Mouse *mouse = SDL_GetMouse();
mouse->CreateCursor = Wayland_CreateCursor;
mouse->CreateSystemCursor = Wayland_CreateSystemCursor;
mouse->ShowCursor = Wayland_ShowCursor;
mouse->FreeCursor = Wayland_FreeCursor;
mouse->WarpMouse = Wayland_WarpMouse;
mouse->SetRelativeMouseMode = Wayland_SetRelativeMouseMode;
SDL_SetDefaultCursor(Wayland_CreateDefaultCursor());
}
void
Wayland_FiniMouse(void)
{
/* This effectively assumes that nobody else
* touches SDL_Mouse which is effectively
* a singleton */
SDL_Mouse *mouse = SDL_GetMouse();
/* Free the current cursor if not the same pointer as
* the default cursor */
if (mouse->def_cursor != mouse->cur_cursor)
Wayland_FreeCursor (mouse->cur_cursor);
Wayland_FreeCursor (mouse->def_cursor);
mouse->def_cursor = NULL;
mouse->cur_cursor = NULL;
mouse->CreateCursor = NULL;
mouse->CreateSystemCursor = NULL;
mouse->ShowCursor = NULL;
mouse->FreeCursor = NULL;
mouse->WarpMouse = NULL;
mouse->SetRelativeMouseMode = NULL;
}
#endif

View File

@ -0,0 +1,31 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
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.
*/
#include "SDL_config.h"
#include "SDL_mouse.h"
#include "SDL_waylandvideo.h"
#if SDL_VIDEO_DRIVER_WAYLAND
extern void Wayland_InitMouse(void);
extern void Wayland_FiniMouse(void);
#endif

View File

@ -0,0 +1,90 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
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.
*/
#include "SDL_config.h"
#if SDL_VIDEO_DRIVER_WAYLAND && SDL_VIDEO_OPENGL_EGL
#include "SDL_waylandvideo.h"
#include "SDL_waylandopengles.h"
#include "SDL_waylandwindow.h"
#include "SDL_waylandevents_c.h"
/* EGL implementation of SDL OpenGL ES support */
int
Wayland_GLES_LoadLibrary(_THIS, const char *path) {
int ret;
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
ret = SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) data->display);
Wayland_PumpEvents(_this);
wayland_schedule_write(data);
return ret;
}
SDL_GLContext
Wayland_GLES_CreateContext(_THIS, SDL_Window * window)
{
SDL_GLContext context;
context = SDL_EGL_CreateContext(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
wayland_schedule_write(_this->driverdata);
return context;
}
void
Wayland_GLES_SwapWindow(_THIS, SDL_Window *window)
{
SDL_EGL_SwapBuffers(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
wayland_schedule_write(_this->driverdata);
}
int
Wayland_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
{
int ret;
if (window && context) {
ret = SDL_EGL_MakeCurrent(_this, ((SDL_WindowData *) window->driverdata)->egl_surface, context);
}
else {
ret = SDL_EGL_MakeCurrent(_this, NULL, NULL);
}
wayland_schedule_write(_this->driverdata);
return ret;
}
void
Wayland_GLES_DeleteContext(_THIS, SDL_GLContext context)
{
SDL_EGL_DeleteContext(_this, context);
wayland_schedule_write(_this->driverdata);
}
#endif /* SDL_VIDEO_DRIVER_WAYLAND && SDL_VIDEO_OPENGL_EGL */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -0,0 +1,46 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
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.
*/
#include "SDL_config.h"
#ifndef _SDL_waylandopengles_h
#define _SDL_waylandopengles_h
#include "../SDL_sysvideo.h"
#include "../SDL_egl_c.h"
typedef struct SDL_PrivateGLESData
{
} SDL_PrivateGLESData;
/* OpenGLES functions */
#define Wayland_GLES_GetAttribute SDL_EGL_GetAttribute
#define Wayland_GLES_GetProcAddress SDL_EGL_GetProcAddress
#define Wayland_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
#define Wayland_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
#define Wayland_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
extern int Wayland_GLES_LoadLibrary(_THIS, const char *path);
extern SDL_GLContext Wayland_GLES_CreateContext(_THIS, SDL_Window * window);
extern void Wayland_GLES_SwapWindow(_THIS, SDL_Window * window);
extern int Wayland_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
extern void Wayland_GLES_DeleteContext(_THIS, SDL_GLContext context);
#endif /* _SDL_waylandopengles_h */

View File

@ -0,0 +1,365 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
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.
*/
#include "SDL_config.h"
#include "SDL_video.h"
#include "SDL_mouse.h"
#include "../../events/SDL_events_c.h"
#include "SDL_waylandvideo.h"
#include "SDL_waylandevents_c.h"
#include "SDL_waylandwindow.h"
#include "SDL_waylandopengles.h"
#include "SDL_waylandmouse.h"
#include <fcntl.h>
#include <xkbcommon/xkbcommon.h>
#define WAYLANDVID_DRIVER_NAME "wayland"
struct wayland_mode {
SDL_DisplayMode mode;
struct wl_list link;
};
/* Initialization/Query functions */
static int
Wayland_VideoInit(_THIS);
static void
Wayland_GetDisplayModes(_THIS, SDL_VideoDisplay *sdl_display);
static int
Wayland_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode);
static void
Wayland_VideoQuit(_THIS);
/* Wayland driver bootstrap functions */
static int
Wayland_Available(void)
{
struct wl_display *display = NULL;
display = wl_display_connect(NULL);
if (display != NULL) {
wl_display_disconnect(display);
}
return (display != NULL);
}
static void
Wayland_DeleteDevice(SDL_VideoDevice *device)
{
SDL_free(device);
}
static SDL_VideoDevice *
Wayland_CreateDevice(int devindex)
{
SDL_VideoDevice *device;
/* Initialize all variables that we clean on shutdown */
device = SDL_calloc(1, sizeof(SDL_VideoDevice));
if (!device) {
SDL_OutOfMemory();
return NULL;
}
/* Set the function pointers */
device->VideoInit = Wayland_VideoInit;
device->VideoQuit = Wayland_VideoQuit;
device->SetDisplayMode = Wayland_SetDisplayMode;
device->GetDisplayModes = Wayland_GetDisplayModes;
device->GetWindowWMInfo = Wayland_GetWindowWMInfo;
device->PumpEvents = Wayland_PumpEvents;
device->GL_SwapWindow = Wayland_GLES_SwapWindow;
device->GL_GetSwapInterval = Wayland_GLES_GetSwapInterval;
device->GL_SetSwapInterval = Wayland_GLES_SetSwapInterval;
device->GL_MakeCurrent = Wayland_GLES_MakeCurrent;
device->GL_CreateContext = Wayland_GLES_CreateContext;
device->GL_LoadLibrary = Wayland_GLES_LoadLibrary;
device->GL_UnloadLibrary = Wayland_GLES_UnloadLibrary;
device->GL_GetProcAddress = Wayland_GLES_GetProcAddress;
device->GL_DeleteContext = Wayland_GLES_DeleteContext;
device->CreateWindow = Wayland_CreateWindow;
device->ShowWindow = Wayland_ShowWindow;
device->SetWindowFullscreen = Wayland_SetWindowFullscreen;
device->SetWindowSize = Wayland_SetWindowSize;
device->DestroyWindow = Wayland_DestroyWindow;
device->free = Wayland_DeleteDevice;
return device;
}
VideoBootStrap Wayland_bootstrap = {
WAYLANDVID_DRIVER_NAME, "SDL Wayland video driver",
Wayland_Available, Wayland_CreateDevice
};
static void
wayland_add_mode(SDL_VideoData *d, SDL_DisplayMode m)
{
struct wayland_mode *mode;
/* Check for duplicate mode */
wl_list_for_each(mode, &d->modes_list, link)
if (mode->mode.w == m.w && mode->mode.h == m.h &&
mode->mode.refresh_rate == m.refresh_rate)
return;
/* Add new mode to the list */
mode = SDL_calloc(1, sizeof *mode);
if (!mode)
return;
mode->mode = m;
wl_list_insert(&d->modes_list, &mode->link);
}
static void
display_handle_geometry(void *data,
struct wl_output *output,
int x, int y,
int physical_width,
int physical_height,
int subpixel,
const char *make,
const char *model,
int transform)
{
SDL_VideoData *d = data;
d->screen_allocation.x = x;
d->screen_allocation.y = y;
}
static void
display_handle_mode(void *data,
struct wl_output *wl_output,
uint32_t flags,
int width,
int height,
int refresh)
{
SDL_VideoData *d = data;
SDL_DisplayMode mode;
SDL_zero(mode);
mode.w = width;
mode.h = height;
mode.refresh_rate = refresh / 1000;
wayland_add_mode(d, mode);
if (flags & WL_OUTPUT_MODE_CURRENT) {
d->screen_allocation.width = width;
d->screen_allocation.height = height;
}
}
static const struct wl_output_listener output_listener = {
display_handle_geometry,
display_handle_mode
};
static void
shm_handle_format(void *data,
struct wl_shm *shm,
uint32_t format)
{
SDL_VideoData *d = data;
d->shm_formats |= (1 << format);
}
static const struct wl_shm_listener shm_listener = {
shm_handle_format
};
static void
display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
const char *interface, uint32_t version)
{
SDL_VideoData *d = data;
if (strcmp(interface, "wl_compositor") == 0) {
d->compositor = wl_registry_bind(d->registry, id, &wl_compositor_interface, 1);
} else if (strcmp(interface, "wl_output") == 0) {
d->output = wl_registry_bind(d->registry, id, &wl_output_interface, 1);
wl_output_add_listener(d->output, &output_listener, d);
} else if (strcmp(interface, "wl_seat") == 0) {
Wayland_display_add_input(d, id);
} else if (strcmp(interface, "wl_shell") == 0) {
d->shell = wl_registry_bind(d->registry, id, &wl_shell_interface, 1);
} else if (strcmp(interface, "wl_shm") == 0) {
d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
d->cursor_theme = wl_cursor_theme_load(NULL, 32, d->shm);
d->default_cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "left_ptr");
wl_shm_add_listener(d->shm, &shm_listener, d);
}
}
static const struct wl_registry_listener registry_listener = {
display_handle_global
};
int
Wayland_VideoInit(_THIS)
{
SDL_VideoData *data;
data = malloc(sizeof *data);
if (data == NULL)
return 0;
memset(data, 0, sizeof *data);
_this->driverdata = data;
wl_list_init(&data->modes_list);
data->display = wl_display_connect(NULL);
if (data->display == NULL) {
SDL_SetError("Failed to connect to a Wayland display");
return 0;
}
data->registry = wl_display_get_registry(data->display);
wl_registry_add_listener(data->registry, &registry_listener, data);
while (data->screen_allocation.width == 0)
wl_display_dispatch(data->display);
data->xkb_context = xkb_context_new(0);
if (!data->xkb_context) {
SDL_SetError("Failed to create XKB context");
return 0;
}
SDL_VideoDisplay display;
SDL_DisplayMode mode;
/* Use a fake 32-bpp desktop mode */
mode.format = SDL_PIXELFORMAT_RGB888;
mode.w = data->screen_allocation.width;
mode.h = data->screen_allocation.height;
mode.refresh_rate = 0;
mode.driverdata = NULL;
wayland_add_mode(data, mode);
SDL_zero(display);
display.desktop_mode = mode;
display.current_mode = mode;
display.driverdata = NULL;
SDL_AddVideoDisplay(&display);
Wayland_InitMouse ();
wayland_schedule_write(data);
return 0;
}
static void
Wayland_GetDisplayModes(_THIS, SDL_VideoDisplay *sdl_display)
{
SDL_VideoData *data = _this->driverdata;
SDL_DisplayMode mode;
struct wayland_mode *m;
Wayland_PumpEvents(_this);
wl_list_for_each(m, &data->modes_list, link) {
m->mode.format = SDL_PIXELFORMAT_RGB888;
SDL_AddDisplayMode(sdl_display, &m->mode);
m->mode.format = SDL_PIXELFORMAT_RGBA8888;
SDL_AddDisplayMode(sdl_display, &m->mode);
}
mode.w = data->screen_allocation.width;
mode.h = data->screen_allocation.height;
mode.refresh_rate = 0;
mode.driverdata = NULL;
mode.format = SDL_PIXELFORMAT_RGB888;
SDL_AddDisplayMode(sdl_display, &mode);
mode.format = SDL_PIXELFORMAT_RGBA8888;
SDL_AddDisplayMode(sdl_display, &mode);
}
static int
Wayland_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
{
return 0;
}
void
Wayland_VideoQuit(_THIS)
{
SDL_VideoData *data = _this->driverdata;
struct wayland_mode *t, *m;
Wayland_FiniMouse ();
if (data->output)
wl_output_destroy(data->output);
Wayland_display_destroy_input(data);
if (data->xkb_context) {
xkb_context_unref(data->xkb_context);
data->xkb_context = NULL;
}
if (data->shm)
wl_shm_destroy(data->shm);
if (data->cursor_theme)
wl_cursor_theme_destroy(data->cursor_theme);
if (data->shell)
wl_shell_destroy(data->shell);
if (data->compositor)
wl_compositor_destroy(data->compositor);
if (data->display) {
wl_display_flush(data->display);
wl_display_disconnect(data->display);
}
wl_list_for_each_safe(m, t, &data->modes_list, link) {
wl_list_remove(&m->link);
free(m);
}
free(data);
_this->driverdata = NULL;
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -0,0 +1,71 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
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.
*/
#include "SDL_config.h"
#ifndef _SDL_waylandvideo_h
#define _SDL_waylandvideo_h
#include <wayland-client.h>
#include <wayland-cursor.h>
#include <wayland-egl.h>
#include <EGL/egl.h>
struct xkb_context;
struct SDL_WaylandInput;
typedef struct {
struct wl_display *display;
struct wl_registry *registry;
struct wl_compositor *compositor;
struct wl_output *output;
struct wl_shm *shm;
struct wl_cursor_theme *cursor_theme;
struct wl_cursor *default_cursor;
struct wl_pointer *pointer;
struct wl_shell *shell;
struct {
int32_t x, y, width, height;
} screen_allocation;
struct wl_list modes_list;
EGLDisplay edpy;
EGLContext context;
EGLConfig econf;
struct xkb_context *xkb_context;
struct SDL_WaylandInput *input;
uint32_t shm_formats;
} SDL_VideoData;
static inline void
wayland_schedule_write(SDL_VideoData *data)
{
wl_display_flush(data->display);
}
#endif /* _SDL_nullvideo_h */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -0,0 +1,192 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
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.
*/
#include "SDL_config.h"
#include "../SDL_sysvideo.h"
#include "../../events/SDL_windowevents_c.h"
#include "../SDL_egl_c.h"
#include "SDL_waylandwindow.h"
#include "SDL_waylandvideo.h"
static void
handle_ping(void *data, struct wl_shell_surface *shell_surface,
uint32_t serial)
{
wl_shell_surface_pong(shell_surface, serial);
}
static void
handle_configure(void *data, struct wl_shell_surface *shell_surface,
uint32_t edges, int32_t width, int32_t height)
{
}
static void
handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
{
}
static const struct wl_shell_surface_listener shell_surface_listener = {
handle_ping,
handle_configure,
handle_popup_done
};
SDL_bool
Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
info->info.wl.display = data->waylandData->display;
info->info.wl.surface = data->surface;
info->info.wl.shell_surface = data->shell_surface;
info->subsystem = SDL_SYSWM_WAYLAND;
return SDL_TRUE;
}
void Wayland_ShowWindow(_THIS, SDL_Window *window)
{
SDL_WindowData *wind = window->driverdata;
if (window->flags & SDL_WINDOW_FULLSCREEN)
wl_shell_surface_set_fullscreen(wind->shell_surface,
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
0, NULL);
else
wl_shell_surface_set_toplevel(wind->shell_surface);
wayland_schedule_write(_this->driverdata);
}
void
Wayland_SetWindowFullscreen(_THIS, SDL_Window * window,
SDL_VideoDisplay * _display, SDL_bool fullscreen)
{
SDL_WindowData *wind = window->driverdata;
if (fullscreen)
wl_shell_surface_set_fullscreen(wind->shell_surface,
WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE,
0, NULL);
else
wl_shell_surface_set_toplevel(wind->shell_surface);
wayland_schedule_write(_this->driverdata);
}
int Wayland_CreateWindow(_THIS, SDL_Window *window)
{
SDL_WindowData *data;
SDL_VideoData *c;
struct wl_region *region;
data = calloc(1, sizeof *data);
if (data == NULL)
return 0;
c = _this->driverdata;
window->driverdata = data;
if (!(window->flags & SDL_WINDOW_OPENGL)) {
SDL_GL_LoadLibrary(NULL);
window->flags |= SDL_WINDOW_OPENGL;
}
if (window->x == SDL_WINDOWPOS_UNDEFINED) {
window->x = 0;
}
if (window->y == SDL_WINDOWPOS_UNDEFINED) {
window->y = 0;
}
data->waylandData = c;
data->sdlwindow = window;
data->surface =
wl_compositor_create_surface(c->compositor);
wl_surface_set_user_data(data->surface, data);
data->shell_surface = wl_shell_get_shell_surface(c->shell,
data->surface);
data->egl_window = wl_egl_window_create(data->surface,
window->w, window->h);
/* Create the GLES window surface */
data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->egl_window);
if (data->egl_surface == EGL_NO_SURFACE) {
SDL_SetError("failed to create a window surface");
return -1;
}
if (data->shell_surface) {
wl_shell_surface_set_user_data(data->shell_surface, data);
wl_shell_surface_add_listener(data->shell_surface,
&shell_surface_listener, data);
}
region = wl_compositor_create_region(c->compositor);
wl_region_add(region, 0, 0, window->w, window->h);
wl_surface_set_opaque_region(data->surface, region);
wl_region_destroy(region);
wayland_schedule_write(c);
return 0;
}
void Wayland_SetWindowSize(_THIS, SDL_Window * window)
{
SDL_VideoData *data = _this->driverdata;
SDL_WindowData *wind = window->driverdata;
struct wl_region *region;
wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
region = wl_compositor_create_region(data->compositor);
wl_region_add(region, 0, 0, window->w, window->h);
wl_surface_set_opaque_region(wind->surface, region);
wl_region_destroy(region);
}
void Wayland_DestroyWindow(_THIS, SDL_Window *window)
{
SDL_VideoData *data = _this->driverdata;
SDL_WindowData *wind = window->driverdata;
window->driverdata = NULL;
if (data) {
SDL_EGL_DestroySurface(_this, wind->egl_surface);
wl_egl_window_destroy(wind->egl_window);
if (wind->shell_surface)
wl_shell_surface_destroy(wind->shell_surface);
wl_surface_destroy(wind->surface);
SDL_free(wind);
wayland_schedule_write(data);
}
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -0,0 +1,58 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
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.
*/
#include "SDL_config.h"
#ifndef _SDL_waylandwindow_h
#define _SDL_waylandwindow_h
#include "../SDL_sysvideo.h"
#include "SDL_syswm.h"
#include "SDL_waylandvideo.h"
struct SDL_WaylandInput;
typedef struct {
SDL_Window *sdlwindow;
SDL_VideoData *waylandData;
struct wl_surface *surface;
struct wl_shell_surface *shell_surface;
struct wl_egl_window *egl_window;
struct SDL_WaylandInput *keyboard_device;
EGLSurface egl_surface;
} SDL_WindowData;
extern void Wayland_ShowWindow(_THIS, SDL_Window *window);
extern void Wayland_SetWindowFullscreen(_THIS, SDL_Window * window,
SDL_VideoDisplay * _display,
SDL_bool fullscreen);
extern int Wayland_CreateWindow(_THIS, SDL_Window *window);
extern void Wayland_SetWindowSize(_THIS, SDL_Window * window);
extern void Wayland_DestroyWindow(_THIS, SDL_Window *window);
extern SDL_bool
Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);
#endif /* _SDL_waylandwindow_h */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -128,13 +128,13 @@ testgesture$(EXE): $(srcdir)/testgesture.c
$(CC) -o $@ $^ $(CFLAGS) $(LIBS) @MATHLIB@
testgl2$(EXE): $(srcdir)/testgl2.c
$(CC) -o $@ $^ $(CFLAGS) $(LIBS) @GLLIB@ @MATHLIB@
$(CC) -o $@ $^ $(CFLAGS) $(LIBS) @MATHLIB@
testgles$(EXE): $(srcdir)/testgles.c
$(CC) -o $@ $^ $(CFLAGS) $(LIBS) @GLESLIB@ @MATHLIB@
testgles2$(EXE): $(srcdir)/testgles2.c
$(CC) -o $@ $^ $(CFLAGS) $(LIBS) @GLES2LIB@ @MATHLIB@
$(CC) -o $@ $^ $(CFLAGS) $(LIBS) @MATHLIB@
testhaptic$(EXE): $(srcdir)/testhaptic.c
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)

View File

@ -24,11 +24,48 @@
#include "SDL_opengl.h"
typedef struct GL_Context
{
#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
#include "../src/render/opengl/SDL_glfuncs.h"
#undef SDL_PROC
} GL_Context;
/* Undefine this if you want a flat cube instead of a rainbow cube */
#define SHADED_CUBE
static SDLTest_CommonState *state;
static SDL_GLContext context;
static GL_Context ctx;
static int LoadContext(GL_Context * data)
{
#if SDL_VIDEO_DRIVER_UIKIT
#define __SDL_NOGETPROCADDR__
#elif SDL_VIDEO_DRIVER_ANDROID
#define __SDL_NOGETPROCADDR__
#elif SDL_VIDEO_DRIVER_PANDORA
#define __SDL_NOGETPROCADDR__
#endif
#if defined __SDL_NOGETPROCADDR__
#define SDL_PROC(ret,func,params) data->func=func;
#else
#define SDL_PROC(ret,func,params) \
do { \
data->func = SDL_GL_GetProcAddress(#func); \
if ( ! data->func ) { \
return SDL_SetError("Couldn't load GL function %s: %s\n", #func, SDL_GetError()); \
} \
} while ( 0 );
#endif /* _SDL_NOGETPROCADDR_ */
#include "../src/render/opengl/SDL_glfuncs.h"
#undef SDL_PROC
return 0;
}
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
static void
@ -67,107 +104,107 @@ Render()
};
/* Do our drawing, too. */
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
ctx.glClearColor(0.0, 0.0, 0.0, 1.0);
ctx.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
ctx.glBegin(GL_QUADS);
#ifdef SHADED_CUBE
glColor3fv(color[0]);
glVertex3fv(cube[0]);
glColor3fv(color[1]);
glVertex3fv(cube[1]);
glColor3fv(color[2]);
glVertex3fv(cube[2]);
glColor3fv(color[3]);
glVertex3fv(cube[3]);
ctx.glColor3fv(color[0]);
ctx.glVertex3fv(cube[0]);
ctx.glColor3fv(color[1]);
ctx.glVertex3fv(cube[1]);
ctx.glColor3fv(color[2]);
ctx.glVertex3fv(cube[2]);
ctx.glColor3fv(color[3]);
ctx.glVertex3fv(cube[3]);
glColor3fv(color[3]);
glVertex3fv(cube[3]);
glColor3fv(color[4]);
glVertex3fv(cube[4]);
glColor3fv(color[7]);
glVertex3fv(cube[7]);
glColor3fv(color[2]);
glVertex3fv(cube[2]);
ctx.glColor3fv(color[3]);
ctx.glVertex3fv(cube[3]);
ctx.glColor3fv(color[4]);
ctx.glVertex3fv(cube[4]);
ctx.glColor3fv(color[7]);
ctx.glVertex3fv(cube[7]);
ctx.glColor3fv(color[2]);
ctx.glVertex3fv(cube[2]);
glColor3fv(color[0]);
glVertex3fv(cube[0]);
glColor3fv(color[5]);
glVertex3fv(cube[5]);
glColor3fv(color[6]);
glVertex3fv(cube[6]);
glColor3fv(color[1]);
glVertex3fv(cube[1]);
ctx.glColor3fv(color[0]);
ctx.glVertex3fv(cube[0]);
ctx.glColor3fv(color[5]);
ctx.glVertex3fv(cube[5]);
ctx.glColor3fv(color[6]);
ctx.glVertex3fv(cube[6]);
ctx.glColor3fv(color[1]);
ctx.glVertex3fv(cube[1]);
glColor3fv(color[5]);
glVertex3fv(cube[5]);
glColor3fv(color[4]);
glVertex3fv(cube[4]);
glColor3fv(color[7]);
glVertex3fv(cube[7]);
glColor3fv(color[6]);
glVertex3fv(cube[6]);
ctx.glColor3fv(color[5]);
ctx.glVertex3fv(cube[5]);
ctx.glColor3fv(color[4]);
ctx.glVertex3fv(cube[4]);
ctx.glColor3fv(color[7]);
ctx.glVertex3fv(cube[7]);
ctx.glColor3fv(color[6]);
ctx.glVertex3fv(cube[6]);
glColor3fv(color[5]);
glVertex3fv(cube[5]);
glColor3fv(color[0]);
glVertex3fv(cube[0]);
glColor3fv(color[3]);
glVertex3fv(cube[3]);
glColor3fv(color[4]);
glVertex3fv(cube[4]);
ctx.glColor3fv(color[5]);
ctx.glVertex3fv(cube[5]);
ctx.glColor3fv(color[0]);
ctx.glVertex3fv(cube[0]);
ctx.glColor3fv(color[3]);
ctx.glVertex3fv(cube[3]);
ctx.glColor3fv(color[4]);
ctx.glVertex3fv(cube[4]);
glColor3fv(color[6]);
glVertex3fv(cube[6]);
glColor3fv(color[1]);
glVertex3fv(cube[1]);
glColor3fv(color[2]);
glVertex3fv(cube[2]);
glColor3fv(color[7]);
glVertex3fv(cube[7]);
ctx.glColor3fv(color[6]);
ctx.glVertex3fv(cube[6]);
ctx.glColor3fv(color[1]);
ctx.glVertex3fv(cube[1]);
ctx.glColor3fv(color[2]);
ctx.glVertex3fv(cube[2]);
ctx.glColor3fv(color[7]);
ctx.glVertex3fv(cube[7]);
#else /* flat cube */
glColor3f(1.0, 0.0, 0.0);
glVertex3fv(cube[0]);
glVertex3fv(cube[1]);
glVertex3fv(cube[2]);
glVertex3fv(cube[3]);
ctx.glColor3f(1.0, 0.0, 0.0);
ctx.glVertex3fv(cube[0]);
ctx.glVertex3fv(cube[1]);
ctx.glVertex3fv(cube[2]);
ctx.glVertex3fv(cube[3]);
glColor3f(0.0, 1.0, 0.0);
glVertex3fv(cube[3]);
glVertex3fv(cube[4]);
glVertex3fv(cube[7]);
glVertex3fv(cube[2]);
ctx.glColor3f(0.0, 1.0, 0.0);
ctx.glVertex3fv(cube[3]);
ctx.glVertex3fv(cube[4]);
ctx.glVertex3fv(cube[7]);
ctx.glVertex3fv(cube[2]);
glColor3f(0.0, 0.0, 1.0);
glVertex3fv(cube[0]);
glVertex3fv(cube[5]);
glVertex3fv(cube[6]);
glVertex3fv(cube[1]);
ctx.glColor3f(0.0, 0.0, 1.0);
ctx.glVertex3fv(cube[0]);
ctx.glVertex3fv(cube[5]);
ctx.glVertex3fv(cube[6]);
ctx.glVertex3fv(cube[1]);
glColor3f(0.0, 1.0, 1.0);
glVertex3fv(cube[5]);
glVertex3fv(cube[4]);
glVertex3fv(cube[7]);
glVertex3fv(cube[6]);
ctx.glColor3f(0.0, 1.0, 1.0);
ctx.glVertex3fv(cube[5]);
ctx.glVertex3fv(cube[4]);
ctx.glVertex3fv(cube[7]);
ctx.glVertex3fv(cube[6]);
glColor3f(1.0, 1.0, 0.0);
glVertex3fv(cube[5]);
glVertex3fv(cube[0]);
glVertex3fv(cube[3]);
glVertex3fv(cube[4]);
ctx.glColor3f(1.0, 1.0, 0.0);
ctx.glVertex3fv(cube[5]);
ctx.glVertex3fv(cube[0]);
ctx.glVertex3fv(cube[3]);
ctx.glVertex3fv(cube[4]);
glColor3f(1.0, 0.0, 1.0);
glVertex3fv(cube[6]);
glVertex3fv(cube[1]);
glVertex3fv(cube[2]);
glVertex3fv(cube[7]);
ctx.glColor3f(1.0, 0.0, 1.0);
ctx.glVertex3fv(cube[6]);
ctx.glVertex3fv(cube[1]);
ctx.glVertex3fv(cube[2]);
ctx.glVertex3fv(cube[7]);
#endif /* SHADED_CUBE */
glEnd();
ctx.glEnd();
glMatrixMode(GL_MODELVIEW);
glRotatef(5.0, 1.0, 1.0, 1.0);
ctx.glMatrixMode(GL_MODELVIEW);
ctx.glRotatef(5.0, 1.0, 1.0, 1.0);
}
int
@ -242,6 +279,13 @@ main(int argc, char *argv[])
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_GL_CreateContext(): %s\n", SDL_GetError());
quit(2);
}
/* Important: call this *after* creating the context */
if (LoadContext(&ctx) < 0) {
SDL_Log("Could not load GL functions\n");
quit(2);
return 0;
}
if (state->render_flags & SDL_RENDERER_PRESENTVSYNC) {
/* try late-swap-tearing first. If not supported, try normal vsync. */
@ -260,10 +304,10 @@ main(int argc, char *argv[])
SDL_GL_GetDrawableSize(state->windows[0], &dw, &dh);
SDL_Log("Draw Size : %d,%d\n", dw, dh);
SDL_Log("\n");
SDL_Log("Vendor : %s\n", glGetString(GL_VENDOR));
SDL_Log("Renderer : %s\n", glGetString(GL_RENDERER));
SDL_Log("Version : %s\n", glGetString(GL_VERSION));
SDL_Log("Extensions : %s\n", glGetString(GL_EXTENSIONS));
SDL_Log("Vendor : %s\n", ctx.glGetString(GL_VENDOR));
SDL_Log("Renderer : %s\n", ctx.glGetString(GL_RENDERER));
SDL_Log("Version : %s\n", ctx.glGetString(GL_VERSION));
SDL_Log("Extensions : %s\n", ctx.glGetString(GL_EXTENSIONS));
SDL_Log("\n");
status = SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &value);
@ -319,14 +363,14 @@ main(int argc, char *argv[])
}
/* Set rendering settings */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0, 2.0, -2.0, 2.0, -20.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glShadeModel(GL_SMOOTH);
ctx.glMatrixMode(GL_PROJECTION);
ctx.glLoadIdentity();
ctx.glOrtho(-2.0, 2.0, -2.0, 2.0, -20.0, 20.0);
ctx.glMatrixMode(GL_MODELVIEW);
ctx.glLoadIdentity();
ctx.glEnable(GL_DEPTH_TEST);
ctx.glDepthFunc(GL_LESS);
ctx.glShadeModel(GL_SMOOTH);
/* Main render loop */
frames = 0;
@ -344,7 +388,7 @@ main(int argc, char *argv[])
continue;
SDL_GL_MakeCurrent(state->windows[i], context);
SDL_GL_GetDrawableSize(state->windows[i], &w, &h);
glViewport(0, 0, w, h);
ctx.glViewport(0, 0, w, h);
Render();
SDL_GL_SwapWindow(state->windows[i]);
}