blob: b14debda57c1c06aaec25fbf60ac1bc0ce6b2726 [file] [log] [blame]
hendrikw885bf092015-08-27 10:38:39 -07001
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 */
hendrikw885bf092015-08-27 10:38:39 -07008#include "SkOnce.h"
9#include "gl/GrGLInterface.h"
10#include "gl/GrGLAssembleInterface.h"
11#include "gl/command_buffer/SkCommandBufferGLContext.h"
kkinnunendd180e72015-12-21 04:05:53 -080012#include "../ports/SkOSEnvironment.h"
hendrikwb1ac52f2015-10-01 18:29:34 -070013#include "../ports/SkOSLibrary.h"
hendrikw885bf092015-08-27 10:38:39 -070014
hendrikw855dc932015-10-27 10:04:34 -070015#if defined SK_BUILD_FOR_MAC
16
17// EGL doesn't exist on the mac, so expose what we need to get the command buffer's EGL running.
18typedef void *EGLDisplay;
19typedef unsigned int EGLBoolean;
20typedef void *EGLConfig;
21typedef void *EGLSurface;
22typedef void *EGLContext;
23typedef int32_t EGLint;
24typedef void* EGLNativeDisplayType;
25typedef void* EGLNativeWindowType;
26typedef 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#else
50
51#include <EGL/egl.h>
52
53#endif
54
hendrikw885bf092015-08-27 10:38:39 -070055typedef EGLDisplay (*GetDisplayProc)(EGLNativeDisplayType display_id);
56typedef EGLBoolean (*InitializeProc)(EGLDisplay dpy, EGLint *major, EGLint *minor);
57typedef EGLBoolean (*TerminateProc)(EGLDisplay dpy);
58typedef EGLBoolean (*ChooseConfigProc)(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, EGLint config_size, EGLint* num_config);
59typedef EGLBoolean (*GetConfigAttrib)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value);
60typedef EGLSurface (*CreateWindowSurfaceProc)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint* attrib_list);
61typedef EGLSurface (*CreatePbufferSurfaceProc)(EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list);
62typedef EGLBoolean (*DestroySurfaceProc)(EGLDisplay dpy, EGLSurface surface);
63typedef EGLContext (*CreateContextProc)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint* attrib_list);
64typedef EGLBoolean (*DestroyContextProc)(EGLDisplay dpy, EGLContext ctx);
65typedef EGLBoolean (*MakeCurrentProc)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
66typedef EGLBoolean (*SwapBuffersProc)(EGLDisplay dpy, EGLSurface surface);
67typedef __eglMustCastToProperFunctionPointerType (*GetProcAddressProc)(const char* procname);
68
69static GetDisplayProc gfGetDisplay = nullptr;
70static InitializeProc gfInitialize = nullptr;
71static TerminateProc gfTerminate = nullptr;
72static ChooseConfigProc gfChooseConfig = nullptr;
73static GetConfigAttrib gfGetConfigAttrib = nullptr;
74static CreateWindowSurfaceProc gfCreateWindowSurface = nullptr;
75static CreatePbufferSurfaceProc gfCreatePbufferSurface = nullptr;
76static DestroySurfaceProc gfDestroySurface = nullptr;
77static CreateContextProc gfCreateContext = nullptr;
78static DestroyContextProc gfDestroyContext = nullptr;
79static MakeCurrentProc gfMakeCurrent = nullptr;
80static SwapBuffersProc gfSwapBuffers = nullptr;
81static GetProcAddressProc gfGetProcAddress = nullptr;
82
hendrikwb1ac52f2015-10-01 18:29:34 -070083static void* gLibrary = nullptr;
hendrikw885bf092015-08-27 10:38:39 -070084static bool gfFunctionsLoadedSuccessfully = false;
85
86static void load_command_buffer_functions() {
hendrikwb1ac52f2015-10-01 18:29:34 -070087 if (!gLibrary) {
88#if defined _WIN32
89 gLibrary = DynamicLoadLibrary("command_buffer_gles2.dll");
hendrikw855dc932015-10-27 10:04:34 -070090#elif defined SK_BUILD_FOR_MAC
91 gLibrary = DynamicLoadLibrary("libcommand_buffer_gles2.dylib");
hendrikwb1ac52f2015-10-01 18:29:34 -070092#else
93 gLibrary = DynamicLoadLibrary("libcommand_buffer_gles2.so");
94#endif // defined _WIN32
95 if (gLibrary) {
96 gfGetDisplay = (GetDisplayProc)GetProcedureAddress(gLibrary, "eglGetDisplay");
97 gfInitialize = (InitializeProc)GetProcedureAddress(gLibrary, "eglInitialize");
98 gfTerminate = (TerminateProc)GetProcedureAddress(gLibrary, "eglTerminate");
99 gfChooseConfig = (ChooseConfigProc)GetProcedureAddress(gLibrary, "eglChooseConfig");
100 gfGetConfigAttrib = (GetConfigAttrib)GetProcedureAddress(gLibrary, "eglGetConfigAttrib");
101 gfCreateWindowSurface = (CreateWindowSurfaceProc)GetProcedureAddress(gLibrary, "eglCreateWindowSurface");
102 gfCreatePbufferSurface = (CreatePbufferSurfaceProc)GetProcedureAddress(gLibrary, "eglCreatePbufferSurface");
103 gfDestroySurface = (DestroySurfaceProc)GetProcedureAddress(gLibrary, "eglDestroySurface");
104 gfCreateContext = (CreateContextProc)GetProcedureAddress(gLibrary, "eglCreateContext");
105 gfDestroyContext = (DestroyContextProc)GetProcedureAddress(gLibrary, "eglDestroyContext");
106 gfMakeCurrent = (MakeCurrentProc)GetProcedureAddress(gLibrary, "eglMakeCurrent");
107 gfSwapBuffers = (SwapBuffersProc)GetProcedureAddress(gLibrary, "eglSwapBuffers");
108 gfGetProcAddress = (GetProcAddressProc)GetProcedureAddress(gLibrary, "eglGetProcAddress");
hendrikw885bf092015-08-27 10:38:39 -0700109
110 gfFunctionsLoadedSuccessfully = gfGetDisplay && gfInitialize && gfTerminate &&
111 gfChooseConfig && gfCreateWindowSurface &&
112 gfCreatePbufferSurface && gfDestroySurface &&
113 gfCreateContext && gfDestroyContext && gfMakeCurrent &&
114 gfSwapBuffers && gfGetProcAddress;
115
hendrikw855dc932015-10-27 10:04:34 -0700116 }
117 }
hendrikw885bf092015-08-27 10:38:39 -0700118}
119
120static GrGLFuncPtr command_buffer_get_gl_proc(void* ctx, const char name[]) {
hendrikw885bf092015-08-27 10:38:39 -0700121 if (!gfFunctionsLoadedSuccessfully) {
122 return nullptr;
123 }
124 return gfGetProcAddress(name);
125}
126
127SK_DECLARE_STATIC_ONCE(loadCommandBufferOnce);
128void LoadCommandBufferOnce() {
129 SkOnce(&loadCommandBufferOnce, load_command_buffer_functions);
130}
131
132const GrGLInterface* GrGLCreateCommandBufferInterface() {
133 LoadCommandBufferOnce();
134 if (!gfFunctionsLoadedSuccessfully) {
135 return nullptr;
136 }
hendrikwb1ac52f2015-10-01 18:29:34 -0700137 return GrGLAssembleGLESInterface(gLibrary, command_buffer_get_gl_proc);
hendrikw885bf092015-08-27 10:38:39 -0700138}
139
kkinnunenf655e932016-03-03 07:39:48 -0800140SkCommandBufferGLContext::SkCommandBufferGLContext()
hendrikw885bf092015-08-27 10:38:39 -0700141 : fContext(EGL_NO_CONTEXT)
142 , fDisplay(EGL_NO_DISPLAY)
143 , fSurface(EGL_NO_SURFACE) {
144
145 static const EGLint configAttribs[] = {
146 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
kkinnunenf655e932016-03-03 07:39:48 -0800147 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
hendrikw885bf092015-08-27 10:38:39 -0700148 EGL_RED_SIZE, 8,
149 EGL_GREEN_SIZE, 8,
150 EGL_BLUE_SIZE, 8,
151 EGL_ALPHA_SIZE, 8,
152 EGL_NONE
153 };
154
155 static const EGLint surfaceAttribs[] = {
156 EGL_WIDTH, 1,
157 EGL_HEIGHT, 1,
158 EGL_NONE
159 };
160
kkinnunenf655e932016-03-03 07:39:48 -0800161 initializeGLContext(nullptr, configAttribs, surfaceAttribs);
hendrikw885bf092015-08-27 10:38:39 -0700162}
163
164SkCommandBufferGLContext::SkCommandBufferGLContext(void* nativeWindow, int msaaSampleCount) {
165 static const EGLint surfaceAttribs[] = { EGL_NONE };
166
167 EGLint configAttribs[] = {
168 EGL_RED_SIZE, 8,
169 EGL_GREEN_SIZE, 8,
170 EGL_BLUE_SIZE, 8,
171 EGL_ALPHA_SIZE, 8,
172 EGL_DEPTH_SIZE, 8,
173 EGL_STENCIL_SIZE, 8,
174 EGL_SAMPLE_BUFFERS, 1,
175 EGL_SAMPLES, msaaSampleCount,
176 EGL_NONE
177 };
178 if (msaaSampleCount == 0) {
179 configAttribs[12] = EGL_NONE;
180 }
181
kkinnunenf655e932016-03-03 07:39:48 -0800182 initializeGLContext(nativeWindow, configAttribs, surfaceAttribs);
hendrikw885bf092015-08-27 10:38:39 -0700183}
184
kkinnunenf655e932016-03-03 07:39:48 -0800185void SkCommandBufferGLContext::initializeGLContext(void* nativeWindow, const int* configAttribs,
hendrikw885bf092015-08-27 10:38:39 -0700186 const int* surfaceAttribs) {
187 LoadCommandBufferOnce();
188 if (!gfFunctionsLoadedSuccessfully) {
kkinnunenef6a1ca2015-12-08 23:52:40 -0800189 SkDebugf("Command Buffer: Could not load EGL functions.\n");
hendrikw885bf092015-08-27 10:38:39 -0700190 return;
191 }
192
kkinnunendd180e72015-12-21 04:05:53 -0800193 // Make sure CHROMIUM_path_rendering is enabled for NVPR support.
kkinnunenf655e932016-03-03 07:39:48 -0800194 sk_setenv("CHROME_COMMAND_BUFFER_GLES2_ARGS", "--enable-gl-path-rendering");
kkinnunenef6a1ca2015-12-08 23:52:40 -0800195 fDisplay = gfGetDisplay(EGL_DEFAULT_DISPLAY);
hendrikw885bf092015-08-27 10:38:39 -0700196 if (EGL_NO_DISPLAY == fDisplay) {
kkinnunenef6a1ca2015-12-08 23:52:40 -0800197 SkDebugf("Command Buffer: Could not create EGL display.\n");
hendrikw885bf092015-08-27 10:38:39 -0700198 return;
199 }
200
kkinnunenf655e932016-03-03 07:39:48 -0800201 EGLint majorVersion;
202 EGLint minorVersion;
203 if (!gfInitialize(fDisplay, &majorVersion, &minorVersion)) {
kkinnunenef6a1ca2015-12-08 23:52:40 -0800204 SkDebugf("Command Buffer: Could not initialize EGL display.\n");
205 this->destroyGLContext();
206 return;
207 }
hendrikw885bf092015-08-27 10:38:39 -0700208
hendrikw885bf092015-08-27 10:38:39 -0700209 EGLint numConfigs;
kkinnunenef6a1ca2015-12-08 23:52:40 -0800210 if (!gfChooseConfig(fDisplay, configAttribs, static_cast<EGLConfig*>(&fConfig), 1,
kkinnunenf655e932016-03-03 07:39:48 -0800211 &numConfigs) || numConfigs != 1) {
kkinnunenef6a1ca2015-12-08 23:52:40 -0800212 SkDebugf("Command Buffer: Could not choose EGL config.\n");
213 this->destroyGLContext();
214 return;
215 }
hendrikw885bf092015-08-27 10:38:39 -0700216
217 if (nativeWindow) {
kkinnunenef6a1ca2015-12-08 23:52:40 -0800218 fSurface = gfCreateWindowSurface(fDisplay,
219 static_cast<EGLConfig>(fConfig),
220 (EGLNativeWindowType)nativeWindow,
221 surfaceAttribs);
hendrikw885bf092015-08-27 10:38:39 -0700222 } else {
kkinnunenef6a1ca2015-12-08 23:52:40 -0800223 fSurface = gfCreatePbufferSurface(fDisplay,
224 static_cast<EGLConfig>(fConfig),
225 surfaceAttribs);
226 }
227 if (EGL_NO_SURFACE == fSurface) {
228 SkDebugf("Command Buffer: Could not create EGL surface.\n");
229 this->destroyGLContext();
230 return;
hendrikw885bf092015-08-27 10:38:39 -0700231 }
232
233 static const EGLint contextAttribs[] = {
kkinnunenf655e932016-03-03 07:39:48 -0800234 EGL_CONTEXT_CLIENT_VERSION, 2,
hendrikw885bf092015-08-27 10:38:39 -0700235 EGL_NONE
236 };
kkinnunenef6a1ca2015-12-08 23:52:40 -0800237 fContext = gfCreateContext(fDisplay, static_cast<EGLConfig>(fConfig), nullptr, contextAttribs);
238 if (EGL_NO_CONTEXT == fContext) {
239 SkDebugf("Command Buffer: Could not create EGL context.\n");
240 this->destroyGLContext();
241 return;
242 }
hendrikw885bf092015-08-27 10:38:39 -0700243
kkinnunenef6a1ca2015-12-08 23:52:40 -0800244 if (!gfMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
245 SkDebugf("Command Buffer: Could not make EGL context current.\n");
246 this->destroyGLContext();
247 return;
248 }
hendrikw885bf092015-08-27 10:38:39 -0700249
250 SkAutoTUnref<const GrGLInterface> gl(GrGLCreateCommandBufferInterface());
251 if (nullptr == gl.get()) {
kkinnunenef6a1ca2015-12-08 23:52:40 -0800252 SkDebugf("Command Buffer: Could not create CommandBuffer GL interface.\n");
hendrikw885bf092015-08-27 10:38:39 -0700253 this->destroyGLContext();
254 return;
255 }
256 if (!gl->validate()) {
kkinnunenef6a1ca2015-12-08 23:52:40 -0800257 SkDebugf("Command Buffer: Could not validate CommandBuffer GL interface.\n");
hendrikw885bf092015-08-27 10:38:39 -0700258 this->destroyGLContext();
259 return;
260 }
261
mtklein18300a32016-03-16 13:53:35 -0700262 this->init(gl.release());
hendrikw885bf092015-08-27 10:38:39 -0700263}
264
265SkCommandBufferGLContext::~SkCommandBufferGLContext() {
266 this->teardown();
267 this->destroyGLContext();
268}
269
270void SkCommandBufferGLContext::destroyGLContext() {
271 if (!gfFunctionsLoadedSuccessfully) {
272 return;
273 }
kkinnunenf655e932016-03-03 07:39:48 -0800274 if (fDisplay) {
275 gfMakeCurrent(fDisplay, 0, 0, 0);
kkinnunen45c2c812016-02-25 02:03:43 -0800276
kkinnunenf655e932016-03-03 07:39:48 -0800277 if (fContext) {
278 gfDestroyContext(fDisplay, fContext);
279 fContext = EGL_NO_CONTEXT;
280 }
kkinnunen45c2c812016-02-25 02:03:43 -0800281
kkinnunenf655e932016-03-03 07:39:48 -0800282 if (fSurface) {
283 gfDestroySurface(fDisplay, fSurface);
284 fSurface = EGL_NO_SURFACE;
285 }
286
287 gfTerminate(fDisplay);
288 fDisplay = EGL_NO_DISPLAY;
kkinnunen45c2c812016-02-25 02:03:43 -0800289 }
hendrikw885bf092015-08-27 10:38:39 -0700290}
291
292void SkCommandBufferGLContext::onPlatformMakeCurrent() const {
293 if (!gfFunctionsLoadedSuccessfully) {
294 return;
295 }
296 if (!gfMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
kkinnunenef6a1ca2015-12-08 23:52:40 -0800297 SkDebugf("Command Buffer: Could not make EGL context current.\n");
hendrikw885bf092015-08-27 10:38:39 -0700298 }
299}
300
301void SkCommandBufferGLContext::onPlatformSwapBuffers() const {
302 if (!gfFunctionsLoadedSuccessfully) {
303 return;
304 }
305 if (!gfSwapBuffers(fDisplay, fSurface)) {
kkinnunenef6a1ca2015-12-08 23:52:40 -0800306 SkDebugf("Command Buffer: Could not complete gfSwapBuffers.\n");
hendrikw885bf092015-08-27 10:38:39 -0700307 }
308}
309
310GrGLFuncPtr SkCommandBufferGLContext::onPlatformGetProcAddress(const char* name) const {
311 if (!gfFunctionsLoadedSuccessfully) {
312 return nullptr;
313 }
314 return gfGetProcAddress(name);
315}
316
317void SkCommandBufferGLContext::presentCommandBuffer() {
318 if (this->gl()) {
319 this->gl()->fFunctions.fFlush();
320 }
321
322 this->onPlatformSwapBuffers();
323}
324
325bool SkCommandBufferGLContext::makeCurrent() {
326 return gfMakeCurrent(fDisplay, fSurface, fSurface, fContext) != EGL_FALSE;
327}
328
329int SkCommandBufferGLContext::getStencilBits() {
330 EGLint result = 0;
kkinnunenef6a1ca2015-12-08 23:52:40 -0800331 gfGetConfigAttrib(fDisplay, static_cast<EGLConfig>(fConfig), EGL_STENCIL_SIZE, &result);
hendrikw885bf092015-08-27 10:38:39 -0700332 return result;
333}
334
335int SkCommandBufferGLContext::getSampleCount() {
336 EGLint result = 0;
kkinnunenef6a1ca2015-12-08 23:52:40 -0800337 gfGetConfigAttrib(fDisplay, static_cast<EGLConfig>(fConfig), EGL_SAMPLES, &result);
hendrikw885bf092015-08-27 10:38:39 -0700338 return result;
339}