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 <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