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 14GLint g_width = WINDOW_WIDTH; 15GLint g_height = WINDOW_HEIGHT; 16 17std::unique_ptr<GLInterface> g_main_gl_interface; 18 19#ifdef USE_OPENGL 20namespace gl { 21#define F(fun, type) type fun = NULL; 22LIST_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 51GLInterface* GLInterface::Create() { 52 return new WaffleInterface; 53} 54 55static 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 65void 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 101void 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 148bool 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 166void 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 174void WaffleInterface::SwapBuffers() { 175 waffle_window_swap_buffers(surface_); 176 WAFFLE_CHECK_ERROR; 177} 178 179bool WaffleInterface::SwapInterval(int interval) { 180 return false; 181} 182 183bool WaffleInterface::MakeCurrent(const GLContext& context) { 184 return waffle_make_current(display_, surface_, context); 185} 186 187const GLContext WaffleInterface::CreateContext() { 188 return waffle_context_create(config_, NULL); 189} 190 191void WaffleInterface::CheckError() { 192} 193 194void WaffleInterface::DeleteContext(const GLContext& context) { 195 waffle_context_destroy(context); 196 WAFFLE_CHECK_ERROR; 197} 198