Chromium Code Reviews| Index: src/gpu/gl/command_buffer/SkCommandBufferGLContext.cpp |
| diff --git a/src/gpu/gl/command_buffer/SkCommandBufferGLContext.cpp b/src/gpu/gl/command_buffer/SkCommandBufferGLContext.cpp |
| index cf9da9365b195a43775305e8f0f98d08d3511eef..75e9b94f3699b9220bfb85c2d32de9ae52f086f8 100644 |
| --- a/src/gpu/gl/command_buffer/SkCommandBufferGLContext.cpp |
| +++ b/src/gpu/gl/command_buffer/SkCommandBufferGLContext.cpp |
| @@ -33,6 +33,7 @@ typedef void (*__eglMustCastToProperFunctionPointerType)(void); |
| #define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0) |
| #define EGL_SURFACE_TYPE 0x3033 |
| #define EGL_PBUFFER_BIT 0x0001 |
| +#define EGL_WINDOW_BIT 0x0004 |
| #define EGL_RENDERABLE_TYPE 0x3040 |
| #define EGL_RED_SIZE 0x3024 |
| #define EGL_GREEN_SIZE 0x3023 |
| @@ -52,6 +53,11 @@ typedef void (*__eglMustCastToProperFunctionPointerType)(void); |
| #endif |
| +#ifndef EGL_OPENGL_ES3_BIT |
| +// Part of EGL 1.5, typical headers are 1.4. |
| +#define EGL_OPENGL_ES3_BIT 0x0040 |
| +#endif |
| + |
| typedef EGLDisplay (*GetDisplayProc)(EGLNativeDisplayType display_id); |
| typedef EGLBoolean (*InitializeProc)(EGLDisplay dpy, EGLint *major, EGLint *minor); |
| typedef EGLBoolean (*TerminateProc)(EGLDisplay dpy); |
| @@ -137,14 +143,15 @@ const GrGLInterface* GrGLCreateCommandBufferInterface() { |
| return GrGLAssembleGLESInterface(gLibrary, command_buffer_get_gl_proc); |
| } |
| -SkCommandBufferGLContext::SkCommandBufferGLContext() |
| +SkCommandBufferGLContext::SkCommandBufferGLContext(ContextVersion minContextVersion) |
| : fContext(EGL_NO_CONTEXT) |
| , fDisplay(EGL_NO_DISPLAY) |
| , fSurface(EGL_NO_SURFACE) { |
| static const EGLint configAttribs[] = { |
| EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, |
| - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, |
| + EGL_RENDERABLE_TYPE, minContextVersion == kGLES3_ContextVersion ? EGL_OPENGL_ES3_BIT |
| + : EGL_OPENGL_ES2_BIT, |
| EGL_RED_SIZE, 8, |
| EGL_GREEN_SIZE, 8, |
| EGL_BLUE_SIZE, 8, |
| @@ -158,13 +165,15 @@ SkCommandBufferGLContext::SkCommandBufferGLContext() |
| EGL_NONE |
| }; |
| - initializeGLContext(nullptr, configAttribs, surfaceAttribs); |
| + initializeGLContext(minContextVersion, nullptr, configAttribs, surfaceAttribs); |
| } |
| SkCommandBufferGLContext::SkCommandBufferGLContext(void* nativeWindow, int msaaSampleCount) { |
| static const EGLint surfaceAttribs[] = { EGL_NONE }; |
| EGLint configAttribs[] = { |
| + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, |
| + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, |
| EGL_RED_SIZE, 8, |
| EGL_GREEN_SIZE, 8, |
| EGL_BLUE_SIZE, 8, |
| @@ -179,10 +188,11 @@ SkCommandBufferGLContext::SkCommandBufferGLContext(void* nativeWindow, int msaaS |
| configAttribs[12] = EGL_NONE; |
| } |
| - initializeGLContext(nativeWindow, configAttribs, surfaceAttribs); |
| + initializeGLContext(kGLES2_ContextVersion, nativeWindow, configAttribs, surfaceAttribs); |
| } |
| -void SkCommandBufferGLContext::initializeGLContext(void* nativeWindow, const int* configAttribs, |
| +void SkCommandBufferGLContext::initializeGLContext(ContextVersion minContextVersion, |
| + void* nativeWindow, const int* configAttribs, |
| const int* surfaceAttribs) { |
| LoadCommandBufferOnce(); |
| if (!gfFunctionsLoadedSuccessfully) { |
| @@ -191,16 +201,14 @@ void SkCommandBufferGLContext::initializeGLContext(void* nativeWindow, const int |
| } |
| // Make sure CHROMIUM_path_rendering is enabled for NVPR support. |
| - sk_setenv("CHROME_COMMAND_BUFFER_GLES2_ARGS", "--enable-gl-path-rendering"); |
| + sk_setenv("CHROME_COMMAND_BUFFER_GLES2_ARGS", "--enable-gl-path-rendering --enable-unsafe-es3-apis"); |
| fDisplay = gfGetDisplay(EGL_DEFAULT_DISPLAY); |
| if (EGL_NO_DISPLAY == fDisplay) { |
| SkDebugf("Command Buffer: Could not create EGL display.\n"); |
| return; |
| } |
| - EGLint majorVersion; |
| - EGLint minorVersion; |
| - if (!gfInitialize(fDisplay, &majorVersion, &minorVersion)) { |
| + if (!gfInitialize(fDisplay, nullptr, nullptr)) { |
| SkDebugf("Command Buffer: Could not initialize EGL display.\n"); |
| this->destroyGLContext(); |
| return; |
| @@ -208,7 +216,7 @@ void SkCommandBufferGLContext::initializeGLContext(void* nativeWindow, const int |
| EGLint numConfigs; |
| if (!gfChooseConfig(fDisplay, configAttribs, static_cast<EGLConfig*>(&fConfig), 1, |
| - &numConfigs) || numConfigs != 1) { |
| + &numConfigs) || numConfigs < 1) { |
| SkDebugf("Command Buffer: Could not choose EGL config.\n"); |
| this->destroyGLContext(); |
| return; |
| @@ -231,7 +239,7 @@ void SkCommandBufferGLContext::initializeGLContext(void* nativeWindow, const int |
| } |
| static const EGLint contextAttribs[] = { |
| - EGL_CONTEXT_CLIENT_VERSION, 2, |
| + EGL_CONTEXT_CLIENT_VERSION, minContextVersion == kGLES3_ContextVersion ? 3 : 2, |
| EGL_NONE |
| }; |
| fContext = gfCreateContext(fDisplay, static_cast<EGLConfig>(fConfig), nullptr, contextAttribs); |
| @@ -271,22 +279,27 @@ void SkCommandBufferGLContext::destroyGLContext() { |
| if (!gfFunctionsLoadedSuccessfully) { |
| return; |
| } |
| - if (fDisplay) { |
| - gfMakeCurrent(fDisplay, 0, 0, 0); |
| - |
| - if (fContext) { |
| - gfDestroyContext(fDisplay, fContext); |
| - fContext = EGL_NO_CONTEXT; |
| - } |
| - |
| - if (fSurface) { |
| - gfDestroySurface(fDisplay, fSurface); |
| - fSurface = EGL_NO_SURFACE; |
| - } |
| + if (EGL_NO_DISPLAY == fDisplay) { |
| + return; |
| + } |
| - gfTerminate(fDisplay); |
| - fDisplay = EGL_NO_DISPLAY; |
| + if (EGL_NO_CONTEXT != fContext) { |
| + gfDestroyContext(fDisplay, fContext); |
| + fContext = EGL_NO_CONTEXT; |
| + } |
| + // Call MakeCurrent after destroying the context, so that the destroyed surface remains current. |
| + // This way command buffer does not need to abandon the context before destruction, and no |
| + // client-side errors are printed. |
| + gfMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); |
| + |
| + if (EGL_NO_SURFACE != fSurface) { |
| + gfDestroySurface(fDisplay, fSurface); |
| + fSurface = EGL_NO_SURFACE; |
| } |
| + // The display is likely to be used again for another test, do not call gfTerminate. Also, |
| + // terminating could imply terminating the "host" EGL inside command buffer. This would |
| + // terminate also EGL that this thread might use outside of command buffer. |
| + fDisplay = EGL_NO_DISPLAY; |
|
Kimmo Kinnunen
2016/02/25 09:37:35
This was changed after review.
|
| } |
| void SkCommandBufferGLContext::onPlatformMakeCurrent() const { |