aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/sk_app/unix/GLWindowContext_unix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/sk_app/unix/GLWindowContext_unix.cpp')
-rw-r--r--tools/sk_app/unix/GLWindowContext_unix.cpp149
1 files changed, 149 insertions, 0 deletions
diff --git a/tools/sk_app/unix/GLWindowContext_unix.cpp b/tools/sk_app/unix/GLWindowContext_unix.cpp
new file mode 100644
index 0000000000..d7a4387880
--- /dev/null
+++ b/tools/sk_app/unix/GLWindowContext_unix.cpp
@@ -0,0 +1,149 @@
+
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <GL/gl.h>
+#include "../GLWindowContext.h"
+#include "WindowContextFactory_unix.h"
+#include "gl/GrGLInterface.h"
+
+using sk_app::window_context_factory::XlibWindowInfo;
+using sk_app::DisplayParams;
+using sk_app::GLWindowContext;
+
+namespace {
+
+class GLWindowContext_xlib : public GLWindowContext {
+public:
+ GLWindowContext_xlib(const XlibWindowInfo&, const DisplayParams&);
+ ~GLWindowContext_xlib() override;
+
+ void onSwapBuffers() override;
+
+ void onDestroyContext() override;
+
+protected:
+ sk_sp<const GrGLInterface> onInitializeContext() override;
+
+private:
+ GLWindowContext_xlib(void*, const DisplayParams&);
+
+ Display* fDisplay;
+ XWindow fWindow;
+ GLXFBConfig* fFBConfig;
+ XVisualInfo* fVisualInfo;
+ GLXContext fGLContext;
+
+ typedef GLWindowContext INHERITED;
+};
+
+GLWindowContext_xlib::GLWindowContext_xlib(const XlibWindowInfo& winInfo, const DisplayParams& params)
+ : INHERITED(params)
+ , fDisplay(winInfo.fDisplay)
+ , fWindow(winInfo.fWindow)
+ , fFBConfig(winInfo.fFBConfig)
+ , fVisualInfo(winInfo.fVisualInfo)
+ , fGLContext() {
+ fWidth = winInfo.fWidth;
+ fHeight = winInfo.fHeight;
+ this->initializeContext();
+}
+
+using CreateContextAttribsFn = GLXContext(Display*, GLXFBConfig, GLXContext, Bool, const int*);
+
+sk_sp<const GrGLInterface> GLWindowContext_xlib::onInitializeContext() {
+ SkASSERT(fDisplay);
+ SkASSERT(!fGLContext);
+ // We attempt to use glXCreateContextAttribsARB as RenderDoc requires that the context be
+ // created with this rather than glXCreateContext.
+ CreateContextAttribsFn* createContextAttribs = (CreateContextAttribsFn*)glXGetProcAddressARB(
+ (const GLubyte*)"glXCreateContextAttribsARB");
+ if (createContextAttribs && fFBConfig) {
+ // Specifying 3.2 allows an arbitrarily high context version (so long as no 3.2 features
+ // have been removed).
+ for (int minor = 2; minor >= 0 && !fGLContext; --minor) {
+ // Ganesh prefers a compatibility profile for possible NVPR support. However, RenderDoc
+ // requires a core profile. Edit this code to use RenderDoc.
+ for (int profile : {GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
+ GLX_CONTEXT_CORE_PROFILE_BIT_ARB}) {
+ int attribs[] = {
+ GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, minor,
+ GLX_CONTEXT_PROFILE_MASK_ARB, profile,
+ 0
+ };
+ fGLContext = createContextAttribs(fDisplay, *fFBConfig, nullptr, True, attribs);
+ if (fGLContext) {
+ break;
+ }
+ }
+ }
+ }
+ if (!fGLContext) {
+ fGLContext = glXCreateContext(fDisplay, fVisualInfo, nullptr, GL_TRUE);
+ }
+ if (!fGLContext) {
+ return nullptr;
+ }
+
+ if (!glXMakeCurrent(fDisplay, fWindow, fGLContext)) {
+ return nullptr;
+ }
+ glClearStencil(0);
+ glClearColor(0, 0, 0, 0);
+ glStencilMask(0xffffffff);
+ glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+
+ glXGetConfig(fDisplay, fVisualInfo, GLX_STENCIL_SIZE, &fStencilBits);
+ glXGetConfig(fDisplay, fVisualInfo, GLX_SAMPLES_ARB, &fSampleCount);
+
+ XWindow root;
+ int x, y;
+ unsigned int border_width, depth;
+ XGetGeometry(fDisplay, fWindow, &root, &x, &y, (unsigned int*)&fWidth, (unsigned int*)&fHeight,
+ &border_width, &depth);
+ glViewport(0, 0, fWidth, fHeight);
+
+ return sk_sp<const GrGLInterface>(GrGLCreateNativeInterface());
+}
+
+GLWindowContext_xlib::~GLWindowContext_xlib() {
+ this->destroyContext();
+}
+
+void GLWindowContext_xlib::onDestroyContext() {
+ if (!fDisplay || !fGLContext) {
+ return;
+ }
+ glXMakeCurrent(fDisplay, None, nullptr);
+ glXDestroyContext(fDisplay, fGLContext);
+ fGLContext = nullptr;
+}
+
+void GLWindowContext_xlib::onSwapBuffers() {
+ if (fDisplay && fGLContext) {
+ glXSwapBuffers(fDisplay, fWindow);
+ }
+}
+
+} // anonymous namespace
+
+namespace sk_app {
+
+namespace window_context_factory {
+
+WindowContext* NewGLForXlib(const XlibWindowInfo& winInfo, const DisplayParams& params) {
+ WindowContext* ctx = new GLWindowContext_xlib(winInfo, params);
+ if (!ctx->isValid()) {
+ delete ctx;
+ return nullptr;
+ }
+ return ctx;
+}
+
+} // namespace window_context_factory
+
+} // namespace sk_app