diff options
Diffstat (limited to 'intern/ghost/intern/GHOST_WindowX11.cpp')
-rw-r--r-- | intern/ghost/intern/GHOST_WindowX11.cpp | 449 |
1 files changed, 139 insertions, 310 deletions
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 86c940b7396..821cc1076fe 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -30,8 +30,6 @@ */ -#include <GL/glxew.h> - #include "GHOST_WindowX11.h" #include "GHOST_SystemX11.h" #include "STR_String.h" @@ -41,6 +39,14 @@ #include "GHOST_DropTargetX11.h" #endif +#if defined(WITH_GL_CONTEXT_DESKTOP) +#include "GHOST_ContextGLX.h" +#endif + +#if defined(WITH_GL_CONTEXT_EMBEDDED) +#include "GHOST_ContextEGL.h" +#endif + /* For standard X11 cursors */ #include <X11/cursorfont.h> #include <X11/Xatom.h> @@ -65,14 +71,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,132 +155,53 @@ static long BLENDER_ICON_48x48x32[] = { }; -GLXContext GHOST_WindowX11::s_firstContext = NULL; GHOST_WindowX11:: GHOST_WindowX11( - GHOST_SystemX11 *system, - Display *display, - const STR_String& title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, - GHOST_TWindowState state, - const GHOST_TEmbedderWindowID parentWindow, - GHOST_TDrawingContextType type, - const bool stereoVisual, - const bool exclusive, - const GHOST_TUns16 numOfAASamples) - : GHOST_Window(width, height, state, type, stereoVisual, exclusive, numOfAASamples), - m_context(NULL), - m_display(display), - m_normal_state(GHOST_kWindowStateNormal), - m_system(system), - m_valid_setup(false), - m_invalid_window(false), - m_empty_cursor(None), - m_custom_cursor(None), - m_visible_cursor(None) + GHOST_SystemX11 *system, + Display *display, + const STR_String& title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + const GHOST_TEmbedderWindowID parentWindow, + GHOST_TDrawingContextType type, + const bool stereoVisual, + const bool exclusive, + const GHOST_TUns16 numOfAASamples + ) : + GHOST_Window(width, height, state, stereoVisual, exclusive, numOfAASamples), + m_display(display), + m_normal_state(GHOST_kWindowStateNormal), + m_system(system), + m_valid_setup(false), + m_invalid_window(false), + m_empty_cursor(None), + 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 | - EnterWindowMask | LeaveWindowMask | - ButtonPressMask | ButtonReleaseMask | - PointerMotionMask | FocusChangeMask | - PropertyChangeMask | KeymapStateMask; + ExposureMask | StructureNotifyMask | + KeyPressMask | KeyReleaseMask | + EnterWindowMask | LeaveWindowMask | + ButtonPressMask | ButtonReleaseMask | + PointerMotionMask | FocusChangeMask | + PropertyChangeMask | KeymapStateMask ; if (exclusive) { xattributes_valuemask |= CWOverrideRedirect; @@ -292,21 +211,20 @@ 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 ); } else { - Window root_return; int x_return, y_return; unsigned int w_return, h_return, border_w_return, depth_return; @@ -314,28 +232,26 @@ GHOST_WindowX11( XGetGeometry(m_display, parentWindow, &root_return, &x_return, &y_return, &w_return, &h_return, &border_w_return, &depth_return); - left = 0; - top = 0; - width = w_return; + left = 0; + top = 0; + width = w_return; height = h_return; - 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 ); XSelectInput(m_display, parentWindow, SubstructureNotifyMask); - } #ifdef WITH_XDND @@ -460,7 +376,7 @@ 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"); } @@ -685,7 +601,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 +624,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 +968,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 +995,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 +1060,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,91 +1077,105 @@ 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_CONTEXT_DESKTOP) + +#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; - } +#elif defined(WITH_GL_CONTEXT_EMBEDDED) + +#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); +#else +#error #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; } + Cursor GHOST_WindowX11:: getStandardCursor( @@ -1530,72 +1428,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; -} |