| // Copyright 2013 The Flutter Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include <epoxy/egl.h> | |
| #include <epoxy/gl.h> | |
| typedef struct { | |
| EGLint config_id; | |
| EGLint buffer_size; | |
| EGLint color_buffer_type; | |
| EGLint transparent_type; | |
| EGLint level; | |
| EGLint red_size; | |
| EGLint green_size; | |
| EGLint blue_size; | |
| EGLint alpha_size; | |
| EGLint depth_size; | |
| EGLint stencil_size; | |
| EGLint samples; | |
| EGLint sample_buffers; | |
| EGLint native_visual_id; | |
| EGLint native_visual_type; | |
| EGLint native_renderable; | |
| EGLint config_caveat; | |
| EGLint bind_to_texture_rgb; | |
| EGLint bind_to_texture_rgba; | |
| EGLint renderable_type; | |
| EGLint conformant; | |
| EGLint surface_type; | |
| EGLint max_pbuffer_width; | |
| EGLint max_pbuffer_height; | |
| EGLint max_pbuffer_pixels; | |
| EGLint min_swap_interval; | |
| EGLint max_swap_interval; | |
| } MockConfig; | |
| typedef struct { | |
| } MockDisplay; | |
| typedef struct { | |
| } MockContext; | |
| typedef struct { | |
| } MockSurface; | |
| static bool display_initialized = false; | |
| static MockDisplay mock_display; | |
| static MockConfig mock_config; | |
| static MockContext mock_context; | |
| static MockSurface mock_surface; | |
| static EGLint mock_error = EGL_SUCCESS; | |
| static bool check_display(EGLDisplay dpy) { | |
| if (dpy == nullptr) { | |
| mock_error = EGL_BAD_DISPLAY; | |
| return false; | |
| } | |
| return true; | |
| } | |
| static bool check_initialized(EGLDisplay dpy) { | |
| if (!display_initialized) { | |
| mock_error = EGL_NOT_INITIALIZED; | |
| return false; | |
| } | |
| return true; | |
| } | |
| static bool check_config(EGLConfig config) { | |
| if (config == nullptr) { | |
| mock_error = EGL_BAD_CONFIG; | |
| return false; | |
| } | |
| return true; | |
| } | |
| static EGLBoolean bool_success() { | |
| mock_error = EGL_SUCCESS; | |
| return EGL_TRUE; | |
| } | |
| static EGLBoolean bool_failure(EGLint error) { | |
| mock_error = error; | |
| return EGL_FALSE; | |
| } | |
| EGLBoolean _eglBindAPI(EGLenum api) { | |
| return bool_success(); | |
| } | |
| EGLBoolean _eglChooseConfig(EGLDisplay dpy, | |
| const EGLint* attrib_list, | |
| EGLConfig* configs, | |
| EGLint config_size, | |
| EGLint* num_config) { | |
| if (!check_display(dpy) || !check_initialized(dpy)) { | |
| return EGL_FALSE; | |
| } | |
| if (configs == nullptr) { | |
| if (num_config != nullptr) { | |
| *num_config = 1; | |
| } | |
| return bool_success(); | |
| } | |
| EGLint n_returned = 0; | |
| if (config_size >= 1) { | |
| configs[0] = &mock_config; | |
| n_returned++; | |
| } | |
| if (num_config != nullptr) { | |
| *num_config = n_returned; | |
| } | |
| return bool_success(); | |
| } | |
| EGLContext _eglCreateContext(EGLDisplay dpy, | |
| EGLConfig config, | |
| EGLContext share_context, | |
| const EGLint* attrib_list) { | |
| if (!check_display(dpy) || !check_initialized(dpy) || !check_config(config)) { | |
| return EGL_NO_CONTEXT; | |
| } | |
| mock_error = EGL_SUCCESS; | |
| return &mock_context; | |
| } | |
| EGLSurface _eglCreatePbufferSurface(EGLDisplay dpy, | |
| EGLConfig config, | |
| const EGLint* attrib_list) { | |
| if (!check_display(dpy) || !check_initialized(dpy) || !check_config(config)) { | |
| return EGL_NO_SURFACE; | |
| } | |
| mock_error = EGL_SUCCESS; | |
| return &mock_surface; | |
| } | |
| EGLSurface _eglCreateWindowSurface(EGLDisplay dpy, | |
| EGLConfig config, | |
| EGLNativeWindowType win, | |
| const EGLint* attrib_list) { | |
| if (!check_display(dpy) || !check_initialized(dpy) || !check_config(config)) { | |
| return EGL_NO_SURFACE; | |
| } | |
| mock_error = EGL_SUCCESS; | |
| return &mock_surface; | |
| } | |
| EGLBoolean _eglGetConfigAttrib(EGLDisplay dpy, | |
| EGLConfig config, | |
| EGLint attribute, | |
| EGLint* value) { | |
| if (!check_display(dpy) || !check_initialized(dpy) || !check_config(config)) { | |
| return EGL_FALSE; | |
| } | |
| MockConfig* c = static_cast<MockConfig*>(config); | |
| switch (attribute) { | |
| case EGL_CONFIG_ID: | |
| *value = c->config_id; | |
| return bool_success(); | |
| case EGL_BUFFER_SIZE: | |
| *value = c->buffer_size; | |
| return bool_success(); | |
| case EGL_COLOR_BUFFER_TYPE: | |
| *value = c->color_buffer_type; | |
| return bool_success(); | |
| case EGL_TRANSPARENT_TYPE: | |
| *value = c->transparent_type; | |
| return bool_success(); | |
| case EGL_LEVEL: | |
| *value = c->level; | |
| return bool_success(); | |
| case EGL_RED_SIZE: | |
| *value = c->red_size; | |
| return bool_success(); | |
| case EGL_GREEN_SIZE: | |
| *value = c->green_size; | |
| return bool_success(); | |
| case EGL_BLUE_SIZE: | |
| *value = c->blue_size; | |
| return bool_success(); | |
| case EGL_ALPHA_SIZE: | |
| *value = c->alpha_size; | |
| return bool_success(); | |
| case EGL_DEPTH_SIZE: | |
| *value = c->depth_size; | |
| return bool_success(); | |
| case EGL_STENCIL_SIZE: | |
| *value = c->stencil_size; | |
| return bool_success(); | |
| case EGL_SAMPLES: | |
| *value = c->samples; | |
| return bool_success(); | |
| case EGL_SAMPLE_BUFFERS: | |
| *value = c->sample_buffers; | |
| return bool_success(); | |
| case EGL_NATIVE_VISUAL_ID: | |
| *value = c->native_visual_id; | |
| return bool_success(); | |
| case EGL_NATIVE_VISUAL_TYPE: | |
| *value = c->native_visual_type; | |
| return bool_success(); | |
| case EGL_NATIVE_RENDERABLE: | |
| *value = c->native_renderable; | |
| return bool_success(); | |
| case EGL_CONFIG_CAVEAT: | |
| *value = c->config_caveat; | |
| return bool_success(); | |
| case EGL_BIND_TO_TEXTURE_RGB: | |
| *value = c->bind_to_texture_rgb; | |
| return bool_success(); | |
| case EGL_BIND_TO_TEXTURE_RGBA: | |
| *value = c->bind_to_texture_rgba; | |
| return bool_success(); | |
| case EGL_RENDERABLE_TYPE: | |
| *value = c->renderable_type; | |
| return bool_success(); | |
| case EGL_CONFORMANT: | |
| *value = c->conformant; | |
| return bool_success(); | |
| case EGL_SURFACE_TYPE: | |
| *value = c->surface_type; | |
| return bool_success(); | |
| case EGL_MAX_PBUFFER_WIDTH: | |
| *value = c->max_pbuffer_width; | |
| return bool_success(); | |
| case EGL_MAX_PBUFFER_HEIGHT: | |
| *value = c->max_pbuffer_height; | |
| return bool_success(); | |
| case EGL_MAX_PBUFFER_PIXELS: | |
| *value = c->max_pbuffer_pixels; | |
| return bool_success(); | |
| case EGL_MIN_SWAP_INTERVAL: | |
| *value = c->min_swap_interval; | |
| return bool_success(); | |
| case EGL_MAX_SWAP_INTERVAL: | |
| *value = c->max_swap_interval; | |
| return bool_success(); | |
| default: | |
| return bool_failure(EGL_BAD_ATTRIBUTE); | |
| } | |
| } | |
| EGLDisplay _eglGetDisplay(EGLNativeDisplayType display_id) { | |
| return &mock_display; | |
| } | |
| EGLint _eglGetError() { | |
| EGLint error = mock_error; | |
| mock_error = EGL_SUCCESS; | |
| return error; | |
| } | |
| void (*_eglGetProcAddress(const char* procname))(void) { | |
| mock_error = EGL_SUCCESS; | |
| return nullptr; | |
| } | |
| EGLBoolean _eglInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) { | |
| if (!check_display(dpy)) { | |
| return EGL_FALSE; | |
| } | |
| if (!display_initialized) { | |
| mock_config.config_id = 1; | |
| mock_config.buffer_size = 32; | |
| mock_config.color_buffer_type = EGL_RGB_BUFFER; | |
| mock_config.transparent_type = EGL_NONE; | |
| mock_config.level = 1; | |
| mock_config.red_size = 8; | |
| mock_config.green_size = 8; | |
| mock_config.blue_size = 8; | |
| mock_config.alpha_size = 0; | |
| mock_config.depth_size = 0; | |
| mock_config.stencil_size = 0; | |
| mock_config.samples = 0; | |
| mock_config.sample_buffers = 0; | |
| mock_config.native_visual_id = 1; | |
| mock_config.native_visual_type = 0; | |
| mock_config.native_renderable = EGL_TRUE; | |
| mock_config.config_caveat = EGL_NONE; | |
| mock_config.bind_to_texture_rgb = EGL_TRUE; | |
| mock_config.bind_to_texture_rgba = EGL_FALSE; | |
| mock_config.renderable_type = EGL_OPENGL_ES2_BIT; | |
| mock_config.conformant = EGL_OPENGL_ES2_BIT; | |
| mock_config.surface_type = EGL_WINDOW_BIT | EGL_PBUFFER_BIT; | |
| mock_config.max_pbuffer_width = 1024; | |
| mock_config.max_pbuffer_height = 1024; | |
| mock_config.max_pbuffer_pixels = 1024 * 1024; | |
| mock_config.min_swap_interval = 0; | |
| mock_config.max_swap_interval = 1000; | |
| display_initialized = true; | |
| } | |
| if (major != nullptr) { | |
| *major = 1; | |
| } | |
| if (minor != nullptr) { | |
| *minor = 5; | |
| } | |
| return bool_success(); | |
| } | |
| EGLBoolean _eglMakeCurrent(EGLDisplay dpy, | |
| EGLSurface draw, | |
| EGLSurface read, | |
| EGLContext ctx) { | |
| if (!check_display(dpy) || !check_initialized(dpy)) { | |
| return EGL_FALSE; | |
| } | |
| return bool_success(); | |
| } | |
| EGLBoolean _eglQueryContext(EGLDisplay display, | |
| EGLContext context, | |
| EGLint attribute, | |
| EGLint* value) { | |
| if (attribute == EGL_CONTEXT_CLIENT_TYPE) { | |
| *value = EGL_OPENGL_API; | |
| return EGL_TRUE; | |
| } | |
| return EGL_FALSE; | |
| } | |
| EGLBoolean _eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) { | |
| if (!check_display(dpy) || !check_initialized(dpy)) { | |
| return EGL_FALSE; | |
| } | |
| return bool_success(); | |
| } | |
| static GLuint bound_texture_2d; | |
| static void _glBindFramebuffer(GLenum target, GLuint framebuffer) {} | |
| static void _glBindTexture(GLenum target, GLuint texture) { | |
| if (target == GL_TEXTURE_2D) { | |
| bound_texture_2d = texture; | |
| } | |
| } | |
| void _glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) {} | |
| void _glDeleteTextures(GLsizei n, const GLuint* textures) {} | |
| static void _glFramebufferTexture2D(GLenum target, | |
| GLenum attachment, | |
| GLenum textarget, | |
| GLuint texture, | |
| GLint level) {} | |
| static void _glGenTextures(GLsizei n, GLuint* textures) { | |
| for (GLsizei i = 0; i < n; i++) { | |
| textures[i] = 0; | |
| } | |
| } | |
| static void _glGenFramebuffers(GLsizei n, GLuint* framebuffers) { | |
| for (GLsizei i = 0; i < n; i++) { | |
| framebuffers[i] = 0; | |
| } | |
| } | |
| static void _glGetIntegerv(GLenum pname, GLint* data) { | |
| if (pname == GL_TEXTURE_BINDING_2D) { | |
| *data = bound_texture_2d; | |
| } | |
| } | |
| static void _glTexParameterf(GLenum target, GLenum pname, GLfloat param) {} | |
| static void _glTexParameteri(GLenum target, GLenum pname, GLint param) {} | |
| static void _glTexImage2D(GLenum target, | |
| GLint level, | |
| GLint internalformat, | |
| GLsizei width, | |
| GLsizei height, | |
| GLint border, | |
| GLenum format, | |
| GLenum type, | |
| const void* pixels) {} | |
| static GLenum _glGetError() { | |
| return GL_NO_ERROR; | |
| } | |
| bool epoxy_has_gl_extension(const char* extension) { | |
| return false; | |
| } | |
| bool epoxy_is_desktop_gl(void) { | |
| return false; | |
| } | |
| int epoxy_gl_version(void) { | |
| return 0; | |
| } | |
| #ifdef __GNUC__ | |
| #define CONSTRUCT(_func) static void _func(void) __attribute__((constructor)); | |
| #define DESTRUCT(_func) static void _func(void) __attribute__((destructor)); | |
| #elif defined(_MSC_VER) && (_MSC_VER >= 1500) | |
| #define CONSTRUCT(_func) \ | |
| static void _func(void); \ | |
| static int _func##_wrapper(void) { \ | |
| _func(); \ | |
| return 0; \ | |
| } \ | |
| __pragma(section(".CRT$XCU", read)) \ | |
| __declspec(allocate(".CRT$XCU")) static int (*_array##_func)(void) = \ | |
| _func##_wrapper; | |
| #else | |
| #error "You will need constructor support for your compiler" | |
| #endif | |
| CONSTRUCT(library_init) | |
| EGLBoolean (*epoxy_eglBindAPI)(EGLenum api); | |
| EGLBoolean (*epoxy_eglChooseConfig)(EGLDisplay dpy, | |
| const EGLint* attrib_list, | |
| EGLConfig* configs, | |
| EGLint config_size, | |
| EGLint* num_config); | |
| EGLContext (*epoxy_eglCreateContext)(EGLDisplay dpy, | |
| EGLConfig config, | |
| EGLContext share_context, | |
| const EGLint* attrib_list); | |
| EGLSurface (*epoxy_eglCreatePbufferSurface)(EGLDisplay dpy, | |
| EGLConfig config, | |
| const EGLint* attrib_list); | |
| EGLSurface (*epoxy_eglCreateWindowSurface)(EGLDisplay dpy, | |
| EGLConfig config, | |
| EGLNativeWindowType win, | |
| const EGLint* attrib_list); | |
| EGLBoolean (*epoxy_eglGetConfigAttrib)(EGLDisplay dpy, | |
| EGLConfig config, | |
| EGLint attribute, | |
| EGLint* value); | |
| EGLDisplay (*epoxy_eglGetDisplay)(EGLNativeDisplayType display_id); | |
| EGLint (*epoxy_eglGetError)(); | |
| void (*(*epoxy_eglGetProcAddress)(const char* procname))(void); | |
| EGLBoolean (*epoxy_eglInitialize)(EGLDisplay dpy, EGLint* major, EGLint* minor); | |
| EGLBoolean (*epoxy_eglMakeCurrent)(EGLDisplay dpy, | |
| EGLSurface draw, | |
| EGLSurface read, | |
| EGLContext ctx); | |
| EGLBoolean (*epoxy_eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface); | |
| void (*epoxy_glBindFramebuffer)(GLenum target, GLuint framebuffer); | |
| void (*epoxy_glBindTexture)(GLenum target, GLuint texture); | |
| void (*epoxy_glDeleteFramebuffers)(GLsizei n, const GLuint* framebuffers); | |
| void (*epoxy_glDeleteTextures)(GLsizei n, const GLuint* textures); | |
| void (*epoxy_glFramebufferTexture2D)(GLenum target, | |
| GLenum attachment, | |
| GLenum textarget, | |
| GLuint texture, | |
| GLint level); | |
| void (*epoxy_glGenFramebuffers)(GLsizei n, GLuint* framebuffers); | |
| void (*epoxy_glGenTextures)(GLsizei n, GLuint* textures); | |
| void (*epoxy_glTexParameterf)(GLenum target, GLenum pname, GLfloat param); | |
| void (*epoxy_glTexParameteri)(GLenum target, GLenum pname, GLint param); | |
| void (*epoxy_glTexImage2D)(GLenum target, | |
| GLint level, | |
| GLint internalformat, | |
| GLsizei width, | |
| GLsizei height, | |
| GLint border, | |
| GLenum format, | |
| GLenum type, | |
| const void* pixels); | |
| GLenum (*epoxy_glGetError)(); | |
| static void library_init() { | |
| epoxy_eglBindAPI = _eglBindAPI; | |
| epoxy_eglChooseConfig = _eglChooseConfig; | |
| epoxy_eglCreateContext = _eglCreateContext; | |
| epoxy_eglCreatePbufferSurface = _eglCreatePbufferSurface; | |
| epoxy_eglCreateWindowSurface = _eglCreateWindowSurface; | |
| epoxy_eglGetConfigAttrib = _eglGetConfigAttrib; | |
| epoxy_eglGetDisplay = _eglGetDisplay; | |
| epoxy_eglGetError = _eglGetError; | |
| epoxy_eglGetProcAddress = _eglGetProcAddress; | |
| epoxy_eglInitialize = _eglInitialize; | |
| epoxy_eglMakeCurrent = _eglMakeCurrent; | |
| epoxy_eglQueryContext = _eglQueryContext; | |
| epoxy_eglSwapBuffers = _eglSwapBuffers; | |
| epoxy_glBindFramebuffer = _glBindFramebuffer; | |
| epoxy_glBindTexture = _glBindTexture; | |
| epoxy_glDeleteFramebuffers = _glDeleteFramebuffers; | |
| epoxy_glDeleteTextures = _glDeleteTextures; | |
| epoxy_glFramebufferTexture2D = _glFramebufferTexture2D; | |
| epoxy_glGenFramebuffers = _glGenFramebuffers; | |
| epoxy_glGenTextures = _glGenTextures; | |
| epoxy_glGetIntegerv = _glGetIntegerv; | |
| epoxy_glTexParameterf = _glTexParameterf; | |
| epoxy_glTexParameteri = _glTexParameteri; | |
| epoxy_glTexImage2D = _glTexImage2D; | |
| epoxy_glGetError = _glGetError; | |
| } |