示例#1
0
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());
}
示例#3
0
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);
}
示例#4
0
文件: main.c 项目: czaber/ogwm
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));
}
示例#5
0
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;
}
示例#6
0
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);
}
示例#8
0
unsigned int WineWindow::get_height() const
{
    unsigned int result;

    glXQueryDrawable(m_xdpy, m_xdrawable, GLX_HEIGHT, &result);
    return result;
}
示例#9
0
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);
}
示例#11
0
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)
示例#12
0
	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;
	}
示例#13
0
/**
 * 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);
      }
   }
}
示例#14
0
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)
示例#15
0
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);
}
示例#16
0
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);
}
示例#17
0
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;
}
示例#18
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);
}
示例#19
0
    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);
    }
示例#20
0
/**
 * 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);
      }
   }
}
示例#21
0
    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);
    }
示例#22
0
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( ));
    }
}
示例#23
0
	//-------------------------------------------------------------------------------------------------//
	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);
	}
示例#24
0
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;
}
示例#25
0
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;
}