// Returns the Visual and depth of the chosen GLXFBConfig // GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig, Visual** visual, int* depth) { GLXFBConfig native; XVisualInfo* result; if (!chooseFBConfig(fbconfig, &native)) { _glfwInputError(GLFW_FORMAT_UNAVAILABLE, "GLX: Failed to find a suitable GLXFBConfig"); return GLFW_FALSE; } result = glXGetVisualFromFBConfig(_glfw.x11.display, native); if (!result) { _glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to retrieve Visual for GLXFBConfig"); return GLFW_FALSE; } *visual = result->visual; *depth = result->depth; XFree(result); return GLFW_TRUE; }
GLXFBConfig GLXGLSupport::selectFBConfig (const int* minAttribs, const int *maxAttribs) { GLXFBConfig *fbConfigs; GLXFBConfig fbConfig = 0; int config, nConfigs = 0; fbConfigs = chooseFBConfig(minAttribs, &nConfigs); // this is a fix for cases where chooseFBConfig is not supported. // On the 10/2010 chooseFBConfig was not supported on VirtualBox // http://www.virtualbox.org/ticket/7195 if (!nConfigs) { fbConfigs = glXGetFBConfigs(mGLDisplay, DefaultScreen(mGLDisplay), &nConfigs); } if (! nConfigs) return 0; fbConfig = fbConfigs[0]; if (maxAttribs) { FBConfigAttribs maximum(maxAttribs); FBConfigAttribs best(maxAttribs); FBConfigAttribs candidate(maxAttribs); best.load(this, fbConfig); for (config = 1; config < nConfigs; config++) { candidate.load(this, fbConfigs[config]); if (candidate > maximum) continue; if (candidate > best) { fbConfig = fbConfigs[config]; best.load(this, fbConfig); } } } XFree (fbConfigs); return fbConfig; }
GLXFBConfig GLXGLSupport::getFBConfigFromVisualID(VisualID visualid) { GLXFBConfig fbConfig = 0; if (GLXEW_SGIX_fbconfig && glXGetFBConfigFromVisualSGIX) { XVisualInfo visualInfo; visualInfo.screen = DefaultScreen(mGLDisplay); visualInfo.depth = DefaultDepth(mGLDisplay, DefaultScreen(mGLDisplay)); visualInfo.visualid = visualid; fbConfig = glXGetFBConfigFromVisualSGIX(mGLDisplay, &visualInfo); } if (! fbConfig) { int minAttribs[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT || GLX_PIXMAP_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_RED_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_GREEN_SIZE, 1, None }; int nConfigs = 0; GLXFBConfig *fbConfigs = chooseFBConfig(minAttribs, &nConfigs); for (int i = 0; i < nConfigs && ! fbConfig; i++) { XVisualInfo *visualInfo = getVisualFromFBConfig(fbConfigs[i]); if (visualInfo->visualid == visualid) fbConfig = fbConfigs[i]; XFree(visualInfo); } XFree(fbConfigs); } return fbConfig; }
// Returns the Visual and depth of the chosen GLXFBConfig // static void ChooseVisualGLX(OSGLContext_glx_data* glxInfo, const FramebufferConfig& fbconfig, Visual** visual, int* depth) { GLXFBConfig native; chooseFBConfig(glxInfo, fbconfig, &native); XVisualInfo* result = glxInfo->_imp->GetVisualFromFBConfig(glxInfo->_imp->x11.display, native); if (!result) { throw std::runtime_error("GLX: Failed to retrieve Visual for GLXFBConfig"); } *visual = result->visual; *depth = result->depth; XFree(result); }
GLXFBConfig GLXGLSupport::selectFBConfig (const int* minAttribs, const int *maxAttribs) { GLXFBConfig *fbConfigs; GLXFBConfig fbConfig = 0; int config, nConfigs = 0; fbConfigs = chooseFBConfig(minAttribs, &nConfigs); if (! nConfigs) return 0; fbConfig = fbConfigs[0]; if (maxAttribs) { FBConfigAttribs maximum(maxAttribs); FBConfigAttribs best(maxAttribs); FBConfigAttribs candidate(maxAttribs); best.load(this, fbConfig); for (config = 1; config < nConfigs; config++) { candidate.load(this, fbConfigs[config]); if (candidate > maximum) continue; if (candidate > best) { fbConfig = fbConfigs[config]; best.load(this, fbConfig); } } } XFree (fbConfigs); return fbConfig; }
// Prepare for creation of the OpenGL context // int _glfwCreateContext(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWfbconfig* fbconfig) { int attribs[40]; GLXFBConfig native; GLXContext share = NULL; if (wndconfig->share) share = wndconfig->share->glx.context; if (!chooseFBConfig(fbconfig, &native)) { _glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to find a suitable GLXFBConfig"); return GL_FALSE; } // Retrieve the corresponding visual if (_glfw.glx.SGIX_fbconfig) { window->glx.visual = _glfw.glx.GetVisualFromFBConfigSGIX(_glfw.x11.display, native); } else window->glx.visual = glXGetVisualFromFBConfig(_glfw.x11.display, native); if (window->glx.visual == NULL) { _glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to retrieve visual for GLXFBConfig"); return GL_FALSE; } if (wndconfig->clientAPI == GLFW_OPENGL_ES_API) { if (!_glfw.glx.ARB_create_context || !_glfw.glx.ARB_create_context_profile || !_glfw.glx.EXT_create_context_es2_profile) { _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: OpenGL ES requested but " "GLX_EXT_create_context_es2_profile is unavailable"); return GL_FALSE; } } if (wndconfig->glForward) { if (!_glfw.glx.ARB_create_context) { _glfwInputError(GLFW_VERSION_UNAVAILABLE, "GLX: Forward compatibility requested but " "GLX_ARB_create_context_profile is unavailable"); return GL_FALSE; } } if (wndconfig->glProfile) { if (!_glfw.glx.ARB_create_context || !_glfw.glx.ARB_create_context_profile) { _glfwInputError(GLFW_VERSION_UNAVAILABLE, "GLX: An OpenGL profile requested but " "GLX_ARB_create_context_profile is unavailable"); return GL_FALSE; } } _glfwGrabXErrorHandler(); if (_glfw.glx.ARB_create_context) { int index = 0, mask = 0, flags = 0, strategy = 0; if (wndconfig->clientAPI == GLFW_OPENGL_API) { if (wndconfig->glForward) flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; if (wndconfig->glDebug) flags |= GLX_CONTEXT_DEBUG_BIT_ARB; if (wndconfig->glProfile) { if (wndconfig->glProfile == GLFW_OPENGL_CORE_PROFILE) mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB; else if (wndconfig->glProfile == GLFW_OPENGL_COMPAT_PROFILE) mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; } } else mask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT; if (wndconfig->glRobustness != GLFW_NO_ROBUSTNESS) { if (_glfw.glx.ARB_create_context_robustness) { if (wndconfig->glRobustness == GLFW_NO_RESET_NOTIFICATION) strategy = GLX_NO_RESET_NOTIFICATION_ARB; else if (wndconfig->glRobustness == GLFW_LOSE_CONTEXT_ON_RESET) strategy = GLX_LOSE_CONTEXT_ON_RESET_ARB; flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB; } } if (wndconfig->glMajor != 1 || wndconfig->glMinor != 0) { // NOTE: Only request an explicitly versioned context when // necessary, as explicitly requesting version 1.0 does not // always return the highest available version setGLXattrib(GLX_CONTEXT_MAJOR_VERSION_ARB, wndconfig->glMajor); setGLXattrib(GLX_CONTEXT_MINOR_VERSION_ARB, wndconfig->glMinor); } if (mask) setGLXattrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask); if (flags) setGLXattrib(GLX_CONTEXT_FLAGS_ARB, flags); if (strategy) setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, strategy); setGLXattrib(None, None); window->glx.context = _glfw.glx.CreateContextAttribsARB(_glfw.x11.display, native, share, True, attribs); if (window->glx.context == NULL) { // HACK: This is a fallback for the broken Mesa implementation of // GLX_ARB_create_context_profile, which fails default 1.0 // context creation with a GLXBadProfileARB error in violation // of the extension spec if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB && wndconfig->clientAPI == GLFW_OPENGL_API && wndconfig->glProfile == GLFW_OPENGL_ANY_PROFILE && wndconfig->glForward == GL_FALSE) { window->glx.context = createLegacyContext(window, native, share); } } } else window->glx.context = createLegacyContext(window, native, share); _glfwReleaseXErrorHandler(); if (window->glx.context == NULL) { _glfwInputXError(GLFW_PLATFORM_ERROR, "GLX: Failed to create context"); return GL_FALSE; } return GL_TRUE; }
// Create the OpenGL or OpenGL ES context // GLFWbool _glfwCreateContextGLX(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig) { int attribs[40]; GLXFBConfig native = NULL; GLXContext share = NULL; if (ctxconfig->share) share = ctxconfig->share->context.glx.handle; if (!chooseFBConfig(fbconfig, &native)) { _glfwInputError(GLFW_FORMAT_UNAVAILABLE, "GLX: Failed to find a suitable GLXFBConfig"); return GLFW_FALSE; } if (ctxconfig->client == GLFW_OPENGL_ES_API) { if (!_glfw.glx.ARB_create_context || !_glfw.glx.ARB_create_context_profile || !_glfw.glx.EXT_create_context_es2_profile) { _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: OpenGL ES requested but GLX_EXT_create_context_es2_profile is unavailable"); return GLFW_FALSE; } } if (ctxconfig->forward) { if (!_glfw.glx.ARB_create_context) { _glfwInputError(GLFW_VERSION_UNAVAILABLE, "GLX: Forward compatibility requested but GLX_ARB_create_context_profile is unavailable"); return GLFW_FALSE; } } if (ctxconfig->profile) { if (!_glfw.glx.ARB_create_context || !_glfw.glx.ARB_create_context_profile) { _glfwInputError(GLFW_VERSION_UNAVAILABLE, "GLX: An OpenGL profile requested but GLX_ARB_create_context_profile is unavailable"); return GLFW_FALSE; } } _glfwGrabErrorHandlerX11(); if (_glfw.glx.ARB_create_context) { int index = 0, mask = 0, flags = 0; if (ctxconfig->client == GLFW_OPENGL_API) { if (ctxconfig->forward) flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE) mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB; else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE) mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; } else mask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT; if (ctxconfig->debug) flags |= GLX_CONTEXT_DEBUG_BIT_ARB; if (ctxconfig->noerror) flags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR; if (ctxconfig->robustness) { if (_glfw.glx.ARB_create_context_robustness) { if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION) { setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, GLX_NO_RESET_NOTIFICATION_ARB); } else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET) { setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, GLX_LOSE_CONTEXT_ON_RESET_ARB); } flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB; } } if (ctxconfig->release) { if (_glfw.glx.ARB_context_flush_control) { if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE) { setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB, GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB); } else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH) { setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB, GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB); } } } // NOTE: Only request an explicitly versioned context when necessary, as // explicitly requesting version 1.0 does not always return the // highest version supported by the driver if (ctxconfig->major != 1 || ctxconfig->minor != 0) { setGLXattrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major); setGLXattrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor); } if (mask) setGLXattrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask); if (flags) setGLXattrib(GLX_CONTEXT_FLAGS_ARB, flags); setGLXattrib(None, None); window->context.glx.handle = _glfw.glx.CreateContextAttribsARB(_glfw.x11.display, native, share, True, attribs); // HACK: This is a fallback for broken versions of the Mesa // implementation of GLX_ARB_create_context_profile that fail // default 1.0 context creation with a GLXBadProfileARB error in // violation of the extension spec if (!window->context.glx.handle) { if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB && ctxconfig->client == GLFW_OPENGL_API && ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE && ctxconfig->forward == GLFW_FALSE) { window->context.glx.handle = createLegacyContext(window, native, share); } } } else window->context.glx.handle = createLegacyContext(window, native, share); _glfwReleaseErrorHandlerX11(); if (!window->context.glx.handle) { _glfwInputErrorX11(GLFW_VERSION_UNAVAILABLE, "GLX: Failed to create context"); return GLFW_FALSE; } window->context.glx.window = glXCreateWindow(_glfw.x11.display, native, window->x11.handle, NULL); if (!window->context.glx.window) { _glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to create window"); return GLFW_FALSE; } window->context.makeCurrent = makeContextCurrent; window->context.swapBuffers = swapBuffers; window->context.swapInterval = swapInterval; window->context.extensionSupported = extensionSupported; window->context.getProcAddress = getProcAddress; window->context.destroy = destroyContext; return GLFW_TRUE; }
int main(int argc, char* argv[]) { Display *display = XOpenDisplay(NULL); if (!display) fail("Failed to open X display\n"); checkGlxVersion(display); auto bestFbc = chooseFBConfig(display); // Get a visual XVisualInfo *vi = glXGetVisualFromFBConfig(display, bestFbc); printf("Chosen visual ID = 0x%lx\n", vi->visualid); printf("Creating colormap\n"); XSetWindowAttributes swa; Colormap cmap; swa.colormap = cmap = XCreateColormap(display, RootWindow(display, vi->screen), vi->visual, AllocNone); swa.background_pixmap = None ; swa.border_pixel = 0; swa.event_mask = StructureNotifyMask; printf("Creating window\n"); Window win = XCreateWindow(display, RootWindow(display, vi->screen), 0, 0, 100, 100, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel|CWColormap|CWEventMask, &swa); if (!win) fail("Failed to create window.\n"); // Done with the visual info data XFree(vi); XStoreName(display, win, "GL 3.0 Window"); printf("Mapping window\n"); XMapWindow(display, win); auto context = createContext(display, bestFbc); printf("Making context current\n"); glXMakeCurrent(display, win, context); initGlew(); GLuint tex_; GLuint fbo_; glGenTextures(1, &tex_); glBindTexture(GL_TEXTURE_2D, tex_); glGenFramebuffers(1, &fbo_); glBindFramebuffer(GL_FRAMEBUFFER, fbo_); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_, 0); printGlErrors(); glBindTexture(GL_TEXTURE_2D, tex_); glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2); char source_pixels[16] = { 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4 }; printGlErrors(); printf("Crash here\n"); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, source_pixels); printf("Crashed :( \n"); printGlErrors(); glCheckFramebufferStatus(GL_FRAMEBUFFER); char pixels[16] = {0}; glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glCheckFramebufferStatus(GL_FRAMEBUFFER); printGlErrors(); glXMakeCurrent(display, 0, 0); glXDestroyContext(display, context); XDestroyWindow(display, win); XFreeColormap(display, cmap); XCloseDisplay(display); printf("Test success\n"); return 0; }
//-------------------------------------------------------------------------------------------------// GLXGLSupport::GLXGLSupport() : mGLDisplay(0), mXDisplay(0) { // A connection that might be shared with the application for GL rendering: mGLDisplay = getGLDisplay(); // A connection that is NOT shared to enable independent event processing: mXDisplay = getXDisplay(); int dummy; if (XQueryExtension(mXDisplay, "RANDR", &dummy, &dummy, &dummy)) { XRRScreenConfiguration *screenConfig; screenConfig = XRRGetScreenInfo(mXDisplay, DefaultRootWindow(mXDisplay)); if (screenConfig) { XRRScreenSize *screenSizes; int nSizes = 0; Rotation currentRotation; int currentSizeID = XRRConfigCurrentConfiguration(screenConfig, ¤tRotation); screenSizes = XRRConfigSizes(screenConfig, &nSizes); mCurrentMode.first.first = screenSizes[currentSizeID].width; mCurrentMode.first.second = screenSizes[currentSizeID].height; mCurrentMode.second = XRRConfigCurrentRate(screenConfig); mOriginalMode = mCurrentMode; for(int sizeID = 0; sizeID < nSizes; sizeID++) { short *rates; int nRates = 0; rates = XRRConfigRates(screenConfig, sizeID, &nRates); for (int rate = 0; rate < nRates; rate++) { VideoMode mode; mode.first.first = screenSizes[sizeID].width; mode.first.second = screenSizes[sizeID].height; mode.second = rates[rate]; mVideoModes.push_back(mode); } } XRRFreeScreenConfigInfo(screenConfig); } } else { mCurrentMode.first.first = DisplayWidth(mXDisplay, DefaultScreen(mXDisplay)); mCurrentMode.first.second = DisplayHeight(mXDisplay, DefaultScreen(mXDisplay)); mCurrentMode.second = 0; mOriginalMode = mCurrentMode; mVideoModes.push_back(mCurrentMode); } GLXFBConfig *fbConfigs; int config, nConfigs = 0; fbConfigs = chooseFBConfig(NULL, &nConfigs); for (config = 0; config < nConfigs; config++) { int caveat, samples; getFBConfigAttrib (fbConfigs[config], GLX_CONFIG_CAVEAT, &caveat); if (caveat != GLX_SLOW_CONFIG) { getFBConfigAttrib (fbConfigs[config], GLX_SAMPLES, &samples); mSampleLevels.push_back(StringConverter::toString(samples)); } } XFree (fbConfigs); remove_duplicates(mSampleLevels); }
void OSGLContext_x11Private::createContextGLX(OSGLContext_glx_data* glxInfo, const FramebufferConfig& fbconfig, int /*major*/, int /*minor*/, bool coreProfile, int rendererID, const OSGLContext_x11* shareContext) { GLXFBConfig native = NULL; GLXContext share = shareContext ? shareContext->_imp->glxContextHandle : 0; chooseFBConfig(glxInfo, fbconfig, &native); GrabErrorHandlerX11(); if (!glxInfo->_imp->ARB_create_context) { glxContextHandle = createLegacyContext(glxInfo, native, share); } else { std::vector<int> attribs; int mask = 0, flags = 0; /*if (ctxconfig->forward) flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;*/ if (coreProfile) { mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB; } else { mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; } // Note that we do NOT request a specific version. Sometimes a driver might report that its maximum compatibility //profile is 3.0 but we ask for 2.0, hence it will fail context creation whereas it should not. Instead we check //OpenGL version once context is created and check that we have at least 2.0 /*if ( (major != 1) || (minor != 0) ) { setGLXattrib(GLX_CONTEXT_MAJOR_VERSION_ARB, major); setGLXattrib(GLX_CONTEXT_MINOR_VERSION_ARB, minor); }*/ if (mask) { setGLXattrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask); } if (flags) { setGLXattrib(GLX_CONTEXT_FLAGS_ARB, flags); } if ( glxInfo->_imp->MESA_query_renderer && (rendererID != -1) && (rendererID != 0) ) { setGLXattrib(GLX_RENDERER_ID_MESA, rendererID); } setGLXattrib(None, None); glxContextHandle = glxInfo->_imp->CreateContextAttribsARB(glxInfo->_imp->x11.display, native, share, True /*direct*/, &attribs[0]); // HACK: This is a fallback for broken versions of the Mesa // implementation of GLX_ARB_create_context_profile that fail // default 1.0 context creation with a GLXBadProfileARB error in // violation of the extension spec if (!glxContextHandle) { if (gX11ErrorCode == glxInfo->_imp->errorBase + GLXBadProfileARB /*&& ctxconfig->client == GLFW_OPENGL_API && ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE && ctxconfig->forward == GLFW_FALSE*/) { glxContextHandle = createLegacyContext(glxInfo, native, share); } } } ReleaseErrorHandlerX11(glxInfo); if (!glxContextHandle) { throw std::runtime_error("GLX: Failed to create context"); } glxWindowHandle = glxInfo->_imp->CreateWindow(glxInfo->_imp->x11.display, native, x11Window.handle, NULL); if (!glxWindowHandle) { glxInfo->_imp->DestroyContext(glxInfo->_imp->x11.display, glxContextHandle); glxContextHandle = 0; throw std::runtime_error("GLX: Failed to create window"); } if ( !glxInfo->_imp->IsDirect(glxInfo->_imp->x11.display, glxContextHandle) ) { glxInfo->_imp->DestroyContext(glxInfo->_imp->x11.display, glxContextHandle); glxContextHandle = 0; glxInfo->_imp->DestroyWindow(glxInfo->_imp->x11.display, glxWindowHandle); glxWindowHandle = 0; throw std::runtime_error("GLX: Created context is not doing direct rendering"); } /*_window = glxInfo->CreateWindow(glxInfo->display, native, window->x11.handle, NULL); if (!_window) { throw std::runtime_error("GLX: Failed to create window"); }*/ } // createContextGLX