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