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