mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
475 lines
14 KiB
C++
475 lines
14 KiB
C++
// 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 _eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) {
|
|
if (!check_display(dpy) || !check_initialized(dpy)) {
|
|
return EGL_FALSE;
|
|
}
|
|
|
|
return bool_success();
|
|
}
|
|
|
|
static void _glBindFramebuffer(GLenum target, GLuint framebuffer) {}
|
|
|
|
static void _glBindTexture(GLenum target, GLuint 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 _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) {}
|
|
|
|
#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);
|
|
|
|
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_eglSwapBuffers = _eglSwapBuffers;
|
|
|
|
epoxy_glBindFramebuffer = _glBindFramebuffer;
|
|
epoxy_glBindTexture = _glBindTexture;
|
|
epoxy_glDeleteFramebuffers = _glDeleteFramebuffers;
|
|
epoxy_glDeleteTextures = _glDeleteTextures;
|
|
epoxy_glFramebufferTexture2D = _glFramebufferTexture2D;
|
|
epoxy_glGenFramebuffers = _glGenFramebuffers;
|
|
epoxy_glGenTextures = _glGenTextures;
|
|
epoxy_glTexParameterf = _glTexParameterf;
|
|
epoxy_glTexParameteri = _glTexParameteri;
|
|
epoxy_glTexImage2D = _glTexImage2D;
|
|
}
|