Changeset 99936 in vbox for trunk/src/VBox/Frontends/VirtualBox
- Timestamp:
- May 23, 2023 3:16:29 PM (20 months ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r99910 r99936 214 214 VirtualBoxVM_DEFS += VBOX_WITH_DEBUGGER_GUI_MENU 215 215 endif 216 endif217 ifdef VBOX_GUI_WITH_QTGLFRAMEBUFFER218 VirtualBoxVM_DEFS += VBOX_GUI_WITH_QTGLFRAMEBUFFER219 216 endif 220 217 ifdef VBOX_WITH_LIBCURL … … 414 411 -framework AppKit -framework Carbon -framework IOKit 415 412 416 ifdef VBOX_GUI_WITH_QTGLFRAMEBUFFER417 VirtualBox_LDFLAGS.darwin += -framework OpenGL418 endif419 420 413 421 414 # … … 460 453 endif 461 454 462 ifdef VBOX_GUI_WITH_QTGLFRAMEBUFFER463 VirtualBoxVM_LDFLAGS.darwin += -framework OpenGL464 endif465 466 455 467 456 # … … 487 476 -framework Carbon \ 488 477 -framework IOKit 489 490 ifdef VBOX_GUI_WITH_QTGLFRAMEBUFFER491 UICommon_LDFLAGS.darwin += -framework OpenGL492 endif493 478 494 479 # … … 534 519 535 520 # These are 2D Video Acceleration and 3D Acceleration related libs: 536 ifdef VBOX_GUI_WITH_QTGLFRAMEBUFFER537 VirtualBox_LIBS.win += $(PATH_SDK_$(VBOX_WINPSDK)_LIB)/Opengl32.lib538 VirtualBox_LIBS.solaris += GL539 VirtualBox_LIBS.linux += GL540 VirtualBox_LIBS.freebsd += GL541 endif542 521 ifdef VBOX_WITH_3D_ACCELERATION 543 522 VirtualBox_LIBS += $(PATH_STAGE_LIB)/VBoxOGLTest$(VBOX_SUFF_LIB) … … 594 573 595 574 # These are 2D Video Acceleration and 3D Acceleration related libs: 596 ifdef VBOX_GUI_WITH_QTGLFRAMEBUFFER597 VirtualBoxVM_LIBS.win += $(PATH_SDK_$(VBOX_WINPSDK)_LIB)/Opengl32.lib598 VirtualBoxVM_LIBS.solaris += GL599 VirtualBoxVM_LIBS.linux += GL600 VirtualBoxVM_LIBS.freebsd += GL601 endif602 575 ifdef VBOX_WITH_3D_ACCELERATION 603 576 VirtualBoxVM_LIBS += $(PATH_STAGE_LIB)/VBoxOGLTest$(VBOX_SUFF_LIB) … … 631 604 632 605 # These are 2D Video Acceleration and 3D Acceleration related libs: 633 ifdef VBOX_GUI_WITH_QTGLFRAMEBUFFER634 UICommon_LIBS.win += $(PATH_SDK_$(VBOX_WINPSDK)_LIB)/Opengl32.lib635 UICommon_LIBS.solaris += GL636 UICommon_LIBS.linux += GL637 UICommon_LIBS.freebsd += GL638 endif639 606 ifdef VBOX_WITH_3D_ACCELERATION 640 607 UICommon_LIBS += $(PATH_STAGE_LIB)/VBoxOGLTest$(VBOX_SUFF_LIB) … … 1697 1664 VirtualBox_QT_MODULES.win += WinExtras 1698 1665 endif 1699 ifdef VBOX_GUI_WITH_QTGLFRAMEBUFFER1700 VirtualBox_QT_MODULES += OpenGL1701 endif1702 1666 1703 1667 … … 1718 1682 VirtualBoxVM_QT_MODULES.win += WinExtras 1719 1683 endif 1720 ifdef VBOX_GUI_WITH_QTGLFRAMEBUFFER1721 VirtualBoxVM_QT_MODULES += OpenGL1722 endif1723 1684 1724 1685 … … 1756 1717 UICommon_QT_MODULES.darwin += MacExtras 1757 1718 UICommon_QT_MODULES.win += WinExtras 1758 endif1759 1760 ifdef VBOX_GUI_WITH_QTGLFRAMEBUFFER1761 UICommon_QT_MODULES += OpenGL1762 1719 endif 1763 1720 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBuffer.cpp
r99438 r99936 64 64 65 65 66 #ifdef VBOX_GUI_WITH_QTGLFRAMEBUFFER67 /* Experimental code. */68 69 /* Qt OpenGL includes: */70 /* On Windows host they require the following two include files, otherwise compilation will fail with warnings.71 * The two files are already included, but they are needed if the Qt files are moved to the 'Qt includes:' section. */72 // #include <iprt/stdint.h>73 // #include <iprt/win/windows.h>74 # include <QOffscreenSurface>75 # include <QOpenGLFunctions>76 # include <QOpenGLTexture>77 # include <QOpenGLWidget>78 79 # ifdef RT_OS_LINUX80 /* GL/glx.h must be included after Qt GL headers (which define GL_GLEXT_LEGACY) to avoid GL_GLEXT_VERSION conflict. */81 # include <GL/glx.h>82 # endif83 84 class UIFrameBufferPrivate;85 class GLWidget;86 87 /* Handles the guest screen texture for the target GLWidget. */88 class GLWidgetSource89 {90 public:91 92 GLWidgetSource(GLWidget *pTarget);93 virtual ~GLWidgetSource();94 95 GLWidget *Target() { return m_pTarget; }96 97 virtual void initGuestScreenTexture(int w, int h) { RT_NOREF(w, h); };98 virtual void uninitGuestScreenTexture() {};99 virtual void updateGuestImage() {};100 virtual void cleanup() {};101 virtual bool IsHW() { return false; };102 103 private:104 105 GLWidget *m_pTarget;106 };107 108 /* Update the guest texture from a QImage. */109 class GLWidgetSourceImage : public GLWidgetSource110 {111 public:112 113 GLWidgetSourceImage(GLWidget *pTarget, QImage *pImage);114 virtual ~GLWidgetSourceImage();115 116 virtual void initGuestScreenTexture(int w, int h);117 virtual void updateGuestImage();118 119 private:120 121 QImage *m_pImage;122 };123 124 # ifdef RT_OS_LINUX125 /* The guest texture is a X pixmap. */126 class GLWidgetSourcePixmap : public GLWidgetSource127 {128 public:129 130 GLWidgetSourcePixmap(GLWidget *pTarget, Pixmap pixmap, VisualID visualid);131 virtual ~GLWidgetSourcePixmap();132 133 virtual void initGuestScreenTexture(int w, int h);134 virtual void uninitGuestScreenTexture();135 virtual void cleanup();136 virtual bool IsHW() { return true; };137 138 private:139 140 /* HW accelerated graphics output from a pixmap. */141 Pixmap m_Pixmap;142 VisualID m_visualid;143 144 GLXPixmap m_glxPixmap;145 146 Display *m_display;147 PFNGLXBINDTEXIMAGEEXTPROC m_pfnglXBindTexImageEXT;148 PFNGLXRELEASETEXIMAGEEXTPROC m_pfnglXReleaseTexImageEXT;149 };150 # endif /* RT_OS_LINUX */151 152 /* This widget allows to use OpenGL. */153 class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions154 {155 Q_OBJECT156 157 public:158 159 GLWidget(QWidget *parent, UIFrameBufferPrivate *pFramebuffer);160 virtual ~GLWidget();161 162 /* Whether OpenGL is supported at all. */163 static bool isSupported();164 165 void lock() { RTCritSectEnter(&m_critSect); }166 void unlock() { RTCritSectLeave(&m_critSect); }167 168 /* Notification about the guest screen size. */169 void resizeGuestScreen(int w, int h);170 /* Which guest area is visible in the VM window. */171 void setGuestVisibleRect(int x, int y, int w, int h);172 /* Update the guest texture before painting. */173 void updateGuestImage();174 175 /* The guest texture OpenGL target. */176 static GLenum const kTextureTarget = GL_TEXTURE_2D;177 178 /* The the guest screen source. */179 void setSource(GLWidgetSource *pSource, bool fForce);180 181 public slots:182 183 void cleanup();184 185 protected:186 187 /* QOpenGLWidget methods, which must be reimplemented. */188 void initializeGL() RT_OVERRIDE;189 void paintGL() RT_OVERRIDE;190 void resizeGL(int w, int h) RT_OVERRIDE;191 192 private:193 194 /* Get and possibly initialize the guest source. */195 GLWidgetSource *getSource();196 197 /* Create the texture which contains the guest screen bitmap. */198 void createGuestTexture();199 /* Delete the texture which contains the guest screen bitmap. */200 void deleteGuestTexture();201 202 /* Backlink. */203 UIFrameBufferPrivate *m_pFramebuffer;204 205 /* Fallback when no guest screen is available. */206 GLWidgetSource m_nullSource;207 /* The current guest screen bitmap source. */208 GLWidgetSource *m_pSource;209 210 /* The guest screen resolution. */211 QSize m_guestSize;212 /* The visible area of the guest screen in guest pixels. */213 QRect m_guestVisibleRect;214 215 /** RTCRITSECT object to protect frame-buffer access. */216 RTCRITSECT m_critSect;217 218 /* A new guest screen source has been set and needs reinitialization. */219 bool m_fReinitSource;220 221 /* Texture which contains entire guest screen. Size is m_guestSize. */222 GLuint m_guestTexture;223 };224 225 /* End of experimental code. */226 #endif /* VBOX_GUI_WITH_QTGLFRAMEBUFFER */227 228 229 66 /** IFramebuffer implementation used to maintain VM display video memory. */ 230 67 class ATL_NO_VTABLE UIFrameBufferPrivate : public QObject, … … 420 257 virtual void viewportResized(QResizeEvent*) 421 258 { 422 #ifdef VBOX_GUI_WITH_QTGLFRAMEBUFFER 423 /* Sync GL widget size with the MachineView widget: */ 424 /** @todo This can be probably done in a more automated way. */ 425 if (m_pGLWidget && m_pMachineView) 426 m_pGLWidget->resize(m_pMachineView->viewport()->size()); 427 #endif 428 } 429 430 #ifdef VBOX_GUI_WITH_QTGLFRAMEBUFFER 431 bool isGLWidgetSupported() 432 { 433 QString s = uiCommon().virtualBox().GetExtraData("GUI/GLWidget"); 434 return s == "1" && GLWidget::isSupported(); 435 } 436 #endif 259 } 437 260 438 261 protected slots: … … 541 364 /** @} */ 542 365 543 #ifdef VBOX_GUI_WITH_QTGLFRAMEBUFFER544 GLWidget *m_pGLWidget;545 #endif546 547 366 private: 548 367 … … 556 375 QRect m_cursorRectangle; 557 376 }; 558 559 560 #ifdef VBOX_GUI_WITH_QTGLFRAMEBUFFER561 #define GLCHECK() \562 do { \563 int glErr = glGetError(); \564 if (glErr != GL_NO_ERROR) LogRel4(("GUI GL 0x%x @%d\n", glErr, __LINE__)); \565 } while(0)566 567 GLWidgetSource::GLWidgetSource(GLWidget *pTarget)568 : m_pTarget(pTarget)569 {570 }571 572 GLWidgetSource::~GLWidgetSource()573 {574 cleanup();575 }576 577 GLWidgetSourceImage::GLWidgetSourceImage(GLWidget *pTarget, QImage *pImage)578 : GLWidgetSource(pTarget)579 , m_pImage(pImage)580 {581 }582 583 GLWidgetSourceImage::~GLWidgetSourceImage()584 {585 }586 587 void GLWidgetSourceImage::initGuestScreenTexture(int w, int h)588 {589 glTexImage2D(GLWidget::kTextureTarget, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);590 GLCHECK();591 }592 593 void GLWidgetSourceImage::updateGuestImage()594 {595 /* Copy the image content to the texture. */596 glTexSubImage2D(GLWidget::kTextureTarget, 0, 0, 0, m_pImage->width(), m_pImage->height(),597 GL_BGRA, GL_UNSIGNED_BYTE, m_pImage->bits());598 GLCHECK();599 }600 601 # ifdef RT_OS_LINUX602 GLWidgetSourcePixmap::GLWidgetSourcePixmap(GLWidget *pTarget, Pixmap pixmap, VisualID visualid)603 : GLWidgetSource(pTarget)604 , m_Pixmap(pixmap)605 , m_visualid(visualid)606 , m_glxPixmap(0)607 , m_display(0)608 , m_pfnglXBindTexImageEXT(0)609 , m_pfnglXReleaseTexImageEXT(0)610 {611 }612 613 GLWidgetSourcePixmap::~GLWidgetSourcePixmap()614 {615 }616 617 void GLWidgetSourcePixmap::cleanup()618 {619 m_pfnglXBindTexImageEXT = 0;620 m_pfnglXReleaseTexImageEXT = 0;621 m_Pixmap = 0;622 m_visualid = 0;623 624 if (m_glxPixmap)625 {626 glXDestroyPixmap(m_display, m_glxPixmap);627 m_glxPixmap = 0;628 }629 630 if (m_display)631 {632 XCloseDisplay(m_display);633 m_display = 0;634 }635 }636 637 void GLWidgetSourcePixmap::initGuestScreenTexture(int w, int h)638 {639 RT_NOREF(w, h);640 641 LogRel4(("GUI: GLWidgetSourcePixmap::initGuestScreenTexture: Search for vid = %lu\n", m_visualid));642 643 if (m_display)644 return; /* Already initialized. */645 646 m_display = XOpenDisplay(0);647 if (m_display)648 {649 const char *glXExt = glXQueryExtensionsString(m_display, 0);650 if (glXExt && RTStrStr(glXExt, "GLX_EXT_texture_from_pixmap"))651 {652 m_pfnglXBindTexImageEXT = (PFNGLXBINDTEXIMAGEEXTPROC)glXGetProcAddress((const GLubyte *)"glXBindTexImageEXT");653 m_pfnglXReleaseTexImageEXT = (PFNGLXRELEASETEXIMAGEEXTPROC)glXGetProcAddress((const GLubyte *)"glXReleaseTexImageEXT");654 if (m_pfnglXBindTexImageEXT && m_pfnglXReleaseTexImageEXT)655 {656 LogRelMax(1, ("GUI: GLX_EXT_texture_from_pixmap supported\n"));657 658 /* FBConfig attributes. */659 static int const aConfigAttribList[] =660 {661 // GLX_RENDER_TYPE, GLX_RGBA_BIT,662 // GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,663 // GLX_X_RENDERABLE, True, // Render to GLX pixmaps664 GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, // Must support GLX pixmaps665 GLX_BIND_TO_TEXTURE_RGBA_EXT, True, // Must support GLX_EXT_texture_from_pixmap666 GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT, // Must support GL_TEXTURE_2D because the device creates the pixmap as TEXTURE_2D667 GLX_DOUBLEBUFFER, False, // No need for double buffering for a pixmap.668 GLX_RED_SIZE, 8, // True color RGB with 8 bits per channel.669 GLX_GREEN_SIZE, 8,670 GLX_BLUE_SIZE, 8,671 GLX_ALPHA_SIZE, 8,672 GLX_STENCIL_SIZE, 0, // No stencil buffer673 GLX_DEPTH_SIZE, 0, // No depth buffer674 None675 };676 677 /* Find a suitable FB config. */678 int cConfigs = 0;679 GLXFBConfig *paConfigs = glXChooseFBConfig(m_display, 0, aConfigAttribList, &cConfigs);680 LogRel4(("GUI: GLWidgetSourcePixmap::initGuestScreenTexture: paConfigs %p cConfigs %d\n", (void *)paConfigs, cConfigs));681 if (paConfigs)682 {683 XVisualInfo *vi = NULL;684 int i = 0;685 for (; i < cConfigs; ++i)686 {687 /* Use XFree to free the data returned in the previous iteration of this loop. */688 if (vi)689 XFree(vi);690 691 vi = glXGetVisualFromFBConfig(m_display, paConfigs[i]);692 if (!vi)693 continue;694 695 LogRel4(("GUI: GLWidgetSourcePixmap::initGuestScreenTexture: %p vid %lu screen %d depth %d r %lu g %lu b %lu clrmap %d bitsperrgb %d\n",696 (void *)vi->visual, vi->visualid, vi->screen, vi->depth,697 vi->red_mask, vi->green_mask, vi->blue_mask, vi->colormap_size, vi->bits_per_rgb));698 699 if (vi->visualid != m_visualid)700 continue;701 702 /* This FB config can be used. */703 break;704 }705 706 if (vi)707 {708 XFree(vi);709 vi = 0;710 }711 712 if (i < cConfigs)713 {714 /* Found the requested config. */715 static int const aPixmapAttribList[] =716 {717 GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,718 GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,719 None720 };721 m_glxPixmap = glXCreatePixmap(m_display, paConfigs[i], m_Pixmap, aPixmapAttribList);722 LogRel4(("GUI: GLWidgetSourcePixmap::initGuestScreenTexture: m_glxPixmap %ld\n", m_glxPixmap));723 724 m_pfnglXBindTexImageEXT(m_display, m_glxPixmap, GLX_FRONT_LEFT_EXT, NULL);725 726 /* "Use XFree to free the memory returned by glXChooseFBConfig." */727 XFree(paConfigs);728 729 /* Success. */730 return;731 }732 733 LogRel4(("GUI: GLWidgetSourcePixmap::initGuestScreenTexture: fbconfig not found\n"));734 /* "Use XFree to free the memory returned by glXChooseFBConfig." */735 XFree(paConfigs);736 }737 }738 739 m_pfnglXBindTexImageEXT = 0;740 m_pfnglXReleaseTexImageEXT = 0;741 }742 743 XCloseDisplay(m_display);744 m_display = 0;745 }746 else747 {748 LogRel4(("GUI: GLWidgetSourcePixmap::initGuestScreenTexture: failed to open Display\n"));749 }750 }751 752 void GLWidgetSourcePixmap::uninitGuestScreenTexture()753 {754 if (!m_glxPixmap)755 return;756 757 AssertReturnVoid(m_display && m_pfnglXReleaseTexImageEXT);758 m_pfnglXReleaseTexImageEXT(m_display, m_glxPixmap, GLX_FRONT_LEFT_EXT);759 }760 # endif /* RT_OS_LINUX */761 762 GLWidget::GLWidget(QWidget *parent, UIFrameBufferPrivate *pFramebuffer)763 : QOpenGLWidget(parent)764 , m_pFramebuffer(pFramebuffer)765 , m_nullSource(this)766 , m_pSource(0)767 , m_fReinitSource(false)768 , m_guestTexture(0)769 {770 int rc = RTCritSectInit(&m_critSect);771 AssertRC(rc);772 773 setMouseTracking(true);774 775 #if 0776 QSurfaceFormat format;777 format.setVersion(3, 3);778 //format.setProfile(QSurfaceFormat::CoreProfile);779 format.setRenderableType(QSurfaceFormat::OpenGL);780 format.setRedBufferSize(8);781 format.setGreenBufferSize(8);782 format.setBlueBufferSize(8);783 format.setAlphaBufferSize(8);784 format.setDepthBufferSize(0);785 format.setStencilBufferSize(0);786 format.setSwapInterval(0);787 format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);788 setFormat(format);789 #endif790 }791 792 GLWidget::~GLWidget()793 {794 cleanup();795 796 RTCritSectDelete(&m_critSect);797 RT_ZERO(m_critSect);798 }799 800 /* Whether OpenGL is usable.801 * OpenGL 2.0 required.802 */803 /* static */ bool GLWidget::isSupported()804 {805 /* Create an OpenGL conntext: */806 QOpenGLContext contextGL;807 contextGL.create();808 if (!contextGL.isValid())809 return false;810 811 /* Create an offscreen surface: */812 QOffscreenSurface surface;813 surface.create();814 if (!surface.isValid())815 return false;816 817 /* Make the OpenGL context current: */818 contextGL.makeCurrent(&surface);819 820 /* Get the OpenGL version: */821 char const *pszVersion = (char const *)contextGL.functions()->glGetString(GL_VERSION);822 size_t cchVersion = pszVersion ? strlen(pszVersion) : 0;823 824 int const verMajor = cchVersion >= 1 && '0' <= pszVersion[0] && pszVersion[0] <= '9'? pszVersion[0] - '0' : 0;825 int const verMinor = cchVersion >= 3 && '0' <= pszVersion[2] && pszVersion[2] <= '9'? pszVersion[2] - '0' : 0;826 int const ver = verMajor * 10 + verMinor;827 828 /* Check if GL_TEXTURE_RECTANGLE is supported: */829 //bool const fTextureRectangle = contextGL.hasExtension("GL_ARB_texture_rectangle")830 // || contextGL.hasExtension("GL_NV_texture_rectangle")831 // || ver >= 31;832 833 /* Reset the current OpenGL context: */834 contextGL.doneCurrent();835 836 /* Decide if OpenGL support is good enough: */837 return ver >= 20 /* && fTextureRectangle */;838 }839 840 /** @todo fForce is a bit of a hack. It does not allow to change the HW source to the QImage source,841 * when QImage source is automatically set during the guest screen resize. Think again!842 */843 void GLWidget::setSource(GLWidgetSource *pSource, bool fForce)844 {845 lock();846 if ( !fForce847 && m_pSource848 && m_pSource->IsHW())849 {850 LogRel4(("GUI: GLWidgetSourcePixmap::setSource: keeping HW source\n"));851 unlock();852 return;853 }854 855 if (m_pSource)856 delete m_pSource;857 858 m_pSource = pSource;859 m_fReinitSource = true;860 unlock();861 }862 863 GLWidgetSource *GLWidget::getSource()864 {865 Assert(RTCritSectIsOwner(&m_critSect));866 if (m_pSource)867 {868 if (m_fReinitSource)869 {870 m_fReinitSource = false;871 LogRel4(("GUI: GLWidgetSourcePixmap::getSource: recreate guest texture\n"));872 873 /* If OpenGL context has been created: */874 if (context())875 {876 /* Delete the current guest texture: */877 deleteGuestTexture();878 879 /* Create and bind the new guest texture: */880 createGuestTexture();881 882 glBindTexture(kTextureTarget, m_guestTexture); GLCHECK();883 }884 }885 return m_pSource;886 }887 return &m_nullSource;888 }889 890 void GLWidget::resizeGuestScreen(int w, int h)891 {892 /* The guest screen has been resized. Remember the size: */893 m_guestSize = QSize(w, h);894 }895 896 void GLWidget::setGuestVisibleRect(int x, int y, int w, int h)897 {898 /* Remember the area of the guest screen which must be displayed: */899 m_guestVisibleRect.setRect(x, y, w, h);900 }901 902 void GLWidget::updateGuestImage()903 {904 /* If OpenGL context has been created: */905 if (!context())906 return;907 908 makeCurrent();909 910 lock();911 GLWidgetSource *pSource = getSource();912 if (m_guestTexture)913 {914 /* Copy the image content to the texture. */915 glBindTexture(kTextureTarget, m_guestTexture);916 GLCHECK();917 918 pSource->updateGuestImage();919 }920 unlock();921 922 doneCurrent();923 }924 925 void GLWidget::cleanup()926 {927 if (!RTCritSectIsInitialized(&m_critSect))928 return;929 930 /* If OpenGL context has been created: */931 if (!context())932 return;933 934 makeCurrent();935 936 lock();937 getSource()->cleanup();938 setSource(0, true);939 unlock();940 941 /* Delete all OpenGL resources which are used by this widget: */942 deleteGuestTexture();943 944 doneCurrent();945 }946 947 void GLWidget::initializeGL()948 {949 /* QOpenGLWidget documentation recommends to connect to the context's aboutToBeDestroyed() signal.950 * See https://doc.qt.io/qt-5/qopenglwidget.html#details951 * Connect the signal: */952 connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &GLWidget::cleanup);953 954 /* Required initialization for QOpenGLFunctions: */955 initializeOpenGLFunctions();956 957 /* Create OpenGL resources: */958 createGuestTexture();959 960 /* Setup the OpenGL context state: */961 glClearColor(0, 0, 0, 1); GLCHECK();962 glDisable(GL_DEPTH_TEST); GLCHECK();963 glDisable(GL_CULL_FACE); GLCHECK();964 }965 966 void GLWidget::paintGL()967 {968 lock();969 if (m_guestTexture)970 {971 /* Dimensions of the target window, i.e. the widget's dimensions. */972 GLint const w = width();973 GLint const h = height();974 975 /* The guest coordinates of the visible guest screen area: */976 float x1 = m_guestVisibleRect.x();977 float y1 = m_guestVisibleRect.y();978 float x2 = x1 + m_guestVisibleRect.width();979 float y2 = y1 + m_guestVisibleRect.height();980 981 x1 /= (float)m_guestSize.width();982 y1 /= (float)m_guestSize.height();983 x2 /= (float)m_guestSize.width();984 y2 /= (float)m_guestSize.height();985 986 glDisable(GL_DEPTH_TEST); GLCHECK();987 glDisable(GL_CULL_FACE); GLCHECK();988 989 glEnable(kTextureTarget); GLCHECK();990 991 /* Bind the guest texture: */992 glBindTexture(kTextureTarget, m_guestTexture); GLCHECK();993 994 /* This will reinitialize the source if necessary. */995 getSource();996 997 /* Draw the texture (upside down, because QImage and OpenGL store the bitmap differently): */998 glBegin(GL_QUADS);999 glTexCoord2f(x1, y1); glVertex2i(0, h);1000 glTexCoord2f(x1, y2); glVertex2i(0, 0);1001 glTexCoord2f(x2, y2); glVertex2i(w, 0);1002 glTexCoord2f(x2, y1); glVertex2i(w, h);1003 glEnd(); GLCHECK();1004 1005 glBindTexture(kTextureTarget, 0); GLCHECK();1006 1007 glDisable(kTextureTarget); GLCHECK();1008 1009 glFlush(); GLCHECK();1010 }1011 unlock();1012 }1013 1014 void GLWidget::resizeGL(int w, int h)1015 {1016 /* Setup ModelViewProjection to work in the window cordinates: */1017 glMatrixMode(GL_MODELVIEW);1018 glLoadIdentity();1019 glOrtho(0, w, 0, h, -1, 1);1020 glMatrixMode(GL_PROJECTION);1021 glLoadIdentity();1022 GLCHECK();1023 }1024 1025 void GLWidget::createGuestTexture()1026 {1027 if (m_guestSize.isEmpty())1028 return;1029 1030 /* Choose GL_NEAREST if no scaling or the scaling factor is an integer: */1031 double const scaleFactor = m_pFramebuffer->scaleFactor();1032 GLenum const filter = floor(scaleFactor) == scaleFactor ? GL_NEAREST : GL_LINEAR;1033 1034 /* Create a new guest texture, which must be the same size as the guest screen: */1035 glGenTextures(1, &m_guestTexture);1036 glEnable(kTextureTarget); GLCHECK();1037 glBindTexture(kTextureTarget, m_guestTexture);1038 glTexParameteri(kTextureTarget, GL_TEXTURE_MAG_FILTER, filter);1039 glTexParameteri(kTextureTarget, GL_TEXTURE_MIN_FILTER, filter);1040 1041 lock();1042 getSource()->initGuestScreenTexture(m_guestSize.width(), m_guestSize.height());1043 unlock();1044 1045 glBindTexture(kTextureTarget, 0);1046 GLCHECK();1047 glDisable(kTextureTarget); GLCHECK();1048 }1049 1050 void GLWidget::deleteGuestTexture()1051 {1052 if (m_guestTexture)1053 {1054 glBindTexture(kTextureTarget, m_guestTexture);1055 1056 lock();1057 getSource()->uninitGuestScreenTexture();1058 unlock();1059 1060 glBindTexture(kTextureTarget, 0); GLCHECK();1061 glDeleteTextures(1, &m_guestTexture); GLCHECK();1062 m_guestTexture = 0;1063 }1064 }1065 #endif /* VBOX_GUI_WITH_QTGLFRAMEBUFFER */1066 377 1067 378 … … 1085 396 , m_dDevicePixelRatioActual(1.0) 1086 397 , m_fUseUnscaledHiDPIOutput(false) 1087 #ifdef VBOX_GUI_WITH_QTGLFRAMEBUFFER1088 , m_pGLWidget(0)1089 #endif1090 398 { 1091 399 LogRel2(("GUI: UIFrameBufferPrivate::UIFrameBufferPrivate %p\n", this)); … … 1154 462 if (m_pMachineView) 1155 463 prepareConnections(); 1156 1157 #ifdef VBOX_GUI_WITH_QTGLFRAMEBUFFER1158 /* Decide if we are going to use GL to draw the guest screen: */1159 m_pGLWidget = 0;1160 if (m_pMachineView && isGLWidgetSupported())1161 m_pGLWidget = new GLWidget(m_pMachineView->viewport(), this);1162 #endif1163 464 } 1164 465 … … 1607 908 } 1608 909 1609 #if defined(VBOX_GUI_WITH_QTGLFRAMEBUFFER) && defined(RT_OS_LINUX)1610 case VBOX3D_NOTIFY_TYPE_HW_SCREEN_CREATED:1611 case VBOX3D_NOTIFY_TYPE_HW_SCREEN_DESTROYED:1612 case VBOX3D_NOTIFY_TYPE_HW_SCREEN_UPDATE_BEGIN:1613 case VBOX3D_NOTIFY_TYPE_HW_SCREEN_UPDATE_END:1614 {1615 HRESULT hr = S_OK;1616 com::SafeArray<BYTE> notifyData(ComSafeArrayInArg(data));1617 if (m_pGLWidget)1618 {1619 if (uType == VBOX3D_NOTIFY_TYPE_HW_SCREEN_CREATED)1620 {1621 LogRel4(("GUI: Notify3DEvent VBOX3D_NOTIFY_TYPE_3D_SCREEN_CREATED\n"));1622 1623 struct NotifyData1624 {1625 uint64_t u64NativeHandle;1626 VisualID visualid;1627 };1628 struct NotifyData *pData = (struct NotifyData *)notifyData.raw();1629 1630 GLWidgetSource *p = new GLWidgetSourcePixmap(m_pGLWidget, (Pixmap)pData->u64NativeHandle, pData->visualid);1631 m_pGLWidget->setSource(p, true);1632 1633 LogRelMax(1, ("GUI: Created a HW accelerated screen\n"));1634 }1635 else if (uType == VBOX3D_NOTIFY_TYPE_HW_SCREEN_DESTROYED)1636 {1637 LogRel4(("GUI: Notify3DEvent VBOX3D_NOTIFY_TYPE_3D_SCREEN_DESTROYED\n"));1638 1639 GLWidgetSource *p = new GLWidgetSourceImage(m_pGLWidget, &m_image);1640 m_pGLWidget->setSource(p, true);1641 }1642 else if (uType == VBOX3D_NOTIFY_TYPE_HW_SCREEN_UPDATE_BEGIN)1643 {1644 /* Do nothing. */1645 }1646 else if (uType == VBOX3D_NOTIFY_TYPE_HW_SCREEN_UPDATE_END)1647 {1648 struct NotifyData1649 {1650 uint64_t u64NativeHandle;1651 int32_t left;1652 int32_t top;1653 int32_t right;1654 int32_t bottom;1655 };1656 struct NotifyData *pData = (struct NotifyData *)notifyData.raw();1657 1658 /* Send the screen update message. */1659 int iX = pData->left;1660 int iY = pData->top;1661 int iWidth = pData->right - pData->left;1662 int iHeight = pData->bottom - pData->top;1663 emit sigNotifyUpdate(iX, iY, iWidth, iHeight);1664 }1665 }1666 else1667 {1668 hr = E_FAIL; // Not supported1669 }1670 unlock();1671 return hr;1672 }1673 #endif /* defined(VBOX_GUI_WITH_QTGLFRAMEBUFFER) && defined(RT_OS_LINUX) */1674 1675 910 default: 1676 911 break; … … 1853 1088 } 1854 1089 1855 #ifdef VBOX_GUI_WITH_QTGLFRAMEBUFFER1856 if (m_pGLWidget)1857 {1858 m_pGLWidget->resizeGuestScreen(m_iWidth, m_iHeight);1859 1860 GLWidgetSource *p = new GLWidgetSourceImage(m_pGLWidget, &m_image);1861 m_pGLWidget->setSource(p, false);1862 }1863 #endif1864 1865 1090 lock(); 1866 1091 … … 2024 1249 if (m_image.isNull()) 2025 1250 return; 2026 2027 #ifdef VBOX_GUI_WITH_QTGLFRAMEBUFFER2028 if (m_pGLWidget)2029 {2030 /* Draw the actually visible guest rectangle on the entire GLWidget.2031 * This code covers non-HiDPI normal and scaled modes. Scrollbars work too. */2032 2033 /** @todo HiDPI support. Possibly need to split the geometry calculations from the QImage handling below2034 * and share the geometry code with the OpenGL code path. */2035 2036 /* Set the visible guest rectangle: */2037 m_pGLWidget->setGuestVisibleRect(m_pMachineView->contentsX(), m_pMachineView->contentsY(),2038 convertHostXTo(m_pGLWidget->width()), convertHostYTo(m_pGLWidget->height()));2039 2040 /* Tell the GL Widget to update the guest screen content from the source: */2041 m_pGLWidget->updateGuestImage();2042 2043 /* Redraw: */2044 m_pGLWidget->update();2045 2046 /* Done: */2047 return;2048 }2049 #endif /* VBOX_GUI_WITH_QTGLFRAMEBUFFER */2050 1251 2051 1252 /* First we take the cached image as the source: */
Note:
See TracChangeset
for help on using the changeset viewer.