Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/ghost/intern/GHOST_WindowX11.cpp')
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp449
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;
-}