1 // Copyright 2015 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #define WAFFLE_API_VERSION 0x0106 6 7 #include <memory> 8 9 #include <stdio.h> 10 #include "main.h" 11 #include "utils.h" 12 #include "waffle_stuff.h" 13 14 GLint g_width = WINDOW_WIDTH; 15 GLint g_height = WINDOW_HEIGHT; 16 17 std::unique_ptr<GLInterface> g_main_gl_interface; 18 19 #ifdef USE_OPENGL 20 namespace gl { 21 #define F(fun, type) type fun = NULL; 22 LIST_PROC_FUNCTIONS(F) 23 #undef F 24 }; 25 #define GL_API WAFFLE_CONTEXT_OPENGL 26 #else 27 #define GL_API WAFFLE_CONTEXT_OPENGL_ES2 28 #endif 29 30 #define ID_PLATFORM_GLX 1 31 #define ID_PLATFORM_X11_EGL 2 32 #define ID_PLATFORM_NULL 3 33 34 #define CONCAT(a, b) a##b 35 #define PLATFORM_ID(x) CONCAT(ID_, x) 36 #define PLATFORM_ENUM(x) CONCAT(WAFFLE_, x) 37 #define THIS_IS(x) PLATFORM_ID(x) == PLATFORM_ID(PLATFORM) 38 39 #if THIS_IS(PLATFORM_GLX) 40 #include "waffle_glx.h" 41 #elif THIS_IS(PLATFORM_X11_EGL) 42 #include "waffle_x11_egl.h" 43 #elif THIS_IS(PLATFORM_NULL) 44 #include "waffle_null.h" 45 #else 46 #error "Compile with -DPLATFORM=PLATFORM_<x> where <x> is NULL, GLX or X11_EGL." 47 #endif 48 49 #define WAFFLE_CHECK_ERROR \ 50 do { \ 51 CHECK(WaffleOK()); \ 52 } while (0) 53 54 GLInterface* GLInterface::Create() { 55 return new WaffleInterface; 56 } 57 58 static bool WaffleOK() { 59 const waffle_error_info* info = waffle_error_get_info(); 60 if (info->code == WAFFLE_NO_ERROR) 61 return true; 62 printf("# Error: %s: %s\n", waffle_error_to_string(info->code), 63 info->message); 64 return false; 65 } 66 67 void WaffleInterface::GetSurfaceSize(GLint* width, GLint* height) { 68 union waffle_native_window* nw = waffle_window_get_native(surface_); 69 70 #if THIS_IS(PLATFORM_NULL) 71 *width = nw->null->width; 72 *height = nw->null->height; 73 #elif THIS_IS(PLATFORM_GLX) 74 unsigned w, h; 75 #if 0 76 // doesn't work with mesa - https://bugs.freedesktop.org/show_bug.cgi?id=54080 77 glXQueryDrawable(nw->glx->xlib_display, nw->glx->xlib_window, GLX_WIDTH, &w); 78 glXQueryDrawable(nw->glx->xlib_display, nw->glx->xlib_window, GLX_HEIGHT, &h); 79 #else 80 Window root; 81 int x, y; 82 unsigned bd, depth; 83 XGetGeometry(nw->glx->xlib_display, nw->glx->xlib_window, &root, &x, &y, &w, 84 &h, &bd, &depth); 85 #endif 86 *width = w; 87 *height = h; 88 #elif THIS_IS(PLATFORM_X11_EGL) 89 EGLint w, h; 90 eglQuerySurface(nw->x11_egl->display.egl_display, nw->x11_egl->egl_surface, 91 EGL_WIDTH, &w); 92 eglQuerySurface(nw->x11_egl->display.egl_display, nw->x11_egl->egl_surface, 93 EGL_HEIGHT, &h); 94 *width = w; 95 *height = h; 96 #else 97 #error "Compile with -DPLATFORM=PLATFORM_<x> where <x> is NULL, GLX or X11_EGL." 98 #endif 99 100 free(nw); 101 } 102 103 void WaffleInterface::InitOnce() { 104 // Prevent multiple initializations. 105 if (surface_) 106 return; 107 108 int32_t initAttribs[] = {WAFFLE_PLATFORM, PLATFORM_ENUM(PLATFORM), 0}; 109 110 waffle_init(initAttribs); 111 WAFFLE_CHECK_ERROR; 112 113 display_ = waffle_display_connect(NULL); 114 WAFFLE_CHECK_ERROR; 115 116 int32_t configAttribs[] = {WAFFLE_CONTEXT_API, GL_API, 117 WAFFLE_RED_SIZE, 1, 118 WAFFLE_GREEN_SIZE, 1, 119 WAFFLE_BLUE_SIZE, 1, 120 WAFFLE_ALPHA_SIZE, 1, 121 WAFFLE_DEPTH_SIZE, 1, 122 WAFFLE_STENCIL_SIZE, 1, 123 WAFFLE_DOUBLE_BUFFERED, true, 124 0}; 125 126 config_ = waffle_config_choose(display_, configAttribs); 127 WAFFLE_CHECK_ERROR; 128 129 if (g_width == -1 && g_height == -1) { 130 const intptr_t attrib[] = {WAFFLE_WINDOW_FULLSCREEN, 1, 0}; 131 surface_ = waffle_window_create2(config_, attrib); 132 GetSurfaceSize(&g_width, &g_height); 133 } else { 134 surface_ = waffle_window_create(config_, g_width, g_height); 135 } 136 WAFFLE_CHECK_ERROR; 137 138 waffle_window_show(surface_); 139 WAFFLE_CHECK_ERROR; 140 } 141 142 bool WaffleInterface::Init() { 143 InitOnce(); 144 145 context_ = CreateContext(); 146 CHECK(context_); 147 148 waffle_make_current(display_, surface_, context_); 149 WAFFLE_CHECK_ERROR; 150 151 #if defined(USE_OPENGL) 152 #define F(fun, type) \ 153 fun = reinterpret_cast<type>(waffle_get_proc_address(#fun)); 154 LIST_PROC_FUNCTIONS(F) 155 #undef F 156 #endif 157 158 return true; 159 } 160 161 void WaffleInterface::Cleanup() { 162 waffle_make_current(display_, NULL, NULL); 163 WAFFLE_CHECK_ERROR; 164 165 waffle_context_destroy(context_); 166 WAFFLE_CHECK_ERROR; 167 } 168 169 void WaffleInterface::SwapBuffers() { 170 waffle_window_swap_buffers(surface_); 171 WAFFLE_CHECK_ERROR; 172 } 173 174 bool WaffleInterface::SwapInterval(int interval) { 175 return false; 176 } 177 178 bool WaffleInterface::MakeCurrent(const GLContext& context) { 179 return waffle_make_current(display_, surface_, context); 180 } 181 182 const GLContext WaffleInterface::CreateContext() { 183 return waffle_context_create(config_, NULL); 184 } 185 186 void WaffleInterface::CheckError() {} 187 188 void WaffleInterface::DeleteContext(const GLContext& context) { 189 waffle_context_destroy(context); 190 WAFFLE_CHECK_ERROR; 191 } 192