Home | History | Annotate | Download | only in src
      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