void QGLContext::makeCurrent() { if ( !d->valid ) { #if defined(QT_CHECK_STATE) qWarning("QGLContext::makeCurrent(): Cannot make invalid context current."); #endif return; } bool ok = TRUE; if ( deviceIsPixmap() ) ok = glXMakeCurrent( d->paintDevice->x11Display(), (GLXPixmap)gpm, (GLXContext)cx ); else ok = glXMakeCurrent( d->paintDevice->x11Display(), ((QWidget *)d->paintDevice)->winId(), (GLXContext)cx ); #if defined(QT_CHECK_NULL) // qDebug("makeCurrent: %i, vi=%i, vi->vi=%i, vi->id=%i", (int)this, (int)vi, (int)((XVisualInfo*)vi)->visual, (int)((XVisualInfo*)vi)->visualid ); if ( !ok ) qWarning("QGLContext::makeCurrent(): Failed."); #endif if ( ok ) currentCtx = this; }
/* state:done?(simple version) */ bool QGLContext::chooseContext( const QGLContext* shareContext ) { qDebug( "qgl_win.cpp:QGLContext::chooseContext()" ); // Some kind of workaround, to force loading of opengl module.... // Seems to be neccessary....why? if ( !force_opengl_loading ) { GLint params; glGetIntegerv( GL_DEPTH_BITS, ¶ms ); force_opengl_loading = TRUE; } /* simple implementation: assumes that: 1.colordepth is SAME as desktop 2.RGBA pixels 3.no alpna 4.no acc 5.32-bit depth buffer 6.no aux/stencil buffers 7. More correct implementation would use glGetXXX to for example:glGetbooleanv for GL_DOUBLEBUFFER...*/ //TODO:what if setContext is NOT yet called and so dc is invalid? HDC aDc; if ( deviceIsPixmap() ) { win = 0; aDc = d->paintDevice->handle(); } else { win = ( ( QWidget* ) d->paintDevice ) ->winId(); aDc = GetDC( win ); //wglGetCurrentDC(); } if ( !aDc ) { // needs a device context #if defined(QT_CHECK_NULL) qWarning( "qgl_win.cpp: QGLContext::chooseContext(): Paint device cannot be null" ); #endif if ( win ) { ReleaseDC( win, aDc ); } return FALSE; } PIXELFORMATDESCRIPTOR pfd; pixelFormatId = choosePixelFormat( &pfd, aDc ); if ( ( !SetPixelFormat( aDc, pixelFormatId, &pfd ) ) ) { qglError( "qgl_win.cpp: QGLContext::choosePixelFormat()", "SetPixelFormat" ); if ( win ) { ReleaseDC( win, aDc ); return FALSE; } } rc = wglCreateContext( aDc ); if ( !rc ) { qglError( "qgl_win.cpp: QGLContext:chooseContext()", "wglCreateContext" ); if ( win ) ReleaseDC( win, aDc ); return FALSE; } return TRUE; }
void QGLContext::swapBuffers() const { if ( !d->valid ) return; if ( !deviceIsPixmap() ) glXSwapBuffers( d->paintDevice->x11Display(), ((QWidget *)d->paintDevice)->winId() ); }
//state:done? //must be kept in sync with chooseContext int QGLContext::choosePixelFormat( void * pfd_void, HDC phdc ) { PIXELFORMATDESCRIPTOR * ppfd = ( PIXELFORMATDESCRIPTOR * ) pfd_void; memset( ppfd, 0, sizeof( PIXELFORMATDESCRIPTOR ) ); ppfd->nSize = sizeof( PIXELFORMATDESCRIPTOR ); ppfd->nVersion = 1; ppfd->dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; ppfd->iPixelType = PFD_TYPE_RGBA; // RGBA type if ( deviceIsPixmap() ) ppfd->dwFlags |= PFD_DRAW_TO_BITMAP; else ppfd->dwFlags |= PFD_DRAW_TO_WINDOW; if ( glFormat.doubleBuffer() && !deviceIsPixmap() ) ppfd->dwFlags |= PFD_DOUBLEBUFFER; if ( glFormat.stereo() ) ppfd->dwFlags |= PFD_STEREO; if ( glFormat.depth() ) ppfd->cDepthBits = 16; else ppfd->dwFlags |= PFD_DEPTH_DONTCARE; if ( glFormat.rgba() ) { ppfd->iPixelType = PFD_TYPE_RGBA; if ( deviceIsPixmap() ) ppfd->cColorBits = 16; else ppfd->cColorBits = 16; } else { ppfd->iPixelType = PFD_TYPE_COLORINDEX; ppfd->cColorBits = 0; } ppfd->cAlphaBits = 0; ppfd->cAccumBits = 0; ppfd->cStencilBits = 0; ppfd->iLayerType = PFD_MAIN_PLANE; int pixelFormat; if ( ( pixelFormat = ChoosePixelFormat( phdc, ppfd ) ) == 0 ) qglError( "qgl_win.cpp:QGLContext::choosePixelFormat()", "ChoosePixelFormat()" ); return pixelFormat; }
void QGLContext::swapBuffers() const { Q_D(const QGLContext); if (!d->valid) return; if (!deviceIsPixmap()) { int interval = d->glFormat.swapInterval(); if (interval > 0) { typedef int (*qt_glXGetVideoSyncSGI)(uint *); typedef int (*qt_glXWaitVideoSyncSGI)(int, int, uint *); static qt_glXGetVideoSyncSGI glXGetVideoSyncSGI = 0; static qt_glXWaitVideoSyncSGI glXWaitVideoSyncSGI = 0; static bool resolved = false; if (!resolved) { QString glxExt = QString(QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS))); if (glxExt.contains(QLatin1String("GLX_SGI_video_sync"))) { #if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) void *handle = dlopen(NULL, RTLD_LAZY); if (handle) { glXGetVideoSyncSGI = (qt_glXGetVideoSyncSGI) dlsym(handle, "glXGetVideoSyncSGI"); glXWaitVideoSyncSGI = (qt_glXWaitVideoSyncSGI) dlsym(handle, "glXWaitVideoSyncSGI"); dlclose(handle); } if (!glXGetVideoSyncSGI) #endif { extern const QString qt_gl_library_name(); QLibrary lib(qt_gl_library_name()); glXGetVideoSyncSGI = (qt_glXGetVideoSyncSGI) lib.resolve("glXGetVideoSyncSGI"); glXWaitVideoSyncSGI = (qt_glXWaitVideoSyncSGI) lib.resolve("glXWaitVideoSyncSGI"); } } resolved = true; } if (glXGetVideoSyncSGI && glXWaitVideoSyncSGI) { uint counter; if (!glXGetVideoSyncSGI(&counter)) glXWaitVideoSyncSGI(interval + 1, (counter + interval) % (interval + 1), &counter); } } glXSwapBuffers(qt_x11Info(d->paintDevice)->display(), static_cast<QWidget *>(d->paintDevice)->winId()); } }
bool QGLContext::chooseContext( const QGLContext* shareContext ) { Display* disp = d->paintDevice->x11Display(); vi = chooseVisual(); if ( !vi ) return FALSE; if ( deviceIsPixmap() && (((XVisualInfo*)vi)->depth != d->paintDevice->x11Depth() || ((XVisualInfo*)vi)->screen != d->paintDevice->x11Screen()) ) { XFree( vi ); XVisualInfo appVisInfo; memset( &appVisInfo, 0, sizeof(XVisualInfo) ); appVisInfo.visualid = XVisualIDFromVisual( (Visual*)d->paintDevice->x11Visual() ); appVisInfo.screen = d->paintDevice->x11Screen(); int nvis; vi = XGetVisualInfo( disp, VisualIDMask | VisualScreenMask, &appVisInfo, &nvis ); if ( !vi ) return FALSE; int useGL; glXGetConfig( disp, (XVisualInfo*)vi, GLX_USE_GL, &useGL ); if ( !useGL ) return FALSE; //# Chickening out already... } int res; glXGetConfig( disp, (XVisualInfo*)vi, GLX_LEVEL, &res ); glFormat.setPlane( res ); glXGetConfig( disp, (XVisualInfo*)vi, GLX_DOUBLEBUFFER, &res ); glFormat.setDoubleBuffer( res ); glXGetConfig( disp, (XVisualInfo*)vi, GLX_DEPTH_SIZE, &res ); glFormat.setDepth( res ); glXGetConfig( disp, (XVisualInfo*)vi, GLX_RGBA, &res ); glFormat.setRgba( res ); glXGetConfig( disp, (XVisualInfo*)vi, GLX_ALPHA_SIZE, &res ); glFormat.setAlpha( res ); glXGetConfig( disp, (XVisualInfo*)vi, GLX_ACCUM_RED_SIZE, &res ); glFormat.setAccum( res ); glXGetConfig( disp, (XVisualInfo*)vi, GLX_STENCIL_SIZE, &res ); glFormat.setStencil( res ); glXGetConfig( disp, (XVisualInfo*)vi, GLX_STEREO, &res ); glFormat.setStereo( res ); Bool direct = format().directRendering() ? True : False; if ( shareContext && ( !shareContext->isValid() || !shareContext->cx ) ) { #if defined(QT_CHECK_NULL) qWarning("QGLContext::chooseContext(): Cannot share with invalid context"); #endif shareContext = 0; } // 1. Sharing between rgba and color-index will give wrong colors. // 2. Contexts cannot be shared btw. direct/non-direct renderers. // 3. Pixmaps cannot share contexts that are set up for direct rendering. if ( shareContext && (format().rgba() != shareContext->format().rgba() || (deviceIsPixmap() && glXIsDirect( disp, (GLXContext)shareContext->cx )))) shareContext = 0; cx = 0; if ( shareContext ) { cx = glXCreateContext( disp, (XVisualInfo *)vi, (GLXContext)shareContext->cx, direct ); if ( cx ) d->sharing = TRUE; } if ( !cx ) cx = glXCreateContext( disp, (XVisualInfo *)vi, None, direct ); if ( !cx ) return FALSE; glFormat.setDirectRendering( glXIsDirect( disp, (GLXContext)cx ) ); if ( deviceIsPixmap() ) { #if defined(GLX_MESA_pixmap_colormap) && defined(QGL_USE_MESA_EXT) gpm = glXCreateGLXPixmapMESA( disp, (XVisualInfo *)vi, d->paintDevice->handle(), choose_cmap( disp, (XVisualInfo *)vi ) ); #else gpm = (Q_UINT32)glXCreateGLXPixmap( disp, (XVisualInfo *)vi, d->paintDevice->handle() ); #endif if ( !gpm ) return FALSE; } return TRUE; }
bool QGLContext::chooseContext(const QGLContext* shareContext) { Q_D(QGLContext); const QX11Info *xinfo = qt_x11Info(d->paintDevice); Display* disp = xinfo->display(); d->vi = chooseVisual(); if (!d->vi) return false; if (deviceIsPixmap() && (((XVisualInfo*)d->vi)->depth != xinfo->depth() || ((XVisualInfo*)d->vi)->screen != xinfo->screen())) { XFree(d->vi); XVisualInfo appVisInfo; memset(&appVisInfo, 0, sizeof(XVisualInfo)); appVisInfo.visualid = XVisualIDFromVisual((Visual *) xinfo->visual()); appVisInfo.screen = xinfo->screen(); int nvis; d->vi = XGetVisualInfo(disp, VisualIDMask | VisualScreenMask, &appVisInfo, &nvis); if (!d->vi) return false; int useGL; glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_USE_GL, &useGL); if (!useGL) return false; //# Chickening out already... } int res; glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_LEVEL, &res); d->glFormat.setPlane(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_DOUBLEBUFFER, &res); d->glFormat.setDoubleBuffer(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_DEPTH_SIZE, &res); d->glFormat.setDepth(res); if (d->glFormat.depth()) d->glFormat.setDepthBufferSize(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_RGBA, &res); d->glFormat.setRgba(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_RED_SIZE, &res); d->glFormat.setRedBufferSize(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_GREEN_SIZE, &res); d->glFormat.setGreenBufferSize(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_BLUE_SIZE, &res); d->glFormat.setBlueBufferSize(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_ALPHA_SIZE, &res); d->glFormat.setAlpha(res); if (d->glFormat.alpha()) d->glFormat.setAlphaBufferSize(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_ACCUM_RED_SIZE, &res); d->glFormat.setAccum(res); if (d->glFormat.accum()) d->glFormat.setAccumBufferSize(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_STENCIL_SIZE, &res); d->glFormat.setStencil(res); if (d->glFormat.stencil()) d->glFormat.setStencilBufferSize(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_STEREO, &res); d->glFormat.setStereo(res); glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_SAMPLE_BUFFERS_ARB, &res); d->glFormat.setSampleBuffers(res); if (d->glFormat.sampleBuffers()) { glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_SAMPLES_ARB, &res); d->glFormat.setSamples(res); } Bool direct = format().directRendering() ? True : False; if (shareContext && (!shareContext->isValid() || !shareContext->d_func()->cx)) { qWarning("QGLContext::chooseContext(): Cannot share with invalid context"); shareContext = 0; } // 1. Sharing between rgba and color-index will give wrong colors. // 2. Contexts cannot be shared btw. direct/non-direct renderers. // 3. Pixmaps cannot share contexts that are set up for direct rendering. // 4. If the contexts are not created on the same screen, they can't be shared if (shareContext && (format().rgba() != shareContext->format().rgba() || (deviceIsPixmap() && glXIsDirect(disp, (GLXContext)shareContext->d_func()->cx)) || (shareContext->d_func()->screen != xinfo->screen()))) { shareContext = 0; } d->cx = 0; if (shareContext) { d->cx = glXCreateContext(disp, (XVisualInfo *)d->vi, (GLXContext)shareContext->d_func()->cx, direct); d->screen = ((XVisualInfo*)d->vi)->screen; if (d->cx) { QGLContext *share = const_cast<QGLContext *>(shareContext); d->sharing = true; share->d_func()->sharing = true; } } if (!d->cx) { d->cx = glXCreateContext(disp, (XVisualInfo *)d->vi, NULL, direct); d->screen = ((XVisualInfo*)d->vi)->screen; } if (!d->cx) return false; d->glFormat.setDirectRendering(glXIsDirect(disp, (GLXContext)d->cx)); if (deviceIsPixmap()) { #if defined(GLX_MESA_pixmap_colormap) && defined(QGL_USE_MESA_EXT) d->gpm = glXCreateGLXPixmapMESA(disp, (XVisualInfo *)d->vi, qt_x11Handle(d->paintDevice), qt_gl_choose_cmap(disp, (XVisualInfo *)d->vi)); #else d->gpm = (quint32)glXCreateGLXPixmap(disp, (XVisualInfo *)d->vi, qt_x11Handle(d->paintDevice)); #endif if (!d->gpm) return false; } QString glxExt = QString(QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS))); if (glxExt.contains(QLatin1String("GLX_SGI_video_sync"))) { if (d->glFormat.swapInterval() == -1) d->glFormat.setSwapInterval(0); } else { d->glFormat.setSwapInterval(-1); } return true; }
/***************************************************************************** QGLContext AGL-specific code *****************************************************************************/ bool QGLContext::chooseContext(const QGLContext* shareContext) { Q_D(QGLContext); d->cx = 0; d->vi = chooseMacVisual(0); if(!d->vi) return false; AGLPixelFormat fmt = (AGLPixelFormat)d->vi; GLint res; aglDescribePixelFormat(fmt, AGL_LEVEL, &res); d->glFormat.setPlane(res); if(deviceIsPixmap()) res = 0; else aglDescribePixelFormat(fmt, AGL_DOUBLEBUFFER, &res); d->glFormat.setDoubleBuffer(res); aglDescribePixelFormat(fmt, AGL_DEPTH_SIZE, &res); d->glFormat.setDepth(res); if (d->glFormat.depth()) d->glFormat.setDepthBufferSize(res); aglDescribePixelFormat(fmt, AGL_RGBA, &res); d->glFormat.setRgba(res); aglDescribePixelFormat(fmt, AGL_RED_SIZE, &res); d->glFormat.setRedBufferSize(res); aglDescribePixelFormat(fmt, AGL_GREEN_SIZE, &res); d->glFormat.setGreenBufferSize(res); aglDescribePixelFormat(fmt, AGL_BLUE_SIZE, &res); d->glFormat.setBlueBufferSize(res); aglDescribePixelFormat(fmt, AGL_ALPHA_SIZE, &res); d->glFormat.setAlpha(res); if (d->glFormat.alpha()) d->glFormat.setAlphaBufferSize(res); aglDescribePixelFormat(fmt, AGL_ACCUM_RED_SIZE, &res); // Bug in Apple OpenGL (rdr://5015603), when we don't have an accumulation // buffer, it still claims that we have a 16-bit one (which is pretty rare). // So, we just assume we can never have a buffer that small. d->glFormat.setAccum(res > 5); if (d->glFormat.accum()) d->glFormat.setAccumBufferSize(res); aglDescribePixelFormat(fmt, AGL_STENCIL_SIZE, &res); d->glFormat.setStencil(res); if (d->glFormat.stencil()) d->glFormat.setStencilBufferSize(res); aglDescribePixelFormat(fmt, AGL_STEREO, &res); d->glFormat.setStereo(res); aglDescribePixelFormat(fmt, AGL_SAMPLE_BUFFERS_ARB, &res); d->glFormat.setSampleBuffers(res); if (d->glFormat.sampleBuffers()) { aglDescribePixelFormat(fmt, AGL_SAMPLES_ARB, &res); d->glFormat.setSamples(res); } if(shareContext && (!shareContext->isValid() || !shareContext->d_func()->cx)) { qWarning("QGLContext::chooseContext(): Cannot share with invalid context"); shareContext = 0; } // sharing between rgba and color-index will give wrong colors if(shareContext && (format().rgba() != shareContext->format().rgba())) shareContext = 0; AGLContext ctx = aglCreateContext(fmt, (AGLContext) (shareContext ? shareContext->d_func()->cx : 0)); if(!ctx) { GLenum err = aglGetError(); if(err == AGL_BAD_MATCH || err == AGL_BAD_CONTEXT) { if(shareContext && shareContext->d_func()->cx) { qWarning("QGLContext::chooseContext(): Context sharing mismatch!"); if(!(ctx = aglCreateContext(fmt, 0))) return false; shareContext = 0; } } if(!ctx) { qWarning("QGLContext::chooseContext(): Unable to create QGLContext"); return false; } } d->cx = ctx; if (shareContext && shareContext->d_func()->cx) { QGLContext *share = const_cast<QGLContext *>(shareContext); d->sharing = true; share->d_func()->sharing = true; } if(deviceIsPixmap()) updatePaintDevice(); // vblank syncing GLint interval = d->reqFormat.swapInterval(); if (interval != -1) { aglSetInteger((AGLContext)d->cx, AGL_SWAP_INTERVAL, &interval); if (interval != 0) aglEnable((AGLContext)d->cx, AGL_SWAP_INTERVAL); else aglDisable((AGLContext)d->cx, AGL_SWAP_INTERVAL); } aglGetInteger((AGLContext)d->cx, AGL_SWAP_INTERVAL, &interval); d->glFormat.setSwapInterval(interval); return true; }