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