| From 94fc503c2764bc6cb2dcbf4c455705abd214091b Mon Sep 17 00:00:00 2001 |
| From: Frank Henigman <fjhenigman@google.com> |
| Date: Wed, 1 Apr 2015 23:55:27 -0400 |
| Subject: [PATCH 6/6] Add waffle backend. |
| |
| Only WAFFLE_PLATFORM_NULL supported so far, though it shouldn't be hard |
| to make it work with any waffle platform. |
| --- |
| src/gl-headers-waffle.h | 128 ++++++++++++++++++++++ |
| src/gl-headers.h | 4 + |
| src/gl-state-waffle.cpp | 259 ++++++++++++++++++++++++++++++++++++++++++++ |
| src/gl-state-waffle.h | 62 +++++++++++ |
| src/main.cpp | 8 ++ |
| src/native-state-waffle.cpp | 155 ++++++++++++++++++++++++++ |
| src/native-state-waffle.h | 47 ++++++++ |
| src/wscript_build | 12 +- |
| wscript | 2 + |
| 9 files changed, 675 insertions(+), 2 deletions(-) |
| create mode 100644 src/gl-headers-waffle.h |
| create mode 100644 src/gl-state-waffle.cpp |
| create mode 100644 src/gl-state-waffle.h |
| create mode 100644 src/native-state-waffle.cpp |
| create mode 100644 src/native-state-waffle.h |
| |
| diff --git a/src/gl-headers-waffle.h b/src/gl-headers-waffle.h |
| new file mode 100644 |
| index 0000000..3efc67a |
| --- /dev/null |
| +++ b/src/gl-headers-waffle.h |
| @@ -0,0 +1,131 @@ |
| +/* |
| + * Copyright 2015 Google Inc. |
| + * |
| + * This program is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU General Public License |
| + * as published by the Free Software Foundation; either version 2 |
| + * of the License, or (at your option) any later version. |
| + * |
| + * This program is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| + * GNU General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU General Public License |
| + * along with this program; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
| + */ |
| +#ifndef GL_HEADERS_WAFFLE_H_ |
| +#define GL_HEADERS_WAFFLE_H_ |
| + |
| +#include <KHR/khrplatform.h> |
| + |
| +namespace hide_gles2 { |
| +// Can't use the function declarations in this header because we need to |
| +// declare them as pointers to be looked up with waffle, so hide them in |
| +// this namespace. |
| +// This way we still get all the #defines in the header. |
| +#include <GLES2/gl2.h> |
| +}; |
| + |
| +// Unfortunately now these types are hidden and need to be exposed. |
| +using hide_gles2::GLbyte; |
| +using hide_gles2::GLclampf; |
| +using hide_gles2::GLfixed; |
| +using hide_gles2::GLshort; |
| +using hide_gles2::GLushort; |
| +using hide_gles2::GLvoid; |
| +using hide_gles2::GLsync; |
| +using hide_gles2::GLint64; |
| +using hide_gles2::GLuint64; |
| +using hide_gles2::GLenum; |
| +using hide_gles2::GLuint; |
| +using hide_gles2::GLchar; |
| +using hide_gles2::GLfloat; |
| +using hide_gles2::GLsizeiptr; |
| +using hide_gles2::GLintptr; |
| +using hide_gles2::GLbitfield; |
| +using hide_gles2::GLint; |
| +using hide_gles2::GLboolean; |
| +using hide_gles2::GLsizei; |
| +using hide_gles2::GLubyte; |
| + |
| +namespace waffle_hide { |
| +#define GLES2_FUNCTION_LIST(f) \ |
| +f(void , glActiveTexture , (GLenum texture)) \ |
| +f(void , glAttachShader , (GLuint program, GLuint shader)) \ |
| +f(void , glBindBuffer , (GLenum target, GLuint buffer)) \ |
| +f(void , glBindFramebuffer , (GLenum target, GLuint framebuffer)) \ |
| +f(void , glBindRenderbuffer , (GLenum target, GLuint renderbuffer)) \ |
| +f(void , glBindTexture , (GLenum target, GLuint texture)) \ |
| +f(void , glBlendFunc , (GLenum sfactor, GLenum dfactor)) \ |
| +f(void , glBlendFuncSeparate , (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha)) \ |
| +f(void , glBufferData , (GLenum target, GLsizeiptr size, const void *data, GLenum usage)) \ |
| +f(void , glBufferSubData , (GLenum target, GLintptr offset, GLsizeiptr size, const void *data)) \ |
| +f(GLenum , glCheckFramebufferStatus , (GLenum target)) \ |
| +f(void , glClearColor , (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)) \ |
| +f(void , glClearDepthf , (GLfloat d)) \ |
| +f(void , glClear , (GLbitfield mask)) \ |
| +f(void , glColorMask , (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)) \ |
| +f(void , glCompileShader , (GLuint shader)) \ |
| +f(GLuint , glCreateProgram , (void)) \ |
| +f(GLuint , glCreateShader , (GLenum type)) \ |
| +f(void , glCullFace , (GLenum mode)) \ |
| +f(void , glDeleteBuffers , (GLsizei n, const GLuint *buffers)) \ |
| +f(void , glDeleteFramebuffers , (GLsizei n, const GLuint *framebuffers)) \ |
| +f(void , glDeleteProgram , (GLuint program)) \ |
| +f(void , glDeleteRenderbuffers , (GLsizei n, const GLuint *renderbuffers)) \ |
| +f(void , glDeleteShader , (GLuint shader)) \ |
| +f(void , glDeleteTextures , (GLsizei n, const GLuint *textures)) \ |
| +f(void , glDepthFunc , (GLenum func)) \ |
| +f(void , glDepthMask , (GLboolean flag)) \ |
| +f(void , glDisable , (GLenum cap)) \ |
| +f(void , glDisableVertexAttribArray, (GLuint index)) \ |
| +f(void , glDrawArrays , (GLenum mode, GLint first, GLsizei count)) \ |
| +f(void , glDrawElements , (GLenum mode, GLsizei count, GLenum type, const void *indices)) \ |
| +f(void , glEnable , (GLenum cap)) \ |
| +f(void , glEnableVertexAttribArray , (GLuint index)) \ |
| +f(void , glFinish , (void)) \ |
| +f(void , glFramebufferRenderbuffer , (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)) \ |
| +f(void , glFramebufferTexture2D , (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)) \ |
| +f(void , glGenBuffers , (GLsizei n, GLuint *buffers)) \ |
| +f(void , glGenerateMipmap , (GLenum target)) \ |
| +f(void , glGenFramebuffers , (GLsizei n, GLuint *framebuffers)) \ |
| +f(void , glGenRenderbuffers , (GLsizei n, GLuint *renderbuffers)) \ |
| +f(void , glGenTextures , (GLsizei n, GLuint *textures)) \ |
| +f(GLint , glGetAttribLocation , (GLuint program, const GLchar *name)) \ |
| +f(void , glGetBooleanv , (GLenum pname, GLboolean *data)) \ |
| +f(GLenum , glGetError , (void)) \ |
| +f(void , glGetIntegerv , (GLenum pname, GLint *data)) \ |
| +f(void , glGetProgramInfoLog , (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog)) \ |
| +f(void , glGetProgramiv , (GLuint program, GLenum pname, GLint *params)) \ |
| +f(void , glGetShaderInfoLog , (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog)) \ |
| +f(void , glGetShaderiv , (GLuint shader, GLenum pname, GLint *params)) \ |
| +f(const GLubyte *, glGetString , (GLenum name)) \ |
| +f(GLint , glGetUniformLocation , (GLuint program, const GLchar *name)) \ |
| +f(GLboolean , glIsEnabled , (GLenum cap)) \ |
| +f(void , glLinkProgram , (GLuint program)) \ |
| +f(void , glReadPixels , (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels)) \ |
| +f(void , glRenderbufferStorage , (GLenum target, GLenum internalformat, GLsizei width, GLsizei height)) \ |
| +f(void , glShaderSource , (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length)) \ |
| +f(void , glTexImage2D , (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels)) \ |
| +f(void , glTexParameteri , (GLenum target, GLenum pname, GLint param)) \ |
| +f(void , glUniform1f , (GLint location, GLfloat v0)) \ |
| +f(void , glUniform1i , (GLint location, GLint v0)) \ |
| +f(void , glUniform2fv , (GLint location, GLsizei count, const GLfloat *value)) \ |
| +f(void , glUniform3fv , (GLint location, GLsizei count, const GLfloat *value)) \ |
| +f(void , glUniform4fv , (GLint location, GLsizei count, const GLfloat *value)) \ |
| +f(void , glUniformMatrix3fv , (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)) \ |
| +f(void , glUniformMatrix4fv , (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)) \ |
| +f(void , glUseProgram , (GLuint program)) \ |
| +f(void , glVertexAttribPointer , (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer)) \ |
| +f(void , glViewport , (GLint x, GLint y, GLsizei width, GLsizei height)) \ |
| + |
| + |
| +#define DECLARE(type, func, args) extern type (*func) args; |
| +GLES2_FUNCTION_LIST(DECLARE) |
| +#undef DECLARE |
| +}; // end namespace waffle_hide |
| +using namespace waffle_hide; |
| + |
| +#endif // GL_HEADERS_WAFFLE_H_ |
| diff --git a/src/gl-headers.h b/src/gl-headers.h |
| index 1d0527a..25b569b 100644 |
| --- a/src/gl-headers.h |
| +++ b/src/gl-headers.h |
| @@ -31,7 +31,11 @@ |
| #define GL_RGB565 0x8D62 |
| #endif |
| #elif GLMARK2_USE_GLESv2 |
| +#ifdef GLMARK2_USE_WAFFLE |
| +#include <gl-headers-waffle.h> |
| +#else |
| #include <GLES2/gl2.h> |
| +#endif |
| #include <GLES2/gl2ext.h> |
| #ifndef GL_WRITE_ONLY |
| #define GL_WRITE_ONLY GL_WRITE_ONLY_OES |
| diff --git a/src/gl-state-waffle.cpp b/src/gl-state-waffle.cpp |
| new file mode 100644 |
| index 0000000..1b2cf40 |
| --- /dev/null |
| +++ b/src/gl-state-waffle.cpp |
| @@ -0,0 +1,259 @@ |
| +/* |
| + * Copyright 2015 Google Inc. |
| + * |
| + * This program is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU General Public License |
| + * as published by the Free Software Foundation; either version 2 |
| + * of the License, or (at your option) any later version. |
| + * |
| + * This program is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| + * GNU General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU General Public License |
| + * along with this program; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
| + */ |
| +#include "gl-state-waffle.h" |
| +#include "log.h" |
| +#include "options.h" |
| +#include "gl-headers.h" |
| +#include "limits.h" |
| +#include "gl-headers.h" |
| +#include <iomanip> |
| +#include <sstream> |
| +#include <waffle_null.h> |
| + |
| +using std::vector; |
| +using std::string; |
| + |
| +/***************************** |
| + * GLStateWaffle public methods * |
| + ****************************/ |
| + |
| +bool |
| +GLStateWaffle::init_display(void* native_display, GLVisualConfig& visual_config) |
| +{ |
| + native_display_ = native_display; |
| + requested_visual_config_ = visual_config; |
| + |
| + return gotValidDisplay(); |
| +} |
| + |
| +bool |
| +GLStateWaffle::init_surface(void* native_window) |
| +{ |
| + native_window_ = native_window; |
| + |
| + return gotValidSurface(); |
| +} |
| + |
| +void |
| +GLStateWaffle::init_gl_extensions() |
| +{ |
| +#if GLMARK2_USE_GLESv2 |
| + if (GLExtensions::support("GL_OES_mapbuffer")) { |
| + GLExtensions::MapBuffer = |
| + reinterpret_cast<PFNGLMAPBUFFEROESPROC>(eglGetProcAddress("glMapBufferOES")); |
| + GLExtensions::UnmapBuffer = |
| + reinterpret_cast<PFNGLUNMAPBUFFEROESPROC>(eglGetProcAddress("glUnmapBufferOES")); |
| + } |
| +#elif GLMARK2_USE_GL |
| + GLExtensions::MapBuffer = glMapBuffer; |
| + GLExtensions::UnmapBuffer = glUnmapBuffer; |
| +#endif |
| +} |
| + |
| +static void |
| +LogWaffleError(const char* msg) |
| +{ |
| + const struct waffle_error_info* info = waffle_error_get_info(); |
| + Log::error("%s - %s - %s\n", msg, info->message, |
| + waffle_error_to_string(info->code)); |
| +} |
| + |
| +bool |
| +GLStateWaffle::valid() |
| +{ |
| + if (!gotValidDisplay()) |
| + return false; |
| + |
| + if (!gotValidConfig()) |
| + return false; |
| + |
| + if (!gotValidSurface()) |
| + return false; |
| + |
| + if (!gotValidContext()) |
| + return false; |
| + |
| + if (!waffle_make_current(waffle_display_, waffle_surface_, waffle_context_)) { |
| + LogWaffleError("waffle_make_current failed"); |
| + return false; |
| + } |
| + |
| + init_gl_extensions(); |
| + |
| + return true; |
| +} |
| + |
| +bool |
| +GLStateWaffle::reset() |
| +{ |
| + if (!gotValidDisplay()) { |
| + return false; |
| + } |
| + |
| + if (!waffle_context_) { |
| + return true; |
| + } |
| + |
| + if (!waffle_context_destroy(waffle_context_)) { |
| + LogWaffleError("waffle_context_destroy failed"); |
| + } |
| + |
| + waffle_context_ = 0; |
| + |
| + return true; |
| +} |
| + |
| +void |
| +GLStateWaffle::swap() |
| +{ |
| + waffle_window_swap_buffers(waffle_surface_); |
| +} |
| + |
| +bool |
| +GLStateWaffle::gotNativeConfig(intptr_t& vid) |
| +{ |
| + if (!gotValidConfig()) |
| + return false; |
| + |
| + vid = (intptr_t) waffle_config_; |
| + return true; |
| +} |
| + |
| +void |
| +GLStateWaffle::getVisualConfig(GLVisualConfig& vc) |
| +{ |
| + if (!gotValidConfig()) |
| + return; |
| + |
| + get_glvisualconfig(waffle_config_, vc); |
| +} |
| + |
| +/****************************** |
| + * GLStateWaffle private methods * |
| + *****************************/ |
| + |
| +bool |
| +GLStateWaffle::gotValidDisplay() |
| +{ |
| + if (waffle_display_) |
| + return true; |
| + |
| + waffle_display_ = (waffle_display*)native_display_; |
| + if (!waffle_display_) { |
| + Log::error("no native display - this shouldn't happen"); |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| +void |
| +GLStateWaffle::get_glvisualconfig(waffle_config* waffle_config, GLVisualConfig& visual_config) |
| +{ |
| + waffle_native_config *n = waffle_config_get_native(waffle_config); |
| + /* |
| + * NOTE: This works for WAFFLE_PLATFORM_NULL only. |
| + * Other platforms will need something different. |
| + */ |
| + EGLDisplay dpy = n->null->display.egl_display; |
| + EGLConfig config = n->null->egl_config; |
| + |
| + free(n); |
| + eglGetConfigAttrib(dpy, config, EGL_BUFFER_SIZE, &visual_config.buffer); |
| + eglGetConfigAttrib(dpy, config, EGL_RED_SIZE, &visual_config.red); |
| + eglGetConfigAttrib(dpy, config, EGL_GREEN_SIZE, &visual_config.green); |
| + eglGetConfigAttrib(dpy, config, EGL_BLUE_SIZE, &visual_config.blue); |
| + eglGetConfigAttrib(dpy, config, EGL_ALPHA_SIZE, &visual_config.alpha); |
| + eglGetConfigAttrib(dpy, config, EGL_DEPTH_SIZE, &visual_config.depth); |
| + eglGetConfigAttrib(dpy, config, EGL_STENCIL_SIZE, &visual_config.stencil); |
| +} |
| + |
| +bool |
| +GLStateWaffle::gotValidConfig() |
| +{ |
| + if (waffle_config_) |
| + return true; |
| + |
| + if (!gotValidDisplay()) |
| + return false; |
| + |
| + const int32_t config_attribs[] = { |
| + WAFFLE_RED_SIZE, requested_visual_config_.red, |
| + WAFFLE_GREEN_SIZE, requested_visual_config_.green, |
| + WAFFLE_BLUE_SIZE, requested_visual_config_.blue, |
| + WAFFLE_ALPHA_SIZE, requested_visual_config_.alpha, |
| + WAFFLE_DEPTH_SIZE, requested_visual_config_.depth, |
| + WAFFLE_STENCIL_SIZE, requested_visual_config_.stencil, |
| +#if GLMARK2_USE_GLESv2 |
| + WAFFLE_CONTEXT_API, WAFFLE_CONTEXT_OPENGL_ES2, |
| +#elif GLMARK2_USE_GL |
| + WAFFLE_CONTEXT_API, WAFFLE_CONTEXT_OPENGL, |
| +#endif |
| + WAFFLE_NONE |
| + }; |
| + |
| + waffle_config_ = waffle_config_choose(waffle_display_, config_attribs); |
| + if (!waffle_config_) { |
| + LogWaffleError("waffle_config_choose failed"); |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| +bool |
| +GLStateWaffle::gotValidSurface() |
| +{ |
| + if (waffle_surface_) |
| + return true; |
| + |
| + if (!gotValidDisplay()) |
| + return false; |
| + |
| + if (!gotValidConfig()) |
| + return false; |
| + |
| + waffle_surface_ = (waffle_window*) native_window_; |
| + if (!waffle_surface_) { |
| + Log::error("no native window - this shouldn't happen"); |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| +bool |
| +GLStateWaffle::gotValidContext() |
| +{ |
| + if (waffle_context_) |
| + return true; |
| + |
| + if (!gotValidDisplay()) |
| + return false; |
| + |
| + if (!gotValidConfig()) |
| + return false; |
| + |
| + waffle_context_ = waffle_context_create(waffle_config_, NULL); |
| + if (!waffle_context_) { |
| + LogWaffleError("waffle_context_create failed"); |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| diff --git a/src/gl-state-waffle.h b/src/gl-state-waffle.h |
| new file mode 100644 |
| index 0000000..e66c079 |
| --- /dev/null |
| +++ b/src/gl-state-waffle.h |
| @@ -0,0 +1,62 @@ |
| +/* |
| + * Copyright 2015 Google Inc. |
| + * |
| + * This program is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU General Public License |
| + * as published by the Free Software Foundation; either version 2 |
| + * of the License, or (at your option) any later version. |
| + * |
| + * This program is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| + * GNU General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU General Public License |
| + * along with this program; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
| + */ |
| +#ifndef GLMARK2_GL_STATE_WAFFLE_H_ |
| +#define GLMARK2_GL_STATE_WAFFLE_H_ |
| + |
| +#include <vector> |
| +#include <EGL/egl.h> |
| +#include <waffle.h> |
| +#include "gl-state.h" |
| +#include "gl-visual-config.h" |
| + |
| +class GLStateWaffle : public GLState |
| +{ |
| + void* native_display_; |
| + void* native_window_; |
| + waffle_display* waffle_display_; |
| + waffle_config* waffle_config_; |
| + waffle_context* waffle_context_; |
| + waffle_window* waffle_surface_; |
| + GLVisualConfig requested_visual_config_; |
| + bool gotValidDisplay(); |
| + bool gotValidConfig(); |
| + bool gotValidSurface(); |
| + bool gotValidContext(); |
| + void get_glvisualconfig(waffle_config* config, GLVisualConfig& visual_config); |
| + EGLConfig select_best_config(std::vector<EGLConfig>& configs); |
| +public: |
| + GLStateWaffle() : |
| + native_display_(0), |
| + native_window_(0), |
| + waffle_display_(0), |
| + waffle_config_(0), |
| + waffle_context_(0), |
| + waffle_surface_(0) {} |
| + |
| + bool init_display(void* native_display, GLVisualConfig& config_pref); |
| + bool init_surface(void* native_window); |
| + void init_gl_extensions(); |
| + bool valid(); |
| + bool reset(); |
| + void swap(); |
| + // Performs a config search, returning a native visual ID on success |
| + bool gotNativeConfig(intptr_t& vid); |
| + void getVisualConfig(GLVisualConfig& vc); |
| +}; |
| + |
| +#endif // GLMARK2_GL_STATE_WAFFLE_H_ |
| diff --git a/src/main.cpp b/src/main.cpp |
| index b84b827..d62bade 100644 |
| --- a/src/main.cpp |
| +++ b/src/main.cpp |
| @@ -42,12 +42,16 @@ |
| #include "native-state-mir.h" |
| #elif GLMARK2_USE_WAYLAND |
| #include "native-state-wayland.h" |
| +#elif GLMARK2_USE_WAFFLE |
| +#include "native-state-waffle.h" |
| #endif |
| |
| #if GLMARK2_USE_EGL |
| #include "gl-state-egl.h" |
| #elif GLMARK2_USE_GLX |
| #include "gl-state-glx.h" |
| +#elif GLMARK2_USE_WAFFLE |
| +#include "gl-state-waffle.h" |
| #endif |
| |
| using std::vector; |
| @@ -168,12 +172,16 @@ main(int argc, char *argv[]) |
| NativeStateMir native_state; |
| #elif GLMARK2_USE_WAYLAND |
| NativeStateWayland native_state; |
| +#elif GLMARK2_USE_WAFFLE |
| + NativeStateWaffle native_state; |
| #endif |
| |
| #if GLMARK2_USE_EGL |
| GLStateEGL gl_state; |
| #elif GLMARK2_USE_GLX |
| GLStateGLX gl_state; |
| +#elif GLMARK2_USE_WAFFLE |
| + GLStateWaffle gl_state; |
| #endif |
| |
| CanvasGeneric canvas(native_state, gl_state, Options::size.first, Options::size.second); |
| diff --git a/src/native-state-waffle.cpp b/src/native-state-waffle.cpp |
| new file mode 100644 |
| index 0000000..90e6c9e |
| --- /dev/null |
| +++ b/src/native-state-waffle.cpp |
| @@ -0,0 +1,157 @@ |
| +/* |
| + * Copyright 2015 Google Inc. |
| + * |
| + * This program is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU General Public License |
| + * as published by the Free Software Foundation; either version 2 |
| + * of the License, or (at your option) any later version. |
| + * |
| + * This program is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| + * GNU General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU General Public License |
| + * along with this program; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
| + */ |
| +#include "gl-headers-waffle.h" |
| +#include "native-state-waffle.h" |
| +#include "log.h" |
| + |
| +#include <waffle_null.h> |
| + |
| +namespace waffle_hide { |
| +#define DEFINE(type, func, args) type (*func) args; |
| +GLES2_FUNCTION_LIST(DEFINE) |
| +#undef DEFINE |
| +}; |
| + |
| +/****************** |
| + * Public methods * |
| + ******************/ |
| + |
| +NativeStateWaffle::~NativeStateWaffle() |
| +{ |
| + if (wdpy_) |
| + { |
| + if (wwin_) |
| + waffle_window_destroy(wwin_); |
| + |
| + waffle_display_disconnect(wdpy_); |
| + waffle_teardown(); |
| + } |
| +} |
| + |
| +bool |
| +NativeStateWaffle::init_display() |
| +{ |
| + if (!wdpy_) { |
| + const int32_t attrib[] = { |
| + WAFFLE_PLATFORM, WAFFLE_PLATFORM_NULL, |
| + 0 |
| + }; |
| + if (!waffle_init(attrib)) |
| + return false; |
| + wdpy_ = waffle_display_connect(NULL); |
| + } |
| + |
| +#define LOOKUP(type, func, args) \ |
| + func = (type (*) args) waffle_dl_sym(WAFFLE_DL_OPENGL_ES2, #func); \ |
| + if (!func) \ |
| + return false; |
| +GLES2_FUNCTION_LIST(LOOKUP) |
| +#undef LOOKUP |
| + |
| + return (wdpy_ != 0); |
| +} |
| + |
| +void* |
| +NativeStateWaffle::display() |
| +{ |
| + return (void*)wdpy_; |
| +} |
| + |
| +bool |
| +NativeStateWaffle::create_window(WindowProperties const& properties) |
| +{ |
| + if (!wdpy_) { |
| + Log::error("Error: waffle display has not been initialized!\n"); |
| + return false; |
| + } |
| + |
| + /* Recreate an existing window only if it has actually been resized */ |
| + if (wwin_) { |
| + if (properties_.fullscreen != properties.fullscreen || |
| + (properties.fullscreen == false && |
| + (properties_.width != properties.width || |
| + properties_.height != properties.height))) |
| + { |
| + waffle_window_destroy(wwin_); |
| + wwin_ = 0; |
| + } |
| + else |
| + { |
| + return true; |
| + } |
| + } |
| + |
| + /* Set desired attributes */ |
| + properties_.fullscreen = properties.fullscreen; |
| + properties_.visual_id = properties.visual_id; |
| + |
| + intptr_t attrib[] = { |
| + /* |
| + * NOTE: This works for WAFFLE_PLATFORM_NULL only. |
| + * Other platforms could call egl/glx-SwapInterval. |
| + */ |
| + WAFFLE_WINDOW_NULL_VSYNC_WAIT, false, |
| + |
| + WAFFLE_WINDOW_WIDTH, properties.width, |
| + WAFFLE_WINDOW_HEIGHT, properties.height, |
| + 0 |
| + }; |
| + if (properties_.fullscreen) { |
| + attrib[2] = WAFFLE_WINDOW_FULLSCREEN; |
| + attrib[3] = true; |
| + attrib[4] = 0; |
| + } |
| + |
| + wwin_ = waffle_window_create2((waffle_config*) properties_.visual_id, |
| + attrib); |
| + |
| + if (!wwin_) { |
| + Log::error("Error: waffle_window_create() failed!\n"); |
| + return false; |
| + } |
| + |
| + union waffle_native_window *nw = waffle_window_get_native(wwin_); |
| + /* |
| + * NOTE: This works for WAFFLE_PLATFORM_NULL only. |
| + * Other platforms will need something different. |
| + */ |
| + properties_.width = nw->null->width; |
| + properties_.height = nw->null->height; |
| + |
| + return true; |
| +} |
| + |
| +void* |
| +NativeStateWaffle::window(WindowProperties& properties) |
| +{ |
| + properties = properties_; |
| + return (void*)wwin_; |
| +} |
| + |
| +void |
| +NativeStateWaffle::visible(bool visible) |
| +{ |
| + if (visible) |
| + waffle_window_show(wwin_); |
| +} |
| + |
| +bool |
| +NativeStateWaffle::should_quit() |
| +{ |
| + return false; |
| +} |
| diff --git a/src/native-state-waffle.h b/src/native-state-waffle.h |
| new file mode 100644 |
| index 0000000..1ea2f1b |
| --- /dev/null |
| +++ b/src/native-state-waffle.h |
| @@ -0,0 +1,47 @@ |
| +/* |
| + * Copyright 2015 Google Inc. |
| + * |
| + * This program is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU General Public License |
| + * as published by the Free Software Foundation; either version 2 |
| + * of the License, or (at your option) any later version. |
| + * |
| + * This program is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| + * GNU General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU General Public License |
| + * along with this program; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
| + */ |
| +#ifndef GLMARK2_NATIVE_STATE_WAFFLE_H_ |
| +#define GLMARK2_NATIVE_STATE_WAFFLE_H_ |
| + |
| +#include "native-state.h" |
| +#define WAFFLE_API_VERSION 0x0106 |
| +#include <waffle.h> |
| + |
| +class NativeStateWaffle : public NativeState |
| +{ |
| +public: |
| + NativeStateWaffle() : wdpy_(0), wwin_(0), properties_() {} |
| + ~NativeStateWaffle(); |
| + |
| + bool init_display(); |
| + void* display(); |
| + bool create_window(WindowProperties const& properties); |
| + void* window(WindowProperties& properties); |
| + void visible(bool v); |
| + bool should_quit(); |
| + void flip() { } |
| + |
| +private: |
| + /** The waffle display associated with this canvas. */ |
| + waffle_display* wdpy_; |
| + /** The waffle window associated with this canvas. */ |
| + waffle_window* wwin_; |
| + WindowProperties properties_; |
| +}; |
| + |
| +#endif /* GLMARK2_NATIVE_STATE_WAFFLE_H_ */ |
| diff --git a/src/wscript_build b/src/wscript_build |
| index c0173c3..4082ade 100644 |
| --- a/src/wscript_build |
| +++ b/src/wscript_build |
| @@ -15,6 +15,7 @@ flavor_sources = { |
| 'drm-glesv2' : ['canvas-generic.cpp', 'native-state-drm.cpp', 'gl-state-egl.cpp'], |
| 'mir-gl' : ['canvas-generic.cpp', 'native-state-mir.cpp', 'gl-state-egl.cpp'], |
| 'mir-glesv2' : ['canvas-generic.cpp', 'native-state-mir.cpp', 'gl-state-egl.cpp'], |
| + 'waffle' : ['canvas-generic.cpp', 'native-state-waffle.cpp', 'gl-state-waffle.cpp'], |
| 'wayland-gl' : ['canvas-generic.cpp', 'native-state-wayland.cpp', 'gl-state-egl.cpp'], |
| 'wayland-glesv2' : ['canvas-generic.cpp', 'native-state-wayland.cpp', 'gl-state-egl.cpp'] |
| } |
| @@ -25,6 +26,7 @@ flavor_uselibs = { |
| 'drm-glesv2' : ['drm', 'gbm', 'egl', 'glesv2', 'matrix-gl'], |
| 'mir-gl' : ['mirclient', 'egl', 'gl', 'matrix-gl'], |
| 'mir-glesv2' : ['mirclient', 'egl', 'glesv2', 'matrix-gl'], |
| + 'waffle' : ['waffle-1', 'egl', 'matrix-glesv2'], |
| 'wayland-gl' : ['wayland-client', 'wayland-egl', 'egl', 'gl', 'matrix-gl'], |
| 'wayland-glesv2' : ['wayland-client', 'wayland-egl', 'egl', 'glesv2', 'matrix-gl'] |
| } |
| @@ -35,6 +37,7 @@ flavor_defines = { |
| 'drm-glesv2' : ['GLMARK2_USE_DRM', 'GLMARK2_USE_GLESv2', 'GLMARK2_USE_EGL', '__GBM__'], |
| 'mir-gl' : ['GLMARK2_USE_MIR', 'GLMARK2_USE_GL', 'GLMARK2_USE_EGL'], |
| 'mir-glesv2' : ['GLMARK2_USE_MIR', 'GLMARK2_USE_GLESv2', 'GLMARK2_USE_EGL'], |
| + 'waffle' : ['GLMARK2_USE_WAFFLE', 'GLMARK2_USE_GLESv2'], |
| 'wayland-gl' : ['GLMARK2_USE_WAYLAND', 'GLMARK2_USE_GL', 'GLMARK2_USE_EGL'], |
| 'wayland-glesv2' : ['GLMARK2_USE_WAYLAND', 'GLMARK2_USE_GLESv2', 'GLMARK2_USE_EGL'] |
| } |
| @@ -58,6 +61,11 @@ for name in bld.env.keys(): |
| ) |
| all_uselibs |= set(flavor_uselibs[flavor]) |
| |
| + |
| +matrix_defines = ['USE_EXCEPTIONS'] |
| +if 'waffle' in flavor: |
| + matrix_defines += ['GLMARK2_USE_WAFFLE'] |
| + |
| if 'matrix-gl' in all_uselibs: |
| bld( |
| features = ['cxx', 'cxxstlib'], |
| @@ -66,7 +74,7 @@ if 'matrix-gl' in all_uselibs: |
| lib = ['m'], |
| includes = ['.'], |
| export_includes = 'libmatrix', |
| - defines = ['GLMARK2_USE_GL', 'USE_EXCEPTIONS'] |
| + defines = matrix_defines + ['GLMARK2_USE_GL'] |
| ) |
| |
| if 'matrix-glesv2' in all_uselibs: |
| @@ -77,5 +85,5 @@ if 'matrix-glesv2' in all_uselibs: |
| lib = ['m'], |
| includes = ['.'], |
| export_includes = 'libmatrix', |
| - defines = ['GLMARK2_USE_GLESv2', 'USE_EXCEPTIONS'] |
| + defines = matrix_defines + ['GLMARK2_USE_GLESv2'] |
| ) |
| diff --git a/wscript b/wscript |
| index 7b0d1c2..e254118 100644 |
| --- a/wscript |
| +++ b/wscript |
| @@ -18,6 +18,7 @@ FLAVORS = { |
| 'drm-glesv2' : 'glmark2-es2-drm', |
| 'mir-gl' : 'glmark2-mir', |
| 'mir-glesv2' : 'glmark2-es2-mir', |
| + 'waffle' : 'glmark2-waffle', |
| 'wayland-gl' : 'glmark2-wayland', |
| 'wayland-glesv2' : 'glmark2-es2-wayland' |
| } |
| @@ -117,6 +118,7 @@ def configure(ctx): |
| ('libdrm','drm', list_contains(Options.options.flavors, 'drm')), |
| ('gbm','gbm', list_contains(Options.options.flavors, 'drm')), |
| ('mirclient','mirclient', list_contains(Options.options.flavors, 'mir')), |
| + ('waffle-1', 'waffle-1', list_contains(Options.options.flavors, 'waffle')), |
| ('wayland-client','wayland-client', list_contains(Options.options.flavors, 'wayland')), |
| ('wayland-egl','wayland-egl', list_contains(Options.options.flavors, 'wayland'))] |
| for (pkg, uselib, mandatory) in opt_pkgs: |
| -- |
| 2.2.0.rc0.207.ga3a616c |
| |