diff options
Diffstat (limited to 'intern/ghost/intern/GHOST_WindowX11.cpp')
-rw-r--r-- | intern/ghost/intern/GHOST_WindowX11.cpp | 394 |
1 files changed, 110 insertions, 284 deletions
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 86c940b7396..97f8ae73d2d 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -30,23 +30,28 @@ */ -#include <GL/glxew.h> - #include "GHOST_WindowX11.h" #include "GHOST_SystemX11.h" #include "STR_String.h" #include "GHOST_Debug.h" #ifdef WITH_XDND -#include "GHOST_DropTargetX11.h" +# include "GHOST_DropTargetX11.h" +#endif + +#if defined(WITH_GL_EGL) +# include "GHOST_ContextEGL.h" +#else +# include "GHOST_ContextGLX.h" #endif + /* For standard X11 cursors */ #include <X11/cursorfont.h> #include <X11/Xatom.h> #if defined(__sun__) || defined(__sun) || defined(__sparc) || defined(__sparc__) || defined(_AIX) -#include <strings.h> +# include <strings.h> #endif #include <cstring> @@ -65,14 +70,6 @@ typedef struct { long input_mode; } MotifWmHints; -// Workaround for MESA bug #54080 -// https://bugs.freedesktop.org/show_bug.cgi?id=54080() -#define SWAP_INTERVALS_WORKAROUND - -#ifdef SWAP_INTERVALS_WORKAROUND -static bool g_swap_interval_disabled = false; -#endif // SWAP_INTERVALS_WORKAROUND - #define MWM_HINTS_DECORATIONS (1L << 1) @@ -157,13 +154,12 @@ static long BLENDER_ICON_48x48x32[] = { }; -GLXContext GHOST_WindowX11::s_firstContext = NULL; GHOST_WindowX11:: GHOST_WindowX11( GHOST_SystemX11 *system, Display *display, - const STR_String& title, + const STR_String &title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -174,8 +170,7 @@ GHOST_WindowX11( const bool stereoVisual, const bool exclusive, const GHOST_TUns16 numOfAASamples) - : GHOST_Window(width, height, state, type, stereoVisual, exclusive, numOfAASamples), - m_context(NULL), + : GHOST_Window(width, height, state, stereoVisual, exclusive, numOfAASamples), m_display(display), m_normal_state(GHOST_kWindowStateNormal), m_system(system), @@ -185,97 +180,19 @@ GHOST_WindowX11( m_custom_cursor(None), m_visible_cursor(None) { - - /* Set up the minimum attributes that we require and see if - * X can find us a visual matching those requirements. */ - - int attributes[40], i, samples; int natom; - int glxVersionMajor, glxVersionMinor; /* As in GLX major.minor */ - - m_visual = NULL; - - if (!glXQueryVersion(m_display, &glxVersionMajor, &glxVersionMinor)) { - printf("%s:%d: X11 glXQueryVersion() failed, verify working openGL system!\n", __FILE__, __LINE__); - - /* exit if this is the first window */ - if (s_firstContext == NULL) { - printf("initial window could not find the GLX extension, exit!\n"); - exit(1); - } - - return; - } - - /* Find the display with highest samples, starting at level requested */ - for (samples = m_numOfAASamples; samples >= 0; samples--) { - i = 0; /* Reusing attributes array, so reset counter */ - - if (m_stereoVisual) - attributes[i++] = GLX_STEREO; - - attributes[i++] = GLX_RGBA; - attributes[i++] = GLX_DOUBLEBUFFER; - attributes[i++] = GLX_RED_SIZE; attributes[i++] = 1; - attributes[i++] = GLX_BLUE_SIZE; attributes[i++] = 1; - attributes[i++] = GLX_GREEN_SIZE; attributes[i++] = 1; - attributes[i++] = GLX_DEPTH_SIZE; attributes[i++] = 1; -#ifdef GHOST_OPENGL_ALPHA - attributes[i++] = GLX_ALPHA_SIZE; attributes[i++] = 1; -#endif - /* GLX >= 1.4 required for multi-sample */ - if (samples && (glxVersionMajor >= 1) && (glxVersionMinor >= 4)) { - attributes[i++] = GLX_SAMPLE_BUFFERS; attributes[i++] = 1; - attributes[i++] = GLX_SAMPLES; attributes[i++] = samples; - } - attributes[i] = None; - - m_visual = glXChooseVisual(m_display, DefaultScreen(m_display), attributes); - - /* Any sample level or even zero, which means oversampling disabled, is good - * but we need a valid visual to continue */ - if (m_visual == NULL) { - if (samples == 0) { - /* All options exhausted, cannot continue */ - printf("%s:%d: X11 glXChooseVisual() failed, verify working openGL system!\n", __FILE__, __LINE__); - - if (s_firstContext == NULL) { - printf("initial window could not find the GLX extension, exit!\n"); - exit(1); - } - - return; - } - } - else { - if (m_numOfAASamples && (m_numOfAASamples > samples)) { - printf("%s:%d: oversampling requested %i but using %i samples\n", - __FILE__, __LINE__, m_numOfAASamples, samples); - } - break; - } - } - - /* Create a bunch of attributes needed to create an X window. */ - - /* First create a colormap for the window and visual. - * This seems pretty much a legacy feature as we are in rgba mode anyway. */ + unsigned int xattributes_valuemask = 0; XSetWindowAttributes xattributes; - unsigned int xattributes_valuemask = (CWBorderPixel | CWColormap | CWEventMask); memset(&xattributes, 0, sizeof(xattributes)); - xattributes.colormap = XCreateColormap(m_display, - RootWindow(m_display, m_visual->screen), - m_visual->visual, - AllocNone - ); - + xattributes_valuemask |= CWBorderPixel; xattributes.border_pixel = 0; /* Specify which events we are interested in hearing. */ + xattributes_valuemask |= CWEventMask; xattributes.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask | @@ -292,15 +209,15 @@ GHOST_WindowX11( /* create the window! */ if (parentWindow == 0) { m_window = XCreateWindow(m_display, - RootWindow(m_display, m_visual->screen), + RootWindow(m_display, DefaultScreen(m_display)), left, top, width, height, - 0, /* no border. */ - m_visual->depth, + 0, /* no border. */ + CopyFromParent, InputOutput, - m_visual->visual, + CopyFromParent, xattributes_valuemask, &xattributes ); @@ -321,15 +238,15 @@ GHOST_WindowX11( m_window = XCreateWindow(m_display, - parentWindow, /* reparent against embedder */ + parentWindow, /* reparent against embedder */ left, top, width, height, - 0, /* no border. */ - m_visual->depth, + 0, /* no border. */ + CopyFromParent, InputOutput, - m_visual->visual, + CopyFromParent, xattributes_valuemask, &xattributes ); @@ -451,8 +368,6 @@ GHOST_WindowX11( BLENDER_ICON_48x48x32[0] * BLENDER_ICON_48x48x32[1] + 2); /* done setting the icon */ - setTitle(title); - #ifdef WITH_X11_XINPUT initXInputDevices(); @@ -460,11 +375,13 @@ GHOST_WindowX11( #endif /* now set up the rendering context. */ - if (installDrawingContext(type) == GHOST_kSuccess) { + if (setDrawingContextType(type) == GHOST_kSuccess) { m_valid_setup = true; GHOST_PRINT("Created window\n"); } + setTitle(title); + if (exclusive) { XMapRaised(m_display, m_window); } @@ -564,7 +481,7 @@ bool GHOST_WindowX11:: getValid() const { - return m_valid_setup; + return GHOST_Window::getValid() && m_valid_setup; } void @@ -685,7 +602,7 @@ screenToClient( Window temp; XTranslateCoordinates(m_display, - RootWindow(m_display, m_visual->screen), + RootWindow(m_display, DefaultScreen(m_display)), m_window, inX, inY, &ax, &ay, @@ -708,7 +625,7 @@ clientToScreen( XTranslateCoordinates( m_display, m_window, - RootWindow(m_display, m_visual->screen), + RootWindow(m_display, DefaultScreen(m_display)), inX, inY, &ax, &ay, &temp); @@ -1052,7 +969,7 @@ setOrder( xev.xclient.data.l[3] = 0; xev.xclient.data.l[4] = 0; - root = RootWindow(m_display, m_visual->screen), + root = RootWindow(m_display, DefaultScreen(m_display)), eventmask = SubstructureRedirectMask | SubstructureNotifyMask; XSendEvent(m_display, root, False, eventmask, &xev); @@ -1079,34 +996,6 @@ setOrder( GHOST_TSuccess GHOST_WindowX11:: -swapBuffers() -{ - if (getDrawingContextType() == GHOST_kDrawingContextTypeOpenGL) { - glXSwapBuffers(m_display, m_window); - return GHOST_kSuccess; - } - else { - return GHOST_kFailure; - } -} - -GHOST_TSuccess -GHOST_WindowX11:: -activateDrawingContext() -{ - if (m_context != NULL) { - glXMakeCurrent(m_display, m_window, m_context); - /* Disable AA by default */ - if (m_numOfAASamples > 0) { - glDisable(GL_MULTISAMPLE_ARB); - } - return GHOST_kSuccess; - } - return GHOST_kFailure; -} - -GHOST_TSuccess -GHOST_WindowX11:: invalidate() { /* So the idea of this function is to generate an expose event @@ -1172,10 +1061,6 @@ GHOST_WindowX11:: XFreeCursor(m_display, m_custom_cursor); } - if (m_context != s_firstContext) { - glXDestroyContext(m_display, m_context); - } - if (p_owner == m_window) { XSetSelectionOwner(m_display, Primary_atom, None, CurrentTime); } @@ -1193,88 +1078,98 @@ GHOST_WindowX11:: delete m_dropTarget; #endif + releaseNativeHandles(); + XDestroyWindow(m_display, m_window); - XFree(m_visual); } - - -/** - * Tries to install a rendering context in this window. - * \param type The type of rendering context installed. - * \return Indication as to whether installation has succeeded. - */ -GHOST_TSuccess -GHOST_WindowX11:: -installDrawingContext( - GHOST_TDrawingContextType type) +GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type) { - /* only support openGL for now. */ - GHOST_TSuccess success; - switch (type) { - case GHOST_kDrawingContextTypeOpenGL: - { -#ifdef WITH_X11_XINPUT - /* use our own event handlers to avoid exiting blender, - * this would happen for eg: - * if you open blender, unplug a tablet, then open a new window. */ - XErrorHandler old_handler = XSetErrorHandler(GHOST_X11_ApplicationErrorHandler); - XIOErrorHandler old_handler_io = XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler); + if (type == GHOST_kDrawingContextTypeOpenGL) { +#if !defined(WITH_GL_EGL) + +#if defined(WITH_GL_PROFILE_CORE) + GHOST_Context *context = new GHOST_ContextGLX( + m_wantStereoVisual, + m_wantNumOfAASamples, + m_window, + m_display, + GLX_CONTEXT_OPENGL_CORE_PROFILE_BIT, + 3, 2, + GHOST_OPENGL_GLX_CONTEXT_FLAGS, + GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY); +#elif defined(WITH_GL_PROFILE_ES20) + GHOST_Context *context = new GHOST_ContextGLX( + m_wantStereoVisual, + m_wantNumOfAASamples, + m_window, + m_display, + GLX_CONTEXT_ES2_PROFILE_BIT_EXT, + 2, 0, + GHOST_OPENGL_GLX_CONTEXT_FLAGS, + GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY); +#elif defined(WITH_GL_PROFILE_COMPAT) + GHOST_Context *context = new GHOST_ContextGLX( + m_wantStereoVisual, + m_wantNumOfAASamples, + m_window, + m_display, + 0, // profile bit + 0, 0, + GHOST_OPENGL_GLX_CONTEXT_FLAGS, + GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY); +#else +# error #endif - m_context = glXCreateContext(m_display, m_visual, s_firstContext, True); - if (m_context != NULL) { - if (!s_firstContext) { - s_firstContext = m_context; - } - glXMakeCurrent(m_display, m_window, m_context); - glClearColor(0.447, 0.447, 0.447, 0); - glClear(GL_COLOR_BUFFER_BIT); - success = GHOST_kSuccess; - } - else { - success = GHOST_kFailure; - } +#else + +#if defined(WITH_GL_PROFILE_CORE) + GHOST_Context *context = new GHOST_ContextEGL( + m_wantStereoVisual, + m_wantNumOfAASamples, + m_window, + m_display, + EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, + 3, 2, + GHOST_OPENGL_EGL_CONTEXT_FLAGS, + GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY, + EGL_OPENGL_API); +#elif defined(WITH_GL_PROFILE_ES20) + GHOST_Context *context = new GHOST_ContextEGL( + m_wantStereoVisual, + m_wantNumOfAASamples, + m_window, + m_display, + 0, // profile bit + 2, 0, + GHOST_OPENGL_EGL_CONTEXT_FLAGS, + GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY, + EGL_OPENGL_ES_API); +#elif defined(WITH_GL_PROFILE_COMPAT) + GHOST_Context *context = new GHOST_ContextEGL( + m_wantStereoVisual, + m_wantNumOfAASamples, + m_window, + m_display, + 0, // profile bit + 0, 0, + GHOST_OPENGL_EGL_CONTEXT_FLAGS, + GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY, + EGL_OPENGL_API); +#else +# error +#endif -#ifdef WITH_X11_XINPUT - /* Restore handler */ - (void) XSetErrorHandler(old_handler); - (void) XSetIOErrorHandler(old_handler_io); #endif - break; - } - case GHOST_kDrawingContextTypeNone: - { - success = GHOST_kSuccess; - break; - } - default: - success = GHOST_kFailure; + if (context->initializeDrawingContext()) + return context; + else + delete context; } - return success; -} - - -/** - * Removes the current drawing context. - * \return Indication as to whether removal has succeeded. - */ -GHOST_TSuccess -GHOST_WindowX11:: -removeDrawingContext() -{ - GHOST_TSuccess success; - - if (m_context != NULL) { - glXDestroyContext(m_display, m_context); - success = GHOST_kSuccess; - } - else { - success = GHOST_kFailure; - } - return success; + return NULL; } @@ -1530,72 +1425,3 @@ endFullScreen() const return GHOST_kSuccess; } - -GHOST_TSuccess -GHOST_WindowX11:: -setSwapInterval(int interval) { - if (!GLX_EXT_swap_control || !glXSwapIntervalEXT -#ifdef SWAP_INTERVALS_WORKAROUND - || g_swap_interval_disabled -#endif // SWAP_INTERVALS_WORKAROUND - ) - { - return GHOST_kFailure; - } - glXSwapIntervalEXT(m_display, m_window, interval); - return GHOST_kSuccess; -} - -#ifdef SWAP_INTERVALS_WORKAROUND -static int QueryDrawable_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent) -{ - fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n", - theEvent->error_code, theEvent->request_code); - if (!g_swap_interval_disabled) { - fprintf(stderr, "Disabling SWAP INTERVALS extension\n"); - g_swap_interval_disabled = true; - } - return 0; -} - -static int QueryDrawable_ApplicationIOErrorHandler(Display *display) -{ - fprintf(stderr, "Ignoring Xlib error: error IO\n"); - if (!g_swap_interval_disabled) { - fprintf(stderr, "Disabling SWAP INTERVALS extension\n"); - g_swap_interval_disabled = true; - } - return 0; -} -#endif // SWAP_INTERVALS_WORKAROUND - -int -GHOST_WindowX11:: -getSwapInterval() { - if (GLX_EXT_swap_control) { -#ifdef SWAP_INTERVALS_WORKAROUND - /* XXX: Current MESA driver will give GLXBadDrawable for all - * the glXQueryDrawable requests with direct contexts. - * - * To prevent crashes and unexpected behaviors, we will - * disable swap intervals extension if query fails here. - * (because if we will override interval without having - * old value we couldn't restore it properly). - */ - XErrorHandler old_handler = XSetErrorHandler(QueryDrawable_ApplicationErrorHandler); - XIOErrorHandler old_handler_io = XSetIOErrorHandler(QueryDrawable_ApplicationIOErrorHandler); -#endif // SWAP_INTERVALS_WORKAROUND - - unsigned int value = 0; - glXQueryDrawable(m_display, m_window, GLX_SWAP_INTERVAL_EXT, &value); - -#ifdef SWAP_INTERVALS_WORKAROUND - /* Restore handler */ - (void) XSetErrorHandler(old_handler); - (void) XSetIOErrorHandler(old_handler_io); -#endif // SWAP_INTERVALS_WORKAROUND - - return (int)value; - } - return 0; -} |