Пример #1
0
CustomWindow::CustomWindow( QWindow *parent ) : QQuickWindow( parent ) {
    connect( this, &CustomWindow::vsyncChanged, this, &CustomWindow::vsyncChangedHandler );

    // Reinitalize the scene graph when the OpenGL context gets destroyed
    // Needed because only when the context gets recreated is the format read
    setPersistentOpenGLContext( false );
    setPersistentSceneGraph( false );

    // Grab window surface format as the OpenGL context will not be created yet
    QSurfaceFormat fmt = format();

#if defined( Q_OS_WIN )

    // Set buffering mode
    // Testing shows that on Windows, vsync stays on (swapBuffers() blocks) while single buffered
    // even when the swap interval is 0 and even while fullscreen! So, we have to turn on double buffering if we
    // want vsync to actually be off, but turn on single buffering while vsynced to avoid unnecessary additional latency
    fmt.setSwapBehavior( vsync ? QSurfaceFormat::SingleBuffer : QSurfaceFormat::DoubleBuffer );
    emit doubleBufferedChanged( fmt.swapBehavior() == QSurfaceFormat::DoubleBuffer );

#elif defined( Q_OS_MACX )

    fmt.setSwapBehavior( QSurfaceFormat::SingleBuffer );
    emit doubleBufferedChanged( fmt.swapBehavior() == QSurfaceFormat::DoubleBuffer );

    // For proper OS X fullscreen
    setFlags( flags() | Qt::WindowFullscreenButtonHint );

#endif

    // Enforce the default value for vsync
    fmt.setSwapInterval( vsync ? 1 : 0 );
    setFormat( fmt );

}
Пример #2
0
static PIXELFORMATDESCRIPTOR
    qPixelFormatFromSurfaceFormat(const QSurfaceFormat &format,
                                  const QWindowsOpenGLAdditionalFormat &additional)
{
    PIXELFORMATDESCRIPTOR pfd;
    initPixelFormatDescriptor(&pfd);
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.iLayerType  = PFD_MAIN_PLANE;
    pfd.dwFlags = PFD_SUPPORT_OPENGL;
    if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA)
        pfd.dwFlags = PFD_SUPPORT_COMPOSITION;
    const bool isPixmap = (additional.formatFlags & QWindowsGLRenderToPixmap) != 0;
    pfd.dwFlags |= isPixmap ? PFD_DRAW_TO_BITMAP : PFD_DRAW_TO_WINDOW;
    if (!(additional.formatFlags & QWindowsGLDirectRendering))
        pfd.dwFlags |= PFD_GENERIC_FORMAT;

    if (format.stereo())
        pfd.dwFlags |= PFD_STEREO;
    if (format.swapBehavior() == QSurfaceFormat::DoubleBuffer && !isPixmap)
        pfd.dwFlags |= PFD_DOUBLEBUFFER;
    pfd.cDepthBits =
        format.depthBufferSize() >= 0 ? format.depthBufferSize() : 32;
    pfd.cAlphaBits = format.alphaBufferSize() > 0 ? format.alphaBufferSize() : 8;
    pfd.cStencilBits = format.stencilBufferSize() > 0 ? format.stencilBufferSize() : 8;
    if (additional.formatFlags & QWindowsGLAccumBuffer)
        pfd.cAccumRedBits = pfd.cAccumGreenBits = pfd.cAccumBlueBits = pfd.cAccumAlphaBits = 16;
    return pfd;
}
Пример #3
0
void CustomWindow::vsyncChangedHandler( bool vsync ) {
    QSurfaceFormat fmt = format();

    // Grab OpenGL context surface format if it's ready to go, it's more filled out than the window one
    // It can be unitialized on startup before so check that it exists before using it
    if( openglContext() ) {
        fmt = openglContext()->format();
    }

#if defined( Q_OS_WIN )

    fmt.setSwapBehavior( vsync ? QSurfaceFormat::SingleBuffer : QSurfaceFormat::DoubleBuffer );

#elif defined( Q_OS_MACX )

    // Leave it alone, OS X happily accepts single buffering

#endif

    fmt.setSwapInterval( vsync ? 1 : 0 );

    // Window must be reset to apply the changes
    resetPlatformWindow( fmt );

    emit doubleBufferedChanged( fmt.swapBehavior() == QSurfaceFormat::DoubleBuffer );
}
Пример #4
0
QT_BEGIN_NAMESPACE

/*!
    Returns an OpenGL format for the window format specified by \a format.
*/
QGLFormat QGLFormat::fromSurfaceFormat(const QSurfaceFormat &format)
{
    QGLFormat retFormat;
    if (format.alphaBufferSize() >= 0)
        retFormat.setAlphaBufferSize(format.alphaBufferSize());
    if (format.blueBufferSize() >= 0)
        retFormat.setBlueBufferSize(format.blueBufferSize());
    if (format.greenBufferSize() >= 0)
        retFormat.setGreenBufferSize(format.greenBufferSize());
    if (format.redBufferSize() >= 0)
        retFormat.setRedBufferSize(format.redBufferSize());
    if (format.depthBufferSize() >= 0)
        retFormat.setDepthBufferSize(format.depthBufferSize());
    if (format.samples() > 1) {
        retFormat.setSampleBuffers(format.samples());
        retFormat.setSamples(true);
    }
    if (format.stencilBufferSize() > 0) {
        retFormat.setStencil(true);
        retFormat.setStencilBufferSize(format.stencilBufferSize());
    }
    retFormat.setDoubleBuffer(format.swapBehavior() != QSurfaceFormat::SingleBuffer);
    retFormat.setStereo(format.stereo());
    return retFormat;
}
Пример #5
0
QSurfaceFormat qglx_reduceSurfaceFormat(const QSurfaceFormat &format, bool *reduced)
{
    QSurfaceFormat retFormat = format;
    *reduced = true;

    if (retFormat.redBufferSize() > 1) {
        retFormat.setRedBufferSize(1);
    } else if (retFormat.greenBufferSize() > 1) {
        retFormat.setGreenBufferSize(1);
    } else if (retFormat.blueBufferSize() > 1) {
        retFormat.setBlueBufferSize(1);
    } else if (retFormat.samples() > 1) {
        retFormat.setSamples(qMin(retFormat.samples() / 2, 16));
    } else if (retFormat.stereo()) {
        retFormat.setStereo(false);
    }else if (retFormat.stencilBufferSize() > 0) {
        retFormat.setStencilBufferSize(0);
    }else if (retFormat.hasAlpha()) {
        retFormat.setAlphaBufferSize(0);
    }else if (retFormat.depthBufferSize() > 0) {
        retFormat.setDepthBufferSize(0);
    }else if (retFormat.swapBehavior() != QSurfaceFormat::SingleBuffer) {
        retFormat.setSwapBehavior(QSurfaceFormat::SingleBuffer);
    }else{
        *reduced = false;
    }
    return retFormat;
}
Пример #6
0
XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format)
{
    Q_ASSERT(format);

    XVisualInfo *visualInfo = 0;

    GLXFBConfig config = qglx_findConfig(display,screen,*format);
    if (config) {
        visualInfo = glXGetVisualFromFBConfig(display, config);
        *format = qglx_surfaceFormatFromGLXFBConfig(display, config);
    }

    // attempt to fall back to glXChooseVisual
    bool reduced = true;
    QSurfaceFormat reducedFormat = *format;
    while (!visualInfo && reduced) {
        QVarLengthArray<int, 13> attribs;
        attribs.append(GLX_RGBA);

        if (reducedFormat.redBufferSize() > 0) {
            attribs.append(GLX_RED_SIZE);
            attribs.append(reducedFormat.redBufferSize());
        }

        if (reducedFormat.greenBufferSize() > 0) {
            attribs.append(GLX_GREEN_SIZE);
            attribs.append(reducedFormat.greenBufferSize());
        }

        if (reducedFormat.blueBufferSize() > 0) {
            attribs.append(GLX_BLUE_SIZE);
            attribs.append(reducedFormat.blueBufferSize());
        }

        if (reducedFormat.stencilBufferSize() > 0) {
            attribs.append(GLX_STENCIL_SIZE);
            attribs.append(reducedFormat.stencilBufferSize());
        }

        if (reducedFormat.depthBufferSize() > 0) {
            attribs.append(GLX_DEPTH_SIZE);
            attribs.append(reducedFormat.depthBufferSize());
        }

        if (reducedFormat.swapBehavior() != QSurfaceFormat::SingleBuffer)
            attribs.append(GLX_DOUBLEBUFFER);

        attribs.append(XNone);

        visualInfo = glXChooseVisual(display, screen, attribs.data());
        if (visualInfo)
            *format = reducedFormat;

        reducedFormat = qglx_reduceSurfaceFormat(reducedFormat, &reduced);
    }

    return visualInfo;
}
Пример #7
0
// Choose a suitable pixelformat using GDI WinAPI in case ARB
// functions cannot be found. First tries to find a suitable
// format using GDI function ChoosePixelFormat(). Since that
// does not handle overlay and direct-rendering requests, manually loop
// over the available formats to find the best one.
// Note: As of Windows 7, it seems direct-rendering is handled, so,
// the code might be obsolete?
static int choosePixelFormat(HDC hdc, const QSurfaceFormat &format,
                            const QWindowsOpenGLAdditionalFormat &additional,
                            PIXELFORMATDESCRIPTOR *obtainedPfd)
{
    // 1) Try ChoosePixelFormat().
    PIXELFORMATDESCRIPTOR requestedPfd = qPixelFormatFromSurfaceFormat(format, QWindowsGLDirectRendering);
    initPixelFormatDescriptor(obtainedPfd);
    int pixelFormat = ChoosePixelFormat(hdc, &requestedPfd);
    if (pixelFormat >= 0) {
        DescribePixelFormat(hdc, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), obtainedPfd);
        if (isAcceptableFormat(additional, *obtainedPfd))
            return pixelFormat;
    }
    // 2) No matching format found, manual search loop.
    const int pfiMax = DescribePixelFormat(hdc, 0, 0, NULL);
    int bestScore = -1;
    int bestPfi = -1;
    const bool stereoRequested = format.stereo();
    const bool accumBufferRequested = testFlag(additional.formatFlags, QWindowsGLAccumBuffer);
    const bool doubleBufferRequested = format.swapBehavior() == QSurfaceFormat::DoubleBuffer;
    const bool directRenderingRequested = testFlag(additional.formatFlags, QWindowsGLDirectRendering);
    for (int pfi = 1; pfi <= pfiMax; pfi++) {
        PIXELFORMATDESCRIPTOR checkPfd;
        initPixelFormatDescriptor(&checkPfd);
        DescribePixelFormat(hdc, pfi, sizeof(PIXELFORMATDESCRIPTOR), &checkPfd);
        if (isAcceptableFormat(additional, checkPfd)) {
            int score = checkPfd.cColorBits + checkPfd.cAlphaBits + checkPfd.cStencilBits;
            if (accumBufferRequested)
                score += checkPfd.cAccumBits;
            if (doubleBufferRequested == testFlag(checkPfd.dwFlags, PFD_DOUBLEBUFFER))
                score += 1000;
            if (stereoRequested == testFlag(checkPfd.dwFlags, PFD_STEREO))
                score += 2000;
            if (directRenderingRequested == isDirectRendering(checkPfd))
                score += 4000;
            if (checkPfd.iPixelType == PFD_TYPE_RGBA)
                score += 8000;
            if (score > bestScore) {
                bestScore = score;
                bestPfi = pfi;
                *obtainedPfd = checkPfd;
            }
            if (QWindowsContext::verboseGL)
                qDebug() << __FUNCTION__ << "    checking  " << pfi << '/' << pfiMax
                         << " score=" << score << " (best " << bestPfi << '/' << bestScore
                         << ") " << checkPfd;
        }
    } // for
    if (bestPfi > 0)
        pixelFormat = bestPfi;
    return pixelFormat;
}
Пример #8
0
QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit)
{
    QVector<int> spec(48);
    int i = 0;

    spec[i++] = GLX_LEVEL;
    spec[i++] = 0;
    spec[i++] = GLX_DRAWABLE_TYPE; spec[i++] = drawableBit;

    spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_RGBA_BIT;

    spec[i++] = GLX_RED_SIZE; spec[i++] = (format.redBufferSize() == -1) ? 1 : format.redBufferSize();
    spec[i++] = GLX_GREEN_SIZE; spec[i++] =  (format.greenBufferSize() == -1) ? 1 : format.greenBufferSize();
    spec[i++] = GLX_BLUE_SIZE; spec[i++] = (format.blueBufferSize() == -1) ? 1 : format.blueBufferSize();
    if (format.hasAlpha()) {
        spec[i++] = GLX_ALPHA_SIZE; spec[i++] = format.alphaBufferSize();
    }

    spec[i++] = GLX_DOUBLEBUFFER; spec[i++] = format.swapBehavior() != QSurfaceFormat::SingleBuffer ? True : False;

    spec[i++] = GLX_STEREO; spec[i++] =  format.stereo() ? True : False;

    if (format.depthBufferSize() > 0) {
        spec[i++] = GLX_DEPTH_SIZE; spec[i++] = format.depthBufferSize();
    }

    if (format.stencilBufferSize() > 0) {
        spec[i++] = GLX_STENCIL_SIZE; spec[i++] =  (format.stencilBufferSize() == -1) ? 1 : format.stencilBufferSize();
    }

    if (format.samples() > 1) {
        spec[i++] = GLX_SAMPLE_BUFFERS_ARB;
        spec[i++] = 1;
        spec[i++] = GLX_SAMPLES_ARB;
        spec[i++] = format.samples();
    }

    spec[i++] = XNone;
    return spec;
}
Пример #9
0
QString VariantHandler::displayString(const QVariant& value)
{
  switch (value.type()) {
#ifndef QT_NO_CURSOR
  case QVariant::Cursor:
  {
    const QCursor cursor = value.value<QCursor>();
    return Util::enumToString(QVariant::fromValue<int>(cursor.shape()), "Qt::CursorShape");
  }
#endif
  case QVariant::Icon:
  {
    const QIcon icon = value.value<QIcon>();
    if (icon.isNull()) {
      return QObject::tr("<no icon>");
    }
    QStringList l;
    foreach (const QSize &size, icon.availableSizes()) {
      l.push_back(displayString(size));
    }
    return l.join(QLatin1String(", "));
  }
  case QVariant::Line:
    return
      QString::fromUtf8("%1 x %2 → %3 x %4").
        arg(value.toLine().x1()).arg(value.toLine().y1()).
        arg(value.toLine().x2()).arg(value.toLine().y2());

  case QVariant::LineF:
    return
      QString::fromUtf8("%1 x %2 → %3 x %4").
        arg(value.toLineF().x1()).arg(value.toLineF().y1()).
        arg(value.toLineF().x2()).arg(value.toLineF().y2());

  case QVariant::Locale:
    return value.value<QLocale>().name();

  case QVariant::Point:
    return
      QString::fromLatin1("%1x%2").
        arg(value.toPoint().x()).
        arg(value.toPoint().y());

  case QVariant::PointF:
    return
      QString::fromLatin1("%1x%2").
        arg(value.toPointF().x()).
        arg(value.toPointF().y());

  case QVariant::Rect:
    return
      QString::fromLatin1("%1x%2 %3x%4").
        arg(value.toRect().x()).
        arg(value.toRect().y()).
        arg(value.toRect().width()).
        arg(value.toRect().height());

  case QVariant::RectF:
    return
      QString::fromLatin1("%1x%2 %3x%4").
        arg(value.toRectF().x()).
        arg(value.toRectF().y()).
        arg(value.toRectF().width()).
        arg(value.toRectF().height());

  case QVariant::Region:
  {
    const QRegion region = value.value<QRegion>();
    if (region.isEmpty()) {
      return QLatin1String("<empty>");
    }
    if (region.rectCount() == 1) {
      return displayString(region.rects().first());
    } else {
      return QString::fromLatin1("<%1 rects>").arg(region.rectCount());
    }
  }

  case QVariant::Palette:
  {
    const QPalette pal = value.value<QPalette>();
    if (pal == qApp->palette()) {
      return QLatin1String("<inherited>");
    }
    return QLatin1String("<custom>");
  }

  case QVariant::Size:
    return
      QString::fromLatin1("%1x%2").
        arg(value.toSize().width()).
        arg(value.toSize().height());

  case QVariant::SizeF:
    return
      QString::fromLatin1("%1x%2").
        arg(value.toSizeF().width()).
        arg(value.toSizeF().height());

  case QVariant::StringList:
    return value.toStringList().join(", ");

  case QVariant::Transform:
  {
    const QTransform t = value.value<QTransform>();
    return
      QString::fromLatin1("[%1 %2 %3, %4 %5 %6, %7 %8 %9]").
        arg(t.m11()).arg(t.m12()).arg(t.m13()).
        arg(t.m21()).arg(t.m22()).arg(t.m23()).
        arg(t.m31()).arg(t.m32()).arg(t.m33());
  }
  default:
    break;
  }

  // types with dynamic type ids
  if (value.type() == (QVariant::Type)qMetaTypeId<QTextLength>()) {
    const QTextLength l = value.value<QTextLength>();
    QString typeStr;
    switch (l.type()) {
    case QTextLength::VariableLength:
      typeStr = QObject::tr("variable");
      break;
    case QTextLength::FixedLength:
      typeStr = QObject::tr("fixed");
      break;
    case QTextLength::PercentageLength:
      typeStr = QObject::tr("percentage");
      break;
    }
    return QString::fromLatin1("%1 (%2)").arg(l.rawValue()).arg(typeStr);
  }

  if (value.userType() == qMetaTypeId<QPainterPath>()) {
    const QPainterPath path = value.value<QPainterPath>();
    if (path.isEmpty()) {
      return QObject::tr("<empty>");
    }
    return QObject::tr("<%1 elements>").arg(path.elementCount());
  }

  if (value.userType() == qMetaTypeId<QMargins>()) {
    const QMargins margins = value.value<QMargins>();
    return QObject::tr("left: %1, top: %2, right: %3, bottom: %4")
       .arg(margins.left()).arg(margins.top())
       .arg(margins.right()).arg(margins.bottom());
  }

  if (value.canConvert<QObject*>()) {
    return Util::displayString(value.value<QObject*>());
  }

#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
  if (value.userType() == qMetaTypeId<QSet<QByteArray> >()) {
    const QSet<QByteArray> set = value.value<QSet<QByteArray> >();
    QStringList l;
    foreach (const QByteArray &b, set)
      l.push_back(QString::fromUtf8(b));
    return l.join(", ");
  }

  if (value.userType() == qMetaTypeId<QSurfaceFormat>()) {
    const QSurfaceFormat format = value.value<QSurfaceFormat>();
    QString s;
    switch (format.renderableType()) {
      case QSurfaceFormat::DefaultRenderableType: s += "Default"; break;
      case QSurfaceFormat::OpenGL: s += "OpenGL"; break;
      case QSurfaceFormat::OpenGLES: s += "OpenGL ES"; break;
      case QSurfaceFormat::OpenVG: s += "OpenVG"; break;
    }

    s += " (" + QString::number(format.majorVersion()) + "." + QString::number(format.minorVersion());
    switch (format.profile()) {
      case QSurfaceFormat::CoreProfile: s += " core"; break;
      case QSurfaceFormat::CompatibilityProfile: s += " compat"; break;
      case QSurfaceFormat::NoProfile: break;
    }
    s += ")";

    s += " RGBA: " + QString::number(format.redBufferSize()) + "/" + QString::number(format.greenBufferSize())
      + "/" + QString::number(format.blueBufferSize()) + "/" + QString::number(format.alphaBufferSize());

    s += " Depth: " + QString::number(format.depthBufferSize());
    s += " Stencil: " + QString::number(format.stencilBufferSize());

    s += " Buffer: ";
    switch (format.swapBehavior()) {
      case QSurfaceFormat::DefaultSwapBehavior: s += "default"; break;
      case QSurfaceFormat::SingleBuffer: s += "single"; break;
      case QSurfaceFormat::DoubleBuffer: s += "double"; break;
      case QSurfaceFormat::TripleBuffer: s += "triple"; break;
      default: s += "unknown";
    }

    return s;
  }

  if (value.userType() == qMetaTypeId<QSurface::SurfaceClass>()) {
    const QSurface::SurfaceClass sc = value.value<QSurface::SurfaceClass>();
    switch (sc) {
      case QSurface::Window: return QObject::tr("Window");
#if QT_VERSION > QT_VERSION_CHECK(5, 1, 0)
      case QSurface::Offscreen: return QObject::tr("Offscreen");
#endif
      default: return QObject::tr("Unknown Surface Class");
    }
  }

  if (value.userType() == qMetaTypeId<QSurface::SurfaceType>()) {
    const QSurface::SurfaceType type = value.value<QSurface::SurfaceType>();
    switch (type) {
      case QSurface::RasterSurface: return QObject::tr("Raster");
      case QSurface::OpenGLSurface: return QObject::tr("OpenGL");
      default: return QObject::tr("Unknown Surface Type");
    }
  }

#endif

  // enums
  const QString enumStr = Util::enumToString(value);
  if (!enumStr.isEmpty()) {
    return enumStr;
  }

  // custom converters
  const QHash<int, Converter<QString>*>::const_iterator it = s_variantHandlerRepository()->stringConverters.constFind(value.userType());
  if (it != s_variantHandlerRepository()->stringConverters.constEnd()) {
    return (*it.value())(value);
  }

  return value.toString();
}
Пример #10
0
// Choose a suitable pixelformat using ARB extension functions.
static int choosePixelFormat(HDC hdc,
                             const QOpenGLStaticContext &staticContext,
                             const QSurfaceFormat &format,
                             const QWindowsOpenGLAdditionalFormat &additional,
                             PIXELFORMATDESCRIPTOR *obtainedPfd)
{
    enum { attribSize =40 };
    if ((additional.formatFlags & QWindowsGLRenderToPixmap) || !staticContext.hasExtensions())
        return 0;

    int iAttributes[attribSize];
    qFill(iAttributes, iAttributes + attribSize, int(0));
    int i = 0;
    iAttributes[i++] = WGL_ACCELERATION_ARB;
    iAttributes[i++] = testFlag(additional.formatFlags, QWindowsGLDirectRendering) ?
                       WGL_FULL_ACCELERATION_ARB : WGL_NO_ACCELERATION_ARB;
    iAttributes[i++] = WGL_SUPPORT_OPENGL_ARB;
    iAttributes[i++] = TRUE;
    iAttributes[i++] = WGL_DRAW_TO_WINDOW_ARB;
    iAttributes[i++] = TRUE;
    iAttributes[i++] = WGL_COLOR_BITS_ARB;
    iAttributes[i++] = 24;
    switch (format.swapBehavior()) {
    case QSurfaceFormat::DefaultSwapBehavior:
        break;
    case QSurfaceFormat::SingleBuffer:
        iAttributes[i++] = WGL_DOUBLE_BUFFER_ARB;
        iAttributes[i++] = FALSE;
        break;
    case QSurfaceFormat::DoubleBuffer:
    case QSurfaceFormat::TripleBuffer:
        iAttributes[i++] = WGL_DOUBLE_BUFFER_ARB;
        iAttributes[i++] = TRUE;
        break;
    }
    if (format.stereo()) {
        iAttributes[i++] = WGL_STEREO_ARB;
        iAttributes[i++] = TRUE;
    }
    if (format.depthBufferSize() >= 0) {
        iAttributes[i++] = WGL_DEPTH_BITS_ARB;
        iAttributes[i++] = format.depthBufferSize();
    }
    iAttributes[i++] = WGL_PIXEL_TYPE_ARB;
    iAttributes[i++] = WGL_TYPE_RGBA_ARB;
    if (format.redBufferSize() >= 0) {
        iAttributes[i++] = WGL_RED_BITS_ARB;
        iAttributes[i++] = format.redBufferSize();
    }
    if (format.greenBufferSize() >= 0) {
        iAttributes[i++] = WGL_GREEN_BITS_ARB;
        iAttributes[i++] = format.greenBufferSize();
    }
    if (format.blueBufferSize() >= 0) {
        iAttributes[i++] = WGL_BLUE_BITS_ARB;
        iAttributes[i++] = format.blueBufferSize();
    }
    iAttributes[i++] = WGL_ALPHA_BITS_ARB;
    iAttributes[i++] = format.alphaBufferSize() >= 0 ? format.alphaBufferSize() : 8;
    if (additional.formatFlags & QWindowsGLAccumBuffer) {
        iAttributes[i++] = WGL_ACCUM_BITS_ARB;
        iAttributes[i++] = 16;
    }
    iAttributes[i++] = WGL_STENCIL_BITS_ARB;
    iAttributes[i++] = 8;
    if (additional.formatFlags & QWindowsGLOverlay) {
        iAttributes[i++] = WGL_NUMBER_OVERLAYS_ARB;
        iAttributes[i++] = 1;
    }
    const int samples = format.samples();
    const bool sampleBuffersRequested = samples > 1
            && testFlag(staticContext.extensions, QOpenGLStaticContext::SampleBuffers);
    int samplesValuePosition = 0;
    if (sampleBuffersRequested) {
        iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB;
        iAttributes[i++] = TRUE;
        iAttributes[i++] = WGL_SAMPLES_ARB;
        samplesValuePosition = i;
        iAttributes[i++] = format.samples();
    } else if (samples == 0 || samples == 1 ) {
        iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB;
        iAttributes[i++] = FALSE;
    }
    // If sample buffer request cannot be satisfied, reduce request.
    int pixelFormat = 0;
    uint numFormats = 0;
    while (true) {
        const bool valid =
            staticContext.wglChoosePixelFormatARB(hdc, iAttributes, 0, 1,
                                               &pixelFormat, &numFormats)
                && numFormats >= 1;
        if (valid || !sampleBuffersRequested)
            break;
        if (iAttributes[samplesValuePosition] > 1) {
            iAttributes[samplesValuePosition] /= 2;
        } else {
            break;
        }
    }
    // Verify if format is acceptable. Note that the returned
    // formats have been observed to not contain PFD_SUPPORT_OPENGL, ignore.
    initPixelFormatDescriptor(obtainedPfd);
    DescribePixelFormat(hdc, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), obtainedPfd);
    if (!isAcceptableFormat(additional, *obtainedPfd, true)) {
        if (QWindowsContext::verboseGL)
            qDebug() << __FUNCTION__ << " obtained px #" << pixelFormat
                     << " not acceptable=" << *obtainedPfd;
        pixelFormat = 0;
    }

#ifndef QT_NO_DEBUG_OUTPUT
    if (QWindowsContext::verboseGL) {
        QDebug nsp = qDebug().nospace();
        nsp << __FUNCTION__;
        if (sampleBuffersRequested)
            nsp << " samples=" << iAttributes[samplesValuePosition];
        nsp << " Attributes: " << hex << showbase;
        for (int ii = 0; ii < i; ++ii)
            nsp << iAttributes[ii] << ',';
        nsp << noshowbase << dec << "\n    obtained px #" << pixelFormat
            << " of " << numFormats << "\n    " << *obtainedPfd;
    } // Debug
#endif

    return pixelFormat;
}
Пример #11
0
    void init()
    {
        LOG_AS("GLInfo");

        if (inited) return;

        if (!initializeOpenGLFunctions())
        {
            throw InitError("GLInfo::init", "Failed to initialize OpenGL");
        }

        // Extensions.
        ext.ARB_draw_instanced             = query("GL_ARB_draw_instanced");
        ext.ARB_instanced_arrays           = query("GL_ARB_instanced_arrays");
        ext.ARB_texture_env_combine        = query("GL_ARB_texture_env_combine") || query("GL_EXT_texture_env_combine");
        ext.ARB_texture_non_power_of_two   = query("GL_ARB_texture_non_power_of_two");

        ext.EXT_blend_subtract             = query("GL_EXT_blend_subtract");
        ext.EXT_framebuffer_blit           = query("GL_EXT_framebuffer_blit");
        ext.EXT_framebuffer_multisample    = query("GL_EXT_framebuffer_multisample");
        ext.EXT_framebuffer_object         = query("GL_EXT_framebuffer_object");
        ext.EXT_packed_depth_stencil       = query("GL_EXT_packed_depth_stencil");
        ext.EXT_texture_compression_s3tc   = query("GL_EXT_texture_compression_s3tc");
        ext.EXT_texture_filter_anisotropic = query("GL_EXT_texture_filter_anisotropic");
        ext.EXT_timer_query                = query("GL_EXT_timer_query");

        ext.ATI_texture_env_combine3       = query("GL_ATI_texture_env_combine3");
        ext.NV_framebuffer_multisample_coverage
                                           = query("GL_NV_framebuffer_multisample_coverage");
        ext.NV_texture_env_combine4        = query("GL_NV_texture_env_combine4");
        ext.SGIS_generate_mipmap           = query("GL_SGIS_generate_mipmap");

#ifdef WIN32
        ext.Windows_ARB_multisample        = query("WGL_ARB_multisample");
        ext.Windows_EXT_swap_control       = query("WGL_EXT_swap_control");

        if (ext.Windows_EXT_swap_control)
        {
            wglSwapIntervalEXT = de::function_cast<decltype(wglSwapIntervalEXT)>
                (QOpenGLContext::currentContext()->getProcAddress("wglSwapIntervalEXT"));
        }
#endif

#ifdef DENG_X11
        ext.X11_EXT_swap_control           = query("GLX_EXT_swap_control");
        ext.X11_SGI_swap_control           = query("GLX_SGI_swap_control");
        ext.X11_MESA_swap_control          = query("GLX_MESA_swap_control");

        if (ext.X11_EXT_swap_control)
        {
            glXSwapIntervalEXT = de::function_cast<decltype(glXSwapIntervalEXT)>
                    (glXGetProcAddress(reinterpret_cast<GLubyte const *>("glXSwapIntervalEXT")));
        }
        if (ext.X11_SGI_swap_control)
        {
            glXSwapIntervalSGI = de::function_cast<decltype(glXSwapIntervalSGI)>
                    (glXGetProcAddress(reinterpret_cast<GLubyte const *>("glXSwapIntervalSGI")));
        }
        if (ext.X11_MESA_swap_control)
        {
            glXSwapIntervalMESA = de::function_cast<decltype(glXSwapIntervalMESA)>
                    (glXGetProcAddress(reinterpret_cast<GLubyte const *>("glXSwapIntervalMESA")));
        }
#endif

        if (ext.ARB_draw_instanced)
        {
            ARB_draw_instanced.reset(new QOpenGLExtension_ARB_draw_instanced);
            ARB_draw_instanced->initializeOpenGLFunctions();
        }
        if (ext.ARB_instanced_arrays)
        {
            ARB_instanced_arrays.reset(new QOpenGLExtension_ARB_instanced_arrays);
            ARB_instanced_arrays->initializeOpenGLFunctions();
        }
        if (ext.EXT_framebuffer_blit)
        {
            EXT_framebuffer_blit.reset(new QOpenGLExtension_EXT_framebuffer_blit);
            EXT_framebuffer_blit->initializeOpenGLFunctions();
        }
        if (ext.EXT_framebuffer_multisample)
        {
            EXT_framebuffer_multisample.reset(new QOpenGLExtension_EXT_framebuffer_multisample);
            EXT_framebuffer_multisample->initializeOpenGLFunctions();
        }
        if (ext.EXT_framebuffer_object)
        {
            EXT_framebuffer_object.reset(new QOpenGLExtension_EXT_framebuffer_object);
            EXT_framebuffer_object->initializeOpenGLFunctions();
        }
        if (ext.NV_framebuffer_multisample_coverage)
        {
            NV_framebuffer_multisample_coverage.reset(new QOpenGLExtension_NV_framebuffer_multisample_coverage);
            NV_framebuffer_multisample_coverage->initializeOpenGLFunctions();
        }

        // Limits.
        glGetIntegerv(GL_MAX_TEXTURE_SIZE,  (GLint *) &lim.maxTexSize);
        glGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint *) &lim.maxTexUnits);

        if (ext.EXT_texture_filter_anisotropic)
        {
            glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, (GLint *) &lim.maxTexFilterAniso);
        }

        // Set a custom maximum size?
        if (CommandLine_CheckWith("-maxtex", 1))
        {
            lim.maxTexSize = min(ceilPow2(String(CommandLine_Next()).toInt()),
                                 lim.maxTexSize);

            LOG_GL_NOTE("Using requested maximum texture size of %i x %i") << lim.maxTexSize << lim.maxTexSize;
        }

        // Check default OpenGL format attributes.
        QOpenGLContext const *ctx = QOpenGLContext::currentContext();
        QSurfaceFormat form = ctx->format();

        LOGDEV_GL_MSG("Initial OpenGL format:");
        LOGDEV_GL_MSG(" - version: %i.%i") << form.majorVersion() << form.minorVersion();
        LOGDEV_GL_MSG(" - profile: %s") << (form.profile() == QSurfaceFormat::CompatibilityProfile? "Compatibility" : "Core");
        LOGDEV_GL_MSG(" - color: R%i G%i B%i A%i bits") << form.redBufferSize() << form.greenBufferSize() << form.blueBufferSize() << form.alphaBufferSize();
        LOGDEV_GL_MSG(" - depth: %i bits") << form.depthBufferSize();
        LOGDEV_GL_MSG(" - stencil: %i bits") << form.stencilBufferSize();
        LOGDEV_GL_MSG(" - samples: %i") << form.samples();
        LOGDEV_GL_MSG(" - swap behavior: %i") << form.swapBehavior();

        inited = true;
    }