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 "base/logging.h" 10 #include "main.h" 11 #include "waffle_stuff.h" 12 #include <stdio.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 do { CHECK(WaffleOK()); } while (0) 50 51 GLInterface* GLInterface::Create() { 52 return new WaffleInterface; 53 } 54 55 static bool WaffleOK() { 56 const waffle_error_info *info = waffle_error_get_info(); 57 if (info->code == WAFFLE_NO_ERROR) 58 return true; 59 printf("# Error: %s: %s\n", 60 waffle_error_to_string(info->code), 61 info->message); 62 return false; 63 } 64 65 void WaffleInterface::GetSurfaceSize(GLint *width, GLint *height) { 66 union waffle_native_window *nw = waffle_window_get_native(surface_); 67 68 #if THIS_IS(PLATFORM_NULL) 69 *width = nw->null->width; 70 *height = nw->null->height; 71 #elif THIS_IS(PLATFORM_GLX) 72 unsigned w, h; 73 #if 0 74 // doesn't work with mesa - https://bugs.freedesktop.org/show_bug.cgi?id=54080 75 glXQueryDrawable(nw->glx->xlib_display, nw->glx->xlib_window, GLX_WIDTH, &w); 76 glXQueryDrawable(nw->glx->xlib_display, nw->glx->xlib_window, GLX_HEIGHT, &h); 77 #else 78 Window root; 79 int x, y; 80 unsigned bd, depth; 81 XGetGeometry(nw->glx->xlib_display, nw->glx->xlib_window, 82 &root, &x, &y, &w, &h, &bd, &depth); 83 #endif 84 *width = w; 85 *height = h; 86 #elif THIS_IS(PLATFORM_X11_EGL) 87 EGLint w, h; 88 eglQuerySurface(nw->x11_egl->display.egl_display, nw->x11_egl->egl_surface, 89 EGL_WIDTH, &w); 90 eglQuerySurface(nw->x11_egl->display.egl_display, nw->x11_egl->egl_surface, 91 EGL_HEIGHT, &h); 92 *width = w; 93 *height = h; 94 #else 95 #error "Compile with -DPLATFORM=PLATFORM_<x> where <x> is NULL, GLX or X11_EGL." 96 #endif 97 98 free(nw); 99 } 100 101 void WaffleInterface::InitOnce() { 102 // Prevent multiple initializations. 103 if (surface_) 104 return; 105 106 int32_t initAttribs[] = { 107 WAFFLE_PLATFORM, PLATFORM_ENUM(PLATFORM), 108 0 109 }; 110 111 waffle_init(initAttribs); 112 WAFFLE_CHECK_ERROR; 113 114 display_ = waffle_display_connect(NULL); 115 WAFFLE_CHECK_ERROR; 116 117 int32_t configAttribs[] = { 118 WAFFLE_CONTEXT_API, GL_API, 119 WAFFLE_RED_SIZE, 1, 120 WAFFLE_GREEN_SIZE, 1, 121 WAFFLE_BLUE_SIZE, 1, 122 WAFFLE_ALPHA_SIZE, 1, 123 WAFFLE_DEPTH_SIZE, 1, 124 WAFFLE_STENCIL_SIZE, 1, 125 WAFFLE_DOUBLE_BUFFERED, true, 126 0 127 }; 128 129 config_ = waffle_config_choose(display_, configAttribs); 130 WAFFLE_CHECK_ERROR; 131 132 if (g_width == -1 && g_height == -1) { 133 const intptr_t attrib[] = { 134 WAFFLE_WINDOW_FULLSCREEN, 1, 135 0 136 }; 137 surface_ = waffle_window_create2(config_, attrib); 138 GetSurfaceSize(&g_width, &g_height); 139 } else { 140 surface_ = waffle_window_create(config_, g_width, g_height); 141 } 142 WAFFLE_CHECK_ERROR; 143 144 waffle_window_show(surface_); 145 WAFFLE_CHECK_ERROR; 146 } 147 148 bool WaffleInterface::Init() { 149 InitOnce(); 150 151 context_ = CreateContext(); 152 CHECK(context_); 153 154 waffle_make_current(display_, surface_, context_); 155 WAFFLE_CHECK_ERROR; 156 157 #if defined(USE_OPENGL) 158 #define F(fun, type) fun = reinterpret_cast<type>(waffle_get_proc_address(#fun)); 159 LIST_PROC_FUNCTIONS(F) 160 #undef F 161 #endif 162 163 return true; 164 } 165 166 void WaffleInterface::Cleanup() { 167 waffle_make_current(display_, NULL, NULL); 168 WAFFLE_CHECK_ERROR; 169 170 waffle_context_destroy(context_); 171 WAFFLE_CHECK_ERROR; 172 } 173 174 void WaffleInterface::SwapBuffers() { 175 waffle_window_swap_buffers(surface_); 176 WAFFLE_CHECK_ERROR; 177 } 178 179 bool WaffleInterface::SwapInterval(int interval) { 180 return false; 181 } 182 183 bool WaffleInterface::MakeCurrent(const GLContext& context) { 184 return waffle_make_current(display_, surface_, context); 185 } 186 187 const GLContext WaffleInterface::CreateContext() { 188 return waffle_context_create(config_, NULL); 189 } 190 191 void WaffleInterface::CheckError() { 192 } 193 194 void WaffleInterface::DeleteContext(const GLContext& context) { 195 waffle_context_destroy(context); 196 WAFFLE_CHECK_ERROR; 197 } 198