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
Create()54 GLInterface* GLInterface::Create() {
55 return new WaffleInterface;
56 }
57
WaffleOK()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
GetSurfaceSize(GLint * width,GLint * height)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
InitOnce()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
Init()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
Cleanup()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
SwapBuffers()169 void WaffleInterface::SwapBuffers() {
170 waffle_window_swap_buffers(surface_);
171 WAFFLE_CHECK_ERROR;
172 }
173
SwapInterval(int interval)174 bool WaffleInterface::SwapInterval(int interval) {
175 return false;
176 }
177
MakeCurrent(const GLContext & context)178 bool WaffleInterface::MakeCurrent(const GLContext& context) {
179 return waffle_make_current(display_, surface_, context);
180 }
181
CreateContext()182 const GLContext WaffleInterface::CreateContext() {
183 return waffle_context_create(config_, NULL);
184 }
185
CheckError()186 void WaffleInterface::CheckError() {}
187
DeleteContext(const GLContext & context)188 void WaffleInterface::DeleteContext(const GLContext& context) {
189 waffle_context_destroy(context);
190 WAFFLE_CHECK_ERROR;
191 }
192