summaryrefslogtreecommitdiffstats
path: root/src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/display_window.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/display_window.cpp')
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/display_window.cpp574
1 files changed, 574 insertions, 0 deletions
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/display_window.cpp b/src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/display_window.cpp
new file mode 100644
index 00000000..c888987c
--- /dev/null
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/display_window.cpp
@@ -0,0 +1,574 @@
+/* $Id: display_window.cpp $ */
+
+/** @file
+ * Presenter API: CrFbDisplayWindow class implementation -- display content into host GUI window.
+ */
+
+/*
+ * Copyright (C) 2014-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include "server_presenter.h"
+
+CrFbDisplayWindow::CrFbDisplayWindow(const RTRECT *pViewportRect, uint64_t parentId) :
+ mpWindow(NULL),
+ mViewportRect(*pViewportRect),
+ mu32Screen(~0),
+ mParentId(parentId)
+{
+ mFlags.u32Value = 0;
+}
+
+
+CrFbDisplayWindow::~CrFbDisplayWindow()
+{
+ if (mpWindow)
+ delete mpWindow;
+}
+
+
+int CrFbDisplayWindow::UpdateBegin(struct CR_FRAMEBUFFER *pFb)
+{
+ int rc = mpWindow ? mpWindow->UpdateBegin() : VINF_SUCCESS;
+ if (RT_SUCCESS(rc))
+ {
+ rc = CrFbDisplayBase::UpdateBegin(pFb);
+ if (RT_SUCCESS(rc))
+ return VINF_SUCCESS;
+ else
+ {
+ WARN(("err"));
+ if (mpWindow)
+ mpWindow->UpdateEnd();
+ }
+ }
+ else
+ WARN(("err"));
+
+ return rc;
+}
+
+
+void CrFbDisplayWindow::UpdateEnd(struct CR_FRAMEBUFFER *pFb)
+{
+ CrFbDisplayBase::UpdateEnd(pFb);
+
+ if (mpWindow)
+ mpWindow->UpdateEnd();
+}
+
+
+int CrFbDisplayWindow::RegionsChanged(struct CR_FRAMEBUFFER *pFb)
+{
+ int rc = CrFbDisplayBase::RegionsChanged(pFb);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ if (mpWindow && mpWindow->GetParentId())
+ {
+ rc = mpWindow->Create();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+int CrFbDisplayWindow::EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+{
+ int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ if (mpWindow && mpWindow->GetParentId())
+ {
+ rc = mpWindow->Create();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+int CrFbDisplayWindow::EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
+{
+ int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ if (mpWindow && mpWindow->GetParentId())
+ {
+ rc = mpWindow->Create();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+int CrFbDisplayWindow::EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+{
+ int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ if (mpWindow && mpWindow->GetParentId())
+ {
+ rc = mpWindow->Create();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+int CrFbDisplayWindow::FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
+{
+ int rc = CrFbDisplayBase::FramebufferChanged(pFb);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ return screenChanged();
+}
+
+
+const RTRECT* CrFbDisplayWindow::getViewportRect()
+{
+ return &mViewportRect;
+}
+
+
+int CrFbDisplayWindow::setViewportRect(const RTRECT *pViewportRect)
+{
+ if (!isUpdating())
+ {
+ WARN(("not updating!"));
+ return VERR_INVALID_STATE;
+ }
+
+ // always call SetPosition to ensure window is adjustep properly
+ // if (pViewportRect->xLeft != mViewportRect.xLeft || pViewportRect->yTop != mViewportRect.yTop)
+ if (mpWindow)
+ {
+ const RTRECT* pRect = getRect();
+ int rc = mpWindow->SetPosition(pRect->xLeft - pViewportRect->xLeft, pRect->yTop - pViewportRect->yTop);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("SetPosition failed"));
+ return rc;
+ }
+ }
+
+ mViewportRect = *pViewportRect;
+
+ return VINF_SUCCESS;
+}
+
+
+CrFbWindow * CrFbDisplayWindow::windowDetach(bool fCleanup)
+{
+ if (isUpdating())
+ {
+ WARN(("updating!"));
+ return NULL;
+ }
+
+ CrFbWindow * pWindow = mpWindow;
+ if (mpWindow)
+ {
+ if (fCleanup)
+ windowCleanup();
+ mpWindow = NULL;
+ }
+ return pWindow;
+}
+
+
+CrFbWindow * CrFbDisplayWindow::windowAttach(CrFbWindow * pNewWindow)
+{
+ if (isUpdating())
+ {
+ WARN(("updating!"));
+ return NULL;
+ }
+
+ CrFbWindow * pOld = mpWindow;
+ if (mpWindow)
+ windowDetach();
+
+ mpWindow = pNewWindow;
+ if (pNewWindow)
+ windowSync();
+
+ return mpWindow;
+}
+
+
+int CrFbDisplayWindow::reparent(uint64_t parentId)
+{
+ if (!isUpdating())
+ {
+ WARN(("not updating!"));
+ return VERR_INVALID_STATE;
+ }
+
+ crDebug("CrFbDisplayWindow: change parent from %p to %p.", mParentId, parentId);
+
+ mParentId = parentId;
+ int rc = VINF_SUCCESS;
+
+ /* Force notify Render SPU about parent window ID change in order to prevent
+ * crashes when it tries to access already deallocated parent window.
+ * Previously, we also used isActive() here, however it might become FALSE for the case
+ * when VM Window goes fullscreen mode and back. */
+ if ( /* isActive() && */ mpWindow)
+ {
+ rc = mpWindow->Reparent(parentId);
+ if (!RT_SUCCESS(rc))
+ WARN(("window reparent failed"));
+
+ mFlags.fNeForce = 1;
+ }
+
+ return rc;
+}
+
+
+bool CrFbDisplayWindow::isVisible()
+{
+ HCR_FRAMEBUFFER hFb = getFramebuffer();
+ if (!hFb)
+ return false;
+ const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(hFb);
+ return !CrVrScrCompositorIsEmpty(pCompositor);
+}
+
+
+int CrFbDisplayWindow::winVisibilityChanged()
+{
+ HCR_FRAMEBUFFER hFb = getFramebuffer();
+ if (!hFb || !CrFbIsEnabled(hFb))
+ {
+ Assert(!mpWindow || !mpWindow->IsVisivle());
+ return VINF_SUCCESS;
+ }
+
+ int rc = VINF_SUCCESS;
+
+ if (mpWindow)
+ {
+ rc = mpWindow->UpdateBegin();
+ if (RT_SUCCESS(rc))
+ {
+ rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
+ if (!RT_SUCCESS(rc))
+ WARN(("SetVisible failed, rc %d", rc));
+
+ mpWindow->UpdateEnd();
+ }
+ else
+ WARN(("UpdateBegin failed, rc %d", rc));
+ }
+
+ return rc;
+}
+
+
+CrFbWindow* CrFbDisplayWindow::getWindow()
+{
+ return mpWindow;
+}
+
+
+void CrFbDisplayWindow::onUpdateEnd()
+{
+ CrFbDisplayBase::onUpdateEnd();
+ bool fVisible = isVisible();
+ if (mFlags.fNeVisible != fVisible || mFlags.fNeForce)
+ {
+ crVBoxServerNotifyEvent(mu32Screen,
+ fVisible? VBOX3D_NOTIFY_EVENT_TYPE_3DDATA_VISIBLE:
+ VBOX3D_NOTIFY_EVENT_TYPE_3DDATA_HIDDEN,
+ NULL, 0);
+ mFlags.fNeVisible = fVisible;
+ mFlags.fNeForce = 0;
+ }
+}
+
+
+void CrFbDisplayWindow::ueRegions()
+{
+ if (mpWindow)
+ mpWindow->SetVisibleRegionsChanged();
+}
+
+
+int CrFbDisplayWindow::screenChanged()
+{
+ if (!isUpdating())
+ {
+ WARN(("not updating!"));
+ return VERR_INVALID_STATE;
+ }
+
+ int rc = windowDimensionsSync();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("windowDimensionsSync failed rc %d", rc));
+ return rc;
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+int CrFbDisplayWindow::windowSetCompositor(bool fSet)
+{
+ if (!mpWindow)
+ return VINF_SUCCESS;
+
+ if (fSet)
+ {
+ const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
+ return mpWindow->SetCompositor(pCompositor);
+ }
+ return mpWindow->SetCompositor(NULL);
+}
+
+
+int CrFbDisplayWindow::windowCleanup()
+{
+ if (!mpWindow)
+ return VINF_SUCCESS;
+
+ int rc = mpWindow->UpdateBegin();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ rc = windowDimensionsSync(true);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ mpWindow->UpdateEnd();
+ return rc;
+ }
+
+ rc = windowSetCompositor(false);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ mpWindow->UpdateEnd();
+ return rc;
+ }
+
+ mpWindow->UpdateEnd();
+
+ return VINF_SUCCESS;
+}
+
+
+int CrFbDisplayWindow::fbCleanup()
+{
+ int rc = windowCleanup();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("windowCleanup failed"));
+ return rc;
+ }
+ return CrFbDisplayBase::fbCleanup();
+}
+
+
+bool CrFbDisplayWindow::isActive()
+{
+ HCR_FRAMEBUFFER hFb = getFramebuffer();
+ return hFb && CrFbIsEnabled(hFb);
+}
+
+
+int CrFbDisplayWindow::windowDimensionsSync(bool fForceCleanup)
+{
+ int rc = VINF_SUCCESS;
+
+ if (!mpWindow)
+ return VINF_SUCCESS;
+
+ //HCR_FRAMEBUFFER hFb = getFramebuffer();
+ if (!fForceCleanup && isActive())
+ {
+ const RTRECT* pRect = getRect();
+
+ if (mpWindow->GetParentId() != mParentId)
+ {
+ rc = mpWindow->Reparent(mParentId);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+ }
+
+ rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ setRegionsChanged();
+
+ rc = mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+ }
+ else
+ {
+ rc = mpWindow->SetVisible(false);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+#if 0
+ rc = mpWindow->Reparent(mDefaultParentId);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+#endif
+ }
+
+ return rc;
+}
+
+
+int CrFbDisplayWindow::windowSync()
+{
+ if (!mpWindow)
+ return VINF_SUCCESS;
+
+ int rc = mpWindow->UpdateBegin();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ rc = windowSetCompositor(true);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ mpWindow->UpdateEnd();
+ return rc;
+ }
+
+ rc = windowDimensionsSync();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ mpWindow->UpdateEnd();
+ return rc;
+ }
+
+ mpWindow->UpdateEnd();
+
+ return rc;
+}
+
+
+int CrFbDisplayWindow::fbSync()
+{
+ int rc = CrFbDisplayBase::fbSync();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ HCR_FRAMEBUFFER hFb = getFramebuffer();
+
+ mu32Screen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
+
+ rc = windowSync();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("windowSync failed %d", rc));
+ return rc;
+ }
+
+ if (CrFbHas3DData(hFb))
+ {
+ if (mpWindow && mpWindow->GetParentId())
+ {
+ rc = mpWindow->Create();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+const struct RTRECT* CrFbDisplayWindow::getRect()
+{
+ const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
+ return CrVrScrCompositorRectGet(pCompositor);
+}
+