1// Copyright 2013 The Flutter Authors. All rights reserved.
2
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5
6#include <epoxy/egl.h>
7#include <epoxy/gl.h>
8
9typedef struct {
10 EGLint config_id;
11 EGLint buffer_size;
12 EGLint color_buffer_type;
13 EGLint transparent_type;
14 EGLint level;
15 EGLint red_size;
16 EGLint green_size;
17 EGLint blue_size;
18 EGLint alpha_size;
19 EGLint depth_size;
20 EGLint stencil_size;
21 EGLint samples;
22 EGLint sample_buffers;
23 EGLint native_visual_id;
24 EGLint native_visual_type;
25 EGLint native_renderable;
26 EGLint config_caveat;
27 EGLint bind_to_texture_rgb;
28 EGLint bind_to_texture_rgba;
29 EGLint renderable_type;
30 EGLint conformant;
31 EGLint surface_type;
32 EGLint max_pbuffer_width;
33 EGLint max_pbuffer_height;
34 EGLint max_pbuffer_pixels;
35 EGLint min_swap_interval;
36 EGLint max_swap_interval;
37} MockConfig;
38
39typedef struct {
40} MockDisplay;
41
42typedef struct {
43} MockContext;
44
45typedef struct {
46} MockSurface;
47
48static bool display_initialized = false;
49static MockDisplay mock_display;
50static MockConfig mock_config;
51static MockContext mock_context;
52static MockSurface mock_surface;
53
54static EGLint mock_error = EGL_SUCCESS;
55
56static bool check_display(EGLDisplay dpy) {
57 if (dpy == nullptr) {
58 mock_error = EGL_BAD_DISPLAY;
59 return false;
60 }
61
62 return true;
63}
64
65static bool check_initialized(EGLDisplay dpy) {
66 if (!display_initialized) {
67 mock_error = EGL_NOT_INITIALIZED;
68 return false;
69 }
70
71 return true;
72}
73
74static bool check_config(EGLConfig config) {
75 if (config == nullptr) {
76 mock_error = EGL_BAD_CONFIG;
77 return false;
78 }
79
80 return true;
81}
82
83static EGLBoolean bool_success() {
84 mock_error = EGL_SUCCESS;
85 return EGL_TRUE;
86}
87
88static EGLBoolean bool_failure(EGLint error) {
89 mock_error = error;
90 return EGL_FALSE;
91}
92
93EGLBoolean _eglBindAPI(EGLenum api) {
94 return bool_success();
95}
96
97EGLBoolean _eglChooseConfig(EGLDisplay dpy,
98 const EGLint* attrib_list,
99 EGLConfig* configs,
100 EGLint config_size,
101 EGLint* num_config) {
102 if (!check_display(dpy) || !check_initialized(dpy)) {
103 return EGL_FALSE;
104 }
105
106 if (configs == nullptr) {
107 if (num_config != nullptr) {
108 *num_config = 1;
109 }
110 return bool_success();
111 }
112
113 EGLint n_returned = 0;
114 if (config_size >= 1) {
115 configs[0] = &mock_config;
116 n_returned++;
117 }
118
119 if (num_config != nullptr) {
120 *num_config = n_returned;
121 }
122
123 return bool_success();
124}
125
126EGLContext _eglCreateContext(EGLDisplay dpy,
127 EGLConfig config,
128 EGLContext share_context,
129 const EGLint* attrib_list) {
130 if (!check_display(dpy) || !check_initialized(dpy) || !check_config(config)) {
131 return EGL_NO_CONTEXT;
132 }
133
134 mock_error = EGL_SUCCESS;
135 return &mock_context;
136}
137
138EGLSurface _eglCreatePbufferSurface(EGLDisplay dpy,
139 EGLConfig config,
140 const EGLint* attrib_list) {
141 if (!check_display(dpy) || !check_initialized(dpy) || !check_config(config)) {
142 return EGL_NO_SURFACE;
143 }
144
145 mock_error = EGL_SUCCESS;
146 return &mock_surface;
147}
148
149EGLSurface _eglCreateWindowSurface(EGLDisplay dpy,
150 EGLConfig config,
151 EGLNativeWindowType win,
152 const EGLint* attrib_list) {
153 if (!check_display(dpy) || !check_initialized(dpy) || !check_config(config)) {
154 return EGL_NO_SURFACE;
155 }
156
157 mock_error = EGL_SUCCESS;
158 return &mock_surface;
159}
160
161EGLBoolean _eglGetConfigAttrib(EGLDisplay dpy,
162 EGLConfig config,
163 EGLint attribute,
164 EGLint* value) {
165 if (!check_display(dpy) || !check_initialized(dpy) || !check_config(config)) {
166 return EGL_FALSE;
167 }
168
169 MockConfig* c = static_cast<MockConfig*>(config);
170 switch (attribute) {
171 case EGL_CONFIG_ID:
172 *value = c->config_id;
173 return bool_success();
174 case EGL_BUFFER_SIZE:
175 *value = c->buffer_size;
176 return bool_success();
177 case EGL_COLOR_BUFFER_TYPE:
178 *value = c->color_buffer_type;
179 return bool_success();
180 case EGL_TRANSPARENT_TYPE:
181 *value = c->transparent_type;
182 return bool_success();
183 case EGL_LEVEL:
184 *value = c->level;
185 return bool_success();
186 case EGL_RED_SIZE:
187 *value = c->red_size;
188 return bool_success();
189 case EGL_GREEN_SIZE:
190 *value = c->green_size;
191 return bool_success();
192 case EGL_BLUE_SIZE:
193 *value = c->blue_size;
194 return bool_success();
195 case EGL_ALPHA_SIZE:
196 *value = c->alpha_size;
197 return bool_success();
198 case EGL_DEPTH_SIZE:
199 *value = c->depth_size;
200 return bool_success();
201 case EGL_STENCIL_SIZE:
202 *value = c->stencil_size;
203 return bool_success();
204 case EGL_SAMPLES:
205 *value = c->samples;
206 return bool_success();
207 case EGL_SAMPLE_BUFFERS:
208 *value = c->sample_buffers;
209 return bool_success();
210 case EGL_NATIVE_VISUAL_ID:
211 *value = c->native_visual_id;
212 return bool_success();
213 case EGL_NATIVE_VISUAL_TYPE:
214 *value = c->native_visual_type;
215 return bool_success();
216 case EGL_NATIVE_RENDERABLE:
217 *value = c->native_renderable;
218 return bool_success();
219 case EGL_CONFIG_CAVEAT:
220 *value = c->config_caveat;
221 return bool_success();
222 case EGL_BIND_TO_TEXTURE_RGB:
223 *value = c->bind_to_texture_rgb;
224 return bool_success();
225 case EGL_BIND_TO_TEXTURE_RGBA:
226 *value = c->bind_to_texture_rgba;
227 return bool_success();
228 case EGL_RENDERABLE_TYPE:
229 *value = c->renderable_type;
230 return bool_success();
231 case EGL_CONFORMANT:
232 *value = c->conformant;
233 return bool_success();
234 case EGL_SURFACE_TYPE:
235 *value = c->surface_type;
236 return bool_success();
237 case EGL_MAX_PBUFFER_WIDTH:
238 *value = c->max_pbuffer_width;
239 return bool_success();
240 case EGL_MAX_PBUFFER_HEIGHT:
241 *value = c->max_pbuffer_height;
242 return bool_success();
243 case EGL_MAX_PBUFFER_PIXELS:
244 *value = c->max_pbuffer_pixels;
245 return bool_success();
246 case EGL_MIN_SWAP_INTERVAL:
247 *value = c->min_swap_interval;
248 return bool_success();
249 case EGL_MAX_SWAP_INTERVAL:
250 *value = c->max_swap_interval;
251 return bool_success();
252 default:
253 return bool_failure(EGL_BAD_ATTRIBUTE);
254 }
255}
256
257EGLDisplay _eglGetDisplay(EGLNativeDisplayType display_id) {
258 return &mock_display;
259}
260
261EGLint _eglGetError() {
262 EGLint error = mock_error;
263 mock_error = EGL_SUCCESS;
264 return error;
265}
266
267void (*_eglGetProcAddress(const char* procname))(void) {
268 mock_error = EGL_SUCCESS;
269 return nullptr;
270}
271
272EGLBoolean _eglInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) {
273 if (!check_display(dpy)) {
274 return EGL_FALSE;
275 }
276
277 if (!display_initialized) {
278 mock_config.config_id = 1;
279 mock_config.buffer_size = 32;
280 mock_config.color_buffer_type = EGL_RGB_BUFFER;
281 mock_config.transparent_type = EGL_NONE;
282 mock_config.level = 1;
283 mock_config.red_size = 8;
284 mock_config.green_size = 8;
285 mock_config.blue_size = 8;
286 mock_config.alpha_size = 0;
287 mock_config.depth_size = 0;
288 mock_config.stencil_size = 0;
289 mock_config.samples = 0;
290 mock_config.sample_buffers = 0;
291 mock_config.native_visual_id = 1;
292 mock_config.native_visual_type = 0;
293 mock_config.native_renderable = EGL_TRUE;
294 mock_config.config_caveat = EGL_NONE;
295 mock_config.bind_to_texture_rgb = EGL_TRUE;
296 mock_config.bind_to_texture_rgba = EGL_FALSE;
297 mock_config.renderable_type = EGL_OPENGL_ES2_BIT;
298 mock_config.conformant = EGL_OPENGL_ES2_BIT;
299 mock_config.surface_type = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
300 mock_config.max_pbuffer_width = 1024;
301 mock_config.max_pbuffer_height = 1024;
302 mock_config.max_pbuffer_pixels = 1024 * 1024;
303 mock_config.min_swap_interval = 0;
304 mock_config.max_swap_interval = 1000;
305 display_initialized = true;
306 }
307
308 if (major != nullptr) {
309 *major = 1;
310 }
311 if (minor != nullptr) {
312 *minor = 5;
313 }
314
315 return bool_success();
316}
317
318EGLBoolean _eglMakeCurrent(EGLDisplay dpy,
319 EGLSurface draw,
320 EGLSurface read,
321 EGLContext ctx) {
322 if (!check_display(dpy) || !check_initialized(dpy)) {
323 return EGL_FALSE;
324 }
325
326 return bool_success();
327}
328
329EGLBoolean _eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) {
330 if (!check_display(dpy) || !check_initialized(dpy)) {
331 return EGL_FALSE;
332 }
333
334 return bool_success();
335}
336
337static void _glBindFramebuffer(GLenum target, GLuint framebuffer) {}
338
339static void _glBindTexture(GLenum target, GLuint texture) {}
340
341void _glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) {}
342
343void _glDeleteTextures(GLsizei n, const GLuint* textures) {}
344
345static void _glFramebufferTexture2D(GLenum target,
346 GLenum attachment,
347 GLenum textarget,
348 GLuint texture,
349 GLint level) {}
350
351static void _glGenTextures(GLsizei n, GLuint* textures) {
352 for (GLsizei i = 0; i < n; i++) {
353 textures[i] = 0;
354 }
355}
356
357static void _glGenFramebuffers(GLsizei n, GLuint* framebuffers) {
358 for (GLsizei i = 0; i < n; i++) {
359 framebuffers[i] = 0;
360 }
361}
362
363static void _glTexParameterf(GLenum target, GLenum pname, GLfloat param) {}
364
365static void _glTexParameteri(GLenum target, GLenum pname, GLint param) {}
366
367static void _glTexImage2D(GLenum target,
368 GLint level,
369 GLint internalformat,
370 GLsizei width,
371 GLsizei height,
372 GLint border,
373 GLenum format,
374 GLenum type,
375 const void* pixels) {}
376
377static GLenum _glGetError() {
378 return GL_NO_ERROR;
379}
380
381bool epoxy_has_gl_extension(const char* extension) {
382 return false;
383}
384
385bool epoxy_is_desktop_gl(void) {
386 return false;
387}
388
389int epoxy_gl_version(void) {
390 return 0;
391}
392
393#ifdef __GNUC__
394#define CONSTRUCT(_func) static void _func(void) __attribute__((constructor));
395#define DESTRUCT(_func) static void _func(void) __attribute__((destructor));
396#elif defined(_MSC_VER) && (_MSC_VER >= 1500)
397#define CONSTRUCT(_func) \
398 static void _func(void); \
399 static int _func##_wrapper(void) { \
400 _func(); \
401 return 0; \
402 } \
403 __pragma(section(".CRT$XCU", read)) __declspec(allocate( \
404 ".CRT$XCU")) static int (*_array##_func)(void) = _func##_wrapper;
405
406#else
407#error "You will need constructor support for your compiler"
408#endif
409
410CONSTRUCT(library_init)
411
412EGLBoolean (*epoxy_eglBindAPI)(EGLenum api);
413EGLBoolean (*epoxy_eglChooseConfig)(EGLDisplay dpy,
414 const EGLint* attrib_list,
415 EGLConfig* configs,
416 EGLint config_size,
417 EGLint* num_config);
418EGLContext (*epoxy_eglCreateContext)(EGLDisplay dpy,
419 EGLConfig config,
420 EGLContext share_context,
421 const EGLint* attrib_list);
422EGLSurface (*epoxy_eglCreatePbufferSurface)(EGLDisplay dpy,
423 EGLConfig config,
424 const EGLint* attrib_list);
425EGLSurface (*epoxy_eglCreateWindowSurface)(EGLDisplay dpy,
426 EGLConfig config,
427 EGLNativeWindowType win,
428 const EGLint* attrib_list);
429EGLBoolean (*epoxy_eglGetConfigAttrib)(EGLDisplay dpy,
430 EGLConfig config,
431 EGLint attribute,
432 EGLint* value);
433EGLDisplay (*epoxy_eglGetDisplay)(EGLNativeDisplayType display_id);
434EGLint (*epoxy_eglGetError)();
435void (*(*epoxy_eglGetProcAddress)(const char* procname))(void);
436EGLBoolean (*epoxy_eglInitialize)(EGLDisplay dpy, EGLint* major, EGLint* minor);
437EGLBoolean (*epoxy_eglMakeCurrent)(EGLDisplay dpy,
438 EGLSurface draw,
439 EGLSurface read,
440 EGLContext ctx);
441EGLBoolean (*epoxy_eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
442
443void (*epoxy_glBindFramebuffer)(GLenum target, GLuint framebuffer);
444void (*epoxy_glBindTexture)(GLenum target, GLuint texture);
445void (*epoxy_glDeleteFramebuffers)(GLsizei n, const GLuint* framebuffers);
446void (*epoxy_glDeleteTextures)(GLsizei n, const GLuint* textures);
447void (*epoxy_glFramebufferTexture2D)(GLenum target,
448 GLenum attachment,
449 GLenum textarget,
450 GLuint texture,
451 GLint level);
452void (*epoxy_glGenFramebuffers)(GLsizei n, GLuint* framebuffers);
453void (*epoxy_glGenTextures)(GLsizei n, GLuint* textures);
454void (*epoxy_glTexParameterf)(GLenum target, GLenum pname, GLfloat param);
455void (*epoxy_glTexParameteri)(GLenum target, GLenum pname, GLint param);
456void (*epoxy_glTexImage2D)(GLenum target,
457 GLint level,
458 GLint internalformat,
459 GLsizei width,
460 GLsizei height,
461 GLint border,
462 GLenum format,
463 GLenum type,
464 const void* pixels);
465GLenum (*epoxy_glGetError)();
466
467static void library_init() {
468 epoxy_eglBindAPI = _eglBindAPI;
469 epoxy_eglChooseConfig = _eglChooseConfig;
470 epoxy_eglCreateContext = _eglCreateContext;
471 epoxy_eglCreatePbufferSurface = _eglCreatePbufferSurface;
472 epoxy_eglCreateWindowSurface = _eglCreateWindowSurface;
473 epoxy_eglGetConfigAttrib = _eglGetConfigAttrib;
474 epoxy_eglGetDisplay = _eglGetDisplay;
475 epoxy_eglGetError = _eglGetError;
476 epoxy_eglGetProcAddress = _eglGetProcAddress;
477 epoxy_eglInitialize = _eglInitialize;
478 epoxy_eglMakeCurrent = _eglMakeCurrent;
479 epoxy_eglSwapBuffers = _eglSwapBuffers;
480
481 epoxy_glBindFramebuffer = _glBindFramebuffer;
482 epoxy_glBindTexture = _glBindTexture;
483 epoxy_glDeleteFramebuffers = _glDeleteFramebuffers;
484 epoxy_glDeleteTextures = _glDeleteTextures;
485 epoxy_glFramebufferTexture2D = _glFramebufferTexture2D;
486 epoxy_glGenFramebuffers = _glGenFramebuffers;
487 epoxy_glGenTextures = _glGenTextures;
488 epoxy_glTexParameterf = _glTexParameterf;
489 epoxy_glTexParameteri = _glTexParameteri;
490 epoxy_glTexImage2D = _glTexImage2D;
491 epoxy_glGetError = _glGetError;
492}
493

source code of flutter_engine/flutter/shell/platform/linux/testing/mock_epoxy.cc