diff options
| author | Linktothepast <kostamarino@gmail.com> | 2015-09-28 16:50:35 +0300 |
|---|---|---|
| committer | Linktothepast <kostamarino@gmail.com> | 2015-09-28 16:50:35 +0300 |
| commit | 748be565b8df535ef558e74b38cd0f4d615f8a21 (patch) | |
| tree | b151efee0a87e99125f2401325a9bddecf84fc73 /Source/Core/Common/GL/GLInterface/GLX.cpp | |
| parent | cf17fccdd3093a1b8476b10183b1c4bde36da74d (diff) | |
| parent | ce493b897d6d3735c930a8465cc0c26bbe5feb86 (diff) | |
Merge remote-tracking branch 'dolphin-emu/master' into gameinis
Diffstat (limited to 'Source/Core/Common/GL/GLInterface/GLX.cpp')
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/GLX.cpp | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/Source/Core/Common/GL/GLInterface/GLX.cpp b/Source/Core/Common/GL/GLInterface/GLX.cpp new file mode 100644 index 0000000000..8ac73b5fd4 --- /dev/null +++ b/Source/Core/Common/GL/GLInterface/GLX.cpp @@ -0,0 +1,197 @@ +// Copyright 2012 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include <string> + +#include "Common/GL/GLInterface/GLX.h" +#include "Common/Logging/Log.h" + +#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 + +typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSPROC)(Display*, GLXFBConfig, GLXContext, Bool, const int*); +typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval); + +static PFNGLXCREATECONTEXTATTRIBSPROC glXCreateContextAttribs = nullptr; +static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = nullptr; + +static bool s_glxError; +static int ctxErrorHandler(Display *dpy, XErrorEvent *ev) +{ + s_glxError = true; + return 0; +} + +void cInterfaceGLX::SwapInterval(int Interval) +{ + if (glXSwapIntervalSGI) + glXSwapIntervalSGI(Interval); + else + ERROR_LOG(VIDEO, "No support for SwapInterval (framerate clamped to monitor refresh rate)."); +} +void* cInterfaceGLX::GetFuncAddress(const std::string& name) +{ + return (void*)glXGetProcAddress((const GLubyte*)name.c_str()); +} + +void cInterfaceGLX::Swap() +{ + glXSwapBuffers(dpy, win); +} + +// Create rendering window. +// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() +bool cInterfaceGLX::Create(void *window_handle, bool core) +{ + dpy = XOpenDisplay(nullptr); + int screen = DefaultScreen(dpy); + + // checking glx version + int glxMajorVersion, glxMinorVersion; + glXQueryVersion(dpy, &glxMajorVersion, &glxMinorVersion); + if (glxMajorVersion < 1 || (glxMajorVersion == 1 && glxMinorVersion < 4)) + { + ERROR_LOG(VIDEO, "glX-Version %d.%d detected, but need at least 1.4", + glxMajorVersion, glxMinorVersion); + return false; + } + + // loading core context creation function + glXCreateContextAttribs = (PFNGLXCREATECONTEXTATTRIBSPROC)GetFuncAddress("glXCreateContextAttribsARB"); + if (!glXCreateContextAttribs) + { + ERROR_LOG(VIDEO, "glXCreateContextAttribsARB not found, do you support GLX_ARB_create_context?"); + return false; + } + + // choosing framebuffer + int visual_attribs[] = + { + GLX_X_RENDERABLE , True, + GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, + GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR, + GLX_RED_SIZE , 8, + GLX_GREEN_SIZE , 8, + GLX_BLUE_SIZE , 8, + GLX_DEPTH_SIZE , 0, + GLX_STENCIL_SIZE , 0, + GLX_DOUBLEBUFFER , True, + None + }; + int fbcount = 0; + GLXFBConfig* fbc = glXChooseFBConfig(dpy, screen, visual_attribs, &fbcount); + if (!fbc || !fbcount) + { + ERROR_LOG(VIDEO, "Failed to retrieve a framebuffer config"); + return false; + } + fbconfig = *fbc; + XFree(fbc); + + // Get an appropriate visual + XVisualInfo* vi = glXGetVisualFromFBConfig(dpy, fbconfig); + + s_glxError = false; + XErrorHandler oldHandler = XSetErrorHandler(&ctxErrorHandler); + + // Create a GLX context. + // We try to get a 4.0 core profile, else we try 3.3, else try it with anything we get. + int context_attribs[] = + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 4, + GLX_CONTEXT_MINOR_VERSION_ARB, 0, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + None + }; + ctx = nullptr; + if (core) + { + ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, context_attribs); + XSync(dpy, False); + } + if (core && (!ctx || s_glxError)) + { + int context_attribs_33[] = + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 3, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + None + }; + s_glxError = false; + ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, context_attribs_33); + XSync(dpy, False); + + } + if (!ctx || s_glxError) + { + int context_attribs_legacy[] = + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 1, + GLX_CONTEXT_MINOR_VERSION_ARB, 0, + None + }; + s_glxError = false; + ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, context_attribs_legacy); + XSync(dpy, False); + + } + if (!ctx || s_glxError) + { + ERROR_LOG(VIDEO, "Unable to create GL context."); + return false; + } + XSetErrorHandler(oldHandler); + + XWindow.Initialize(dpy); + + Window parent = (Window)window_handle; + + XWindowAttributes attribs; + if (!XGetWindowAttributes(dpy, parent, &attribs)) + { + ERROR_LOG(VIDEO, "Window attribute retrieval failed"); + return false; + } + + s_backbuffer_width = attribs.width; + s_backbuffer_height = attribs.height; + + win = XWindow.CreateXWindow(parent, vi); + XFree(vi); + + return true; +} + +bool cInterfaceGLX::MakeCurrent() +{ + bool success = glXMakeCurrent(dpy, win, ctx); + if (success) + { + // load this function based on the current bound context + glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)GLInterface->GetFuncAddress("glXSwapIntervalSGI"); + } + return success; +} + +bool cInterfaceGLX::ClearCurrent() +{ + return glXMakeCurrent(dpy, None, nullptr); +} + + +// Close backend +void cInterfaceGLX::Shutdown() +{ + XWindow.DestroyXWindow(); + if (ctx) + { + glXDestroyContext(dpy, ctx); + XCloseDisplay(dpy); + ctx = nullptr; + } +} + |
