Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qopenglwidget.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qopenglwidget.h"
5#include <QtGui/QOpenGLContext>
6#include <QtGui/QOffscreenSurface>
7#include <QtGui/QOpenGLFunctions>
8#include <QtGui/QWindow>
9#include <QtGui/QGuiApplication>
10#include <QtGui/QScreen>
11#include <QtGui/qpa/qplatformwindow.h>
12#include <QtGui/qpa/qplatformintegration.h>
13#include <QtOpenGL/QOpenGLFramebufferObject>
14#include <QtOpenGL/QOpenGLPaintDevice>
15
16#include <QtGui/private/qguiapplication_p.h>
17#include <QtGui/private/qopenglextensions_p.h>
18#include <QtGui/private/qfont_p.h>
19#include <QtGui/private/qopenglcontext_p.h>
20#include <QtOpenGL/private/qopenglframebufferobject_p.h>
21#include <QtOpenGL/private/qopenglpaintdevice_p.h>
22
23#include <QtWidgets/private/qwidget_p.h>
24#include <QtWidgets/private/qwidgetrepaintmanager_p.h>
25
26#include <rhi/qrhi.h>
27
29
518{
519public:
522 w(widget) { }
523
524 void beginPaint() override;
525 void endPaint() override;
526
528};
529
531{
532public:
535 void ensureActiveTarget() override;
536};
537
539{
540 Q_DECLARE_PUBLIC(QOpenGLWidget)
541public:
543
544 void reset();
546 void recreateFbos();
548
549 QWidgetPrivate::TextureData texture() const override;
550 QPlatformTextureList::Flags textureListFlags() override;
551
553
554 void initialize();
555 void render();
556
557 void invalidateFbo();
558
559 void destroyFbos();
560
563 QImage grabFramebuffer() override;
565 void endBackingStorePainting() override { inBackingStorePaint = false; }
566 void beginCompose() override;
567 void endCompose() override;
568 void initializeViewportFramebuffer() override;
569 bool isStereoEnabled() override;
570 bool toggleStereoTargetBuffer() override;
571 void resizeViewportFramebuffer() override;
572 void resolveSamples() override;
573
575
586 bool initialized = false;
587 bool fakeHidden = false;
589 bool hasBeenComposed = false;
590 bool flushPending = false;
591 bool inPaintGL = false;
593};
594
596{
597 // NB! autoFillBackground is and must be false by default. Otherwise we would clear on
598 // every QPainter begin() which is not desirable. This is only for legacy use cases,
599 // like using QOpenGLWidget as the viewport of a graphics view, that expect clearing
600 // with the palette's background color.
601 if (w->autoFillBackground()) {
603 if (w->format().hasAlpha()) {
604 f->glClearColor(0, 0, 0, 0);
605 } else {
606 QColor c = w->palette().brush(w->backgroundRole()).color();
607 float alpha = c.alphaF();
608 f->glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha);
609 }
610 f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
611 }
612}
613
615{
617 if (!wd->initialized)
618 return;
619
620 if (!wd->inPaintGL)
622}
623
625{
628 if (!wd->initialized)
629 return;
630
632 d->w->makeCurrent();
633 else
634 wd->fbos[wd->currentTargetBuffer]->bind();
635
636
637 if (!wd->inPaintGL)
639
640 // When used as a viewport, drawing is done via opening a QPainter on the widget
641 // without going through paintEvent(). We will have to make sure a glFlush() is done
642 // before the texture is accessed also in this case.
643 wd->flushPending = true;
644}
645
647{
649}
650
651#ifndef GL_SRGB
652#define GL_SRGB 0x8C40
653#endif
654#ifndef GL_SRGB8
655#define GL_SRGB8 0x8C41
656#endif
657#ifndef GL_SRGB_ALPHA
658#define GL_SRGB_ALPHA 0x8C42
659#endif
660#ifndef GL_SRGB8_ALPHA8
661#define GL_SRGB8_ALPHA8 0x8C43
662#endif
663
664QPlatformTextureList::Flags QOpenGLWidgetPrivate::textureListFlags()
665{
666 QPlatformTextureList::Flags flags = QWidgetPrivate::textureListFlags();
667 switch (textureFormat) {
668 case GL_SRGB:
669 case GL_SRGB8:
670 case GL_SRGB_ALPHA:
671 case GL_SRGB8_ALPHA8:
673 break;
674 default:
675 break;
676 }
677 return flags;
678}
679
681{
682 Q_Q(QOpenGLWidget);
683
684 // Destroy the OpenGL resources first. These need the context to be current.
685 if (initialized)
686 q->makeCurrent();
687
688 delete paintDevice;
689 paintDevice = nullptr;
690
691 destroyFbos();
692
693 if (initialized)
694 q->doneCurrent();
695
696 // Delete the context first, then the surface. Slots connected to
697 // the context's aboutToBeDestroyed() may still call makeCurrent()
698 // to perform some cleanup.
699 delete context;
700 context = nullptr;
701 delete surface;
702 surface = nullptr;
704}
705
707{
708 // QRhi resource created from the QRhi. These must be released whenever the
709 // widget gets associated with a different QRhi, even when all OpenGL
710 // contexts share resources.
711
712 delete wrapperTextures[0];
713 wrapperTextures[0] = nullptr;
714
715 if (isStereoEnabled()) {
716 delete wrapperTextures[1];
717 wrapperTextures[1] = nullptr;
718 }
719}
720
722{
723 Q_Q(QOpenGLWidget);
724
725 emit q->aboutToResize();
726
728
729 destroyFbos();
730
732 QOpenGLExtensions *extfuncs = static_cast<QOpenGLExtensions *>(context->functions());
734 samples = 0;
735
738 format.setSamples(samples);
739 if (textureFormat)
740 format.setInternalTextureFormat(textureFormat);
741
742 const QSize deviceSize = q->size() * q->devicePixelRatio();
744 if (samples > 0)
746
747 const bool stereo = isStereoEnabled();
748
749 if (stereo) {
751 if (samples > 0)
753 }
754
755 textureFormat = fbos[QOpenGLWidget::LeftBuffer]->format().internalTextureFormat();
756
758 fbos[currentTargetBuffer]->bind();
759 context->functions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
761
762 if (stereo) {
764 fbos[currentTargetBuffer]->bind();
765 context->functions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
768 }
769
770 flushPending = true; // Make sure the FBO is initialized before use
771
772 paintDevice->setSize(deviceSize);
773 paintDevice->setDevicePixelRatio(q->devicePixelRatio());
774
775 emit q->resized();
776}
777
779{
780 Q_Q(QOpenGLWidget);
781
782 QRhi *rhi = nullptr;
783 if (QWidgetRepaintManager *repaintManager = QWidgetPrivate::get(q->window())->maybeRepaintManager())
784 rhi = repaintManager->rhi();
785
786 // If there is no rhi, because we are completely offscreen, then there's no wrapperTexture either
787 if (rhi && rhi->backend() == QRhi::OpenGLES2) {
788 const QSize deviceSize = q->size() * q->devicePixelRatio();
789 if (!wrapperTextures[currentTargetBuffer] || wrapperTextures[currentTargetBuffer]->pixelSize() != deviceSize) {
790 const uint textureId = resolvedFbos[currentTargetBuffer] ?
792 : (fbos[currentTargetBuffer] ? fbos[currentTargetBuffer]->texture() : 0);
795 else
797 if (!wrapperTextures[currentTargetBuffer]->createFrom({textureId, 0 }))
798 qWarning("QOpenGLWidget: Failed to create wrapper texture");
799 }
800 }
801}
802
804{
805 Q_Q(QOpenGLWidget);
806 if (flushPending) {
807 flushPending = false;
808 q->makeCurrent();
809 static_cast<QOpenGLExtensions *>(context->functions())->flushShared();
810 }
811 hasBeenComposed = true;
812 emit q->aboutToCompose();
813}
814
816{
817 Q_Q(QOpenGLWidget);
818 emit q->frameSwapped();
819}
820
822{
823 Q_Q(QOpenGLWidget);
824 if (initialized)
825 return;
826
827 // If no global shared context get our toplevel's context with which we
828 // will share in order to make the texture usable by the underlying window's backingstore.
829 QWidget *tlw = q->window();
830 QWidgetPrivate *tlwd = get(tlw);
831
832 // Do not include the sample count. Requesting a multisampled context is not necessary
833 // since we render into an FBO, never to an actual surface. What's more, attempting to
834 // create a pbuffer with a multisampled config crashes certain implementations. Just
835 // avoid the entire hassle, the result is the same.
838
839 QRhi *rhi = nullptr;
840 if (QWidgetRepaintManager *repaintManager = tlwd->maybeRepaintManager())
841 rhi = repaintManager->rhi();
842
843 // Could be that something else already initialized the window with some
844 // other graphics API for the QRhi, that's not good.
845 if (rhi && rhi->backend() != QRhi::OpenGLES2) {
846 qWarning("The top-level window is not using OpenGL for composition, '%s' is not compatible with QOpenGLWidget",
847 rhi->backendName());
848 return;
849 }
850
851 // If rhi or contextFromRhi is null, showing content on-screen will not work.
852 // However, offscreen rendering and grabFramebuffer() will stay fully functional.
853
854 QOpenGLContext *contextFromRhi = rhi ? static_cast<const QRhiGles2NativeHandles *>(rhi->nativeHandles())->context : nullptr;
855
858 if (contextFromRhi) {
859 context->setShareContext(contextFromRhi);
860 context->setScreen(contextFromRhi->screen());
861 }
862 if (Q_UNLIKELY(!context->create())) {
863 qWarning("QOpenGLWidget: Failed to create context");
864 return;
865 }
866
870 surface->create();
871
873 qWarning("QOpenGLWidget: Failed to make context current");
874 return;
875 }
876
877 // Propagate settings that make sense only for the tlw. Note that this only
878 // makes sense for properties that get picked up even after the native
879 // window is created.
880 if (tlw->windowHandle()) {
881 QSurfaceFormat tlwFormat = tlw->windowHandle()->format();
882 if (requestedFormat.swapInterval() != tlwFormat.swapInterval()) {
883 // Most platforms will pick up the changed swap interval on the next
884 // makeCurrent or swapBuffers.
886 tlw->windowHandle()->setFormat(tlwFormat);
887 }
888 if (requestedFormat.swapBehavior() != tlwFormat.swapBehavior()) {
890 tlw->windowHandle()->setFormat(tlwFormat);
891 }
892 }
893
895 paintDevice->setSize(q->size() * q->devicePixelRatio());
896 paintDevice->setDevicePixelRatio(q->devicePixelRatio());
897
898 initialized = true;
899
900 q->initializeGL();
901}
902
904{
907}
908
910{
911 Q_Q(QOpenGLWidget);
912 if (resolvedFbos[targetBuffer]) {
913 q->makeCurrent(targetBuffer);
914 QRect rect(QPoint(0, 0), fbos[targetBuffer]->size());
916 flushPending = true;
917 }
918}
919
921{
922 Q_Q(QOpenGLWidget);
923
924 if (fakeHidden || !initialized)
925 return;
926
928
930 if (!ctx) {
931 qWarning("QOpenGLWidget: No current context, cannot render");
932 return;
933 }
934
936 qWarning("QOpenGLWidget: No fbo, cannot render");
937 return;
938 }
939
940 const bool stereo = isStereoEnabled();
941 if (stereo) {
942 static bool warningGiven = false;
943 if (!fbos[QOpenGLWidget::RightBuffer] && !warningGiven) {
944 qWarning("QOpenGLWidget: Stereo is enabled, but no right buffer. Using only left buffer");
945 warningGiven = true;
946 }
947 }
948
951
952 if (stereo && fbos[QOpenGLWidget::RightBuffer]) {
956 }
957
958 hasBeenComposed = false;
959 }
960
961 QOpenGLFunctions *f = ctx->functions();
962 f->glViewport(0, 0, q->width() * q->devicePixelRatio(), q->height() * q->devicePixelRatio());
963 inPaintGL = true;
964
965#ifdef Q_OS_WASM
966 f->glDepthMask(GL_TRUE);
967#endif
968
970 q->paintGL();
971
972 if (stereo && fbos[QOpenGLWidget::RightBuffer]) {
975 q->paintGL();
976 }
978
979 inPaintGL = false;
980 flushPending = true;
981}
982
984{
986 if (f->hasOpenGLExtension(QOpenGLExtensions::DiscardFramebuffer)) {
987 const int gl_color_attachment0 = 0x8CE0; // GL_COLOR_ATTACHMENT0
988 const int gl_depth_attachment = 0x8D00; // GL_DEPTH_ATTACHMENT
989 const int gl_stencil_attachment = 0x8D20; // GL_STENCIL_ATTACHMENT
990#ifdef Q_OS_WASM
991 // webgl does not allow separate depth and stencil attachments
992 // QTBUG-69913
993 const int gl_depth_stencil_attachment = 0x821A; // GL_DEPTH_STENCIL_ATTACHMENT
994
995 const GLenum attachments[] = {
996 gl_color_attachment0, gl_depth_attachment, gl_stencil_attachment, gl_depth_stencil_attachment
997 };
998#else
999 const GLenum attachments[] = {
1000 gl_color_attachment0, gl_depth_attachment, gl_stencil_attachment
1001 };
1002#endif
1003 f->glDiscardFramebufferEXT(GL_FRAMEBUFFER, sizeof attachments / sizeof *attachments, attachments);
1004 } else {
1005 f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1006 }
1007}
1008
1010{
1015
1020
1022}
1023
1025{
1027}
1028
1030{
1031 Q_Q(QOpenGLWidget);
1032
1033 initialize();
1034 if (!initialized)
1035 return QImage();
1036
1037 // The second fbo is only created when stereoscopic rendering is enabled
1038 // Just use the default one if not.
1039 if (targetBuffer == QOpenGLWidget::RightBuffer && !isStereoEnabled())
1040 targetBuffer = QOpenGLWidget::LeftBuffer;
1041
1042 if (!fbos[targetBuffer]) // could be completely offscreen, without ever getting a resize event
1043 recreateFbos();
1044
1045 if (!inPaintGL)
1046 render();
1047
1048 setCurrentTargetBuffer(targetBuffer);
1049 if (resolvedFbos[targetBuffer]) {
1050 resolveSamplesForBuffer(targetBuffer);
1051 resolvedFbos[targetBuffer]->bind();
1052 }
1053
1054 const bool hasAlpha = q->format().hasAlpha();
1055 QImage res = qt_gl_read_framebuffer(q->size() * q->devicePixelRatio(), hasAlpha, hasAlpha);
1056 res.setDevicePixelRatio(q->devicePixelRatio());
1057
1058 // While we give no guarantees of what is going to be left bound, prefer the
1059 // multisample fbo instead of the resolved one. Clients may continue to
1060 // render straight after calling this function.
1061 if (resolvedFbos[targetBuffer]) {
1062 setCurrentTargetBuffer(targetBuffer);
1063 }
1064
1065 return res;
1066}
1067
1069{
1070 Q_Q(QOpenGLWidget);
1071 // Legacy behavior for compatibility with QGLWidget when used as a graphics view
1072 // viewport: enable clearing on each painter begin.
1073 q->setAutoFillBackground(true);
1074}
1075
1077{
1078 Q_Q(QOpenGLWidget);
1079 // Note that because this internally might use the requested format,
1080 // then this can return a false positive on hardware where
1081 // steroscopic rendering is not supported.
1082 return q->format().stereo();
1083}
1084
1086{
1090}
1091
1093{
1094 Q_Q(QOpenGLWidget);
1095 if (!initialized)
1096 return;
1097
1098 if (!fbos[currentTargetBuffer] || q->size() * q->devicePixelRatio() != fbos[currentTargetBuffer]->size()) {
1099 recreateFbos();
1100 q->update();
1101 }
1102}
1103
1109{
1110 Q_D(QOpenGLWidget);
1113 qWarning("QOpenGLWidget is not supported on this platform.");
1114 else
1115 d->setRenderToTexture();
1116}
1117
1136{
1137 // NB! resetting graphics resources must be done from this destructor,
1138 // *not* from the private class' destructor. This is due to how destruction
1139 // works and due to the QWidget dtor (for toplevels) destroying the repaint
1140 // manager and rhi before the (QObject) private gets destroyed. Hence must
1141 // do it here early on.
1142
1143 Q_D(QOpenGLWidget);
1144 d->reset();
1145}
1146
1152{
1153 Q_D(QOpenGLWidget);
1154 d->updateBehavior = updateBehavior;
1155}
1156
1162{
1163 Q_D(const QOpenGLWidget);
1164 return d->updateBehavior;
1165}
1166
1185{
1186 Q_D(QOpenGLWidget);
1187 if (Q_UNLIKELY(d->initialized)) {
1188 qWarning("QOpenGLWidget: Already initialized, setting the format has no effect");
1189 return;
1190 }
1191
1192 d->requestedFormat = format;
1193}
1194
1212{
1213 Q_D(const QOpenGLWidget);
1214 return d->initialized ? d->context->format() : d->requestedFormat;
1215}
1216
1234{
1235 Q_D(QOpenGLWidget);
1236 if (Q_UNLIKELY(d->initialized)) {
1237 qWarning("QOpenGLWidget: Already initialized, setting the internal texture format has no effect");
1238 return;
1239 }
1240
1241 d->textureFormat = texFormat;
1242}
1243
1253{
1254 Q_D(const QOpenGLWidget);
1255 return d->textureFormat;
1256}
1257
1264{
1265 Q_D(const QOpenGLWidget);
1266 return d->initialized && d->context->isValid();
1267}
1268
1280{
1281 Q_D(QOpenGLWidget);
1282 if (!d->initialized)
1283 return;
1284
1285 d->context->makeCurrent(d->surface);
1286
1287 if (d->fbos[d->currentTargetBuffer]) // there may not be one if we are in reset()
1288 d->fbos[d->currentTargetBuffer]->bind();
1289}
1290
1307{
1308 Q_D(QOpenGLWidget);
1309 if (!d->initialized)
1310 return;
1311
1312 // The FBO for the right buffer is only initialized when stereo is set
1313 if (targetBuffer == TargetBuffer::RightBuffer && !format().stereo())
1314 return;
1315
1316 d->setCurrentTargetBuffer(targetBuffer); // calls makeCurrent
1317}
1318
1327{
1328 Q_D(QOpenGLWidget);
1329 if (!d->initialized)
1330 return;
1331
1332 d->context->doneCurrent();
1333}
1334
1344{
1345 Q_D(const QOpenGLWidget);
1346 return d->context;
1347}
1348
1362{
1363 Q_D(const QOpenGLWidget);
1364 return d->fbos[TargetBuffer::LeftBuffer] ? d->fbos[TargetBuffer::LeftBuffer]->handle() : 0;
1365}
1366
1384{
1385 Q_D(const QOpenGLWidget);
1386 return d->fbos[targetBuffer] ? d->fbos[targetBuffer]->handle() : 0;
1387}
1388
1403{
1404}
1405
1418{
1419 Q_UNUSED(w);
1420 Q_UNUSED(h);
1421}
1422
1453{
1454}
1455
1466{
1467 Q_D(QOpenGLWidget);
1468
1469 if (e->size().isEmpty()) {
1470 d->fakeHidden = true;
1471 return;
1472 }
1473 d->fakeHidden = false;
1474
1475 d->initialize();
1476 if (!d->initialized)
1477 return;
1478
1479 d->recreateFbos();
1480 // Make sure our own context is current before invoking user overrides. If
1481 // the fbo was recreated then there's a chance something else is current now.
1482 makeCurrent();
1483 resizeGL(width(), height());
1484 d->sendPaintEvent(QRect(QPoint(0, 0), size()));
1485}
1486
1499{
1500 Q_UNUSED(e);
1501 Q_D(QOpenGLWidget);
1502
1503 d->initialize();
1504 if (d->initialized) {
1505 d->ensureRhiDependentResources();
1506 if (updatesEnabled())
1507 d->render();
1508 }
1509}
1510
1518{
1519 Q_D(QOpenGLWidget);
1520 return d->grabFramebuffer();
1521}
1522
1535{
1536 Q_D(QOpenGLWidget);
1537 return d->grabFramebuffer(targetBuffer);
1538}
1539
1551{
1552 Q_D(const QOpenGLWidget);
1553 return d->currentTargetBuffer;
1554}
1555
1560{
1561 Q_D(const QOpenGLWidget);
1562 if (d->inBackingStorePaint)
1563 return QWidget::metric(metric);
1564
1567
1568 const float dpmx = qt_defaultDpiX() * 100. / 2.54;
1569 const float dpmy = qt_defaultDpiY() * 100. / 2.54;
1570
1571 switch (metric) {
1572 case PdmWidth:
1573 return width();
1574 case PdmHeight:
1575 return height();
1576 case PdmDepth:
1577 return 32;
1578 case PdmWidthMM:
1579 if (screen)
1580 return width() * screen->physicalSize().width() / screen->geometry().width();
1581 else
1582 return width() * 1000 / dpmx;
1583 case PdmHeightMM:
1584 if (screen)
1585 return height() * screen->physicalSize().height() / screen->geometry().height();
1586 else
1587 return height() * 1000 / dpmy;
1588 case PdmNumColors:
1589 return 0;
1590 case PdmDpiX:
1591 if (screen)
1593 else
1594 return qRound(dpmx * 0.0254);
1595 case PdmDpiY:
1596 if (screen)
1598 else
1599 return qRound(dpmy * 0.0254);
1600 case PdmPhysicalDpiX:
1601 if (screen)
1603 else
1604 return qRound(dpmx * 0.0254);
1605 case PdmPhysicalDpiY:
1606 if (screen)
1608 else
1609 return qRound(dpmy * 0.0254);
1611 return QWidget::metric(metric);
1613 return QWidget::metric(metric);
1614 default:
1615 qWarning("QOpenGLWidget::metric(): unknown metric %d", metric);
1616 return 0;
1617 }
1618}
1619
1624{
1625 Q_D(const QOpenGLWidget);
1626 if (d->inBackingStorePaint)
1627 return QWidget::redirected(p);
1628
1629 return d->paintDevice;
1630}
1631
1636{
1637 Q_D(const QOpenGLWidget);
1638 // QWidget needs to "punch a hole" into the backingstore. This needs the
1639 // normal paint engine and device, not the GL one. So in this mode, behave
1640 // like a normal widget.
1641 if (d->inBackingStorePaint)
1642 return QWidget::paintEngine();
1643
1644 if (!d->initialized)
1645 return nullptr;
1646
1647 return d->paintDevice->paintEngine();
1648}
1649
1650
1652{
1653 Q_Q(QOpenGLWidget);
1654
1655 if (targetBuffer == QOpenGLWidget::RightBuffer && !isStereoEnabled())
1656 return false;
1657
1658 currentTargetBuffer = targetBuffer;
1659 q->makeCurrent();
1660
1661 return true;
1662}
1663
1668{
1669 Q_D(QOpenGLWidget);
1670 switch (e->type()) {
1672 d->resetRhiDependentResources();
1673 break;
1676 break;
1677 if (d->initialized)
1678 d->reset();
1679 if (isHidden())
1680 break;
1681 Q_FALLTHROUGH();
1682 case QEvent::Show: // reparenting may not lead to a resize so reinitialize on Show too
1683 if (d->initialized && !d->wrapperTextures[d->currentTargetBuffer] && window()->windowHandle()) {
1684 // Special case: did grabFramebuffer() for a hidden widget that then became visible.
1685 // Recreate all resources since the context now needs to share with the TLW's.
1687 d->reset();
1688 }
1689 if (QWidgetRepaintManager *repaintManager = QWidgetPrivate::get(window())->maybeRepaintManager()) {
1690 if (!d->initialized && !size().isEmpty() && repaintManager->rhi()) {
1691 d->initialize();
1692 if (d->initialized) {
1693 d->recreateFbos();
1694 // QTBUG-89812: generate a paint event, like resize would do,
1695 // otherwise a QOpenGLWidget in a QDockWidget may not show the
1696 // content upon (un)docking.
1697 d->sendPaintEvent(QRect(QPoint(0, 0), size()));
1698 }
1699 }
1700 }
1701 break;
1703 if (d->initialized && d->paintDevice->devicePixelRatio() != devicePixelRatio())
1704 d->recreateFbos();
1705 break;
1706 default:
1707 break;
1708 }
1709 return QWidget::event(e);
1710}
1711
1713
1714#include "moc_qopenglwidget.cpp"
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
float alphaF() const noexcept
Returns the alpha color component of this color.
Definition qcolor.cpp:1497
static bool testAttribute(Qt::ApplicationAttribute attribute)
Returns true if attribute attribute is set; otherwise returns false.
\inmodule QtCore
Definition qcoreevent.h:45
@ DevicePixelRatioChange
Definition qcoreevent.h:287
@ WindowAboutToChangeInternal
Definition qcoreevent.h:285
@ WindowChangeInternal
Definition qcoreevent.h:275
static QPlatformIntegration * platformIntegration()
QScreen * primaryScreen
the primary (or default) screen of the application.
\inmodule QtGui
Definition qimage.h:37
\inmodule QtGui
void setScreen(QScreen *screen)
Sets the screen to which the offscreen surface is connected.
void create()
Allocates the platform resources associated with the offscreen surface.
void setFormat(const QSurfaceFormat &format)
Sets the offscreen surface format.
static QOpenGLContextPrivate * get(QOpenGLContext *context)
\inmodule QtGui
bool create()
Attempts to create the OpenGL context with the current configuration.
void setScreen(QScreen *screen)
Sets the screen the OpenGL context should be valid for.
bool makeCurrent(QSurface *surface)
Makes the context current in the current thread, against the given surface.
QSurfaceFormat format() const
Returns the format of the underlying platform context, if create() has been called.
void setShareContext(QOpenGLContext *shareContext)
Makes this context share textures, shaders, and other OpenGL resources with shareContext.
void setFormat(const QSurfaceFormat &format)
Sets the format the OpenGL context should be compatible with.
static QOpenGLContext * currentContext()
Returns the last context which called makeCurrent in the current thread, or \nullptr,...
QScreen * screen() const
Returns the screen the context was created for.
QOpenGLFunctions * functions() const
Get the QOpenGLFunctions instance for this context.
bool hasOpenGLExtension(QOpenGLExtensions::OpenGLExtension extension) const
Returns true if extension is present on this system's OpenGL implementation; false otherwise.
The QOpenGLFramebufferObjectFormat class specifies the format of an OpenGL framebuffer object.
The QOpenGLFramebufferObject class encapsulates an OpenGL framebuffer object.
static void blitFramebuffer(QOpenGLFramebufferObject *target, const QRect &targetRect, QOpenGLFramebufferObject *source, const QRect &sourceRect, GLbitfield buffers, GLenum filter, int readColorAttachmentIndex, int drawColorAttachmentIndex, FramebufferRestorePolicy restorePolicy)
GLuint handle() const
Returns the OpenGL framebuffer object handle for this framebuffer object (returned by the {glGenFrame...
GLuint texture() const
Returns the texture id for the texture attached as the default rendering target in this framebuffer o...
bool bind()
Switches rendering from the default, windowing system provided framebuffer to this framebuffer object...
The QOpenGLFunctions class provides cross-platform access to the OpenGL ES 2.0 API.
void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
Convenience function that calls glClearColor(red, green, blue, alpha).
void glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
Convenience function that calls glViewport(x, y, width, height).
void glClear(GLbitfield mask)
Convenience function that calls glClear(mask).
The QOpenGLPaintDevice class enables painting to an OpenGL context using QPainter.
QScopedPointer< QOpenGLPaintDevicePrivate > d_ptr
void setDevicePixelRatio(qreal devicePixelRatio)
Sets the device pixel ratio for the paint device to devicePixelRatio.
void setSize(const QSize &size)
Sets the pixel size of the paint device to size.
QOpenGLWidgetPaintDevicePrivate(QOpenGLWidget *widget)
QOpenGLWidgetPaintDevice(QOpenGLWidget *widget)
void ensureActiveTarget() override
This virtual method is provided as a callback to allow re-binding a target frame buffer object or con...
void endBackingStorePainting() override
void beginCompose() override
QRhiTexture * wrapperTextures[2]
QOffscreenSurface * surface
QPlatformTextureList::Flags textureListFlags() override
QOpenGLWidget::TargetBuffer currentTargetBuffer
bool setCurrentTargetBuffer(QOpenGLWidget::TargetBuffer targetBuffer)
QOpenGLWidgetPrivate()=default
QOpenGLFramebufferObject * fbos[2]
QOpenGLContext * context
void initializeViewportFramebuffer() override
QWidgetPrivate::TextureData texture() const override
QOpenGLFramebufferObject * resolvedFbos[2]
void beginBackingStorePainting() override
void endCompose() override
QPlatformBackingStoreRhiConfig rhiConfig() const override
QImage grabFramebuffer() override
QOpenGLWidget::UpdateBehavior updateBehavior
void resolveSamplesForBuffer(QOpenGLWidget::TargetBuffer targetBuffer)
QSurfaceFormat requestedFormat
void resolveSamples() override
bool isStereoEnabled() override
void resizeViewportFramebuffer() override
bool toggleStereoTargetBuffer() override
QOpenGLPaintDevice * paintDevice
\inmodule QtOpenGLWidgets
QSurfaceFormat format() const
Returns the context and surface format used by this widget and its toplevel window.
void setUpdateBehavior(UpdateBehavior updateBehavior)
Sets this widget's update behavior to updateBehavior.
UpdateBehavior updateBehavior() const
GLenum textureFormat() const
virtual void paintGL()
This virtual function is called whenever the widget needs to be painted.
QOpenGLContext * context() const
virtual void resizeGL(int w, int h)
This virtual function is called whenever the widget has been resized.
GLuint defaultFramebufferObject() const
QPaintDevice * redirected(QPoint *p) const override
\reimp
bool isValid() const
void setFormat(const QSurfaceFormat &format)
Sets the requested surface format.
void doneCurrent()
Releases the context.
bool event(QEvent *e) override
\reimp
void paintEvent(QPaintEvent *e) override
Handles paint events.
virtual void initializeGL()
This virtual function is called once before the first call to paintGL() or resizeGL().
void resizeEvent(QResizeEvent *e) override
Handles resize events that are passed in the e event parameter.
TargetBuffer currentTargetBuffer() const
Returns the currently active target buffer.
QPaintEngine * paintEngine() const override
\reimp
int metric(QPaintDevice::PaintDeviceMetric metric) const override
\reimp
QImage grabFramebuffer()
Renders and returns a 32-bit RGB image of the framebuffer.
~QOpenGLWidget()
Destroys the QOpenGLWidget instance, freeing its resources.
QOpenGLWidget(QWidget *parent=nullptr, Qt::WindowFlags f=Qt::WindowFlags())
Constructs a widget which is a child of parent, with widget flags set to f.
void makeCurrent()
Prepares for rendering OpenGL content for this widget by making the corresponding context current and...
void setTextureFormat(GLenum texFormat)
Sets a custom internal texture format of texFormat.
qreal devicePixelRatio() const
@ PdmDevicePixelRatioScaled
\inmodule QtGui
The QPaintEvent class contains event parameters for paint events.
Definition qevent.h:485
\inmodule QtCore\reentrant
Definition qpoint.h:23
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:238
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:235
The QResizeEvent class contains event parameters for resize events.
Definition qevent.h:547
\variable QRhiGles2InitParams::format
\inmodule QtGui
Definition qrhi.h:883
@ RenderTarget
Definition qrhi.h:886
void setPixelSize(const QSize &sz)
Sets the texture size, specified in pixels, to sz.
Definition qrhi.h:964
\inmodule QtGui
Definition qrhi.h:1767
Implementation backend() const
Definition qrhi.cpp:8289
@ OpenGLES2
Definition qrhi.h:1772
const char * backendName() const
Definition qrhi.cpp:8321
QRhiTexture * newTexture(QRhiTexture::Format format, const QSize &pixelSize, int sampleCount=1, QRhiTexture::Flags flags={})
Definition qrhi.cpp:10133
const QRhiNativeHandles * nativeHandles()
Definition qrhi.cpp:9708
T * data() const noexcept
Returns the value of the pointer referenced by this object.
The QScreen class is used to query screen properties. \inmodule QtGui.
Definition qscreen.h:32
qreal logicalDotsPerInchY
the number of logical dots or pixels per inch in the vertical direction
Definition qscreen.h:57
qreal logicalDotsPerInchX
the number of logical dots or pixels per inch in the horizontal direction
Definition qscreen.h:56
QSizeF physicalSize
the screen's physical size (in millimeters)
Definition qscreen.h:50
QRect geometry
the screen's geometry in pixels
Definition qscreen.h:45
qreal physicalDotsPerInchY
the number of physical dots or pixels per inch in the vertical direction
Definition qscreen.h:54
qreal physicalDotsPerInchX
the number of physical dots or pixels per inch in the horizontal direction
Definition qscreen.h:52
constexpr qreal width() const noexcept
Returns the width.
Definition qsize.h:321
constexpr qreal height() const noexcept
Returns the height.
Definition qsize.h:324
\inmodule QtCore
Definition qsize.h:25
The QSurfaceFormat class represents the format of a QSurface. \inmodule QtGui.
int samples() const
Returns the number of samples per pixel when multisampling is enabled, or -1 when multisampling is di...
void setSwapBehavior(SwapBehavior behavior)
Set the swap behavior of the surface.
static QSurfaceFormat defaultFormat()
Returns the global default surface format.
int swapInterval() const
Returns the swap interval.
void setSamples(int numSamples)
Set the preferred number of samples per pixel when multisampling is enabled to numSamples.
void setSwapInterval(int interval)
Sets the preferred swap interval.
SwapBehavior swapBehavior() const
Returns the configured swap behaviour.
static QWidgetPrivate * get(QWidget *w)
Definition qwidget_p.h:211
QWidgetRepaintManager * maybeRepaintManager() const
Definition qwidget_p.h:850
virtual QPlatformTextureList::Flags textureListFlags()
Definition qwidget_p.h:593
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
int metric(PaintDeviceMetric) const override
Internal implementation of the virtual QPaintDevice::metric() function.
QWidget * window() const
Returns the window for this widget, i.e.
Definition qwidget.cpp:4320
bool isHidden() const
Returns true if the widget is hidden, otherwise returns false.
Definition qwidget.h:877
QSize size
the size of the widget excluding any window frame
Definition qwidget.h:113
int width
the width of the widget excluding any window frame
Definition qwidget.h:114
bool updatesEnabled
whether updates are enabled
Definition qwidget.h:143
int height
the height of the widget excluding any window frame
Definition qwidget.h:115
QPaintEngine * paintEngine() const override
Returns the widget's paint engine.
QWindow * windowHandle() const
If this is a native widget, return the associated QWindow.
Definition qwidget.cpp:2490
QPaintDevice * redirected(QPoint *offset) const override
bool event(QEvent *event) override
This is the main event handler; it handles event event.
Definition qwidget.cpp:8912
QScreen * screen() const
Returns the screen the widget is on.
Definition qwidget.cpp:2503
QSurfaceFormat format() const override
Returns the actual format of this window.
Definition qwindow.cpp:888
EGLContext ctx
QOpenGLWidget * widget
[1]
double e
rect
[4]
Combined button and popup list for selecting options.
@ AA_ShareOpenGLContexts
Definition qnamespace.h:446
#define Q_FALLTHROUGH()
#define Q_UNLIKELY(x)
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:281
Q_GUI_EXPORT int qt_defaultDpiX()
Definition qfont.cpp:107
Q_GUI_EXPORT int qt_defaultDpiY()
Definition qfont.cpp:122
#define qWarning
Definition qlogging.h:162
GLsizei samples
GLfloat GLfloat GLfloat w
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLfloat GLfloat f
typedef GLenum(GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC)(void)
GLbitfield flags
GLsizei const GLenum * attachments
GLint GLsizei GLsizei GLenum format
GLfloat GLfloat GLfloat GLfloat h
GLuint res
const GLubyte * c
const GLintptr const GLsizei const GLuint const GLuint * fbos
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
#define GL_FRAMEBUFFER
GLfloat GLfloat p
[1]
GLfloat GLfloat GLfloat alpha
Definition qopenglext.h:418
static QImage qt_gl_read_framebuffer(const QSize &size, GLenum internal_format, bool include_alpha, bool flip)
#define GL_SRGB_ALPHA
#define GL_SRGB8_ALPHA8
#define GL_SRGB
#define GL_SRGB8
static bool hasAlpha(const QImage &image)
#define GLuint
#define emit
#define Q_UNUSED(x)
unsigned int uint
Definition qtypes.h:29
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent