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 |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..0cc55e4558f473e7fdec33bd1336ad5032401a96 |
| --- /dev/null |
| +++ b/src/gpu/gl/command_buffer/SkCommandBufferGLContext.cpp |
| @@ -0,0 +1,198 @@ |
| + |
| +/* |
| + * Copyright 2015 Google Inc. |
| + * |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. |
| + */ |
| +#include <EGL/egl.h> |
| + |
| +#include "gl/GrGLInterface.h" |
| +#include "gl/GrGLAssembleInterface.h" |
| +#include "gl/command_buffer/SkCommandBufferGLContext.h" |
| + |
| +typedef EGLDisplay (*GetDisplayProc)(EGLNativeDisplayType display_id); |
| +typedef EGLBoolean (*InitializeProc)(EGLDisplay dpy, EGLint *major, EGLint *minor); |
| +typedef EGLBoolean (*TerminateProc)(EGLDisplay dpy); |
| +typedef EGLBoolean (*ChooseConfigProc)(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, EGLint config_size, EGLint* num_config); |
| +typedef EGLSurface (*CreateWindowSurfaceProc)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint* attrib_list); |
| +typedef EGLSurface (*CreatePbufferSurfaceProc)(EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list); |
| +typedef EGLBoolean (*DestroySurfaceProc)(EGLDisplay dpy, EGLSurface surface); |
| +typedef EGLContext (*CreateContextProc)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint* attrib_list); |
| +typedef EGLBoolean (*DestroyContextProc)(EGLDisplay dpy, EGLContext ctx); |
| +typedef EGLBoolean (*MakeCurrentProc)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); |
| +typedef EGLBoolean (*SwapBuffersProc)(EGLDisplay dpy, EGLSurface surface); |
| +typedef __eglMustCastToProperFunctionPointerType (*GetProcAddressProc)(const char* procname); |
| + |
| +static GetDisplayProc gfGetDisplay = nullptr; |
| +static InitializeProc gfInitialize = nullptr; |
| +static TerminateProc gfTerminate = nullptr; |
| +static ChooseConfigProc gfChooseConfig = nullptr; |
| +static CreateWindowSurfaceProc gfCreateWindowSurface = nullptr; |
| +static CreatePbufferSurfaceProc gfCreatePbufferSurface = nullptr; |
| +static DestroySurfaceProc gfDestroySurface = nullptr; |
| +static CreateContextProc gfCreateContext = nullptr; |
| +static DestroyContextProc gfDestroyContext = nullptr; |
| +static MakeCurrentProc gfMakeCurrent = nullptr; |
| +static SwapBuffersProc gfSwapBuffers = nullptr; |
| +static GetProcAddressProc gfGetProcAddress = nullptr; |
| + |
| +static HMODULE ghLibrary = nullptr; |
|
bsalomon
2015/08/26 18:19:55
Should we use SkONCE here for thread safety?
hendrikw
2015/08/27 01:28:35
Done.
|
| +static bool gfFunctionsLoadedSuccessfully = false; |
| + |
| +static bool LoadCommandBufferFunctions() |
| +{ |
| + if (!ghLibrary) { |
| + ghLibrary = LoadLibrary("command_buffer_gles2.dll"); |
| + |
| + if (ghLibrary) { |
| + gfGetDisplay = (GetDisplayProc)::GetProcAddress(ghLibrary, "CommandBuffer_GetDisplay"); |
| + gfInitialize = (InitializeProc)::GetProcAddress(ghLibrary, "CommandBuffer_Initialize"); |
| + gfTerminate = (TerminateProc)::GetProcAddress(ghLibrary, "CommandBuffer_Terminate"); |
| + gfChooseConfig = (ChooseConfigProc)::GetProcAddress(ghLibrary, "CommandBuffer_ChooseConfig"); |
| + gfCreateWindowSurface = (CreateWindowSurfaceProc)::GetProcAddress(ghLibrary, "CommandBuffer_CreateWindowSurface"); |
| + gfCreatePbufferSurface = (CreatePbufferSurfaceProc)::GetProcAddress(ghLibrary, "CommandBuffer_CreatePbufferSurface"); |
| + gfDestroySurface = (DestroySurfaceProc)::GetProcAddress(ghLibrary, "CommandBuffer_DestroySurface"); |
| + gfCreateContext = (CreateContextProc)::GetProcAddress(ghLibrary, "CommandBuffer_CreateContext"); |
| + gfDestroyContext = (DestroyContextProc)::GetProcAddress(ghLibrary, "CommandBuffer_DestroyContext"); |
| + gfMakeCurrent = (MakeCurrentProc)::GetProcAddress(ghLibrary, "CommandBuffer_MakeCurrent"); |
| + gfSwapBuffers = (SwapBuffersProc)::GetProcAddress(ghLibrary, "CommandBuffer_SwapBuffers"); |
| + gfGetProcAddress = (GetProcAddressProc)::GetProcAddress(ghLibrary, "CommandBuffer_GetProcAddress"); |
| + |
| + gfFunctionsLoadedSuccessfully = gfGetDisplay && gfInitialize && gfTerminate && |
| + gfChooseConfig && gfCreateWindowSurface && |
| + gfCreatePbufferSurface && gfDestroySurface && |
| + gfCreateContext && gfDestroyContext && gfMakeCurrent && |
| + gfSwapBuffers && gfGetProcAddress; |
| + |
| + } |
| + } |
| + return gfFunctionsLoadedSuccessfully; |
| +} |
| + |
| +static GrGLFuncPtr command_buffer_get_gl_proc(void* ctx, const char name[]) { |
| + GrGLFuncPtr proc = (GrGLFuncPtr) GetProcAddress((HMODULE)ctx, name); |
| + if (proc) { |
| + return proc; |
| + } |
| + if (!gfFunctionsLoadedSuccessfully) |
| + return nullptr; |
| + return gfGetProcAddress(name); |
| +} |
| + |
| +const GrGLInterface* GrGLCreateCommandBufferInterface() { |
| + if (!LoadCommandBufferFunctions()) |
| + return nullptr; |
| + return GrGLAssembleGLESInterface(ghLibrary, command_buffer_get_gl_proc); |
| +} |
| + |
| +SkCommandBufferGLContext::SkCommandBufferGLContext() |
| + : fContext(EGL_NO_CONTEXT) |
| + , fDisplay(EGL_NO_DISPLAY) |
| + , fSurface(EGL_NO_SURFACE) { |
| + |
| + if (!LoadCommandBufferFunctions()) |
| + return; |
| + |
| + EGLint numConfigs; |
| + static const EGLint configAttribs[] = { |
| + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, |
| + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, |
| + EGL_RED_SIZE, 8, |
| + EGL_GREEN_SIZE, 8, |
| + EGL_BLUE_SIZE, 8, |
| + EGL_ALPHA_SIZE, 8, |
| + EGL_NONE |
| + }; |
| + |
| + fDisplay = gfGetDisplay(static_cast<EGLNativeDisplayType>(EGL_DEFAULT_DISPLAY)); |
| + if (EGL_NO_DISPLAY == fDisplay) { |
| + SkDebugf("Could not create EGL display!"); |
| + return; |
| + } |
| + |
| + EGLint majorVersion; |
| + EGLint minorVersion; |
| + gfInitialize(fDisplay, &majorVersion, &minorVersion); |
| + |
| + EGLConfig surfaceConfig; |
| + gfChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs); |
| + |
| + static const EGLint surfaceAttribs[] = { |
| + EGL_WIDTH, 1, |
| + EGL_HEIGHT, 1, |
| + EGL_NONE |
| + }; |
| + |
| + fSurface = gfCreatePbufferSurface(fDisplay, surfaceConfig, surfaceAttribs); |
| + |
| + static const EGLint contextAttribs[] = { |
| + EGL_CONTEXT_CLIENT_VERSION, 2, |
| + EGL_NONE |
| + }; |
| + fContext = gfCreateContext(fDisplay, surfaceConfig, NULL, contextAttribs); |
| + |
| + gfMakeCurrent(fDisplay, fSurface, fSurface, fContext); |
| + |
| + SkAutoTUnref<const GrGLInterface> gl(GrGLCreateCommandBufferInterface()); |
| + if (NULL == gl.get()) { |
| + SkDebugf("Could not create CommandBuffer GL interface!\n"); |
| + this->destroyGLContext(); |
| + return; |
| + } |
| + if (!gl->validate()) { |
| + SkDebugf("Could not validate CommandBuffer GL interface!\n"); |
| + this->destroyGLContext(); |
| + return; |
| + } |
| + |
| + this->init(gl.detach()); |
| +} |
| + |
| +SkCommandBufferGLContext::~SkCommandBufferGLContext() { |
| + this->teardown(); |
| + this->destroyGLContext(); |
| +} |
| + |
| +void SkCommandBufferGLContext::destroyGLContext() { |
| + if (!gfFunctionsLoadedSuccessfully) |
|
bsalomon
2015/08/26 18:19:55
style nit, {} and 4 space indent
hendrikw
2015/08/27 01:28:35
Done.
|
| + 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; |
| + } |
| + |
| + gfTerminate(fDisplay); |
| + fDisplay = EGL_NO_DISPLAY; |
| + } |
| +} |
| + |
| +void SkCommandBufferGLContext::onPlatformMakeCurrent() const { |
| + if (!gfFunctionsLoadedSuccessfully) |
|
bsalomon
2015/08/26 18:19:55
{}/4
hendrikw
2015/08/27 01:28:35
Done.
|
| + return; |
| + if (!gfMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { |
| + SkDebugf("Could not set the context.\n"); |
| + } |
| +} |
| + |
| +void SkCommandBufferGLContext::onPlatformSwapBuffers() const { |
| + if (!gfFunctionsLoadedSuccessfully) |
|
bsalomon
2015/08/26 18:19:55
{}/4
hendrikw
2015/08/27 01:28:35
Done.
|
| + return; |
| + if (!gfSwapBuffers(fDisplay, fSurface)) { |
| + SkDebugf("Could not complete gfSwapBuffers.\n"); |
| + } |
| +} |
| + |
| +GrGLFuncPtr SkCommandBufferGLContext::onPlatformGetProcAddress(const char* name) const { |
| + if (!gfFunctionsLoadedSuccessfully) |
|
bsalomon
2015/08/26 18:19:55
{}/4
hendrikw
2015/08/27 01:28:35
Done.
|
| + return nullptr; |
| + return gfGetProcAddress(name); |
| +} |