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