void Ut_MGLE2Renderer::testDrawing() { #ifdef M_USE_OPENGL QGLWidget glw; glw.resize(67,67); glw.makeCurrent(); MGLES2Renderer::activate(&glw); MGLES2Renderer* r = MGLES2Renderer::instance(); QPixmap pm(32,32); pm.fill(Qt::red); //draw with default shader r->setViewportSize(glw.size()); r->begin(NULL); r->bindTexture(pm); r->draw(QRect(1,1,32,32)); r->draw(34,1); r->draw(1,34,32,32); r->setInvertTexture(true); r->draw(QRect(34,34,32,32), QRect(4,4,24,24)); r->end(); //draw with custom shader r->begin(NULL, r->getShaderProgram(qApp->applicationDirPath() + "/shader1.frag", qApp->applicationDirPath() + "/shader1.vert")); r->bindTexture(pm); r->draw(17,17,33,33); r->end(); //compare resulted image with reference image QImage image1 = glw.grabFrameBuffer(); //image1.save("glw1.png", "PNG"); QImage image2(qApp->applicationDirPath() + "/glw1.png", "PNG"); QVERIFY(image1 == image2); //draw patches glw.resize(64,64); QList<QRect> targets; targets.append(QRect(0,0,32,32)); targets.append(QRect(32,0,32,32)); targets.append(QRect(0,32,32,32)); targets.append(QRect(32,32,32,32)); QList<QRect> sources; sources.append(QRect(17,17,16,16)); sources.append(QRect(32,17,16,16)); sources.append(QRect(17,32,16,16)); sources.append(QRect(32,32,16,16)); pm.convertFromImage(image2); r->begin(NULL); r->bindTexture(pm); r->draw(targets, sources); r->end(); //compare resulted image with reference image image1 = glw.grabFrameBuffer(); //image1.save("glw2.png", "PNG"); image2.load(qApp->applicationDirPath() + "/glw2.png", "PNG"); QVERIFY(image1 == image2); #endif }
void QGLInfo::initialize() { QWidget *win = qobject_cast<QGLWidget *>(parent()); // We need some kind of GL context to do the querying. QGLWidget *glWidget = new QGLWidget(win); glWidget->makeCurrent(); m_qtGLVersionInfo = reportQtGLVersionInfo(); m_qtGLFeatures = reportQtGLFeatures(); m_glVersionInfo = reportGLVersionInfo(); m_glExtensionInfo = reportGLExtensionInfo(); m_eglVersionInfo = reportEGLVersionInfo(); m_eglExtensionInfo = reportEGLExtensionInfo(); m_eglConfigInfo = reportEGLConfigInfo(); glWidget->doneCurrent(); delete glWidget; QString welcome; { QSettings freshStart; if (!freshStart.contains(QLatin1String("new_install"))) { welcome = QLatin1String("<h1>Welcome to Qt3D!</h1>" "<p>Try running the FPS test from the " "View menu above to confirm that Qt3D " "is installed correctly.</p><hr>"); } freshStart.setValue(QLatin1String("new_install"), true); } QString html = tr("<h1>Qt GL Info Report</h1>" "<p>Generated at: %1</p>" "<h2>Qt GL Version Info</h2>" "<p>%2</p>" "<h2>Qt GL Features</h2>" "<p>%3</p>" "<h2>GL Version Info</h2>" "<p>%4</p>" "<h2>GL Extension Info</h2>" "<p>%5</p>") .arg(QDateTime::currentDateTime().toString()) .arg(nice(m_qtGLVersionInfo)) .arg(nice(m_qtGLFeatures)) .arg(nice(m_glVersionInfo)) .arg(nice(m_glExtensionInfo)); if (!welcome.isEmpty()) html.prepend(welcome); #if !defined(QT_NO_EGL) html += tr("<h2>EGL Version Info</h2>" "<p>%1</p>" "<h2>EGL Extension Info</h2>" "<p>%2</p>" "<h2>EGL Configurations</h2>" "<p>%3</p>") .arg(nice(m_eglVersionInfo)) .arg(nice(m_eglExtensionInfo)) .arg(nice(m_eglConfigInfo)); #endif emit reportHtml(html); }
int main(int argc, char **argv) { QApplication app(argc, argv); if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_5) == 0) { QMessageBox::critical(0, "OpenGL features missing", "OpenGL version 1.5 or higher is required to run this demo.\n" "The program will now exit."); return -1; } int maxTextureSize = 1024; QGLWidget *widget = new QGLWidget(QGLFormat(QGL::SampleBuffers)); widget->makeCurrent(); if (!necessaryExtensionsSupported()) { QMessageBox::critical(0, "OpenGL features missing", "The OpenGL extensions required to run this demo are missing.\n" "The program will now exit."); delete widget; return -2; } // Check if all the necessary functions are resolved. if (!getGLExtensionFunctions().resolve(widget->context())) { QMessageBox::critical(0, "OpenGL features missing", "Failed to resolve OpenGL functions required to run this demo.\n" "The program will now exit."); delete widget; return -3; } // TODO: Make conditional for final release QMessageBox::information(0, "For your information", "This demo can be GPU and CPU intensive and may\n" "work poorly or not at all on your system."); widget->makeCurrent(); // The current context must be set before calling Scene's constructor Scene scene(1024, 768, maxTextureSize); GraphicsView view; view.setViewport(widget); view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate); view.setScene(&scene); view.show(); return app.exec(); }
FitView(QGraphicsScene *scene) : QGraphicsView(scene) { setSceneRect(Config.Rect); setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing | QPainter::SmoothPixmapTransform); #if !defined(QT_NO_OPENGL) && defined(USING_OPENGL) if (QGLFormat::hasOpenGL()) { QGLWidget *widget = new QGLWidget(QGLFormat(QGL::SampleBuffers)); widget->makeCurrent(); setViewport(widget); setViewportUpdateMode(QGraphicsView::FullViewportUpdate); } #endif }
virtual bool RequestCurrentGLContext() { QGraphicsView* view = GetViewWidget(); if (view) { QGLWidget* qglwidget = qobject_cast<QGLWidget*>(view->viewport()); if (qglwidget) { qglwidget->makeCurrent(); QGLContext* context = const_cast<QGLContext*>(QGLContext::currentContext()); if (context) return true; } } return false; }
QGLWidget* DTIDEGLWidgets::requestWidget(QString title, int width, int height) { QGLFormat glFormat(QGL::SampleBuffers); glFormat.setSwapInterval(0); QGLWidget* res = new QGLWidget(glFormat); res->resize(width, height); res->setWindowTitle(title); res->show(); activeWidgets.append(res); res->makeCurrent(); return res; }
void QGLInfo::initialize() { QWidget *win = qobject_cast<QGLWidget *>(parent()); // We need some kind of GL context to do the querying. QGLWidget *glWidget = new QGLWidget(win); glWidget->makeCurrent(); m_qtGLVersionInfo = reportQtGLVersionInfo(); m_qtGLFeatures = reportQtGLFeatures(); m_glVersionInfo = reportGLVersionInfo(); m_glExtensionInfo = reportGLExtensionInfo(); m_eglVersionInfo = reportEGLVersionInfo(); m_eglExtensionInfo = reportEGLExtensionInfo(); m_eglConfigInfo = reportEGLConfigInfo(); glWidget->doneCurrent(); delete glWidget; QString html = tr("<h1>Qt GL Info Report</h1>" "<p>Generated at: %1</p>" "<h2>Qt GL Version Info</h2>" "<p>%2</p>" "<h2>Qt GL Features</h2>" "<p>%3</p>" "<h2>GL Version Info</h2>" "<p>%4</p>" "<h2>GL Extension Info</h2>" "<p>%5</p>") .arg(QDateTime::currentDateTime().toString()) .arg(nice(m_qtGLVersionInfo)) .arg(nice(m_qtGLFeatures)) .arg(nice(m_glVersionInfo)) .arg(nice(m_glExtensionInfo)); #if !defined(QT_NO_EGL) html += tr("<h2>EGL Version Info</h2>" "<p>%1</p>" "<h2>EGL Extension Info</h2>" "<p>%2</p>" "<h2>EGL Configurations</h2>" "<p>%3</p>") .arg(nice(m_eglVersionInfo)) .arg(nice(m_eglExtensionInfo)) .arg(nice(m_eglConfigInfo)); #endif emit reportHtml(html); }
bool QGLPixelBuffer::hasOpenGLPbuffers() { bool ret = false; QGLWidget *dmy = 0; if (!QGLContext::currentContext()) { dmy = new QGLWidget; dmy->makeCurrent(); } PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB"); if (wglGetExtensionsStringARB) { QString extensions(QLatin1String(wglGetExtensionsStringARB(wglGetCurrentDC()))); if (extensions.contains(QLatin1String("WGL_ARB_pbuffer")) && extensions.contains(QLatin1String("WGL_ARB_pixel_format"))) { ret = true; } } if (dmy) delete dmy; return ret; }
void glinfo:: test() { // It should provide a human readable text string of a Qt managed open gl render context. { std::string name = "glinfo"; int argc = 1; char * argv = &name[0]; QApplication a(argc,&argv); // takes 0.4 s if this is the first instantiation of QApplication QGLWidget w; w.makeCurrent (); string ws = glinfo::pretty_format (w); string fs = glinfo::pretty_format (w.format ()); string ds = glinfo::driver_info (); EXCEPTION_ASSERT(ws.find ("doubleBuffer") != std::string::npos); EXCEPTION_ASSERT(fs.find ("depthBufferSize") != std::string::npos); EXCEPTION_ASSERT(ws.find (fs) != std::string::npos); EXCEPTION_ASSERT(ds.find ("GL_ARB_depth_buffer_float") != std::string::npos); } }
GraphicsView::GraphicsView(QWidget *parent) : QGraphicsView(parent), dt(1/100.0) { // use opengl for rendering QGLWidget *widget = new QGLWidget(QGLFormat(QGL::SampleBuffers)); widget->makeCurrent(); setViewport(widget); setViewportUpdateMode(QGraphicsView::FullViewportUpdate); setCacheMode(QGraphicsView::CacheNone); // create graphics scene GraphicsScene *graphicsScene = new GraphicsScene(this); setScene(graphicsScene); // create world rendering thing WorldView* worldView = new WorldView(this, &worldModel); // make world rendering thing render when grahpics scene needs to draw stuff connect(graphicsScene, SIGNAL(render()), worldView, SLOT(render())); tick(); }
void DCPUToolchain_ActivateContext(void* context) { QGLWidget* w = static_cast<QGLWidget*>(context); w->makeCurrent(); }
void GlOverviewGraphicsItem::draw(bool generatePixmap) { if(baseScene.getLayersList().empty()) return; if (_frameWidth%2==1) { ++_frameWidth; } // Initialize the context avoid segfault when trying to render graph without any initialised gl context. QGLWidget *firstWidget = GlMainWidget::getFirstQGLWidget(); firstWidget->makeCurrent(); if(!overviewBorder.parentItem()) { //This flag is needed to don't display overview rectangle outside overview setFlag(QGraphicsItem::ItemClipsChildrenToShape); overview.setFlag(QGraphicsItem::ItemClipsChildrenToShape); overview.setShapeMode(QGraphicsPixmapItem::BoundingRectShape); setBrush(QBrush(QColor(255,255,255,255))); QPainterPath path; path.addRect(_frameWidth/2, _frameWidth/2, width-_frameWidth, height-_frameWidth); overviewBorder.setPath(path); overviewBorder.setParentItem(this); overview.setParentItem(&overviewBorder); //Init lines and polygons item for(unsigned int i=0; i<8; ++i) { line[i].setParentItem(&overview); if (i < 4) { poly[i].setParentItem(&overview); poly[i].setBrush(QBrush(QColor(0,0,0,64))); poly[i].setPen(Qt::NoPen); } } } Color backgroundColor = baseScene.getBackgroundColor(); int bgV = backgroundColor.getV(); for(unsigned int i=0; i<8; ++i) { if (bgV < 128) { line[i].setPen(QColor(255, 255, 255)); } else { line[i].setPen(QColor(0, 0, 0)); } if (i < 4) { if (bgV < 128) { poly[i].setBrush(QBrush(QColor(255,255,255,64))); } else { poly[i].setBrush(QBrush(QColor(0,0,0,64))); } } } // Backup initial viewport Vector<int,4> backupViewport=baseScene.getViewport(); // Backup initial cameras vector<Camera> cameras; const vector<pair<string, GlLayer*> >& layerList=baseScene.getLayersList(); for(vector<pair<string, GlLayer*> >::const_iterator it=layerList.begin(); it!=layerList.end(); ++it) { cameras.push_back((*it).second->getCamera()); } // Compute visible part of the scene Camera &baseCamera=baseScene.getGraphCamera(); vector<Coord> cameraBoundingBox; cameraBoundingBox.push_back(baseCamera.screenTo3DWorld(Coord(backupViewport[0],backupViewport[1],0))); cameraBoundingBox.push_back(baseCamera.screenTo3DWorld(Coord(backupViewport[0]+backupViewport[2],backupViewport[1],0))); cameraBoundingBox.push_back(baseCamera.screenTo3DWorld(Coord(backupViewport[0]+backupViewport[2],backupViewport[1]+backupViewport[3],0))); cameraBoundingBox.push_back(baseCamera.screenTo3DWorld(Coord(backupViewport[0],backupViewport[1]+backupViewport[3],0))); // This code modify cameraBoundingBox coords to have coords with (x,y,0) // If we don't do this we will have invalid polygon when we do worldTo2DScreen transformations Coord eyesVector=baseCamera.getEyes()-baseCamera.getCenter(); eyesVector=eyesVector*(1.f/eyesVector[2]); for(unsigned int i=0; i<4; i++) cameraBoundingBox[i]=cameraBoundingBox[i]-eyesVector*cameraBoundingBox[i][2]; // Change viewport of the scene to the overview viewport baseScene.setViewport(0,0,width, height); if(generatePixmap || _oldCameras.size()!=layerList.size()) { // Center the scene baseScene.centerScene(); _oldCameras.clear(); for(vector<pair<string, GlLayer*> >::const_iterator it=layerList.begin(); it!=layerList.end(); ++it) { _oldCameras.push_back(it->second->getCamera()); } } else { unsigned int i=0; for(vector<pair<string, GlLayer*> >::const_iterator it=layerList.begin(); it!=layerList.end(); ++it) { it->second->getCamera().loadCameraParametersWith(_oldCameras[i]); ++i; } } // Project camera bounding box Camera &overviewCamera=baseScene.getGraphCamera(); Coord p0=overviewCamera.worldTo2DScreen(cameraBoundingBox[0]); Coord p1=overviewCamera.worldTo2DScreen(cameraBoundingBox[1]); Coord p2=overviewCamera.worldTo2DScreen(cameraBoundingBox[2]); Coord p3=overviewCamera.worldTo2DScreen(cameraBoundingBox[3]); // Rotation of the coordinates to have no crossing lines while(p1[0]>p3[0]) { Coord tmp(p0); p0=p1; p1=p2; p2=p3; p3=tmp; } while(p1[1]<p3[1]) { Coord tmp(p0); p0=p3; p3=p2; p2=p1; p1=tmp; } if(generatePixmap) { bool edgesLabels=baseScene.getGlGraphComposite()->getRenderingParametersPointer()->isViewEdgeLabel(); bool nodesLabels=baseScene.getGlGraphComposite()->getRenderingParametersPointer()->isViewNodeLabel(); bool metaNodesLabels=baseScene.getGlGraphComposite()->getRenderingParametersPointer()->isViewMetaLabel(); baseScene.getGlGraphComposite()->getRenderingParametersPointer()->setViewEdgeLabel(false); baseScene.getGlGraphComposite()->getRenderingParametersPointer()->setViewNodeLabel(false); baseScene.getGlGraphComposite()->getRenderingParametersPointer()->setViewMetaLabel(false); vector<bool> layersVisibility; const vector<pair<string, GlLayer*> > &layersList=baseScene.getLayersList(); for(vector<pair<string, GlLayer*> >::const_iterator it=layersList.begin(); it!=layersList.end(); ++it) { layersVisibility.push_back(it->second->isVisible()); if(it->second->isAWorkingLayer()) it->second->setVisible(false); if(_hiddenLayers.count(it->first)!=0) it->second->setVisible(false); } // Draw the scene GlOffscreenRenderer::getInstance()->setViewPortSize(width-2*_frameWidth, height-2*_frameWidth); GlOffscreenRenderer::getInstance()->renderExternalScene(&baseScene, true); vector<bool>::iterator itTmp=layersVisibility.begin(); for(vector<pair<string, GlLayer*> >::const_iterator it=layersList.begin(); it!=layersList.end(); ++it) { if((*itTmp)==true) it->second->setVisible(true); ++itTmp; } GlGraphRenderingParameters *param = baseScene.getGlGraphComposite()->getRenderingParametersPointer(); param->setViewEdgeLabel(edgesLabels); param->setViewNodeLabel(nodesLabels); param->setViewMetaLabel(metaNodesLabels); } // invert applied camera transformations unsigned int i=0; for(vector<pair<string, GlLayer*> >::const_iterator it=layerList.begin(); it!=layerList.end(); ++it) { it->second->getCamera()=cameras[i]; ++i; } // invert applied viewport baseScene.setViewport(backupViewport); if(generatePixmap) { // Load scene pixmap to the item QPixmap pixmap; QImage img = GlOffscreenRenderer::getInstance()->getImage(); pixmap.convertFromImage(img); overview.setPos(_frameWidth, _frameWidth); overview.setPixmap(pixmap); } // set lines and polygons coordinates line[0].setLine(width-2*_frameWidth,0,p0[0],height-p0[1]); line[1].setLine(0,0,p1[0],height-p1[1]); line[2].setLine(0,height-2*_frameWidth,p2[0],height-p2[1]); line[3].setLine(width-2*_frameWidth,height-2*_frameWidth,p3[0],height-p3[1]); line[4].setLine(p0[0],height-p0[1], p1[0],height-p1[1]); line[5].setLine(p1[0],height-p1[1], p2[0],height-p2[1]); line[6].setLine(p2[0],height-p2[1], p3[0],height-p3[1]); line[7].setLine(p3[0],height-p3[1], p0[0],height-p0[1]); QVector<QPointF> tmpVect; tmpVect.push_back(QPointF(width-2*_frameWidth,0)); tmpVect.push_back(QPointF(p0[0],height-p0[1])); tmpVect.push_back(QPointF(p1[0],height-p1[1])); tmpVect.push_back(QPointF(0,0)); poly[0].setPolygon(QPolygonF(tmpVect)); tmpVect.clear(); tmpVect.push_back(QPointF(0,0)); tmpVect.push_back(QPointF(p1[0],height-p1[1])); tmpVect.push_back(QPointF(p2[0],height-p2[1])); tmpVect.push_back(QPointF(0,height-2*_frameWidth)); poly[1].setPolygon(QPolygonF(tmpVect)); tmpVect.clear(); tmpVect.push_back(QPointF(0,height-2*_frameWidth)); tmpVect.push_back(QPointF(p2[0],height-p2[1])); tmpVect.push_back(QPointF(p3[0],height-p3[1])); tmpVect.push_back(QPointF(width-2*_frameWidth,height-2*_frameWidth)); poly[2].setPolygon(QPolygonF(tmpVect)); tmpVect.clear(); tmpVect.push_back(QPointF(width-2*_frameWidth,height-2*_frameWidth)); tmpVect.push_back(QPointF(p3[0],height-p3[1])); tmpVect.push_back(QPointF(p0[0],height-p0[1])); tmpVect.push_back(QPointF(width-2*_frameWidth,0)); poly[3].setPolygon(QPolygonF(tmpVect)); QPen pen(QColor(_frameColor[0], _frameColor[1], _frameColor[2], _frameColor[3])); pen.setWidth(_frameWidth); pen.setJoinStyle(Qt::MiterJoin); overviewBorder.setPen(pen); }
int main(int argc, char *argv[]) { // We don't need meego graphics system setenv("QT_GRAPHICSSYSTEM", "raster", 1); #ifdef WINDOW_DEBUG // React to context-commander's fake events; required by test20.py // to be able to fake a phone call. setenv("CONTEXT_COMMANDING", "1", 1); #endif // Don't load any Qt plugins QCoreApplication::setLibraryPaths(QStringList()); MCompositeManager app(argc, argv); QGraphicsScene *scene = app.scene(); QGraphicsView view(scene); view.setProperty("NoMStyle", true); view.setUpdatesEnabled(false); view.setAutoFillBackground(false); view.setBackgroundBrush(Qt::NoBrush); view.setForegroundBrush(Qt::NoBrush); view.setFrameShadow(QFrame::Plain); view.setWindowFlags(Qt::X11BypassWindowManagerHint); view.setAttribute(Qt::WA_NoSystemBackground); #if QT_VERSION >= 0x040600 view.move(-2, -2); view.setViewportUpdateMode(QGraphicsView::NoViewportUpdate); view.setOptimizationFlags(QGraphicsView::IndirectPainting); #endif app.setSurfaceWindow(view.winId()); view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); view.setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); view.setMinimumSize(QApplication::desktop()->width() + 2, QApplication::desktop()->height() + 2); view.setMaximumSize(QApplication::desktop()->width() + 2, QApplication::desktop()->height() + 2); QGLFormat fmt; fmt.setSamples(0); fmt.setSampleBuffers(false); QGLWidget *w = new QGLWidget(fmt); w->setAttribute(Qt::WA_PaintOutsidePaintEvent); #ifndef GLES2_VERSION QPalette p = w->palette(); p.setColor(QPalette::Background, QColor(Qt::black)); w->setPalette(p); w->update(); #endif w->setAutoFillBackground(false); w->setMinimumSize(QApplication::desktop()->width(), QApplication::desktop()->height()); w->setMaximumSize(QApplication::desktop()->width(), QApplication::desktop()->height()); app.setGLWidget(w); view.setViewport(w); w->makeCurrent(); view.show(); // The directory is hard-coded for now. could be moved this // to $plugindir later. int testPlugin; const QStringList &args = app.arguments(); app.prepareEvents(); app.redirectWindows(); for (testPlugin = 1; testPlugin < args.length(); testPlugin++) if (!args[testPlugin].isEmpty() && args[testPlugin][0] != '-') break; app.loadPlugins(testPlugin < args.length() ? args[testPlugin] : QString(), "/usr/lib/mcompositor"); return app.exec(); }
CgContext::CgContext() : mbGpuSupported(false), mCgContext(0), mVertexIdentityProfile(CG_PROFILE_UNKNOWN), mFragmentIdentityProfile(CG_PROFILE_UNKNOWN) { const QGLContext* pContext = QGLContext::currentContext(); bool validGlContext = ( (pContext != NULL) && (pContext->isValid()) ); QGLWidget* pGlWidget = NULL; if (!validGlContext) { //create a valid open gl context, so that the Cg //context can be initialized correctly class tmpGL : public QGLWidget { public: tmpGL(QWidget *parent) : QGLWidget(parent) {} protected: virtual void initializeGL() {} virtual void resizeGL(int w, int h) {} virtual void paintGL() {} private: tmpGL(const tmpGL& rhs) {} tmpGL& operator=(const tmpGL& rhs) { return *this; } }; pGlWidget = new tmpGL(NULL); pGlWidget->makeCurrent(); } glewInit(); mCgContext = cgCreateContext(); if (mCgContext) { bool bVertexCgProgramsSupported = true; bool bFragmentCgProgramsSupported = true; // Get the latest vertex profile or choose the CG_PROFILE_VP30 profile if (cgGLIsProfileSupported(cgGLGetLatestProfile(CG_GL_VERTEX))) { mVertexIdentityProfile = cgGLGetLatestProfile(CG_GL_VERTEX); } else if (cgGLIsProfileSupported(CG_PROFILE_VP30)) { mVertexIdentityProfile = CG_PROFILE_VP30; } else { bVertexCgProgramsSupported = false; } // Set the optimal options cgGLSetOptimalOptions(mVertexIdentityProfile); // Get the latest fragment profile or choose the CG_PROFILE_FP30 profile if (cgGLIsProfileSupported(cgGLGetLatestProfile(CG_GL_FRAGMENT))) { mFragmentIdentityProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); } else if (cgGLIsProfileSupported(CG_PROFILE_FP30)) { mFragmentIdentityProfile = CG_PROFILE_FP30; } else { bFragmentCgProgramsSupported = false; } // Set the optimal options cgGLSetOptimalOptions(mFragmentIdentityProfile); if ((bVertexCgProgramsSupported == true) && (bFragmentCgProgramsSupported == true)) { mbGpuSupported = true; } else { cgDestroyContext(mCgContext); mCgContext = 0; } } if (pGlWidget != NULL) { delete pGlWidget; } }
void GlSyncObjectMutex:: test() { string name = "GlSyncObjectMutex"; int argc = 1; char * argv = &name[0]; QApplication a(argc,&argv); QGLWidget w; w.makeCurrent (); thread t; // It should provide a mutex mechanism for OpenGL resources. try { unsigned vbo; GlException_SAFE_CALL( glGenBuffers (1, &vbo) ); unsigned texture; GlException_SAFE_CALL( glGenTextures (1, &texture) ); spinning_barrier barrier(2); // Most predictable benefit for large data sets, small datasets "might" work anyways int width = 1024; int height = 1024; const float N = 4*width*height; vector<float> result(N); vector<float> texture_init(N); vector<float> texture_update(N); auto resetVbosAndTexture = [&]() { for (unsigned i=0; i<N; i++) { result[i] = 1 + i; texture_init[i] = 2 + i; texture_update[i] = 3 + i; } GlException_SAFE_CALL( GlState::glBindBuffer (GL_ARRAY_BUFFER, vbo) ); GlException_SAFE_CALL( glBufferData (GL_ARRAY_BUFFER, sizeof(float)*N, &texture_update[0], GL_DYNAMIC_COPY) ); GlException_SAFE_CALL( GlState::glBindBuffer (GL_ARRAY_BUFFER, 0) ); GlException_SAFE_CALL( glBindTexture (GL_TEXTURE_2D, texture) ); GlException_SAFE_CALL( glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_FLOAT, &texture_init[0]) ); // read with glGetTexImage to create an OpenGL client read state of the texture GlException_SAFE_CALL( glGetTexImage (GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &result[0]) ); }; auto copyFromVboToTextureAsync = [&]() { GlException_SAFE_CALL( glBindTexture (GL_TEXTURE_2D, texture) ); GlException_SAFE_CALL( GlState::glBindBuffer (GL_PIXEL_UNPACK_BUFFER, vbo) ); GlException_SAFE_CALL( glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, 0) ); GlException_SAFE_CALL( GlState::glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0) ); }; auto copyFromTextureToResult = [&]() { GlException_SAFE_CALL( glBindTexture (GL_TEXTURE_2D, texture) ); GlException_SAFE_CALL( glGetTexImage (GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &result[0]) ); }; // Run OpenGL commands in a separate thread auto openglThread = [&](function<void()> f) { QGLWidget w2(0, &w); w2.makeCurrent (); f(); // Finish all OpenGL commands on the gpu before destroying thread glFinish(); }; // Take 1. single threaded { resetVbosAndTexture(); copyFromVboToTextureAsync(); copyFromTextureToResult(); EXCEPTION_ASSERT_EQUALS( 0, memcmp(&result[0], &texture_update[0], N*sizeof(float))); } // Take 2. multi-threaded, synchronized on cpu { resetVbosAndTexture(); t = thread(openglThread, [&](){ copyFromVboToTextureAsync(); barrier.wait (); glFlush (); barrier.wait (); }); barrier.wait (); copyFromTextureToResult(); // should not have gotten all data from the other thread even though // the gl commands are issued (thanks to barrier.wait()) EXCEPTION_ASSERT_NOTEQUALS( result[0], texture_update[0]); EXCEPTION_ASSERT_NOTEQUALS( result[N-1], texture_update[N-1]); EXCEPTION_ASSERT_EQUALS( result[0], texture_init[0]); EXCEPTION_ASSERT_EQUALS( result[N-1], texture_init[N-1]); EXCEPTION_ASSERT_EQUALS( 0, memcmp(&result[0], &texture_init[0], N*sizeof(float))); barrier.wait (); copyFromTextureToResult(); t.join (); // Even after a glFlush() the texture state was not updated because this context // has used the texture more recently and discarded the update EXCEPTION_ASSERT_EQUALS( 0, memcmp(&result[0], &texture_init[0], N*sizeof(float))); EXCEPTION_ASSERT_NOTEQUALS( 0, memcmp(&result[0], &texture_update[0], N*sizeof(float))); } // Take 3. multi-threaded, synchronized cpu and gpu with glFlush after write { resetVbosAndTexture(); t = thread(openglThread, [&](){ copyFromVboToTextureAsync(); glFlush (); barrier.wait (); }); barrier.wait (); copyFromTextureToResult(); t.join (); // the texture update is flushed to the gpu by the other thread // before this thread uses the texture // This time the transfer has finished EXCEPTION_ASSERT_EQUALS( result[0], texture_update[0]); EXCEPTION_ASSERT_EQUALS( result[N-1], texture_update[N-1]); EXCEPTION_ASSERT_EQUALS( 0, memcmp(&result[0], &texture_update[0], N*sizeof(float))); } // Take 4. multi-threaded, synchronized cpu and gpu with glClientWait before read, without glFlush { // unclear if/when GlSyncObjectMutex m(clientsync=false) is useful GlSyncObjectMutex m(true); resetVbosAndTexture(); t = thread(openglThread, [&](){ lock_guard<GlSyncObjectMutex> l(m); barrier.wait (); copyFromVboToTextureAsync(); (void)l; // RAII, mark a synchronization point in the command queue }); barrier.wait (); { lock_guard<GlSyncObjectMutex> l(m); copyFromTextureToResult(); (void)l; // RAII } t.join (); // GlSyncObjectMutex will make sure that when the texture is // modified in different threads they first wait for the other // update is finished // This time the transfer has finished EXCEPTION_ASSERT_EQUALS( result[0], texture_update[0]); EXCEPTION_ASSERT_EQUALS( result[N-1], texture_update[N-1]); EXCEPTION_ASSERT_EQUALS( 0, memcmp(&result[0], &texture_update[0], N*sizeof(float))); } GlException_SAFE_CALL( glDeleteBuffers (1, &vbo) ); GlException_SAFE_CALL( glDeleteTextures (1, &texture) ); } catch (...) { if (t.joinable ()) t.join (); throw; } }
/*! Overridden from QGLWidget to render the scenegraph */ void QuarterWidget::paintEvent(QPaintEvent* event) { std::clock_t begin = std::clock(); if(!initialized) { glEnable(GL_DEPTH_TEST); this->getSoRenderManager()->reinitialize(); initialized = true; } getSoRenderManager()->activate(); glEnable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); QGLWidget* w = static_cast<QGLWidget*>(this->viewport()); assert(w->isValid() && "No valid GL context found!"); // We might have to process the delay queue here since we don't know // if paintGL() is called from Qt, and we might have some sensors // waiting to trigger (the redraw sensor has a lower priority than a // normal field sensor to guarantee that your sensor is processed // before the next redraw). Disable autorendering while we do this // to avoid recursive redraws. // We set the PRIVATE(this)->processdelayqueue = false in redraw() // to avoid processing the delay queue when paintGL() is triggered // by us, and we don't want to process the delay queue in those // cases PRIVATE(this)->autoredrawenabled = false; if(PRIVATE(this)->processdelayqueue && SoDB::getSensorManager()->isDelaySensorPending()) { // processing the sensors might trigger a redraw in another // context. Release this context temporarily w->doneCurrent(); SoDB::getSensorManager()->processDelayQueue(false); w->makeCurrent(); } assert(w->isValid() && "No valid GL context found!"); glDrawBuffer(w->doubleBuffer() ? GL_BACK : GL_FRONT); w->makeCurrent(); this->actualRedraw(); //start the standard graphics view processing for all widgets and graphic items. As //QGraphicsView initaliizes a QPainter which changes the Opengl context in an unpredictable //manner we need to store the context and recreate it after Qt is done. glPushAttrib(GL_MULTISAMPLE_BIT_EXT); inherited::paintEvent(event); glPopAttrib(); if (w->doubleBuffer()) { w->swapBuffers(); } PRIVATE(this)->autoredrawenabled = true; // process the delay queue the next time we enter this function, // unless we get here after a call to redraw(). PRIVATE(this)->processdelayqueue = true; std::clock_t end = std::clock(); renderTime = double(double(end-begin)/CLOCKS_PER_SEC)*1000.0; }
void Layer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { QtPainter *qvpainter = NULL; #ifdef QT_OPENGL_LIB QPainter *fboPainter; QGLFramebufferObject *fbo = NULL; QGLWidget *qglWidget = qobject_cast<QGLWidget *>(widget); if (qglWidget) { // on-screen OpenGL QGLContext *context = const_cast<QGLContext *>(qglWidget->context()); qvpainter = new OpenGLPainter(painter, context); } else if (cacheMode() != QGraphicsItem::NoCache && QGLFramebufferObject::hasOpenGLFramebufferObjects()) { // caching, try FBO // if we have direct rendering and FBO support, make use of // FBO, but this could still just be in software // NOTE: In Qt 4.6, 'painter' would already target an FBO, if we // were using the 'OpenGL2' paint engine. We have decided to stick // with the original engine for now, as the OpenGL2 engine relies // heavily on shaders, which is slow for our use case. // Apparently, we must use the QGLContext associated with // the view being painted. Thus, PlotView tracks whether it is // inside a paintEvent, so we can get the current QGLWidget. OverlayScene *overlayScene = qobject_cast<OverlayScene *>(scene()); if (overlayScene) qglWidget = qobject_cast<QGLWidget *>(overlayScene->view()->viewport()); else { QList<QGraphicsView *> views = scene()->views(); for (int i = 0; i < views.size() && !qglWidget; i++) { PlotView *view = qobject_cast<PlotView *>(views[i]); if (view && view->isPainting()) qglWidget = qobject_cast<QGLWidget *>(view->viewport()); } } if (qglWidget) { QSize size(painter->device()->width(), painter->device()->height()); QGLContext *context = const_cast<QGLContext *>(qglWidget->context()); // GC during paint callback may have reset this if (qglWidget->context() != QGLContext::currentContext()) qglWidget->makeCurrent(); // NOTE: need Qt 4.6 for antialiasing to work with FBOs #if QT_VERSION >= 0x40600 if (!fboMultisamplingFailed) { QGLFramebufferObjectFormat fboFormat; fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil); fboFormat.setSamples(4); // 4X antialiasing should be enough? qInstallMsgHandler(fboDebugMsgCatcher); fbo = new QGLFramebufferObject(size, fboFormat); qInstallMsgHandler(0); if (fboMultisamplingFailed) { delete fbo; fbo = NULL; } } #endif if (!fbo) fbo = new QGLFramebufferObject(size); // clear the FBO fboPainter = new QPainter(fbo); fboPainter->setCompositionMode(QPainter::CompositionMode_Source); fboPainter->fillRect(0, 0, size.width(), size.height(), Qt::transparent); fboPainter->setCompositionMode(QPainter::CompositionMode_SourceOver); qvpainter = new OpenGLPainter(fboPainter, context); qvpainter->setTransform(painter->worldTransform()); } } #endif if (!qvpainter) // fallback to Qt renderer qvpainter = new QtPainter(painter); // NOTE: in QT 4.6 exposedRect will just be the bounding rect, by default paintPlot(qvpainter, option->exposedRect); delete qvpainter; #ifdef QT_OPENGL_LIB if (fbo) { // silliness: download to image, only to upload to texture painter->setWorldMatrixEnabled(false); qglWidget->makeCurrent(); // gc during callback may have cleared this // need to tell Qt that 'fboImage' is actually premultiplied QImage fboImage = fbo->toImage(); const uchar *data = fboImage.bits(); // no deep copy QImage premultImage = QImage(data, fboImage.width(), fboImage.height(), QImage::Format_ARGB32_Premultiplied); // Not sure why this can't be (0, 0)... painter->drawImage(QPointF(1, -1), premultImage); delete fboPainter; delete fbo; } #endif }
void GlTraceFilterModel::checkExtensions() { const GLubyte *extensionString, *versionString; int supportedMajor, supportedMinor; QGLWidget w; w.makeCurrent(); extensionString = glGetString(GL_EXTENSIONS); versionString = glGetString(GL_VERSION); supportedMajor = versionString[0] - '0'; supportedMinor = versionString[2] - '0'; QByteArray extensions = QByteArray( reinterpret_cast<const char*>(extensionString)); #ifdef GLSLDB_WIN PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = 0; wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); if(wglGetExtensionsStringARB) { extensions.append(' '); extensions.append(QByteArray(reinterpret_cast<const char*>(wglGetExtensionsStringARB(wglGetCurrentDC())))); } #elif defined(GLSLDB_LINUX) int supportedXMajor, supportedXMinor; const char *versionXString; versionXString = glXQueryServerString(XOpenDisplay(NULL), 0, GLX_VERSION); supportedXMajor = versionXString[0] - '0'; supportedXMinor = versionXString[2] - '0'; extensions.append(' '); extensions.append( QByteArray( reinterpret_cast<const char*>(glXQueryServerString( XOpenDisplay(NULL), 0, GLX_EXTENSIONS)))); extensions.append(' '); extensions.append( QByteArray( reinterpret_cast<const char*>(glXGetClientString( XOpenDisplay(NULL), GLX_EXTENSIONS)))); extensions.append(' '); extensions.append( QByteArray( reinterpret_cast<const char*>(glXQueryExtensionsString( XOpenDisplay(NULL), 0)))); #elif defined(GLSLDB_OSX) #warning "FIXME: any OSX specific extensions wee need to add here?" #endif QList<QByteArray> extList = extensions.split(' '); for (int i = 0; i < this->rootItem->childCount(); i++) { GlTraceFilterItem *item = this->rootItem->child(i); if (strstr(item->function->extname, "GL_VERSION_") == item->function->extname) { int major, minor; major = item->function->extname[11] - '0'; minor = item->function->extname[13] - '0'; if (major < supportedMajor || (major == supportedMajor && minor <= supportedMinor)) { item->isSupported = true; } else { item->isSupported = false; } } #if defined(_WIN32) else if (strstr(item->function->extname, "WGL_VERSION_") == item->function->extname) { item->isSupported = true; } #elif defined(GLSLDB_LINUX) else if (strstr(item->function->extname, "GLX_VERSION_") == item->function->extname) { int major, minor; major = item->function->extname[12] - '0'; minor = item->function->extname[14] - '0'; if (major < supportedXMajor || (major == supportedXMajor && minor <= supportedXMinor)) { item->isSupported = true; } else { item->isSupported = false; } } #elif defined(GLSLDB_OSX) #warning "FIXME: any OSX specific extensions wee need to add here?" #endif else { item->isSupported = extList.contains(item->function->extname); } } }
bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget) { QGLWidget dmy; dmy.makeCurrent(); // needed for wglGetProcAddress() to succeed PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC) wglGetProcAddress("wglCreatePbufferARB"); PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC) wglGetProcAddress("wglGetPbufferDCARB"); PFNWGLQUERYPBUFFERARBPROC wglQueryPbufferARB = (PFNWGLQUERYPBUFFERARBPROC) wglGetProcAddress("wglQueryPbufferARB"); PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) wglGetProcAddress("wglChoosePixelFormatARB"); if (!wglCreatePbufferARB) // assumes that if one can be resolved, all of them can return false; dc = GetDC(dmy.winId()); Q_ASSERT(dc); PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB"); if (wglGetExtensionsStringARB) { QString extensions(QLatin1String(wglGetExtensionsStringARB(dc))); has_render_texture = extensions.contains(QLatin1String("WGL_ARB_render_texture")); } int attribs[40]; qt_format_to_attrib_list(has_render_texture, f, attribs); // Find pbuffer capable pixel format. unsigned int num_formats = 0; int pixel_format; wglChoosePixelFormatARB(dc, attribs, 0, 1, &pixel_format, &num_formats); // some GL implementations don't support pbuffers with accum // buffers, so try that before we give up if (num_formats == 0 && f.accum()) { QGLFormat tmp = f; tmp.setAccum(false); qt_format_to_attrib_list(has_render_texture, tmp, attribs); wglChoosePixelFormatARB(dc, attribs, 0, 1, &pixel_format, &num_formats); } if (num_formats == 0) { qWarning("QGLPixelBuffer: Unable to find a pixel format with pbuffer - giving up."); ReleaseDC(dmy.winId(), dc); return false; } format = pfiToQGLFormat(dc, pixel_format); // NB! The below ONLY works if the width/height are powers of 2. // Set some pBuffer attributes so that we can use this pBuffer as // a 2D RGBA texture target. int pb_attribs[] = {WGL_TEXTURE_FORMAT_ARB, WGL_TEXTURE_RGBA_ARB, WGL_TEXTURE_TARGET_ARB, WGL_TEXTURE_2D_ARB, 0}; pbuf = wglCreatePbufferARB(dc, pixel_format, size.width(), size.height(), has_render_texture ? pb_attribs : 0); if(!pbuf) { // try again without the render_texture extension pbuf = wglCreatePbufferARB(dc, pixel_format, size.width(), size.height(), 0); has_render_texture = false; if (!pbuf) { qWarning("QGLPixelBuffer: Unable to create pbuffer [w=%d, h=%d] - giving up.", size.width(), size.height()); ReleaseDC(dmy.winId(), dc); return false; } } ReleaseDC(dmy.winId(), dc); dc = wglGetPbufferDCARB(pbuf); ctx = wglCreateContext(dc); if (!dc || !ctx) { qWarning("QGLPixelBuffer: Unable to create pbuffer context - giving up."); return false; } HGLRC share_ctx = shareWidget ? shareWidget->d_func()->glcx->d_func()->rc : 0; if (share_ctx && !wglShareLists(share_ctx, ctx)) qWarning("QGLPixelBuffer: Unable to share display lists - with share widget."); int width, height; wglQueryPbufferARB(pbuf, WGL_PBUFFER_WIDTH_ARB, &width); wglQueryPbufferARB(pbuf, WGL_PBUFFER_HEIGHT_ARB, &height); return true; }
MythRenderOpenGL* MythRenderOpenGL::Create(const QString &painter, QPaintDevice* device) { #ifdef USE_OPENGL_QT5 MythRenderFormat format = QSurfaceFormat::defaultFormat(); format.setDepthBufferSize(0); format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); # ifdef USING_OPENGLES format.setRenderableType(QSurfaceFormat::OpenGLES); # endif #else MythRenderFormat format = QGLFormat(QGL::NoDepthBuffer); #endif bool setswapinterval = false; int synctovblank = -1; #ifdef USING_X11 synctovblank = CheckNVOpenGLSyncToVBlank(); #endif if (synctovblank < 0) { LOG(VB_GENERAL, LOG_WARNING, LOC + "Could not determine whether Sync " "to VBlank is enabled."); } else if (synctovblank == 0) { // currently only Linux NVidia is supported and there is no way of // forcing sync to vblank after the app has started. util-nvctrl will // warn the user and offer advice on settings. } else { LOG(VB_GENERAL, LOG_INFO, LOC + "Sync to VBlank is enabled (good!)"); } #if defined(Q_OS_MAC) LOG(VB_GENERAL, LOG_INFO, LOC + "Forcing swap interval for OS X."); setswapinterval = true; #endif if (setswapinterval) format.setSwapInterval(1); #if ANDROID int openGLVersionFlags = QGLFormat::OpenGL_ES_Version_2_0; LOG(VB_GENERAL, LOG_INFO, "OpenGL ES2 forced for Android"); #elif defined USE_OPENGL_QT5 && defined USING_OPENGLES int openGLVersionFlags = QGLFormat::OpenGL_ES_Version_2_0; #else // Check OpenGL version supported QGLWidget *dummy = new QGLWidget; dummy->makeCurrent(); QGLFormat qglFormat = dummy->format(); int openGLVersionFlags = qglFormat.openGLVersionFlags(); delete dummy; #endif #ifdef USING_OPENGLES if (!(openGLVersionFlags & QGLFormat::OpenGL_ES_Version_2_0)) { LOG(VB_GENERAL, LOG_WARNING, "Using OpenGL ES 2.0 render, however OpenGL ES 2.0 " "version not supported"); } if (device) return new MythRenderOpenGL2ES(format, device); return new MythRenderOpenGL2ES(format); #else if ((openGLVersionFlags & QGLFormat::OpenGL_Version_2_0) && (painter.contains(OPENGL2_PAINTER) || painter.contains(AUTO_PAINTER) || painter.isEmpty())) { LOG(VB_GENERAL, LOG_INFO, "Trying the OpenGL 2.0 render"); format.setVersion(2,0); if (device) return new MythRenderOpenGL2(format, device); return new MythRenderOpenGL2(format); } if (!(openGLVersionFlags & QGLFormat::OpenGL_Version_1_2)) { LOG(VB_GENERAL, LOG_WARNING, "OpenGL 1.2 not supported, get new hardware!"); return NULL; } LOG(VB_GENERAL, LOG_INFO, "Trying the OpenGL 1.2 render"); format.setVersion(1,3); if (device) return new MythRenderOpenGL1(format, device); return new MythRenderOpenGL1(format); #endif }
/*! Empty method in Coin. Can be used by subclasses to be told when status change. */ void SoFCSelection::redrawHighlighted(SoAction * action , SbBool doHighlight ) { //Base::Console().Log("SoFCSelection::redrawHighlighted() (%p) doHigh=%d \n",this,doHighlight?1:0); #ifdef NO_FRONTBUFFER #else // If we are about to highlight, and there is something else highlighted, // that something else needs to unhighlight. if (doHighlight && currenthighlight != NULL && !(*((SoFullPath *)action->getCurPath()) == *currenthighlight)) { SoNode *tail = currenthighlight->getTail(); if (tail->isOfType( SoFCSelection::getClassTypeId())) ((SoFCSelection *)tail)->redrawHighlighted(action, FALSE); else { // Just get rid of the path. It's no longer valid for redraw. currenthighlight->unref(); currenthighlight = NULL; } } SoPath *pathToRender; // save the path to ourself for later de-highlight if (doHighlight) { if (currenthighlight != NULL) currenthighlight->unref(); currenthighlight = (SoFullPath *) action->getCurPath()->copy(); currenthighlight->ref(); // We will be rendering this new path to highlight it pathToRender = currenthighlight; pathToRender->ref(); } // delete our path if we are no longer highlighted else { if (currenthighlight) { // We will be rendering this old path to unhighlight it pathToRender = currenthighlight; pathToRender->ref(); currenthighlight->unref(); currenthighlight = NULL; } } // If highlighting is forced on for this node, we don't need this special render. if (highlightMode.getValue() != AUTO) { pathToRender->unref(); return; } SoState *state = action->getState(); //void* window; //void* context; //void *display; QGLWidget* window; SoGLRenderAction *glAction; //SoWindowElement::get(state, window, context, display, glAction); SoGLWidgetElement::get(state, window); SoGLRenderActionElement::get(state, glAction); // If we don't have a current window, then simply return... if (window == 0 /*|| context == NULL || display == NULL*/ || glAction == NULL) return; window->makeCurrent(); #ifndef WIN32 // set the current window //glXMakeCurrent(display, window, context); #endif // render into the front buffer (save the current buffering type) GLint whichBuffer; glGetIntegerv(GL_DRAW_BUFFER, &whichBuffer); if (whichBuffer != GL_FRONT) glDrawBuffer(GL_FRONT); highlighted = TRUE; glAction->apply(pathToRender); highlighted = FALSE; // restore the buffering type if (whichBuffer != GL_FRONT) glDrawBuffer((GLenum)whichBuffer); glFlush(); pathToRender->unref(); #endif }