void Window::setXDrawable( XID drawable ) { if( _xDrawable == drawable ) return; if( _xDrawable ) exitEventHandler(); _xDrawable = drawable; if( !drawable ) return; initEventHandler(); // query pixel viewport of window EQASSERT( _xDisplay ); switch( getIAttribute( eq::Window::IATTR_HINT_DRAWABLE )) { case PBUFFER: { unsigned width = 0; unsigned height = 0; glXQueryDrawable( _xDisplay, drawable, GLX_WIDTH, &width ); glXQueryDrawable( _xDisplay, drawable, GLX_HEIGHT, &height ); getWindow()->setPixelViewport( PixelViewport( 0, 0, int32_t( width ), int32_t( height ))); break; } case WINDOW: { XWindowAttributes wa; XGetWindowAttributes( _xDisplay, drawable, &wa ); // position is relative to parent: translate to absolute coords ::Window root, parent, *children; unsigned nChildren; XQueryTree( _xDisplay, drawable, &root, &parent, &children, &nChildren ); if( children != 0 ) XFree( children ); int x,y; ::Window childReturn; XTranslateCoordinates( _xDisplay, parent, root, wa.x, wa.y, &x, &y, &childReturn ); getWindow()->setPixelViewport( PixelViewport( x, y, wa.width, wa.height )); break; } default: EQUNIMPLEMENTED; case FBO: EQASSERT( getWindow()->getPixelViewport().hasArea( )); } }
//----------------------------------------------------------------------------// void OpenGLGLXPBTextureTarget::initialisePBuffer() { int creation_attrs[] = { GLX_PBUFFER_WIDTH, d_area.getWidth(), GLX_PBUFFER_HEIGHT, d_area.getHeight(), GLX_LARGEST_PBUFFER, True, GLX_PRESERVED_CONTENTS, True, None }; // release any existing pbuffer if (d_pbuffer) glXDestroyPbuffer(d_dpy, d_pbuffer); d_pbuffer = glXCreatePbuffer(d_dpy, d_fbconfig, creation_attrs); if (!d_pbuffer) throw RendererException("OpenGLGLXPBTextureTarget::initialisePBuffer - " "pbuffer creation error: glXCreatePbuffer() failed"); // get the real size of the buffer that was created GLuint actual_width, actual_height; glXQueryDrawable(d_dpy, d_pbuffer, GLX_WIDTH, &actual_width); glXQueryDrawable(d_dpy, d_pbuffer, GLX_HEIGHT, &actual_height); d_area.setSize(Size(actual_width, actual_height)); // ensure CEGUI::Texture is wrapping real GL texture and has correct size d_CEGUITexture->setOpenGLTexture(d_texture, d_area.getSize()); }
void TopCanvas::CreateGLX(_XDisplay *_x_display, X11Window x_window, GLXFBConfig *fb_cfg) { x_display = _x_display; glx_context = glXCreateNewContext(_x_display, *fb_cfg, GLX_RGBA_TYPE, nullptr, true); if (glx_context == nullptr) { fprintf(stderr, "Failed to create GLX context\n"); exit(EXIT_FAILURE); } glx_window = glXCreateWindow(_x_display, *fb_cfg, x_window, nullptr); XSync(x_display, false); if (!glXMakeContextCurrent(_x_display, glx_window, glx_window, glx_context)) { fprintf(stderr, "Failed to attach GLX context to GLX window\n"); exit(EXIT_FAILURE); } unsigned int glx_width = -1, glx_height = -1; glXQueryDrawable(_x_display, glx_window, GLX_WIDTH, &glx_width); glXQueryDrawable(_x_display, glx_window, GLX_HEIGHT, &glx_height); if ((glx_width <= 0) || (glx_height <= 0)) { fprintf(stderr, "Failed to query GLX drawable size\n"); exit(EXIT_FAILURE); } const PixelSize effective_size = { glx_width, glx_height }; OpenGL::SetupContext(); OpenGL::SetupViewport(UnsignedPoint2D(effective_size.cx, effective_size.cy)); Canvas::Create(effective_size); }
void add(Window w) { XWindowAttributes attr; int i; if (w == root || w == overlay || w == canvas-1) return; debug("[AddWindow] Adding window 0x%x\n", w); if (workspace == NULL) { workspace = malloc(sizeof(Client) * MAX_CLIENTS); memset(workspace, 0, sizeof(Client) * MAX_CLIENTS); } for (i=0; i<MAX_CLIENTS && workspace[i].window != 0; i++) if (workspace[i].window == 0) break; unsigned int v; int target; GLuint texture; GLXFBConfig fbc = choose_fbconfig(); Pixmap pixmap = XCompositeNameWindowPixmap(dpy, w); debug("Got pixmap 0x%x for 0x%x\n", pixmap, w); XGetWindowAttributes(dpy, w, &attr); if (attr.depth == 32) pixmap_attr[1] = GLX_TEXTURE_FORMAT_RGBA_EXT; else pixmap_attr[1] = GLX_TEXTURE_FORMAT_RGB_EXT; GLXPixmap glxpixmap = glXCreatePixmap(dpy, fbc, pixmap, pixmap_attr); debug("Got glxpixmap 0x%x for 0x%x\n", glxpixmap, pixmap); check_gl(__LINE__); glXQueryDrawable(dpy, glxpixmap, GLX_WIDTH, &v); check_gl(__LINE__); debug("GLX is %d width\n", v); glXQueryDrawable(dpy, glxpixmap, GLX_HEIGHT, &v); check_gl(__LINE__); debug("GLX is %d height\n", v); glXQueryDrawableProc(dpy, glxpixmap, GLX_TEXTURE_TARGET_EXT, &target); check_gl(__LINE__); debug("GLX is 0x%x\n", target); glGenTextures(1, &texture); check_gl(__LINE__); switch (target) { case GLX_TEXTURE_2D_EXT: warn("GLX_TEXTURE_2D_EXT requested but we don't support that yet\n"); target = GL_TEXTURE_2D; break; case GLX_TEXTURE_RECTANGLE_EXT: target = GL_TEXTURE_RECTANGLE_ARB; break; default: die(ERR_INVALID_TEXTURE, "Invalid target: 0x%x\n", target); } info("Window 0x%x has glx = %x, target 0x%x and texture %d\n", w, glxpixmap, target, texture); workspace[i].window = w; workspace[i].glxpixmap = glxpixmap; workspace[i].target = target; workspace[i].texture = texture; XGetWindowAttributes(dpy, w, &(workspace[i].geom)); }
enum piglit_result draw(Display *dpy) { GLXContext ctx; bool pass = true; unsigned int age; int i; static GLfloat colors[5][4] = { {1.0, 0.0, 0.0, 1.0}, {0.0, 1.0, 0.0, 1.0}, {0.0, 0.0, 1.0, 1.0}, {1.0, 0.0, 1.0, 1.0}, {0.0, 1.0, 1.0, 1.0} }; ctx = piglit_get_glx_context(dpy, visinfo); glXMakeCurrent(dpy, window, ctx); piglit_dispatch_default_init(PIGLIT_DISPATCH_GL); glXQueryDrawable(dpy, window, GLX_BACK_BUFFER_AGE_EXT, &age); if (age != 0) { fprintf(stderr, "Initial age was %d, should be 0\n", age); pass = false; } for (i = 0; i < 5; i++) { glClearColor(colors[i][0], colors[i][1], colors[i][2], colors[i][3]); glClear(GL_COLOR_BUFFER_BIT); glXSwapBuffers(dpy, window); glXQueryDrawable(dpy, window, GLX_BACK_BUFFER_AGE_EXT, &age); printf("Frame %d: age %d\n", i + 1, age); if (age > 0) { int color_i = i - (age - 1); if (color_i < 0) { fprintf(stderr, "too old\n"); pass = false; } else { pass = piglit_probe_rect_rgba(0, 0, piglit_width, piglit_height, colors[color_i]) && pass; } } } glXMakeCurrent(dpy, None, NULL); glXDestroyContext(dpy, ctx); return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
PixelSize TopCanvas::GetNativeSize() const { unsigned w = 0, h = 0; glXQueryDrawable(x_display, glx_window, GLX_WIDTH, &w); glXQueryDrawable(x_display, glx_window, GLX_HEIGHT, &h); if (w <= 0 || h <= 0) return PixelSize(0, 0); return PixelSize(w, h); }
void XCompositeGLXClientBufferIntegration::bindTextureToBuffer(struct ::wl_resource *buffer) { XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(buffer); Pixmap pixmap = XCompositeNameWindowPixmap(mDisplay, compositorBuffer->window()); QVector<int> glxConfigSpec = qglx_buildSpec(); int numberOfConfigs; GLXFBConfig *configs = glXChooseFBConfig(mDisplay,mScreen,glxConfigSpec.constData(),&numberOfConfigs); QVector<int> attribList; attribList.append(GLX_TEXTURE_FORMAT_EXT); attribList.append(GLX_TEXTURE_FORMAT_RGB_EXT); attribList.append(GLX_TEXTURE_TARGET_EXT); attribList.append(GLX_TEXTURE_2D_EXT); attribList.append(0); GLXPixmap glxPixmap = glXCreatePixmap(mDisplay,*configs,pixmap,attribList.constData()); uint inverted = 0; glXQueryDrawable(mDisplay, glxPixmap, GLX_Y_INVERTED_EXT,&inverted); compositorBuffer->setInvertedY(!inverted); XFree(configs); m_glxBindTexImageEXT(mDisplay,glxPixmap,GLX_FRONT_EXT, 0); //Do we need to change the api so that we do bind and release in the painevent? //The specification states that when deleting the texture the color buffer is deleted // m_glxReleaseTexImageEXT(mDisplay,glxPixmap,GLX_FRONT_EXT); }
unsigned int WineWindow::get_height() const { unsigned int result; glXQueryDrawable(m_xdpy, m_xdrawable, GLX_HEIGHT, &result); return result; }
unsigned int WineWindow::get_width() const { unsigned int result; glXQueryDrawable(m_xdpy, m_xdrawable, GLX_WIDTH, &result); return result; }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GLX13_nglXQueryDrawable(JNIEnv *__env, jclass clazz, jlong displayAddress, jlong drawAddress, jint attribute, jlong valueAddress, jlong __functionAddress) { Display *display = (Display *)(intptr_t)displayAddress; GLXDrawable draw = (GLXDrawable)(intptr_t)drawAddress; unsigned int *value = (unsigned int *)(intptr_t)valueAddress; glXQueryDrawablePROC glXQueryDrawable = (glXQueryDrawablePROC)(intptr_t)__functionAddress; UNUSED_PARAMS(__env, clazz) glXQueryDrawable(display, draw, attribute, value); }
void GlxBackend::present() { if (lastDamage().isEmpty()) return; const QSize &screenSize = screens()->size(); const QRegion displayRegion(0, 0, screenSize.width(), screenSize.height()); const bool fullRepaint = supportsBufferAge() || (lastDamage() == displayRegion); if (fullRepaint) { if (m_haveINTELSwapEvent) Compositor::self()->aboutToSwapBuffers(); if (haveSwapInterval) { if (gs_tripleBufferNeedsDetection) { glXWaitGL(); m_swapProfiler.begin(); } glXSwapBuffers(display(), glxWindow); if (gs_tripleBufferNeedsDetection) { glXWaitGL(); if (char result = m_swapProfiler.end()) { gs_tripleBufferUndetected = gs_tripleBufferNeedsDetection = false; if (result == 'd' && GLPlatform::instance()->driver() == Driver_NVidia) { // TODO this is a workaround, we should get __GL_YIELD set before libGL checks it if (qstrcmp(qgetenv("__GL_YIELD"), "USLEEP")) { options->setGlPreferBufferSwap(0); setSwapInterval(0); result = 0; // hint proper behavior qCWarning(KWIN_CORE) << "\nIt seems you are using the nvidia driver without triple buffering\n" "You must export __GL_YIELD=\"USLEEP\" to prevent large CPU overhead on synced swaps\n" "Preferably, enable the TripleBuffer Option in the xorg.conf Device\n" "For this reason, the tearing prevention has been disabled.\n" "See https://bugs.kde.org/show_bug.cgi?id=322060\n"; } } setBlocksForRetrace(result == 'd'); } } else if (blocksForRetrace()) { // at least the nvidia blob manages to swap async, ie. return immediately on double // buffering - what messes our timing calculation and leads to laggy behavior #346275 glXWaitGL(); } } else { waitSync(); glXSwapBuffers(display(), glxWindow); } if (supportsBufferAge()) { glXQueryDrawable(display(), glxWindow, GLX_BACK_BUFFER_AGE_EXT, (GLuint *) &m_bufferAge); } } else if (m_haveMESACopySubBuffer) { foreach (const QRect & r, lastDamage().rects()) { // convert to OpenGL coordinates int y = screenSize.height() - r.y() - r.height(); glXCopySubBufferMESA(display(), glxWindow, r.x(), y, r.width(), r.height()); } } else { // Copy Pixels (horribly slow on Mesa)
GLXFBConfig GLXGLSupport::getFBConfigFromDrawable(GLXDrawable drawable, unsigned int *width, unsigned int *height) { GLXFBConfig fbConfig = 0; if (GLXEW_VERSION_1_3) { int fbConfigAttrib[] = { GLX_FBCONFIG_ID, 0, None }; GLXFBConfig *fbConfigs; int nElements = 0; glXQueryDrawable (mGLDisplay, drawable, GLX_FBCONFIG_ID, (unsigned int*)&fbConfigAttrib[1]); fbConfigs = glXChooseFBConfig(mGLDisplay, DefaultScreen(mGLDisplay), fbConfigAttrib, &nElements); if (nElements) { fbConfig = fbConfigs[0]; XFree (fbConfigs); glXQueryDrawable(mGLDisplay, drawable, GLX_WIDTH, width); glXQueryDrawable(mGLDisplay, drawable, GLX_HEIGHT, height); } } if (! fbConfig && GLXEW_SGIX_fbconfig) { XWindowAttributes windowAttrib; if (XGetWindowAttributes(mGLDisplay, drawable, &windowAttrib)) { VisualID visualid = XVisualIDFromVisual(windowAttrib.visual); fbConfig = getFBConfigFromVisualID(visualid); *width = windowAttrib.width; *height = windowAttrib.height; } } return fbConfig; }
/** * Attempt to determine whether or not the display is synched to vblank. */ static void query_vsync(Display *dpy, GLXDrawable drawable) { int interval = 0; #if defined(GLX_EXT_swap_control) if (is_glx_extension_supported(dpy, "GLX_EXT_swap_control")) { PFNGLXSWAPINTERVALEXTPROC pglXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddressARB((const GLubyte *) "glXSwapIntervalEXT"); unsigned int tmp = -1; if (swapinterval >= 1) (*pglXSwapIntervalEXT)(dpy, drawable, swapinterval); glXQueryDrawable(dpy, drawable, GLX_SWAP_INTERVAL_EXT, &tmp); interval = tmp; } else #endif if (is_glx_extension_supported(dpy, "GLX_MESA_swap_control")) { PFNGLXGETSWAPINTERVALMESAPROC pglXGetSwapIntervalMESA = (PFNGLXGETSWAPINTERVALMESAPROC) glXGetProcAddressARB((const GLubyte *) "glXGetSwapIntervalMESA"); if (swapinterval >= 1) { PFNGLXSWAPINTERVALMESAPROC pglXSwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC) glXGetProcAddressARB((const GLubyte *) "glXSwapIntervalMESA"); (*pglXSwapIntervalMESA)(swapinterval); } interval = (*pglXGetSwapIntervalMESA)(); } else if (is_glx_extension_supported(dpy, "GLX_SGI_swap_control")) { /* The default swap interval with this extension is 0. Assume that it * is set to the default unless it was overridden on the command line. */ interval = 0; if (swapinterval >= 1) { PFNGLXSWAPINTERVALSGIPROC pglXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) glXGetProcAddressARB((const GLubyte *) "glXSwapIntervalSGI"); (*pglXSwapIntervalSGI)(swapinterval); interval = swapinterval; } } if (interval > 0) { printf("Running synchronized to the vertical refresh. The framerate should be\n"); if (interval == 1) { printf("approximately the same as the monitor refresh rate.\n"); } else if (interval > 1) { printf("approximately 1/%d the monitor refresh rate.\n", interval); } } }
void GlxBackend::present() { if (lastDamage().isEmpty()) return; const QRegion displayRegion(0, 0, displayWidth(), displayHeight()); const bool fullRepaint = supportsBufferAge() || (lastDamage() == displayRegion); if (fullRepaint) { if (haveSwapInterval) { if (gs_tripleBufferNeedsDetection) { glXWaitGL(); m_swapProfiler.begin(); } glXSwapBuffers(display(), glxWindow); if (gs_tripleBufferNeedsDetection) { glXWaitGL(); if (char result = m_swapProfiler.end()) { gs_tripleBufferUndetected = gs_tripleBufferNeedsDetection = false; if (result == 'd' && GLPlatform::instance()->driver() == Driver_NVidia) { // TODO this is a workaround, we should get __GL_YIELD set before libGL checks it if (qstrcmp(qgetenv("__GL_YIELD"), "USLEEP")) { options->setGlPreferBufferSwap(0); setSwapInterval(0); qWarning() << "\nIt seems you are using the nvidia driver without triple buffering\n" "You must export __GL_YIELD=\"USLEEP\" to prevent large CPU overhead on synced swaps\n" "Preferably, enable the TripleBuffer Option in the xorg.conf Device\n" "For this reason, the tearing prevention has been disabled.\n" "See https://bugs.kde.org/show_bug.cgi?id=322060\n"; } } setBlocksForRetrace(result == 'd'); } } } else { waitSync(); glXSwapBuffers(display(), glxWindow); } if (supportsBufferAge()) { glXQueryDrawable(display(), glxWindow, GLX_BACK_BUFFER_AGE_EXT, (GLuint *) &m_bufferAge); } } else if (glXCopySubBuffer) { foreach (const QRect & r, lastDamage().rects()) { // convert to OpenGL coordinates int y = displayHeight() - r.y() - r.height(); glXCopySubBuffer(display(), glxWindow, r.x(), y, r.width(), r.height()); } } else { // Copy Pixels (horribly slow on Mesa)
static void query_bad_drawable(Display *display, GLXDrawable draw) { unsigned int width; (void) draw; XSetErrorHandler(expect_glxbaddrawable); glXQueryDrawable(display, 0, GLX_WIDTH, &width); XSync(display, 0); if (!found_error_glxbaddrawable) { fprintf(stderr, "error: glXQueryDrawable(draw=0) did not generate " "GLXBadDrawable\n"); piglit_report_result(PIGLIT_FAIL); } piglit_report_result(PIGLIT_PASS); }
static void query_width(Display *display, GLXDrawable draw) { unsigned int width = 0; XSetErrorHandler(expect_no_error); glXQueryDrawable(display, draw, GLX_WIDTH, &width); /* Sync before checking width in order to catch X errors. */ XSync(display, 0); if (width != piglit_width) { fprintf(stderr, "error: width=%d but glXQueryDrawable returned %d\n", piglit_width, width); piglit_report_result(PIGLIT_FAIL); } piglit_report_result(PIGLIT_PASS); }
int iface::vsync_interval() const { if (glXGetProcAddress((GLubyte const*)"glXSwapIntervalEXT")) { unsigned int interval; glXQueryDrawable(gui::g_display, window_, GLX_SWAP_INTERVAL_EXT, &interval); return interval; } typedef int(*glXGetSwapIntervalMESA_fun)(); glXGetSwapIntervalMESA_fun glXGetSwapIntervalMESA = (glXGetSwapIntervalMESA_fun)glXGetProcAddress((GLubyte const*)"glXGetSwapIntervalMESA"); if (glXGetSwapIntervalMESA) { return glXGetSwapIntervalMESA(); } return 0; }
static void query_height(Display *display, GLXDrawable draw) { unsigned int height = 0; XSetErrorHandler(expect_no_error); glXQueryDrawable(display, draw, GLX_HEIGHT, &height); /* Sync before checking height in order to catch X errors. */ XSync(display, 0); if (height != piglit_height) { fprintf(stderr, "error: height=%d but glXQueryDrawable returned %d\n", piglit_height, height); piglit_report_result(PIGLIT_FAIL); } piglit_report_result(PIGLIT_PASS); }
void createPixmap(uint32_t winId) { XWindowAttributes attr; XGetWindowAttributes(m_display, winId, &attr); XRenderPictFormat* format = XRenderFindVisualFormat(m_display, attr.visual); m_hasAlpha = (format->type == PictTypeDirect && format->direct.alphaMask); m_size = IntSize(attr.width, attr.height); int numberOfConfigs; GLXFBConfig* configs = glXChooseFBConfig(m_display, XDefaultScreen(m_display), glxSpec, &numberOfConfigs); m_xPixmap = XCompositeNameWindowPixmap(m_display, winId); m_glxPixmap = glXCreatePixmap(m_display, *configs, m_xPixmap, glxAttributes); uint inverted = 0; glXQueryDrawable(m_display, m_glxPixmap, GLX_Y_INVERTED_EXT, &inverted); m_textureIsYInverted = !!inverted; XFree(configs); }
/** * Attempt to determine whether or not the display is synched to vblank. */ static void query_vsync(Display *dpy, GLXDrawable drawable) { int interval = 0; #if defined(GLX_EXT_swap_control) if (is_glx_extension_supported(dpy, "GLX_EXT_swap_control")) { unsigned int tmp = -1; glXQueryDrawable(dpy, drawable, GLX_SWAP_INTERVAL_EXT, &tmp); interval = tmp; } else #endif if (is_glx_extension_supported(dpy, "GLX_MESA_swap_control")) { PFNGLXGETSWAPINTERVALMESAPROC pglXGetSwapIntervalMESA = (PFNGLXGETSWAPINTERVALMESAPROC) glXGetProcAddressARB((const GLubyte *) "glXGetSwapIntervalMESA"); interval = (*pglXGetSwapIntervalMESA)(); } else if (is_glx_extension_supported(dpy, "GLX_SGI_swap_control")) { /* The default swap interval with this extension is 1. Assume that it * is set to the default. * * Many Mesa-based drivers default to 0, but all of these drivers also * export GLX_MESA_swap_control. In that case, this branch will never * be taken, and the correct result should be reported. */ interval = 1; } if (interval > 0) { printf("Running synchronized to the vertical refresh. The framerate should be\n"); if (interval == 1) { printf("approximately the same as the monitor refresh rate.\n"); } else if (interval > 1) { printf("approximately 1/%d the monitor refresh rate.\n", interval); } } }
void createPixmap(uint32_t winId) { XWindowAttributes attr; XGetWindowAttributes(m_display, winId, &attr); XRenderPictFormat* format = XRenderFindVisualFormat(m_display, attr.visual); m_hasAlpha = (format->type == PictTypeDirect && format->direct.alphaMask); int numberOfConfigs; GLXFBConfig* configs = glXChooseFBConfig(m_display, XDefaultScreen(m_display), glxSpec, &numberOfConfigs); // If origin window has alpha then find config with alpha. GLXFBConfig& config = m_hasAlpha ? findFBConfigWithAlpha(configs, numberOfConfigs) : configs[0]; m_xPixmap = XCompositeNameWindowPixmap(m_display, winId); m_glxPixmap = glXCreatePixmap(m_display, config, m_xPixmap, glxAttributes); uint inverted = 0; glXQueryDrawable(m_display, m_glxPixmap, GLX_Y_INVERTED_EXT, &inverted); m_textureIsYInverted = !!inverted; XFree(configs); }
void Window::setXDrawable( XID drawable ) { LBASSERT( _impl->xDisplay ); if( _impl->xDrawable == drawable ) return; if( _impl->xDrawable ) exitEventHandler(); _impl->xDrawable = drawable; if( !drawable ) return; const int32_t drawableType = getIAttribute( IATTR_HINT_DRAWABLE ); if( drawableType != OFF ) initEventHandler(); // query pixel viewport of window switch( drawableType ) { case PBUFFER: { unsigned width = 0; unsigned height = 0; glXQueryDrawable( _impl->xDisplay, drawable, GLX_WIDTH, &width ); glXQueryDrawable( _impl->xDisplay, drawable, GLX_HEIGHT, &height ); setPixelViewport( PixelViewport( 0, 0, int32_t( width ), int32_t( height ))); break; } case WINDOW: case AUTO: case UNDEFINED: { XWindowAttributes wa; XGetWindowAttributes( _impl->xDisplay, drawable, &wa ); // position is relative to parent: translate to absolute coords ::Window root, parent, *children; unsigned nChildren; XQueryTree( _impl->xDisplay, drawable, &root, &parent, &children, &nChildren ); if( children != 0 ) XFree( children ); int x,y; ::Window childReturn; XTranslateCoordinates( _impl->xDisplay, parent, root, wa.x, wa.y, &x, &y, &childReturn ); setPixelViewport( PixelViewport( x, y, wa.width, wa.height )); break; } default: LBERROR << "Unknown drawable type " << drawableType << std::endl; LBUNIMPLEMENTED; case OFF: case FBO: LBASSERT( getPixelViewport().hasArea( )); } }
//-------------------------------------------------------------------------------------------------// GLXPBuffer::GLXPBuffer(GLXGLSupport* glsupport, PixelComponentType format, size_t width, size_t height): mGLSupport(glsupport), GLPBuffer(format, width, height), mContext(0) { Display *glDisplay = mGLSupport->getGLDisplay(); ::GLXDrawable glxDrawable = 0; ::GLXFBConfig fbConfig = 0; bool isFloat = false; int bits = 0; switch (mFormat) { case PCT_BYTE: bits = 8; break; case PCT_SHORT: bits = 16; break; case PCT_FLOAT16: bits = 16; break; case PCT_FLOAT32: bits = 32; break; default: break; } int renderAttrib = GLX_RENDER_TYPE; int renderValue = GLX_RGBA_BIT; if (mFormat == PCT_FLOAT16 || mFormat == PCT_FLOAT32) { if (GLXEW_NV_float_buffer) { renderAttrib = GLX_FLOAT_COMPONENTS_NV; renderValue = GL_TRUE; } if (GLXEW_ATI_pixel_format_float) { renderAttrib = GLX_RENDER_TYPE; renderValue = GLX_RGBA_FLOAT_ATI_BIT; } if (GLXEW_ARB_fbconfig_float) { renderAttrib = GLX_RENDER_TYPE; renderValue = GLX_RGBA_FLOAT_BIT; } if (renderAttrib == GLX_RENDER_TYPE && renderValue == GLX_RGBA_BIT) { OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, "No support for Floating point PBuffers", "GLRenderTexture::createPBuffer"); } } int minAttribs[] = { GLX_DRAWABLE_TYPE, GLX_PBUFFER, renderAttrib, renderValue, GLX_DOUBLEBUFFER, 0, None }; int maxAttribs[] = { GLX_RED_SIZE, bits, GLX_GREEN_SIZE, bits, GLX_BLUE_SIZE, bits, GLX_ALPHA_SIZE, bits, GLX_STENCIL_SIZE, INT_MAX, None }; int pBufferAttribs[] = { GLX_PBUFFER_WIDTH, mWidth, GLX_PBUFFER_HEIGHT, mHeight, GLX_PRESERVED_CONTENTS, GL_TRUE, None }; fbConfig = mGLSupport->selectFBConfig(minAttribs, maxAttribs); glxDrawable = glXCreatePbuffer(glDisplay, fbConfig, pBufferAttribs); if (! fbConfig || ! glxDrawable) { OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to create Pbuffer", "GLXPBuffer::GLXPBuffer"); } GLint fbConfigID; GLuint iWidth, iHeight; glXGetFBConfigAttrib(glDisplay, fbConfig, GLX_FBCONFIG_ID, &fbConfigID); glXQueryDrawable(glDisplay, glxDrawable, GLX_WIDTH, &iWidth); glXQueryDrawable(glDisplay, glxDrawable, GLX_HEIGHT, &iHeight); mWidth = iWidth; mHeight = iHeight; LogManager::getSingleton().logMessage(LML_NORMAL, "GLXPBuffer::create used final dimensions " + StringConverter::toString(mWidth) + " x " + StringConverter::toString(mHeight)); LogManager::getSingleton().logMessage("GLXPBuffer::create used FBConfigID " + StringConverter::toString(fbConfigID)); mContext = new GLXContext(mGLSupport, fbConfig, glxDrawable); }
void PBuffer::initialise() { /// Smaller dimensions are not sane if(mWidth < 64) mWidth = 64; if(mHeight < 64) mHeight = 64; Display *dpy = GLEngine::getInstance().getDisplay(); GLXContext context = GLEngine::getInstance().getSharedContext(); int screen = DefaultScreen(dpy); /// Find out which extension to use for floating point /// Possible floating point extensions, in order of preference #define RTF_NONE 0 #define RTF_NV 1 /** GLX_NV_float_buffer */ #define RTF_ATI 2 /** GLX_ATI_pixel_format_float */ #define RTF_ARB 3 /** GLX_ARB_fbconfig_float */ int floatBuffer = RTF_NONE; if(mIsFloat) { /// Query supported float buffer extensions /// Choose the best one std::stringstream ext; std::string instr; ext << glXQueryExtensionsString(dpy, screen) << " " << glXGetClientString(dpy, GLX_EXTENSIONS); while(ext >> instr) { if(instr == "GLX_NV_float_buffer" && floatBuffer<RTF_NV) floatBuffer = RTF_NV; if(instr == "GLX_ATI_pixel_format_float" && floatBuffer<RTF_ATI) floatBuffer = RTF_ATI; if(instr == "GLX_ARB_fbconfig_float" && floatBuffer<RTF_ARB) floatBuffer = RTF_ARB; } if(floatBuffer == RTF_NONE) { GPGPU_EXCEPT(ERR_RENDERSYSTEM, "Floating point rendertargets not supported on this hardware"); } } /// Make the buffer int attribs[50]; int attrib = 0; if (floatBuffer == RTF_ATI) { attribs[attrib++] = GLX_RENDER_TYPE; attribs[attrib++] = GLX_RGBA_FLOAT_ATI_BIT; } else if (floatBuffer == RTF_ARB) { attribs[attrib++] = GLX_RENDER_TYPE; attribs[attrib++] = GLX_RGBA_FLOAT_BIT; } else { attribs[attrib++] = GLX_RENDER_TYPE; attribs[attrib++] = GLX_RGBA_BIT; } attribs[attrib++] = GLX_DRAWABLE_TYPE; attribs[attrib++] = GLX_PBUFFER_BIT; attribs[attrib++] = GLX_STENCIL_SIZE; attribs[attrib++] = 8; attribs[attrib++] = GLX_DEPTH_SIZE; attribs[attrib++] = 24; attribs[attrib++] = GLX_RED_SIZE; attribs[attrib++] = mBitDepth; attribs[attrib++] = GLX_GREEN_SIZE; attribs[attrib++] = mBitDepth; attribs[attrib++] = GLX_BLUE_SIZE; attribs[attrib++] = mBitDepth; attribs[attrib++] = GLX_ALPHA_SIZE; attribs[attrib++] = mBitDepth; if (floatBuffer == RTF_NV) { attribs[attrib++] = GLX_FLOAT_COMPONENTS_NV; attribs[attrib++] = 1; } attribs[attrib++] = None; GLXFBConfig * fbConfigs; int nConfigs; fbConfigs = glXChooseFBConfig(dpy, screen, attribs, &nConfigs); if (nConfigs == 0 || !fbConfigs) GPGPU_EXCEPT(ERR_RENDERSYSTEM, "RenderTexture::Initialize() creation error: Couldn't find a suitable pixel format"); /// Determine the type of context to create int renderType = GLX_RGBA_TYPE; if(floatBuffer == RTF_ARB) { renderType = GLX_RGBA_FLOAT_TYPE; } /// Pick the first returned format that will return a pbuffer for (int i = 0; i < nConfigs; i++) { // Check colour format int redSize, greenSize, blueSize, alphaSize; glXGetFBConfigAttrib(dpy, fbConfigs[i], GLX_RED_SIZE, &redSize); glXGetFBConfigAttrib(dpy, fbConfigs[i], GLX_GREEN_SIZE, &greenSize); glXGetFBConfigAttrib(dpy, fbConfigs[i], GLX_BLUE_SIZE, &blueSize); glXGetFBConfigAttrib(dpy, fbConfigs[i], GLX_ALPHA_SIZE, &alphaSize); if(redSize == mBitDepth && greenSize == mBitDepth && blueSize == mBitDepth && alphaSize == mBitDepth) { attrib = 0; attribs[attrib++] = GLX_PBUFFER_WIDTH; attribs[attrib++] = mWidth; // Get from texture? attribs[attrib++] = GLX_PBUFFER_HEIGHT; attribs[attrib++] = mHeight; // Get from texture? attribs[attrib++] = GLX_PRESERVED_CONTENTS; attribs[attrib++] = 1; attribs[attrib++] = None; mPBuffer = glXCreatePbuffer(dpy, fbConfigs[i], attribs); if (mPBuffer) { mContext = glXCreateNewContext(dpy, fbConfigs[i], renderType, context, True); break; } } } if (!mPBuffer) GPGPU_EXCEPT(ERR_RENDERSYSTEM, "RenderTexture::Initialize() pbuffer creation error: No exact match found"); if (!mContext) GPGPU_EXCEPT(ERR_RENDERSYSTEM, "RenderTexture::Initialize() creation error: glXCreateContext() failed"); /// Read final size int _iWidth, _iHeight; glXQueryDrawable(dpy, mPBuffer, GLX_WIDTH, (GLuint *) & _iWidth); glXQueryDrawable(dpy, mPBuffer, GLX_HEIGHT, (GLuint *) & _iHeight); mWidth = _iWidth; mHeight = _iHeight; }
void GlxContext::createContext(GlxContext* shared) { // Get a working copy of the context settings ContextSettings settings = m_settings; XVisualInfo* visualInfo = NULL; if (m_pbuffer) { unsigned int fbConfigId = 0; glXQueryDrawable(m_display, m_pbuffer, GLX_FBCONFIG_ID, &fbConfigId); int attributes[] = { GLX_FBCONFIG_ID, static_cast<int>(fbConfigId), 0, 0 }; int count = 0; GLXFBConfig* fbconfig = glXChooseFBConfig(m_display, DefaultScreen(m_display), attributes, &count); if (count == 1) visualInfo = glXGetVisualFromFBConfig(m_display, *fbconfig); if (fbconfig) XFree(fbconfig); } else { // Retrieve the attributes of the target window XWindowAttributes windowAttributes; if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0) { err() << "Failed to get the window attributes" << std::endl; return; } // Get its visuals XVisualInfo tpl; tpl.screen = DefaultScreen(m_display); tpl.visualid = XVisualIDFromVisual(windowAttributes.visual); int nbVisuals = 0; visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals); } if (!visualInfo) { err() << "Failed to get visual info" << std::endl; return; } // Get the context to share display lists with GLXContext toShare = shared ? shared->m_context : NULL; // There are no GLX versions prior to 1.0 int major = 0; int minor = 0; if (!glXQueryVersion(m_display, &major, &minor)) err() << "Failed to query GLX version, limited to legacy context creation" << std::endl; // Check if glXCreateContextAttribsARB is available (requires GLX 1.3 or greater) bool hasCreateContextArb = (sfglx_ext_ARB_create_context == sfglx_LOAD_SUCCEEDED) && ((major > 1) || (minor >= 3)); // Create the OpenGL context -- first try using glXCreateContextAttribsARB if (hasCreateContextArb) { // Get a GLXFBConfig that matches the window's visual, for glXCreateContextAttribsARB GLXFBConfig* config = NULL; // We don't supply attributes to match against, since // the visual we are matching against was already // deemed suitable in selectBestVisual() int nbConfigs = 0; GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), NULL, &nbConfigs); for (int i = 0; configs && (i < nbConfigs); ++i) { XVisualInfo* visual = glXGetVisualFromFBConfig(m_display, configs[i]); if (!visual) continue; if (visual->visualid == visualInfo->visualid) { config = &configs[i]; break; } } if (!config) err() << "Failed to get GLXFBConfig which corresponds to the window's visual" << std::endl; while (config && !m_context && m_settings.majorVersion) { std::vector<int> attributes; // Check if the user requested a specific context version (anything > 1.1) if ((m_settings.majorVersion > 1) || ((m_settings.majorVersion == 1) && (m_settings.minorVersion > 1))) { attributes.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB); attributes.push_back(m_settings.majorVersion); attributes.push_back(GLX_CONTEXT_MINOR_VERSION_ARB); attributes.push_back(m_settings.minorVersion); } // Check if setting the profile is supported if (sfglx_ext_ARB_create_context_profile == sfglx_LOAD_SUCCEEDED) { int profile = (m_settings.attributeFlags & ContextSettings::Core) ? GLX_CONTEXT_CORE_PROFILE_BIT_ARB : GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; int debug = (m_settings.attributeFlags & ContextSettings::Debug) ? GLX_CONTEXT_DEBUG_BIT_ARB : 0; attributes.push_back(GLX_CONTEXT_PROFILE_MASK_ARB); attributes.push_back(profile); attributes.push_back(GLX_CONTEXT_FLAGS_ARB); attributes.push_back(debug); } else { if ((m_settings.attributeFlags & ContextSettings::Core) || (m_settings.attributeFlags & ContextSettings::Debug)) err() << "Selecting a profile during context creation is not supported," << "disabling comptibility and debug" << std::endl; m_settings.attributeFlags = ContextSettings::Default; } // Append the terminating 0 attributes.push_back(0); attributes.push_back(0); // RAII GLX error handler (we simply ignore errors here) // On an error, glXCreateContextAttribsARB will return 0 anyway GlxErrorHandler handler(m_display); // Create the context m_context = glXCreateContextAttribsARB(m_display, *config, toShare, true, &attributes[0]); if (!m_context) { // If we couldn't create the context, first try disabling flags, // then lower the version number and try again -- stop at 0.0 // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care if (m_settings.attributeFlags != ContextSettings::Default) { m_settings.attributeFlags = ContextSettings::Default; } else if (m_settings.minorVersion > 0) { // If the minor version is not 0, we decrease it and try again m_settings.minorVersion--; m_settings.attributeFlags = settings.attributeFlags; } else { // If the minor version is 0, we decrease the major version m_settings.majorVersion--; m_settings.minorVersion = 9; m_settings.attributeFlags = settings.attributeFlags; } } } if (configs) XFree(configs); } // If glXCreateContextAttribsARB failed, use glXCreateContext if (!m_context) { // set the context version to 2.1 (arbitrary) and disable flags m_settings.majorVersion = 2; m_settings.minorVersion = 1; m_settings.attributeFlags = ContextSettings::Default; #if defined(GLX_DEBUGGING) GlxErrorHandler handler(m_display); #endif // Create the context, using the target window's visual m_context = glXCreateContext(m_display, visualInfo, toShare, true); #if defined(GLX_DEBUGGING) if (glxErrorOccurred) err() << "GLX error in GlxContext::createContext()" << std::endl; #endif } if (!m_context) err() << "Failed to create an OpenGL context for this window" << std::endl; // Free the visual info XFree(visualInfo); }
// create a new window and set it's characteristics Window OpenGLPbufferDisplayDevice::open_window(char *nm, int *size, int *loc, int argc, char** argv ) { char *dispname; if ((dispname = getenv("VMDGDISPLAY")) == NULL) dispname = getenv("DISPLAY"); if(!(glxsrv.dpy = XOpenDisplay(dispname))) { msgErr << "Exiting due to X-Windows GLX/OpenGL Pbuffer creation failure." << sendmsg; if (dispname != NULL) { msgErr << "Failed to open display: " << dispname << sendmsg; } return (Window)0; } // // Check for "Composite" extension and any others that might cause // stability issues and warn the user about any potential problems... // char **xextensionlist; int nextensions, xtn; int warncompositeext=0; xextensionlist = XListExtensions(glxsrv.dpy, &nextensions); for (xtn=0; xtn<nextensions; xtn++) { // printf("xtn[%d]: '%s'\n", xtn, xextensionlist[xtn]); if (xextensionlist[xtn] && !strcmp(xextensionlist[xtn], "Composite")) { warncompositeext=1; } } if (warncompositeext) { msgWarn << "Detected X11 'Composite' extension: if incorrect display occurs" << sendmsg; msgWarn << "try disabling this X server option. Most OpenGL drivers" << sendmsg; msgWarn << "disable stereoscopic display when 'Composite' is enabled." << sendmsg; } XFreeExtensionList(xextensionlist); // // get info about root window // glxsrv.dpyScreen = DefaultScreen(glxsrv.dpy); glxsrv.rootWindowID = RootWindow(glxsrv.dpy, glxsrv.dpyScreen); screenX = DisplayWidth(glxsrv.dpy, glxsrv.dpyScreen); screenY = DisplayHeight(glxsrv.dpy, glxsrv.dpyScreen); // (3) make sure the GLX extension is available if (!glXQueryExtension(glxsrv.dpy, NULL, NULL)) { msgErr << "The X server does not support the OpenGL GLX extension." << " Exiting ..." << sendmsg; XCloseDisplay(glxsrv.dpy); return (Window)0; } ext->hasstereo = TRUE; // stereo on until we find out otherwise. ext->stereodrawforced = FALSE; // no need for force stereo draws initially ext->hasmultisample = TRUE; // multisample on until we find out otherwise. // Find the best matching OpenGL framebuffer config for our purposes GLXFBConfig *fbc; fbc = vmd_get_fbconfig(&glxsrv, &ext->hasstereo, &ext->hasmultisample, &ext->nummultisamples); if (fbc == NULL) { msgErr << "No OpenGL Pbuffer configurations available" << sendmsg; return (Window)0; } // Create the OpenGL Pbuffer and associated GLX context const int pbconf[] = {GLX_PBUFFER_WIDTH, DEF_PBUFFER_XRES, GLX_PBUFFER_HEIGHT, DEF_PBUFFER_YRES, GLX_LARGEST_PBUFFER, 1, GLX_PRESERVED_CONTENTS, 1, None}; GLXPbuffer PBuffer = glXCreatePbuffer(glxsrv.dpy, fbc[0], pbconf); glxsrv.cx = glXCreateNewContext(glxsrv.dpy, fbc[0], GLX_RGBA_TYPE, 0, GL_TRUE); if (PBuffer == 0 || glxsrv.cx == NULL) { msgErr << "A TrueColor OpenGL Pbuffer is required, but not available." << sendmsg; msgErr << "The X server is not capable of displaying double-buffered," << sendmsg; msgErr << "RGB images with a Z buffer. Exiting ..." << sendmsg; XCloseDisplay(glxsrv.dpy); return (Window)0; } // set maximum allowable rendered image size for the Pbuffer // that was actually allocated, which may be smaller than we hoped... PbufferMaxXsz = DEF_PBUFFER_XRES; PbufferMaxYsz = DEF_PBUFFER_YRES; glXQueryDrawable(glxsrv.dpy, PBuffer, GLX_WIDTH, &PbufferMaxXsz); glXQueryDrawable(glxsrv.dpy, PBuffer, GLX_HEIGHT, &PbufferMaxYsz); msgInfo << "OpenGL Pbuffer size: " << PbufferMaxXsz << "x" << PbufferMaxYsz << sendmsg; // set default image size to incoming values, when possible. xSize = size[0]; ySize = size[1]; if (xSize < 0 || xSize > PbufferMaxXsz || ySize < 0 || ySize > PbufferMaxYsz) { msgWarn << "Ignored out-of-range OpenGL Pbuffer image dimension request: " << xSize << "x" << ySize << " (max: " << PbufferMaxXsz << "x" << PbufferMaxYsz << ")" << sendmsg; xSize = PbufferMaxXsz; ySize = PbufferMaxYsz; } // make the Pbuffer active glXMakeContextCurrent(glxsrv.dpy, PBuffer, PBuffer, glxsrv.cx); glXMakeCurrent(glxsrv.dpy, PBuffer, glxsrv.cx); // If we have acquired a multisample buffer with GLX, we // still need to test to see if we can actually use it. if (ext->hasmultisample) { int msampeext = 0; // check for ARB multisampling if (ext->vmdQueryExtension("GL_ARB_multisample")) { msampeext = 1; } if (!msampeext) { ext->hasmultisample = FALSE; ext->nummultisamples = 0; } } // (9) configure the rendering properly setup_initial_opengl_state(); // setup initial OpenGL state // normal return: window was successfully created have_window = TRUE; // return window id return PBuffer; }