• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2015 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 #include "SkMutex.h"
10 #include "SkOnce.h"
11 #include "gl/GrGLInterface.h"
12 #include "gl/GrGLAssembleInterface.h"
13 #include "gl/command_buffer/GLTestContext_command_buffer.h"
14 #include "../ports/SkOSLibrary.h"
15 
16 typedef void *EGLDisplay;
17 typedef unsigned int EGLBoolean;
18 typedef void *EGLConfig;
19 typedef void *EGLSurface;
20 typedef void *EGLContext;
21 typedef int32_t EGLint;
22 typedef void* EGLNativeDisplayType;
23 typedef void* EGLNativeWindowType;
24 typedef void (*__eglMustCastToProperFunctionPointerType)(void);
25 #define EGL_FALSE 0
26 #define EGL_OPENGL_ES2_BIT 0x0004
27 #define EGL_CONTEXT_CLIENT_VERSION 0x3098
28 #define EGL_NO_SURFACE ((EGLSurface)0)
29 #define EGL_NO_DISPLAY ((EGLDisplay)0)
30 #define EGL_NO_CONTEXT ((EGLContext)0)
31 #define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0)
32 #define EGL_SURFACE_TYPE 0x3033
33 #define EGL_PBUFFER_BIT 0x0001
34 #define EGL_RENDERABLE_TYPE 0x3040
35 #define EGL_RED_SIZE 0x3024
36 #define EGL_GREEN_SIZE 0x3023
37 #define EGL_BLUE_SIZE 0x3022
38 #define EGL_ALPHA_SIZE 0x3021
39 #define EGL_DEPTH_SIZE 0x3025
40 #define EGL_STENCIL_SIZE 0x3025
41 #define EGL_SAMPLES 0x3031
42 #define EGL_SAMPLE_BUFFERS 0x3032
43 #define EGL_NONE 0x3038
44 #define EGL_WIDTH 0x3057
45 #define EGL_HEIGHT 0x3056
46 
47 typedef EGLDisplay (*GetDisplayProc)(EGLNativeDisplayType display_id);
48 typedef EGLBoolean (*InitializeProc)(EGLDisplay dpy, EGLint *major, EGLint *minor);
49 typedef EGLBoolean (*TerminateProc)(EGLDisplay dpy);
50 typedef EGLBoolean (*ChooseConfigProc)(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, EGLint config_size, EGLint* num_config);
51 typedef EGLBoolean (*GetConfigAttrib)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value);
52 typedef EGLSurface (*CreateWindowSurfaceProc)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint* attrib_list);
53 typedef EGLSurface (*CreatePbufferSurfaceProc)(EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list);
54 typedef EGLBoolean (*DestroySurfaceProc)(EGLDisplay dpy, EGLSurface surface);
55 typedef EGLContext (*CreateContextProc)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint* attrib_list);
56 typedef EGLBoolean (*DestroyContextProc)(EGLDisplay dpy, EGLContext ctx);
57 typedef EGLBoolean (*MakeCurrentProc)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
58 typedef EGLBoolean (*SwapBuffersProc)(EGLDisplay dpy, EGLSurface surface);
59 typedef __eglMustCastToProperFunctionPointerType (*GetProcAddressProc)(const char* procname);
60 
61 static GetDisplayProc gfGetDisplay = nullptr;
62 static InitializeProc gfInitialize = nullptr;
63 static TerminateProc gfTerminate = nullptr;
64 static ChooseConfigProc gfChooseConfig = nullptr;
65 static GetConfigAttrib gfGetConfigAttrib = nullptr;
66 static CreateWindowSurfaceProc gfCreateWindowSurface = nullptr;
67 static CreatePbufferSurfaceProc gfCreatePbufferSurface = nullptr;
68 static DestroySurfaceProc gfDestroySurface = nullptr;
69 static CreateContextProc gfCreateContext = nullptr;
70 static DestroyContextProc gfDestroyContext = nullptr;
71 static MakeCurrentProc gfMakeCurrent = nullptr;
72 static SwapBuffersProc gfSwapBuffers = nullptr;
73 static GetProcAddressProc gfGetProcAddress = nullptr;
74 
75 static void* gLibrary = nullptr;
76 static bool gfFunctionsLoadedSuccessfully = false;
77 
78 namespace {
load_command_buffer_functions()79 static void load_command_buffer_functions() {
80     if (!gLibrary) {
81         static constexpr const char* libName =
82 #if defined _WIN32
83         "command_buffer_gles2.dll";
84 #elif defined SK_BUILD_FOR_MAC
85         "libcommand_buffer_gles2.dylib";
86 #else
87         "libcommand_buffer_gles2.so";
88 #endif // defined _WIN32
89         gLibrary = DynamicLoadLibrary(libName);
90         if (gLibrary) {
91             gfGetDisplay = (GetDisplayProc)GetProcedureAddress(gLibrary, "eglGetDisplay");
92             gfInitialize = (InitializeProc)GetProcedureAddress(gLibrary, "eglInitialize");
93             gfTerminate = (TerminateProc)GetProcedureAddress(gLibrary, "eglTerminate");
94             gfChooseConfig = (ChooseConfigProc)GetProcedureAddress(gLibrary, "eglChooseConfig");
95             gfGetConfigAttrib = (GetConfigAttrib)GetProcedureAddress(gLibrary, "eglGetConfigAttrib");
96             gfCreateWindowSurface = (CreateWindowSurfaceProc)GetProcedureAddress(gLibrary, "eglCreateWindowSurface");
97             gfCreatePbufferSurface = (CreatePbufferSurfaceProc)GetProcedureAddress(gLibrary, "eglCreatePbufferSurface");
98             gfDestroySurface = (DestroySurfaceProc)GetProcedureAddress(gLibrary, "eglDestroySurface");
99             gfCreateContext = (CreateContextProc)GetProcedureAddress(gLibrary, "eglCreateContext");
100             gfDestroyContext = (DestroyContextProc)GetProcedureAddress(gLibrary, "eglDestroyContext");
101             gfMakeCurrent = (MakeCurrentProc)GetProcedureAddress(gLibrary, "eglMakeCurrent");
102             gfSwapBuffers = (SwapBuffersProc)GetProcedureAddress(gLibrary, "eglSwapBuffers");
103             gfGetProcAddress = (GetProcAddressProc)GetProcedureAddress(gLibrary, "eglGetProcAddress");
104 
105             gfFunctionsLoadedSuccessfully = gfGetDisplay && gfInitialize && gfTerminate &&
106                                             gfChooseConfig && gfCreateWindowSurface &&
107                                             gfCreatePbufferSurface && gfDestroySurface &&
108                                             gfCreateContext && gfDestroyContext && gfMakeCurrent &&
109                                             gfSwapBuffers && gfGetProcAddress;
110 
111         }
112     }
113 }
114 
command_buffer_get_gl_proc(void * ctx,const char name[])115 static GrGLFuncPtr command_buffer_get_gl_proc(void* ctx, const char name[]) {
116     if (!gfFunctionsLoadedSuccessfully) {
117         return nullptr;
118     }
119     return gfGetProcAddress(name);
120 }
121 
load_command_buffer_once()122 static void load_command_buffer_once() {
123     static SkOnce once;
124     once(load_command_buffer_functions);
125 }
126 
create_command_buffer_interface()127 static const GrGLInterface* create_command_buffer_interface() {
128     load_command_buffer_once();
129     if (!gfFunctionsLoadedSuccessfully) {
130         return nullptr;
131     }
132     return GrGLAssembleGLESInterface(gLibrary, command_buffer_get_gl_proc);
133 }
134 
135 }  // anonymous namespace
136 
137 namespace sk_gpu_test {
138 
CommandBufferGLTestContext(CommandBufferGLTestContext * shareContext)139 CommandBufferGLTestContext::CommandBufferGLTestContext(CommandBufferGLTestContext* shareContext)
140     : fContext(EGL_NO_CONTEXT), fDisplay(EGL_NO_DISPLAY), fSurface(EGL_NO_SURFACE) {
141 
142     static const EGLint configAttribs[] = {
143         EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
144         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
145         EGL_RED_SIZE, 8,
146         EGL_GREEN_SIZE, 8,
147         EGL_BLUE_SIZE, 8,
148         EGL_ALPHA_SIZE, 8,
149         EGL_NONE
150     };
151 
152     static const EGLint surfaceAttribs[] = {
153         EGL_WIDTH, 1,
154         EGL_HEIGHT, 1,
155         EGL_NONE
156     };
157 
158     load_command_buffer_once();
159     if (!gfFunctionsLoadedSuccessfully) {
160         return;
161     }
162 
163     fDisplay = gfGetDisplay(EGL_DEFAULT_DISPLAY);
164     if (EGL_NO_DISPLAY == fDisplay) {
165         SkDebugf("Command Buffer: Could not create EGL display.\n");
166         return;
167     }
168     if (!gfInitialize(fDisplay, nullptr, nullptr)) {
169         SkDebugf("Command Buffer: Could not initialize EGL display.\n");
170         this->destroyGLContext();
171         return;
172     }
173     EGLint numConfigs;
174     if (!gfChooseConfig(fDisplay, configAttribs, static_cast<EGLConfig *>(&fConfig), 1,
175                         &numConfigs) || numConfigs != 1) {
176         SkDebugf("Command Buffer: Could not choose EGL config.\n");
177         this->destroyGLContext();
178         return;
179     }
180 
181     fSurface = gfCreatePbufferSurface(fDisplay,
182                                         static_cast<EGLConfig>(fConfig),
183                                         surfaceAttribs);
184 
185     if (EGL_NO_SURFACE == fSurface) {
186         SkDebugf("Command Buffer: Could not create EGL surface.\n");
187         this->destroyGLContext();
188         return;
189     }
190 
191     static const EGLint contextAttribs[] = {
192         EGL_CONTEXT_CLIENT_VERSION, 2,
193         EGL_NONE
194     };
195     EGLContext eglShareContext = shareContext
196             ? reinterpret_cast<EGLContext>(shareContext->fContext) : nullptr;
197     fContext = gfCreateContext(fDisplay, static_cast<EGLConfig>(fConfig), eglShareContext,
198                                contextAttribs);
199     if (EGL_NO_CONTEXT == fContext) {
200         SkDebugf("Command Buffer: Could not create EGL context.\n");
201         this->destroyGLContext();
202         return;
203     }
204 
205     if (!gfMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
206         SkDebugf("Command Buffer: Could not make EGL context current.\n");
207         this->destroyGLContext();
208         return;
209     }
210 
211     sk_sp<const GrGLInterface> gl(create_command_buffer_interface());
212     if (nullptr == gl.get()) {
213         SkDebugf("Command Buffer: Could not create CommandBuffer GL interface.\n");
214         this->destroyGLContext();
215         return;
216     }
217     if (!gl->validate()) {
218         SkDebugf("Command Buffer: Could not validate CommandBuffer GL interface.\n");
219         this->destroyGLContext();
220         return;
221     }
222 
223     this->init(gl.release());
224 }
225 
~CommandBufferGLTestContext()226 CommandBufferGLTestContext::~CommandBufferGLTestContext() {
227     this->teardown();
228     this->destroyGLContext();
229 }
230 
destroyGLContext()231 void CommandBufferGLTestContext::destroyGLContext() {
232     if (!gfFunctionsLoadedSuccessfully) {
233         return;
234     }
235     if (EGL_NO_DISPLAY == fDisplay) {
236         return;
237     }
238     if (EGL_NO_CONTEXT != fContext) {
239         gfDestroyContext(fDisplay, fContext);
240         fContext = EGL_NO_CONTEXT;
241     }
242     // Call MakeCurrent after destroying the context, so that the EGL implementation knows that
243     // the context is not used anymore after it is released from being current.  This way
244     // command buffer does not need to abandon the context before destruction, and no
245     // client-side errors are printed.
246     gfMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
247 
248     if (EGL_NO_SURFACE != fSurface) {
249         gfDestroySurface(fDisplay, fSurface);
250         fSurface = EGL_NO_SURFACE;
251     }
252     fDisplay = EGL_NO_DISPLAY;
253 }
254 
onPlatformMakeCurrent() const255 void CommandBufferGLTestContext::onPlatformMakeCurrent() const {
256     if (!gfFunctionsLoadedSuccessfully) {
257         return;
258     }
259     if (!gfMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
260         SkDebugf("Command Buffer: Could not make EGL context current.\n");
261     }
262 }
263 
onPlatformSwapBuffers() const264 void CommandBufferGLTestContext::onPlatformSwapBuffers() const {
265     if (!gfFunctionsLoadedSuccessfully) {
266         return;
267     }
268     if (!gfSwapBuffers(fDisplay, fSurface)) {
269         SkDebugf("Command Buffer: Could not complete gfSwapBuffers.\n");
270     }
271 }
272 
onPlatformGetProcAddress(const char * name) const273 GrGLFuncPtr CommandBufferGLTestContext::onPlatformGetProcAddress(const char *name) const {
274     if (!gfFunctionsLoadedSuccessfully) {
275         return nullptr;
276     }
277     return gfGetProcAddress(name);
278 }
279 
presentCommandBuffer()280 void CommandBufferGLTestContext::presentCommandBuffer() {
281     if (this->gl()) {
282         this->gl()->fFunctions.fFlush();
283     }
284 
285     this->onPlatformSwapBuffers();
286 }
287 
makeCurrent()288 bool CommandBufferGLTestContext::makeCurrent() {
289     return gfMakeCurrent(fDisplay, fSurface, fSurface, fContext) != EGL_FALSE;
290 }
291 
getStencilBits()292 int CommandBufferGLTestContext::getStencilBits() {
293     EGLint result = 0;
294     gfGetConfigAttrib(fDisplay, static_cast<EGLConfig>(fConfig), EGL_STENCIL_SIZE, &result);
295     return result;
296 }
297 
getSampleCount()298 int CommandBufferGLTestContext::getSampleCount() {
299     EGLint result = 0;
300     gfGetConfigAttrib(fDisplay, static_cast<EGLConfig>(fConfig), EGL_SAMPLES, &result);
301     return result;
302 }
303 
304 }  // namespace sk_gpu_test
305