From 1700c7d32f7d9d101cbba9f1fcb8bb57ed16a727 Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Sat, 5 Apr 2014 22:17:15 +0200 Subject: Imported Upstream version 4.3.10-dfsg --- .../common/VBoxGuestLib/VBoxGuestR0LibCrOgl.cpp | 15 +- src/VBox/Additions/common/crOpenGL/Makefile.kmk | 5 - src/VBox/Additions/linux/installer/vboxadd-x11.sh | 16 +- src/VBox/Additions/x11/VBoxClient/draganddrop.cpp | 92 +- src/VBox/Additions/x11/vboxvideo/Makefile.kmk | 2 +- src/VBox/Debugger/DBGPlugInLinux.cpp | 23 +- src/VBox/Devices/EFI/DevEFI.cpp | 2 +- src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd | Bin 1048576 -> 1048576 bytes src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd | Bin 1048576 -> 1048576 bytes .../Graphics/BIOS/VBoxVgaBiosAlternative.asm | 253 +-- .../Graphics/BIOS/VBoxVgaBiosAlternative.md5sum | 2 +- src/VBox/Devices/Graphics/DevVGA.cpp | 6 + src/VBox/Devices/Graphics/DevVGA.h | 11 +- src/VBox/Devices/Graphics/DevVGA_VBVA.cpp | 74 +- src/VBox/Devices/Graphics/DevVGA_VDMA.cpp | 2098 ++++++++++++-------- src/VBox/Devices/Makefile.kmk | 5 +- src/VBox/Devices/Network/lwip-new/CHANGELOG | 44 + src/VBox/Devices/Network/lwip-new/Makefile.kmk | 34 +- src/VBox/Devices/Network/lwip-new/src/api/tcpip.c | 1 + .../Devices/Network/lwip-new/src/core/ipv4/icmp.c | 4 + .../Devices/Network/lwip-new/src/core/ipv4/ip4.c | 4 +- .../Network/lwip-new/src/core/ipv4/ip_frag.c | 15 +- .../Devices/Network/lwip-new/src/core/ipv6/icmp6.c | 10 +- .../Devices/Network/lwip-new/src/core/ipv6/ip6.c | 17 +- .../Devices/Network/lwip-new/src/core/ipv6/mld6.c | 2 + .../Devices/Network/lwip-new/src/core/ipv6/nd6.c | 6 + src/VBox/Devices/Network/lwip-new/src/core/memp.c | 12 +- src/VBox/Devices/Network/lwip-new/src/core/netif.c | 66 +- .../Devices/Network/lwip-new/src/core/snmp/mib2.c | 10 +- src/VBox/Devices/Network/lwip-new/src/core/stats.c | 4 +- src/VBox/Devices/Network/lwip-new/src/core/tcp.c | 9 +- .../Devices/Network/lwip-new/src/core/tcp_out.c | 7 +- .../Devices/Network/lwip-new/src/core/timers.c | 22 +- .../lwip-new/src/include/ipv4/lwip/autoip.h | 3 + .../Network/lwip-new/src/include/ipv4/lwip/inet.h | 16 +- .../lwip-new/src/include/ipv4/lwip/ip4_addr.h | 3 + .../Network/lwip-new/src/include/ipv6/lwip/inet6.h | 2 +- .../lwip-new/src/include/ipv6/lwip/ip6_addr.h | 9 +- .../Network/lwip-new/src/include/lwip/debug.h | 8 +- .../Network/lwip-new/src/include/lwip/memp_std.h | 2 +- .../Network/lwip-new/src/include/lwip/netif.h | 2 +- .../Network/lwip-new/src/include/lwip/netifapi.h | 3 + .../Network/lwip-new/src/include/lwip/opt.h | 28 +- .../Network/lwip-new/src/include/lwip/snmp.h | 4 +- .../Network/lwip-new/src/include/lwip/sockets.h | 51 +- .../Devices/Network/lwip-new/vbox/VBoxLwipCore.cpp | 10 +- .../Network/lwip-new/vbox/include/lwip-log.h | 93 + .../Network/lwip-new/vbox/include/lwip-namespace.h | 26 +- .../Network/lwip-new/vbox/include/lwipopts.h | 222 --- src/VBox/Devices/Network/lwipopts.h | 177 ++ src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.asm | 4 +- .../Devices/PC/BIOS/VBoxBiosAlternative.md5sum | 2 +- src/VBox/Devices/Storage/DrvHostBase.cpp | 4 +- src/VBox/Devices/VMMDev/VMMDevHGCM.cpp | 12 + .../src/globals/UIExtraDataEventHandler.cpp | 20 +- .../src/globals/UIExtraDataEventHandler.h | 1 + .../src/platform/darwin/UICocoaApplication.h | 23 + .../src/platform/darwin/UICocoaApplication.mm | 94 +- .../src/platform/darwin/VBoxUtils-darwin-cocoa.mm | 43 + .../src/platform/darwin/VBoxUtils-darwin.cpp | 20 + .../src/platform/darwin/VBoxUtils-darwin.h | 10 + .../VirtualBox/src/runtime/UIFrameBuffer.cpp | 8 + .../VirtualBox/src/runtime/UIKeyboardHandler.cpp | 12 +- .../Frontends/VirtualBox/src/runtime/UIMachine.cpp | 53 +- .../VirtualBox/src/runtime/UIMachineLogic.cpp | 77 +- .../VirtualBox/src/runtime/UIMachineLogic.h | 15 +- .../VirtualBox/src/runtime/UIMachineView.cpp | 2 +- .../VirtualBox/src/runtime/UIMachineWindow.cpp | 36 +- .../VirtualBox/src/runtime/UIMachineWindow.h | 18 +- .../VirtualBox/src/runtime/UIMouseHandler.cpp | 51 +- .../VirtualBox/src/runtime/UIMouseHandler.h | 7 + .../Frontends/VirtualBox/src/runtime/UISession.cpp | 48 +- .../Frontends/VirtualBox/src/runtime/UISession.h | 9 - .../fullscreen/UIMachineLogicFullscreen.cpp | 448 ++++- .../runtime/fullscreen/UIMachineLogicFullscreen.h | 58 +- .../fullscreen/UIMachineWindowFullscreen.cpp | 228 ++- .../runtime/fullscreen/UIMachineWindowFullscreen.h | 39 +- .../src/runtime/normal/UIMachineLogicNormal.cpp | 12 +- .../src/runtime/normal/UIMachineWindowNormal.cpp | 16 +- .../src/runtime/scale/UIMachineLogicScale.cpp | 12 +- .../src/runtime/scale/UIMachineWindowScale.cpp | 16 +- .../runtime/seamless/UIMachineLogicSeamless.cpp | 40 +- .../src/runtime/seamless/UIMachineLogicSeamless.h | 3 + .../runtime/seamless/UIMachineWindowSeamless.cpp | 47 +- .../src/runtime/seamless/UIMachineWindowSeamless.h | 6 +- .../src/settings/global/UIGlobalSettingsInput.cpp | 20 +- .../VirtualBox/src/widgets/UIMiniToolBar.cpp | 28 +- .../VirtualBox/src/widgets/UIMiniToolBar.h | 13 + .../src/wizards/newvm/UIWizardNewVMPageBasic1.cpp | 4 +- src/VBox/GuestHost/OpenGL/include/cr_server.h | 13 +- src/VBox/GuestHost/OpenGL/include/cr_vreg.h | 18 +- src/VBox/GuestHost/OpenGL/packer/pack_pixels.c | 3 +- src/VBox/GuestHost/OpenGL/util/blitter.cpp | 2 +- src/VBox/GuestHost/OpenGL/util/htable.cpp | 2 +- .../VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp | 84 +- src/VBox/HostServices/SharedOpenGL/Makefile.kmk | 6 + .../SharedOpenGL/crserver/crservice.cpp | 73 +- .../HostServices/SharedOpenGL/crserverlib/server.h | 6 +- .../SharedOpenGL/crserverlib/server_main.c | 290 ++- .../SharedOpenGL/crserverlib/server_muralfbo.cpp | 18 +- .../SharedOpenGL/crserverlib/server_presenter.cpp | 397 +++- .../SharedOpenGL/crserverlib/server_stream.c | 22 + .../SharedOpenGL/crserverlib/server_window.c | 44 +- .../SharedOpenGL/render/renderspu_wgl.c | 41 +- .../darwin/VirtualBox_mpkg/Localizable.strings | 4 +- .../darwin/VirtualBox_mpkg/distribution.dist | 24 +- src/VBox/Installer/linux/run-inst.sh | 25 +- src/VBox/Main/include/ApplianceImpl.h | 1 + src/VBox/Main/include/ConsoleImpl.h | 10 +- src/VBox/Main/include/DisplayImpl.h | 12 +- src/VBox/Main/include/EventImpl.h | 2 +- src/VBox/Main/include/MachineImpl.h | 2 + src/VBox/Main/src-all/EventImpl.cpp | 420 ++-- src/VBox/Main/src-client/ConsoleImpl.cpp | 708 +++---- src/VBox/Main/src-client/ConsoleImpl2.cpp | 8 +- src/VBox/Main/src-client/DisplayImpl.cpp | 77 +- src/VBox/Main/src-client/GuestFileImpl.cpp | 2 +- src/VBox/Main/src-client/GuestImpl.cpp | 2 +- src/VBox/Main/src-client/GuestProcessImpl.cpp | 2 +- src/VBox/Main/src-client/GuestSessionImpl.cpp | 2 +- src/VBox/Main/src-client/KeyboardImpl.cpp | 2 +- src/VBox/Main/src-client/MouseImpl.cpp | 2 +- src/VBox/Main/src-client/VirtualBoxClientImpl.cpp | 2 +- src/VBox/Main/src-server/ApplianceImpl.cpp | 2 + src/VBox/Main/src-server/ApplianceImplExport.cpp | 17 +- src/VBox/Main/src-server/HostDnsService.cpp | 4 +- src/VBox/Main/src-server/MachineImpl.cpp | 90 +- src/VBox/Main/src-server/NATNetworkImpl.cpp | 4 +- src/VBox/Main/src-server/VirtualBoxImpl.cpp | 8 +- src/VBox/Main/src-server/darwin/iokit.cpp | 4 +- src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp | 6 +- src/VBox/NetworkServices/NAT/Makefile.kmk | 1 + src/VBox/NetworkServices/NAT/VBoxNetLwipNAT.cpp | 421 ++-- src/VBox/NetworkServices/NAT/lwipopts.h | 179 ++ src/VBox/NetworkServices/NAT/portfwd.c | 57 +- .../NetworkServices/NetLib/VBoxNetBaseService.cpp | 14 +- .../NetLib/VBoxNetPortForwardString.cpp | 27 +- .../NetworkServices/NetLib/VBoxPortForwardString.h | 2 - src/VBox/Runtime/VBox/log-vbox.cpp | 1 + .../Runtime/common/asm/ASMAtomicCmpXchgExU64.asm | 8 +- .../Runtime/common/asm/ASMAtomicCmpXchgU64.asm | 4 +- src/VBox/Runtime/common/asm/ASMCpuIdExSlow.asm | 5 +- src/VBox/Runtime/common/asm/ASMCpuId_Idx_ECX.asm | 10 +- src/VBox/Runtime/common/string/strformatrt.cpp | 173 +- src/VBox/Runtime/generic/env-generic.cpp | 5 + src/VBox/Runtime/r0drv/nt/ntBldSymDb.cpp | 19 +- src/VBox/Runtime/r0drv/nt/symdbdata.h | 96 +- src/VBox/Runtime/r3/linux/sysfs.cpp | 164 +- .../Runtime/r3/win/RTSystemQueryDmiString-win.cpp | 8 +- src/VBox/Runtime/testcase/tstHandleTable.cpp | 8 +- src/VBox/Runtime/testcase/tstMemAutoPtr.cpp | 6 +- src/VBox/Runtime/testcase/tstRTStrFormat.cpp | 108 +- src/VBox/Storage/VD.cpp | 2 +- src/VBox/Storage/VHD.cpp | 2 +- src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp | 214 +- src/VBox/VMM/VMMAll/PGMAllPool.cpp | 7 +- src/VBox/VMM/VMMR0/HMR0.cpp | 2 +- src/VBox/VMM/VMMR0/HMVMXR0.cpp | 214 +- src/VBox/VMM/VMMR3/CPUM.cpp | 8 + src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp | 65 +- src/VBox/VMM/VMMR3/CPUMR3Db.cpp | 11 + src/VBox/VMM/VMMR3/CSAM.cpp | 15 +- src/VBox/VMM/VMMR3/PATM.cpp | 5 +- src/VBox/VMM/VMMR3/PATMSSM.cpp | 9 - src/VBox/VMM/VMMR3/SSM.cpp | 31 + src/VBox/VMM/VMMR3/VM.cpp | 9 + src/VBox/VMM/VMMR3/cpus/AMD_Athlon_64_3200.h | 1 + .../VMMR3/cpus/AMD_Athlon_64_X2_Dual_Core_4200.h | 188 ++ src/VBox/VMM/VMMR3/cpus/AMD_FX_8150_Eight_Core.h | 1 + src/VBox/VMM/VMMR3/cpus/AMD_Phenom_II_X6_1100T.h | 1 + src/VBox/VMM/VMMR3/cpus/Intel_Core_i5_3570.h | 9 +- src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_2635QM.h | 326 +++ src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_3820QM.h | 5 +- src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_3960X.h | 9 +- src/VBox/VMM/VMMR3/cpus/Intel_Pentium_4_3_00GHz.h | 3 +- .../VMMR3/cpus/Intel_Pentium_M_processor_2_00GHz.h | 5 +- src/VBox/VMM/VMMR3/cpus/Intel_Xeon_X5482_3_20GHz.h | 5 +- .../VMM/VMMR3/cpus/Quad_Core_AMD_Opteron_2384.h | 1 + .../VMM/VMMR3/cpus/VIA_QuadCore_L4700_1_2_GHz.h | 3 +- src/VBox/VMM/include/CPUMInternal.h | 18 +- src/VBox/VMM/include/CPUMInternal.mac | 2 +- src/VBox/VMM/include/HMInternal.h | 2 +- src/VBox/VMM/include/PATMInternal.h | 1 - src/VBox/VMM/testcase/tstGlobalConfig.cpp | 4 +- src/VBox/VMM/testcase/tstInstrEmul.cpp | 10 +- src/VBox/VMM/testcase/tstVMMFork.cpp | 4 +- src/VBox/VMM/tools/Makefile.kmk | 2 +- src/VBox/VMM/tools/VBoxCpuReport.cpp | 168 +- src/libs/xpcom18a4/python/server/loader.py | 14 +- src/libs/xpcom18a4/python/src/PyGBase.cpp | 3 +- src/libs/xpcom18a4/python/src/PyIID.cpp | 2 +- src/libs/xpcom18a4/python/src/PyISupports.cpp | 4 +- 192 files changed, 6970 insertions(+), 3281 deletions(-) create mode 100644 src/VBox/Devices/Network/lwip-new/vbox/include/lwip-log.h delete mode 100644 src/VBox/Devices/Network/lwip-new/vbox/include/lwipopts.h create mode 100644 src/VBox/Devices/Network/lwipopts.h create mode 100644 src/VBox/NetworkServices/NAT/lwipopts.h create mode 100644 src/VBox/VMM/VMMR3/cpus/AMD_Athlon_64_X2_Dual_Core_4200.h create mode 100644 src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_2635QM.h (limited to 'src') diff --git a/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR0LibCrOgl.cpp b/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR0LibCrOgl.cpp index 3fa03d204..893b47181 100644 --- a/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR0LibCrOgl.cpp +++ b/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR0LibCrOgl.cpp @@ -91,9 +91,18 @@ DECLVBGL(int) vboxCrCtlConConnect(HVBOXCRCTL hCtl, uint32_t *pu32ClientID) RTStrCopy(info.Loc.u.host.achName, sizeof (info.Loc.u.host.achName), "VBoxSharedCrOpenGL"); rc = vbglDriverIOCtl (&hCtl->driver, VBOXGUEST_IOCTL_HGCM_CONNECT, &info, sizeof (info)); if (RT_SUCCESS(rc)) - *pu32ClientID = info.u32ClientID; - else - *pu32ClientID = 0; + { + rc = info.result; + if (RT_SUCCESS(rc)) + { + Assert(info.u32ClientID); + *pu32ClientID = info.u32ClientID; + return rc; + } + } + + Assert(RT_FAILURE(rc)); + *pu32ClientID = 0; return rc; } diff --git a/src/VBox/Additions/common/crOpenGL/Makefile.kmk b/src/VBox/Additions/common/crOpenGL/Makefile.kmk index 42a04d74f..9d21e1a2a 100644 --- a/src/VBox/Additions/common/crOpenGL/Makefile.kmk +++ b/src/VBox/Additions/common/crOpenGL/Makefile.kmk @@ -240,7 +240,6 @@ ifdef VBOX_WITH_WDDM # # VBoxOGL-x86 - x86 VBoxOGL version built for amd64 build # -DLLS.win.amd64 += VBoxOGL-x86 VBoxOGL-x86_EXTENDS = VBoxOGL VBoxOGL-x86_BLD_TRG_ARCH = x86 VBoxOGL-x86_LIBS = $(VBOX_LIB_IPRT_GUEST_R3_SHARED_X86) \ @@ -468,7 +467,6 @@ ifdef VBOX_WITH_WDDM # # VBoxOGLarrayspu-x86 - x86 version of VBoxOGLarrayspu built for amd64 build # -DLLS.win.amd64 += VBoxOGLarrayspu-x86 VBoxOGLarrayspu-x86_EXTENDS = VBoxOGLarrayspu VBoxOGLarrayspu-x86_BLD_TRG_ARCH = x86 VBoxOGLarrayspu-x86_LIBS = $(VBOX_LIB_OGL_CRUTIL_X86) \ @@ -512,7 +510,6 @@ ifdef VBOX_WITH_WDDM # # VBoxOGLpassthroughspu-x86 - x86 version of VBoxOGLpassthroughspu built for amd64 build # -DLLS.win.amd64 += VBoxOGLpassthroughspu-x86 VBoxOGLpassthroughspu-x86_EXTENDS = VBoxOGLpassthroughspu VBoxOGLpassthroughspu-x86_BLD_TRG_ARCH = x86 VBoxOGLpassthroughspu-x86_LIBS = $(VBOX_LIB_OGL_CRUTIL_X86) @@ -594,7 +591,6 @@ ifdef VBOX_WITH_WDDM # # VBoxOGLpackspu-x86 - x86 version of VBoxOGLpackspu built for amd64 build # -DLLS.win.amd64 += VBoxOGLpackspu-x86 VBoxOGLpackspu-x86_EXTENDS = VBoxOGLpackspu VBoxOGLpackspu-x86_BLD_TRG_ARCH = x86 VBoxOGLpackspu-x86_LIBS = $(VBOX_LIB_OGL_CRUTIL_X86) \ @@ -671,7 +667,6 @@ ifdef VBOX_WITH_WDDM # # VBoxOGLfeedbackspu-x86 - x86 version of VBoxOGLfeedbackspu built for amd64 build # -DLLS.win.amd64 += VBoxOGLfeedbackspu-x86 VBoxOGLfeedbackspu-x86_EXTENDS = VBoxOGLfeedbackspu VBoxOGLfeedbackspu-x86_BLD_TRG_ARCH = x86 VBoxOGLfeedbackspu-x86_LIBS = $(VBOX_LIB_OGL_CRUTIL_X86) \ diff --git a/src/VBox/Additions/linux/installer/vboxadd-x11.sh b/src/VBox/Additions/linux/installer/vboxadd-x11.sh index 1d871270f..7188e4f89 100755 --- a/src/VBox/Additions/linux/installer/vboxadd-x11.sh +++ b/src/VBox/Additions/linux/installer/vboxadd-x11.sh @@ -1,6 +1,6 @@ #! /bin/sh # -# Linux Additions X11 setup init script ($Revision: 91688 $) +# Linux Additions X11 setup init script ($Revision: 92745 $) # # @@ -38,17 +38,19 @@ cpu=`uname -m`; case "$cpu" in i[3456789]86|x86) cpu="x86" - LIB="/usr/lib" + lib_candidates="/usr/lib/i386-linux-gnu /usr/lib /lib" ;; x86_64|amd64) cpu="amd64" - if test -d "/usr/lib64"; then - LIB="/usr/lib64" - else - LIB="/usr/lib" - fi + lib_candidates="/usr/lib/x86_64-linux-gnu /usr/lib64 /usr/lib /lib64 /lib" ;; esac +for i in $lib_candidates; do + if test -d "$i/VBoxGuestAdditions"; then + LIB=$i + break + fi +done # Find the version of X installed # The last of the three is for the X.org 6.7 included in Fedora Core 2 diff --git a/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp b/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp index cc44fae85..f38a89f57 100644 --- a/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp +++ b/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp @@ -14,6 +14,9 @@ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. */ +#include +#include + #include #include //#include @@ -423,7 +426,6 @@ public: , m_hX11Thread(NIL_RTTHREAD) , m_hEventSem(NIL_RTSEMEVENT) , m_pCurDnD(0) - , m_fSrvStopping(false) {} virtual const char *getPidFilePath() { return ".vboxclient-draganddrop.pid"; } @@ -434,14 +436,13 @@ public: virtual void cleanup() { - /* Cleanup */ - x11DragAndDropTerm(); + /* Nothing to do, everything should be cleaned up automatically when the + * user process/X11 client exits. */ VbglR3DnDTerm(); }; private: int x11DragAndDropInit(); - int x11DragAndDropTerm(); static int hgcmEventThread(RTTHREAD hThread, void *pvUser); static int x11EventThread(RTTHREAD hThread, void *pvUser); @@ -474,7 +475,6 @@ private: RTTHREAD m_hX11Thread; RTSEMEVENT m_hEventSem; DragInstance *m_pCurDnD; - bool m_fSrvStopping; friend class DragInstance; }; @@ -1662,7 +1662,8 @@ int DragAndDropService::run(bool fDaemonised /* = false */) } } } - } while (!ASMAtomicReadBool(&m_fSrvStopping)); + XFlush(m_pDisplay); + } while (1); } while (0); LogRelFlowFunc(("returning %Rrc\n", rc)); @@ -1698,51 +1699,12 @@ int DragAndDropService::x11DragAndDropInit() "X11-NOTIFY"); } while (0); - /* Cleanup on failure */ - if (RT_FAILURE(rc)) - x11DragAndDropTerm(); + /* No clean-up code for now, as we have no good way of testing it and things + * should get cleaned up when the user process/X11 client exits. */ return rc; } -int DragAndDropService::x11DragAndDropTerm() -{ - /* Mark that we are stopping. */ - ASMAtomicWriteBool(&m_fSrvStopping, true); - RTSemEventSignal(m_hEventSem); - - if (m_pDisplay) - { - /* Send a x11 client messages to the x11 event loop. */ - XClientMessageEvent m; - RT_ZERO(m); - m.type = ClientMessage; - m.display = m_pDisplay; - m.window = None; - m.message_type = xAtom(XA_dndstop); - m.format = 32; - int xrc = XSendEvent(m_pDisplay, None, True, NoEventMask, reinterpret_cast(&m)); - if (RT_UNLIKELY(xrc == 0)) - DO(("DnD_TERM: error sending xevent\n")); - } - - /* We cannot signal the m_hHGCMThread as it is most likely waiting in vbglR3DoIOCtl() */ - /* Wait for our event threads to stop. */ - if (m_hX11Thread) - RTThreadWait(m_hX11Thread, RT_INDEFINITE_WAIT, NULL); - /* Cleanup */ - /* todo: This doesn't work. The semaphore was interrupted by the user - * signal. It is not possible to destroy a semaphore while it is in interrupted state. - * According to Frank, the cleanup stuff done here is done _wrong_. We just - * should signal the main loop to stop and do the cleanup there. Needs - * adoption in all VBoxClient::Service's. */ -// if (m_hEventSem) -// RTSemEventDestroy(m_hEventSem); - if (m_pDisplay) - XCloseDisplay(m_pDisplay); - return VINF_SUCCESS; -} - /* static */ int DragAndDropService::hgcmEventThread(RTTHREAD hThread, void *pvUser) { @@ -1762,7 +1724,7 @@ int DragAndDropService::hgcmEventThread(RTTHREAD hThread, void *pvUser) if (RT_FAILURE(rc)) return rc; } - } while (!ASMAtomicReadBool(&pThis->m_fSrvStopping)); + } while (1); return VINF_SUCCESS; } @@ -1775,24 +1737,17 @@ int DragAndDropService::x11EventThread(RTTHREAD hThread, void *pvUser) DnDEvent e; do { - /* Wait for new events. We can't use XIfEvent here, cause this locks + /* Wait for new events. We can't use XIfEvent here, because this locks * the window connection with a mutex and if no X11 events occurs this - * blocks any other calls we made to X11. So instead check for new - * events and if there are not any new one, sleep for a certain amount - * of time. */ + * blocks any other calls we made to X11. So instead poll for new events + * on the connection file descriptor. */ + /** @todo Make sure the locking is right - Xlib displays should never be + * used from two threads at once. */ if (XEventsQueued(pThis->m_pDisplay, QueuedAfterFlush) > 0) { RT_ZERO(e); e.type = DnDEvent::X11_Type; XNextEvent(pThis->m_pDisplay, &e.x11); -#if 0 - /* We never detect the stop event here for some reason */ - /* Check for a stop message. */ - if ( e.x11.type == ClientMessage - && e.x11.xclient.message_type == xAtom(XA_dndstop)) - break; -#endif -// if (isDnDRespondEvent(pThis->m_pDisplay, &e.x11, 0)) { /* Appending makes a copy of the event structure. */ pThis->m_eventQueue.append(e); @@ -1802,8 +1757,21 @@ int DragAndDropService::x11EventThread(RTTHREAD hThread, void *pvUser) } } else - RTThreadSleep(25); - } while (!ASMAtomicReadBool(&pThis->m_fSrvStopping)); + { + struct pollfd pollFD; + + pollFD.fd = ConnectionNumber(pThis->m_pDisplay); + pollFD.events = POLLIN | POLLPRI; + if ( (poll(&pollFD, 1, -1) < 0 && errno != EINTR) + || pollFD.revents & POLLNVAL) + { + LogRel(("X11 event thread: poll failed, stopping.\n")); + /** @todo Just stop the whole service. What use is it just + * to stop one thread? */ + return RTErrConvertFromErrno(errno); + } + } + } while (1); return VINF_SUCCESS; } diff --git a/src/VBox/Additions/x11/vboxvideo/Makefile.kmk b/src/VBox/Additions/x11/vboxvideo/Makefile.kmk index 7dde54c0a..67c53486d 100644 --- a/src/VBox/Additions/x11/vboxvideo/Makefile.kmk +++ b/src/VBox/Additions/x11/vboxvideo/Makefile.kmk @@ -376,7 +376,7 @@ ifdef VBOX_USE_SYSTEM_XORG_HEADERS /usr/include/libdrm \ /usr/include/xorg \ /usr/include/pixman-1 - vboxvideo_drv_system_SOURCES := $(vboxvideo_drv_15_SOURCES) + vboxvideo_drv_system_SOURCES := $(vboxvideo_drv_17_SOURCES) endif diff --git a/src/VBox/Debugger/DBGPlugInLinux.cpp b/src/VBox/Debugger/DBGPlugInLinux.cpp index 05c27f859..bbe5df34c 100644 --- a/src/VBox/Debugger/DBGPlugInLinux.cpp +++ b/src/VBox/Debugger/DBGPlugInLinux.cpp @@ -197,13 +197,13 @@ static DECLCALLBACK(bool) dbgDiggerLinuxProbe(PUVM pUVM, void *pvData) DBGFADDRESS KernelAddr; DBGFR3AddrFromFlat(pUVM, &KernelAddr, g_au64LnxKernelAddresses[i]); DBGFADDRESS HitAddr; - static const uint8_t s_abLinuxVersion[] = "Linux version 2."; + static const uint8_t s_abLinuxVersion2x[] = "Linux version 2."; int rc = DBGFR3MemScan(pUVM, 0, &KernelAddr, LNX_MAX_KERNEL_SIZE, 1, - s_abLinuxVersion, sizeof(s_abLinuxVersion) - 1, &HitAddr); + s_abLinuxVersion2x, sizeof(s_abLinuxVersion2x) - 1, &HitAddr); if (RT_SUCCESS(rc)) { char szTmp[128]; - char const *pszY = &szTmp[sizeof(s_abLinuxVersion) - 1]; + char const *pszY = &szTmp[sizeof(s_abLinuxVersion2x) - 1]; rc = DBGFR3MemReadString(pUVM, 0, &HitAddr, szTmp, sizeof(szTmp)); if ( RT_SUCCESS(rc) && *pszY >= '0' @@ -214,6 +214,23 @@ static DECLCALLBACK(bool) dbgDiggerLinuxProbe(PUVM pUVM, void *pvData) return true; } } + static const uint8_t s_abLinuxVersion3x[] = "Linux version 3."; + rc = DBGFR3MemScan(pUVM, 0, &KernelAddr, LNX_MAX_KERNEL_SIZE, 1, + s_abLinuxVersion3x, sizeof(s_abLinuxVersion3x) - 1, &HitAddr); + if (RT_SUCCESS(rc)) + { + char szTmp[128]; + char const *pszY = &szTmp[sizeof(s_abLinuxVersion3x) - 1]; + rc = DBGFR3MemReadString(pUVM, 0, &HitAddr, szTmp, sizeof(szTmp)); + if ( RT_SUCCESS(rc) + && *pszY >= '0' + && *pszY <= '9') + { + pThis->AddrKernelBase = KernelAddr; + pThis->AddrLinuxBanner = HitAddr; + return true; + } + } } return false; } diff --git a/src/VBox/Devices/EFI/DevEFI.cpp b/src/VBox/Devices/EFI/DevEFI.cpp index 1400a63b0..34b4b24f5 100644 --- a/src/VBox/Devices/EFI/DevEFI.cpp +++ b/src/VBox/Devices/EFI/DevEFI.cpp @@ -2241,7 +2241,7 @@ static DECLCALLBACK(int) efiConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMN */ pThis->u64TscFrequency = TMCpuTicksPerSecond(PDMDevHlpGetVM(pDevIns)); pThis->u64CpuFrequency = pThis->u64TscFrequency; - pThis->u64FsbFrequency = CPUMGetGuestBusFrequency(PDMDevHlpGetVM(pDevIns)); + pThis->u64FsbFrequency = CPUMGetGuestScalableBusFrequency(PDMDevHlpGetVM(pDevIns)); /* * GOP graphics. diff --git a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd index 22c648a31..dd8f84641 100644 Binary files a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd and b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd differ diff --git a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd index eab9b08ae..d64748c3b 100644 Binary files a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd and b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd differ diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.asm b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.asm index 850c34f8d..183842bb8 100644 --- a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.asm +++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.asm @@ -1642,7 +1642,7 @@ vga_read_char_attr_: ; 0xc0acb LB 0xa8 call 02f93h ; e8 73 24 movzx bx, ch ; 0f b6 dd sal bx, 003h ; c1 e3 03 - cmp byte [bx+0482fh], 000h ; 80 bf 2f 48 00 + cmp byte [bx+04830h], 000h ; 80 bf 30 48 00 jne short 00b5ah ; 75 2d mov dx, ax ; 89 c2 imul dx, di ; 0f af d7 @@ -1658,7 +1658,7 @@ vga_read_char_attr_: ; 0xc0acb LB 0xa8 add ax, ax ; 01 c0 mov dx, cx ; 89 ca add dx, ax ; 01 c2 - mov ax, word [bx+04832h] ; 8b 87 32 48 + mov ax, word [bx+04833h] ; 8b 87 33 48 call 02f93h ; e8 3c 24 mov word [ss:si], ax ; 36 89 04 lea sp, [bp-008h] ; 8d 66 f8 @@ -1724,18 +1724,18 @@ vga_get_font_info_: ; 0xc0b73 LB 0x82 retn 00002h ; c2 02 00 mov dx, 0010ch ; ba 0c 01 jmp short 00b91h ; eb bf - mov ax, 05daeh ; b8 ae 5d + mov ax, 05dafh ; b8 af 5d mov dx, 0c000h ; ba 00 c0 jmp short 00b96h ; eb bc - mov ax, 055aeh ; b8 ae 55 + mov ax, 055afh ; b8 af 55 jmp short 00bd5h ; eb f6 - mov ax, 059aeh ; b8 ae 59 + mov ax, 059afh ; b8 af 59 jmp short 00bd5h ; eb f1 - mov ax, 07baeh ; b8 ae 7b + mov ax, 07bafh ; b8 af 7b jmp short 00bd5h ; eb ec - mov ax, 06baeh ; b8 ae 6b + mov ax, 06bafh ; b8 af 6b jmp short 00bd5h ; eb e7 - mov ax, 07cdbh ; b8 db 7c + mov ax, 07cdch ; b8 dc 7c jmp short 00bd5h ; eb e2 jmp short 00bc4h ; eb cf vga_read_pixel_: ; 0xc0bf5 LB 0x139 @@ -1757,9 +1757,9 @@ vga_read_pixel_: ; 0xc0bf5 LB 0x139 je near 00d27h ; 0f 84 0d 01 movzx bx, al ; 0f b6 d8 sal bx, 003h ; c1 e3 03 - cmp byte [bx+0482fh], 000h ; 80 bf 2f 48 00 + cmp byte [bx+04830h], 000h ; 80 bf 30 48 00 je near 00d27h ; 0f 84 fe 00 - mov bl, byte [bx+04830h] ; 8a 9f 30 48 + mov bl, byte [bx+04831h] ; 8a 9f 31 48 cmp bl, 003h ; 80 fb 03 jc short 00c43h ; 72 11 jbe short 00c4bh ; 76 17 @@ -1818,7 +1818,7 @@ vga_read_pixel_: ; 0xc0bf5 LB 0x139 call 02f77h ; e8 b4 22 movzx bx, cl ; 0f b6 d9 sal bx, 003h ; c1 e3 03 - cmp byte [bx+04831h], 002h ; 80 bf 31 48 02 + cmp byte [bx+04832h], 002h ; 80 bf 32 48 02 jne short 00cebh ; 75 1b mov cx, si ; 89 f1 xor ch, ch ; 30 ed @@ -2119,7 +2119,7 @@ biosfn_set_active_page_: ; 0xc0f00 LB 0xdc movzx bx, ch ; 0f b6 dd mov si, bx ; 89 de sal si, 003h ; c1 e6 03 - cmp byte [si+0482fh], 000h ; 80 bc 2f 48 00 + cmp byte [si+04830h], 000h ; 80 bc 30 48 00 jne short 00f83h ; 75 40 mov dx, strict word 0004ah ; ba 4a 00 mov ax, strict word 00040h ; b8 40 00 @@ -2146,10 +2146,10 @@ biosfn_set_active_page_: ; 0xc0f00 LB 0xdc lea bx, [si+001h] ; 8d 5c 01 imul bx, di ; 0f af df jmp short 00f95h ; eb 12 - movzx bx, byte [bx+048aeh] ; 0f b6 9f ae 48 + movzx bx, byte [bx+048afh] ; 0f b6 9f af 48 sal bx, 006h ; c1 e3 06 movzx ax, cl ; 0f b6 c1 - mov bx, word [bx+048c5h] ; 8b 9f c5 48 + mov bx, word [bx+048c6h] ; 8b 9f c6 48 imul bx, ax ; 0f af d8 mov dx, strict word 00063h ; ba 63 00 mov ax, strict word 00040h ; b8 40 00 @@ -2214,15 +2214,15 @@ biosfn_set_video_mode_: ; 0xc0fdc LB 0x387 cmp AL, strict byte 0ffh ; 3c ff je near 01359h ; 0f 84 43 03 movzx si, al ; 0f b6 f0 - mov al, byte [si+048aeh] ; 8a 84 ae 48 + mov al, byte [si+048afh] ; 8a 84 af 48 mov byte [bp-00ch], al ; 88 46 f4 movzx bx, al ; 0f b6 d8 sal bx, 006h ; c1 e3 06 - movzx ax, byte [bx+048c2h] ; 0f b6 87 c2 48 - mov word [bp-018h], ax ; 89 46 e8 movzx ax, byte [bx+048c3h] ; 0f b6 87 c3 48 - mov word [bp-016h], ax ; 89 46 ea + mov word [bp-018h], ax ; 89 46 e8 movzx ax, byte [bx+048c4h] ; 0f b6 87 c4 48 + mov word [bp-016h], ax ; 89 46 ea + movzx ax, byte [bx+048c5h] ; 0f b6 87 c5 48 mov word [bp-014h], ax ; 89 46 ec mov dx, 00087h ; ba 87 00 mov ax, strict word 00040h ; b8 40 00 @@ -2238,13 +2238,13 @@ biosfn_set_video_mode_: ; 0xc0fdc LB 0x387 jne near 010ebh ; 0f 85 8a 00 mov bx, si ; 89 f3 sal bx, 003h ; c1 e3 03 - mov al, byte [bx+04834h] ; 8a 87 34 48 + mov al, byte [bx+04835h] ; 8a 87 35 48 mov dx, 003c6h ; ba c6 03 out DX, AL ; ee xor al, al ; 30 c0 mov dx, 003c8h ; ba c8 03 out DX, AL ; ee - mov bl, byte [bx+04835h] ; 8a 9f 35 48 + mov bl, byte [bx+04836h] ; 8a 9f 36 48 cmp bl, 001h ; 80 fb 01 jc short 0108bh ; 72 0e jbe short 01094h ; 76 15 @@ -2255,13 +2255,13 @@ biosfn_set_video_mode_: ; 0xc0fdc LB 0x387 jmp short 010a1h ; eb 16 test bl, bl ; 84 db jne short 010a1h ; 75 12 - mov di, 05042h ; bf 42 50 + mov di, 05043h ; bf 43 50 jmp short 010a1h ; eb 0d - mov di, 05102h ; bf 02 51 + mov di, 05103h ; bf 03 51 jmp short 010a1h ; eb 08 - mov di, 051c2h ; bf c2 51 + mov di, 051c3h ; bf c3 51 jmp short 010a1h ; eb 03 - mov di, 05282h ; bf 82 52 + mov di, 05283h ; bf 83 52 xor bx, bx ; 31 db jmp short 010b4h ; eb 0f xor al, al ; 30 c0 @@ -2274,8 +2274,8 @@ biosfn_set_video_mode_: ; 0xc0fdc LB 0x387 jnc short 010deh ; 73 2a movzx si, byte [bp-012h] ; 0f b6 76 ee sal si, 003h ; c1 e6 03 - movzx si, byte [si+04835h] ; 0f b6 b4 35 48 - movzx dx, byte [si+048beh] ; 0f b6 94 be 48 + movzx si, byte [si+04836h] ; 0f b6 b4 36 48 + movzx dx, byte [si+048bfh] ; 0f b6 94 bf 48 cmp bx, dx ; 39 d3 jnbe short 010a5h ; 77 dc imul si, bx, strict byte 00003h ; 6b f3 03 @@ -2307,7 +2307,7 @@ biosfn_set_video_mode_: ; 0xc0fdc LB 0x387 movzx si, byte [bp-00ch] ; 0f b6 76 f4 sal si, 006h ; c1 e6 06 add si, bx ; 01 de - mov al, byte [si+048e5h] ; 8a 84 e5 48 + mov al, byte [si+048e6h] ; 8a 84 e6 48 out DX, AL ; ee inc bx ; 43 jmp short 010f5h ; eb e4 @@ -2331,7 +2331,7 @@ biosfn_set_video_mode_: ; 0xc0fdc LB 0x387 movzx si, byte [bp-00ch] ; 0f b6 76 f4 sal si, 006h ; c1 e6 06 add si, bx ; 01 de - mov al, byte [si+048c6h] ; 8a 84 c6 48 + mov al, byte [si+048c7h] ; 8a 84 c7 48 mov dx, 003c5h ; ba c5 03 out DX, AL ; ee inc bx ; 43 @@ -2346,14 +2346,14 @@ biosfn_set_video_mode_: ; 0xc0fdc LB 0x387 movzx si, byte [bp-00ch] ; 0f b6 76 f4 sal si, 006h ; c1 e6 06 add si, bx ; 01 de - mov al, byte [si+048f9h] ; 8a 84 f9 48 + mov al, byte [si+048fah] ; 8a 84 fa 48 mov dx, 003cfh ; ba cf 03 out DX, AL ; ee inc bx ; 43 jmp short 0114ch ; eb e1 movzx bx, byte [bp-012h] ; 0f b6 5e ee sal bx, 003h ; c1 e3 03 - cmp byte [bx+04830h], 001h ; 80 bf 30 48 01 + cmp byte [bx+04831h], 001h ; 80 bf 31 48 01 jne short 0117eh ; 75 05 mov dx, 003b4h ; ba b4 03 jmp short 01181h ; eb 03 @@ -2373,12 +2373,12 @@ biosfn_set_video_mode_: ; 0xc0fdc LB 0x387 mov di, cx ; 89 cf add di, bx ; 01 df lea dx, [si+001h] ; 8d 54 01 - mov al, byte [di+048cch] ; 8a 85 cc 48 + mov al, byte [di+048cdh] ; 8a 85 cd 48 out DX, AL ; ee inc bx ; 43 jmp short 0118bh ; eb e0 mov bx, cx ; 89 cb - mov al, byte [bx+048cbh] ; 8a 87 cb 48 + mov al, byte [bx+048cch] ; 8a 87 cc 48 mov dx, 003c2h ; ba c2 03 out DX, AL ; ee mov AL, strict byte 020h ; b0 20 @@ -2392,9 +2392,9 @@ biosfn_set_video_mode_: ; 0xc0fdc LB 0x387 jne short 01226h ; 75 5f movzx bx, byte [bp-012h] ; 0f b6 5e ee sal bx, 003h ; c1 e3 03 - cmp byte [bx+0482fh], 000h ; 80 bf 2f 48 00 + cmp byte [bx+04830h], 000h ; 80 bf 30 48 00 jne short 011e8h ; 75 13 - mov es, [bx+04832h] ; 8e 87 32 48 + mov es, [bx+04833h] ; 8e 87 33 48 mov cx, 04000h ; b9 00 40 mov ax, 00720h ; b8 20 07 xor di, di ; 31 ff @@ -2404,7 +2404,7 @@ biosfn_set_video_mode_: ; 0xc0fdc LB 0x387 jmp short 01226h ; eb 3e cmp byte [bp-00eh], 00dh ; 80 7e f2 0d jnc short 01200h ; 73 12 - mov es, [bx+04832h] ; 8e 87 32 48 + mov es, [bx+04833h] ; 8e 87 33 48 mov cx, 04000h ; b9 00 40 xor ax, ax ; 31 c0 xor di, di ; 31 ff @@ -2422,7 +2422,7 @@ biosfn_set_video_mode_: ; 0xc0fdc LB 0x387 mov word [bp-01ah], ax ; 89 46 e6 mov AL, strict byte 00fh ; b0 0f out DX, AL ; ee - mov es, [bx+04832h] ; 8e 87 32 48 + mov es, [bx+04833h] ; 8e 87 33 48 mov cx, 08000h ; b9 00 80 xor ax, ax ; 31 c0 xor di, di ; 31 ff @@ -2441,7 +2441,7 @@ biosfn_set_video_mode_: ; 0xc0fdc LB 0x387 call 02fa1h ; e8 62 1d movzx bx, byte [bp-00ch] ; 0f b6 5e f4 sal bx, 006h ; c1 e3 06 - mov bx, word [bx+048c5h] ; 8b 9f c5 48 + mov bx, word [bx+048c6h] ; 8b 9f c6 48 mov dx, strict word 0004ch ; ba 4c 00 mov ax, strict word 00040h ; b8 40 00 call 02fa1h ; e8 4e 1d @@ -2480,7 +2480,7 @@ biosfn_set_video_mode_: ; 0xc0fdc LB 0x387 mov ax, strict word 00040h ; b8 40 00 call 02f85h ; e8 ce 1c mov cx, ds ; 8c d9 - mov bx, 05592h ; bb 92 55 + mov bx, 05593h ; bb 93 55 mov dx, 000a8h ; ba a8 00 mov ax, strict word 00040h ; b8 40 00 call 02fc1h ; e8 fc 1c @@ -2494,7 +2494,7 @@ biosfn_set_video_mode_: ; 0xc0fdc LB 0x387 call 02f85h ; e8 aa 1c movzx bx, byte [bp-012h] ; 0f b6 5e ee sal bx, 003h ; c1 e3 03 - cmp byte [bx+0482fh], 000h ; 80 bf 2f 48 00 + cmp byte [bx+04830h], 000h ; 80 bf 30 48 00 jne short 012f2h ; 75 09 mov dx, strict word 00007h ; ba 07 00 mov ax, strict word 00006h ; b8 06 00 @@ -2512,7 +2512,7 @@ biosfn_set_video_mode_: ; 0xc0fdc LB 0x387 call 00f00h ; e8 f5 fb movzx bx, byte [bp-012h] ; 0f b6 5e ee sal bx, 003h ; c1 e3 03 - cmp byte [bx+0482fh], 000h ; 80 bf 2f 48 00 + cmp byte [bx+04830h], 000h ; 80 bf 30 48 00 jne short 01329h ; 75 10 xor bl, bl ; 30 db mov AL, strict byte 004h ; b0 04 @@ -2522,7 +2522,7 @@ biosfn_set_video_mode_: ; 0xc0fdc LB 0x387 mov AL, strict byte 003h ; b0 03 mov AH, strict byte 011h ; b4 11 int 010h ; cd 10 - mov dx, 059aeh ; ba ae 59 + mov dx, 059afh ; ba af 59 mov ax, strict word 0001fh ; b8 1f 00 call 00a00h ; e8 ce f6 mov ax, word [bp-014h] ; 8b 46 ec @@ -2532,13 +2532,13 @@ biosfn_set_video_mode_: ; 0xc0fdc LB 0x387 je short 0134fh ; 74 10 cmp ax, strict word 00008h ; 3d 08 00 jne short 01359h ; 75 15 - mov dx, 055aeh ; ba ae 55 + mov dx, 055afh ; ba af 55 mov ax, strict word 00043h ; b8 43 00 call 00a00h ; e8 b3 f6 jmp short 01359h ; eb 0a - mov dx, 05daeh ; ba ae 5d + mov dx, 05dafh ; ba af 5d jmp short 01347h ; eb f3 - mov dx, 06baeh ; ba ae 6b + mov dx, 06bafh ; ba af 6b jmp short 01347h ; eb ee lea sp, [bp-00ah] ; 8d 66 f6 pop di ; 5f @@ -2848,7 +2848,7 @@ biosfn_scroll_: ; 0xc1568 LB 0x506 mov word [bp-01ah], ax ; 89 46 e6 mov ax, word [bp-016h] ; 8b 46 ea imul ax, cx ; 0f af c1 - cmp byte [di+0482fh], 000h ; 80 bd 2f 48 00 + cmp byte [di+04830h], 000h ; 80 bd 30 48 00 jne near 017c7h ; 0f 85 9f 01 mov dx, ax ; 89 c2 add dx, ax ; 01 c2 @@ -2871,7 +2871,7 @@ biosfn_scroll_: ; 0xc1568 LB 0x506 movzx dx, byte [bp-00ch] ; 0f b6 56 f4 sal dx, 008h ; c1 e2 08 add dx, strict byte 00020h ; 83 c2 20 - mov es, [di+04832h] ; 8e 85 32 48 + mov es, [di+04833h] ; 8e 85 33 48 mov cx, ax ; 89 c1 mov ax, dx ; 89 d0 mov di, bx ; 89 df @@ -2905,7 +2905,7 @@ biosfn_scroll_: ; 0xc1568 LB 0x506 add di, dx ; 01 d7 movzx si, byte [bp-00eh] ; 0f b6 76 f2 sal si, 003h ; c1 e6 03 - mov es, [si+04832h] ; 8e 84 32 48 + mov es, [si+04833h] ; 8e 84 33 48 cld ; fc jcxz 016d3h ; e3 02 rep stosw ; f3 ab @@ -2919,7 +2919,7 @@ biosfn_scroll_: ; 0xc1568 LB 0x506 add dx, dx ; 01 d2 movzx si, byte [bp-00eh] ; 0f b6 76 f2 sal si, 003h ; c1 e6 03 - mov ax, word [si+04832h] ; 8b 84 32 48 + mov ax, word [si+04833h] ; 8b 84 33 48 mov si, word [bp-014h] ; 8b 76 ec imul si, word [bp-016h] ; 0f af 76 ea add cx, si ; 01 f1 @@ -2963,7 +2963,7 @@ biosfn_scroll_: ; 0xc1568 LB 0x506 add di, dx ; 01 d7 movzx si, byte [bp-00eh] ; 0f b6 76 f2 sal si, 003h ; c1 e6 03 - mov es, [si+04832h] ; 8e 84 32 48 + mov es, [si+04833h] ; 8e 84 33 48 cld ; fc jcxz 01774h ; e3 02 rep stosw ; f3 ab @@ -2978,7 +2978,7 @@ biosfn_scroll_: ; 0xc1568 LB 0x506 add dx, dx ; 01 d2 movzx si, byte [bp-00eh] ; 0f b6 76 f2 sal si, 003h ; c1 e6 03 - mov ax, word [si+04832h] ; 8b 84 32 48 + mov ax, word [si+04833h] ; 8b 84 33 48 mov si, word [bp-014h] ; 8b 76 ec imul si, word [bp-016h] ; 0f af 76 ea add di, si ; 01 f7 @@ -2998,11 +2998,11 @@ biosfn_scroll_: ; 0xc1568 LB 0x506 jc near 01a65h ; 0f 82 a4 02 dec word [bp-014h] ; ff 4e ec jmp near 01723h ; e9 5c ff - movzx bx, byte [si+048aeh] ; 0f b6 9c ae 48 + movzx bx, byte [si+048afh] ; 0f b6 9c af 48 sal bx, 006h ; c1 e3 06 - mov dl, byte [bx+048c4h] ; 8a 97 c4 48 + mov dl, byte [bx+048c5h] ; 8a 97 c5 48 mov byte [bp-00ah], dl ; 88 56 f6 - mov bl, byte [di+04830h] ; 8a 9d 30 48 + mov bl, byte [di+04831h] ; 8a 9d 31 48 cmp bl, 004h ; 80 fb 04 je short 017eeh ; 74 0f cmp bl, 003h ; 80 fb 03 @@ -3035,7 +3035,7 @@ biosfn_scroll_: ; 0xc1568 LB 0x506 movzx ax, byte [bp-00ch] ; 0f b6 46 f4 movzx bx, byte [bp-00eh] ; 0f b6 5e f2 sal bx, 003h ; c1 e3 03 - mov es, [bx+04832h] ; 8e 87 32 48 + mov es, [bx+04833h] ; 8e 87 33 48 xor di, di ; 31 ff cld ; fc jcxz 0183fh ; e3 02 @@ -3117,7 +3117,7 @@ biosfn_scroll_: ; 0xc1568 LB 0x506 jc near 01a65h ; 0f 82 3d 01 dec word [bp-014h] ; ff 4e ec jmp short 018bch ; eb 8f - mov dl, byte [di+04831h] ; 8a 95 31 48 + mov dl, byte [di+04832h] ; 8a 95 32 48 cmp byte [bp-010h], 000h ; 80 7e f0 00 jne short 01974h ; 75 3d cmp byte [bp-008h], 000h ; 80 7e f8 00 @@ -3135,7 +3135,7 @@ biosfn_scroll_: ; 0xc1568 LB 0x506 movzx cx, dl ; 0f b6 ca imul cx, ax ; 0f af c8 movzx ax, byte [bp-00ch] ; 0f b6 46 f4 - mov es, [di+04832h] ; 8e 85 32 48 + mov es, [di+04833h] ; 8e 85 33 48 xor di, di ; 31 ff cld ; fc jcxz 01971h ; e3 02 @@ -3237,11 +3237,11 @@ write_gfx_char_pl4_: ; 0xc1a6e LB 0xeb je short 01a8ch ; 74 0b cmp byte [bp+006h], 00eh ; 80 7e 06 0e jne short 01a91h ; 75 0a - mov di, 05daeh ; bf ae 5d + mov di, 05dafh ; bf af 5d jmp short 01a94h ; eb 08 - mov di, 06baeh ; bf ae 6b + mov di, 06bafh ; bf af 6b jmp short 01a94h ; eb 03 - mov di, 055aeh ; bf ae 55 + mov di, 055afh ; bf af 55 movzx si, cl ; 0f b6 f1 movzx bx, byte [bp+006h] ; 0f b6 5e 06 imul si, bx ; 0f af f3 @@ -3328,7 +3328,7 @@ write_gfx_char_cga_: ; 0xc1b59 LB 0x11e push di ; 57 sub sp, strict byte 00008h ; 83 ec 08 mov byte [bp-008h], dl ; 88 56 f8 - mov si, 055aeh ; be ae 55 + mov si, 055afh ; be af 55 xor bh, bh ; 30 ff movzx di, byte [bp+006h] ; 0f b6 7e 06 imul di, bx ; 0f af fb @@ -3442,7 +3442,7 @@ write_gfx_char_lin_: ; 0xc1c77 LB 0x91 push di ; 57 sub sp, strict byte 00008h ; 83 ec 08 mov byte [bp-006h], dl ; 88 56 fa - mov di, 055aeh ; bf ae 55 + mov di, 055afh ; bf af 55 movzx dx, cl ; 0f b6 d1 movzx cx, byte [bp+004h] ; 0f b6 4e 04 imul cx, dx ; 0f af ca @@ -3537,7 +3537,7 @@ biosfn_write_char_attr_: ; 0xc1d08 LB 0x168 movzx bx, cl ; 0f b6 d9 mov di, bx ; 89 df sal di, 003h ; c1 e7 03 - cmp byte [di+0482fh], 000h ; 80 bd 2f 48 00 + cmp byte [di+04830h], 000h ; 80 bd 30 48 00 jne short 01dc3h ; 75 47 mov bx, word [bp-018h] ; 8b 5e e8 imul bx, ax ; 0f af d8 @@ -3558,18 +3558,18 @@ biosfn_write_char_attr_: ; 0xc1d08 LB 0x168 add ax, bx ; 01 d8 mov word [bp-01ah], ax ; 89 46 e6 mov ax, word [bp-01ah] ; 8b 46 e6 - mov es, [di+04832h] ; 8e 85 32 48 + mov es, [di+04833h] ; 8e 85 33 48 mov cx, si ; 89 f1 mov di, dx ; 89 d7 cld ; fc jcxz 01dc0h ; e3 02 rep stosw ; f3 ab jmp near 01e69h ; e9 a6 00 - movzx bx, byte [bx+048aeh] ; 0f b6 9f ae 48 + movzx bx, byte [bx+048afh] ; 0f b6 9f af 48 sal bx, 006h ; c1 e3 06 - mov al, byte [bx+048c4h] ; 8a 87 c4 48 + mov al, byte [bx+048c5h] ; 8a 87 c5 48 mov byte [bp-008h], al ; 88 46 f8 - mov al, byte [di+04831h] ; 8a 85 31 48 + mov al, byte [di+04832h] ; 8a 85 32 48 mov byte [bp-014h], al ; 88 46 ec dec si ; 4e cmp si, strict byte 0ffffh ; 83 fe ff @@ -3579,7 +3579,7 @@ biosfn_write_char_attr_: ; 0xc1d08 LB 0x168 jnc near 01e69h ; 0f 83 7d 00 movzx bx, byte [bp-006h] ; 0f b6 5e fa sal bx, 003h ; c1 e3 03 - mov al, byte [bx+04830h] ; 8a 87 30 48 + mov al, byte [bx+04831h] ; 8a 87 31 48 cmp AL, strict byte 003h ; 3c 03 jc short 01e07h ; 72 0c jbe short 01e0dh ; 76 10 @@ -3667,7 +3667,7 @@ biosfn_write_char_only_: ; 0xc1e70 LB 0x16f movzx di, cl ; 0f b6 f9 mov bx, di ; 89 fb sal bx, 003h ; c1 e3 03 - cmp byte [bx+0482fh], 000h ; 80 bf 2f 48 00 + cmp byte [bx+04830h], 000h ; 80 bf 30 48 00 jne short 01f2eh ; 75 4a mov dx, word [bp-018h] ; 8b 56 e8 imul dx, ax ; 0f af d0 @@ -3689,7 +3689,7 @@ biosfn_write_char_only_: ; 0xc1e70 LB 0x16f movzx ax, byte [bp-012h] ; 0f b6 46 ee movzx bx, byte [bp-00eh] ; 0f b6 5e f2 sal bx, 003h ; c1 e3 03 - mov di, word [bx+04832h] ; 8b bf 32 48 + mov di, word [bx+04833h] ; 8b bf 33 48 mov bx, ax ; 89 c3 mov dx, cx ; 89 ca mov ax, di ; 89 f8 @@ -3697,11 +3697,11 @@ biosfn_write_char_only_: ; 0xc1e70 LB 0x16f inc cx ; 41 inc cx ; 41 jmp short 01f0ah ; eb dc - movzx di, byte [di+048aeh] ; 0f b6 bd ae 48 + movzx di, byte [di+048afh] ; 0f b6 bd af 48 sal di, 006h ; c1 e7 06 - mov al, byte [di+048c4h] ; 8a 85 c4 48 + mov al, byte [di+048c5h] ; 8a 85 c5 48 mov byte [bp-00ah], al ; 88 46 f6 - mov al, byte [bx+04831h] ; 8a 87 31 48 + mov al, byte [bx+04832h] ; 8a 87 32 48 mov byte [bp-008h], al ; 88 46 f8 dec si ; 4e cmp si, strict byte 0ffffh ; 83 fe ff @@ -3711,7 +3711,7 @@ biosfn_write_char_only_: ; 0xc1e70 LB 0x16f jnc near 01fd8h ; 0f 83 81 00 movzx bx, byte [bp-00eh] ; 0f b6 5e f2 sal bx, 003h ; c1 e3 03 - mov bl, byte [bx+04830h] ; 8a 9f 30 48 + mov bl, byte [bx+04831h] ; 8a 9f 31 48 cmp bl, 003h ; 80 fb 03 jc short 01f75h ; 72 0e jbe short 01f7ch ; 76 13 @@ -3774,9 +3774,9 @@ biosfn_write_pixel_: ; 0xc1fdf LB 0x16a je near 02121h ; 0f 84 1e 01 movzx bx, al ; 0f b6 d8 sal bx, 003h ; c1 e3 03 - cmp byte [bx+0482fh], 000h ; 80 bf 2f 48 00 + cmp byte [bx+04830h], 000h ; 80 bf 30 48 00 je near 02121h ; 0f 84 0f 01 - mov al, byte [bx+04830h] ; 8a 87 30 48 + mov al, byte [bx+04831h] ; 8a 87 31 48 cmp AL, strict byte 003h ; 3c 03 jc short 02029h ; 72 0f jbe short 02030h ; 76 14 @@ -3830,7 +3830,7 @@ biosfn_write_pixel_: ; 0xc1fdf LB 0x16a mov ax, cx ; 89 c8 shr ax, 1 ; d1 e8 imul ax, ax, strict byte 00050h ; 6b c0 50 - cmp byte [bx+04831h], 002h ; 80 bf 31 48 02 + cmp byte [bx+04832h], 002h ; 80 bf 32 48 02 jne short 020abh ; 75 08 mov bx, word [bp-00ah] ; 8b 5e f6 shr bx, 002h ; c1 eb 02 @@ -3848,7 +3848,7 @@ biosfn_write_pixel_: ; 0xc1fdf LB 0x16a mov bl, al ; 88 c3 movzx si, byte [bp-004h] ; 0f b6 76 fc sal si, 003h ; c1 e6 03 - cmp byte [si+04831h], 002h ; 80 bc 31 48 02 + cmp byte [si+04832h], 002h ; 80 bc 32 48 02 jne short 020f1h ; 75 19 mov al, byte [bp-00ah] ; 8a 46 f6 and AL, strict byte 003h ; 24 03 @@ -3988,7 +3988,7 @@ biosfn_write_teletype_: ; 0xc2149 LB 0x284 movzx bx, byte [bp-00eh] ; 0f b6 5e f2 mov si, bx ; 89 de sal si, 003h ; c1 e6 03 - cmp byte [si+0482fh], 000h ; 80 bc 2f 48 00 + cmp byte [si+04830h], 000h ; 80 bc 30 48 00 jne short 02293h ; 75 4b mov ax, word [bp-012h] ; 8b 46 ee imul ax, word [bp-014h] ; 0f af 46 ec @@ -4004,7 +4004,7 @@ biosfn_write_teletype_: ; 0xc2149 LB 0x284 add cx, cx ; 01 c9 add cx, dx ; 01 d1 movzx bx, byte [bp-00ch] ; 0f b6 5e f4 - mov ax, word [si+04832h] ; 8b 84 32 48 + mov ax, word [si+04833h] ; 8b 84 33 48 mov dx, cx ; 89 ca call 02f85h ; e8 0b 0d cmp byte [bp-010h], 003h ; 80 7e f0 03 @@ -4012,14 +4012,14 @@ biosfn_write_teletype_: ; 0xc2149 LB 0x284 movzx bx, byte [bp-006h] ; 0f b6 5e fa mov dx, cx ; 89 ca inc dx ; 42 - mov ax, word [si+04832h] ; 8b 84 32 48 + mov ax, word [si+04833h] ; 8b 84 33 48 call 02f85h ; e8 f5 0c jmp near 02311h ; e9 7e 00 - movzx bx, byte [bx+048aeh] ; 0f b6 9f ae 48 + movzx bx, byte [bx+048afh] ; 0f b6 9f af 48 sal bx, 006h ; c1 e3 06 - mov ah, byte [bx+048c4h] ; 8a a7 c4 48 - mov dl, byte [si+04831h] ; 8a 94 31 48 - mov al, byte [si+04830h] ; 8a 84 30 48 + mov ah, byte [bx+048c5h] ; 8a a7 c5 48 + mov dl, byte [si+04832h] ; 8a 94 32 48 + mov al, byte [si+04831h] ; 8a 84 31 48 cmp AL, strict byte 003h ; 3c 03 jc short 022b7h ; 72 0c jbe short 022bdh ; 76 10 @@ -4075,7 +4075,7 @@ biosfn_write_teletype_: ; 0xc2149 LB 0x284 mov bh, byte [bp-012h] ; 8a 7e ee db 0feh, 0cfh ; dec bh ; fe cf - cmp byte [si+0482fh], 000h ; 80 bc 2f 48 00 + cmp byte [si+04830h], 000h ; 80 bc 30 48 00 jne short 0238dh ; 75 46 mov ax, word [bp-012h] ; 8b 46 ee imul ax, word [bp-014h] ; 0f af 46 ec @@ -4092,7 +4092,7 @@ biosfn_write_teletype_: ; 0xc2149 LB 0x284 add cx, cx ; 01 c9 add dx, cx ; 01 ca inc dx ; 42 - mov ax, word [si+04832h] ; 8b 84 32 48 + mov ax, word [si+04833h] ; 8b 84 33 48 call 02f77h ; e8 02 0c push strict byte 00001h ; 6a 01 movzx dx, byte [bp-004h] ; 0f b6 56 fc @@ -4367,7 +4367,7 @@ biosfn_load_text_8_14_pat_: ; 0xc2571 LB 0x70 mov di, bx ; 89 df sal di, 005h ; c1 e7 05 add di, word [bp-00ch] ; 03 7e f4 - add si, 05daeh ; 81 c6 ae 5d + add si, 05dafh ; 81 c6 af 5d mov cx, strict word 0000eh ; b9 0e 00 mov dx, 0c000h ; ba 00 c0 mov ax, 0a000h ; b8 00 a0 @@ -4423,7 +4423,7 @@ biosfn_load_text_8_8_pat_: ; 0xc25e1 LB 0x72 mov di, bx ; 89 df sal di, 005h ; c1 e7 05 add di, word [bp-00ch] ; 03 7e f4 - add si, 055aeh ; 81 c6 ae 55 + add si, 055afh ; 81 c6 af 55 mov cx, strict word 00008h ; b9 08 00 mov dx, 0c000h ; ba 00 c0 mov ax, 0a000h ; b8 00 a0 @@ -4479,7 +4479,7 @@ biosfn_load_text_8_16_pat_: ; 0xc2653 LB 0x72 mov di, bx ; 89 df sal di, 005h ; c1 e7 05 add di, word [bp-00ch] ; 03 7e f4 - add si, 06baeh ; 81 c6 ae 6b + add si, 06bafh ; 81 c6 af 6b mov cx, strict word 00010h ; b9 10 00 mov dx, 0c000h ; ba 00 c0 mov ax, 0a000h ; b8 00 a0 @@ -4613,7 +4613,7 @@ biosfn_read_state_info_: ; 0xc278b LB 0x101 push dx ; 52 push bx ; 53 mov cx, ds ; 8c d9 - mov bx, 05582h ; bb 82 55 + mov bx, 05583h ; bb 83 55 mov dx, word [bp-00ah] ; 8b 56 f6 mov ax, word [bp-008h] ; 8b 46 f8 call 02fc1h ; e8 20 08 @@ -5513,7 +5513,7 @@ find_vga_entry_: ; 0xc2f50 LB 0x27 jnbe short 02f71h ; 77 0e movzx bx, al ; 0f b6 d8 sal bx, 003h ; c1 e3 03 - cmp dl, byte [bx+0482eh] ; 3a 97 2e 48 + cmp dl, byte [bx+0482fh] ; 3a 97 2f 48 jne short 02f5dh ; 75 ee mov ah, al ; 88 c4 mov al, ah ; 88 e0 @@ -6779,10 +6779,10 @@ vesa_pm_end: ; 0xc4714 LB 0x1 ; Padding 0xeb bytes at 0xc4715 times 235 db 0 -section _DATA progbits vstart=0x4800 align=1 ; size=0x36e0 class=DATA group=DGROUP -_msg_vga_init: ; 0xc4800 LB 0x2e - db 'Oracle VM VirtualBox Version 4.3.8 VGA BIOS', 00dh, 00ah, 000h -_vga_modes: ; 0xc482e LB 0x80 +section _DATA progbits vstart=0x4800 align=1 ; size=0x36e1 class=DATA group=DGROUP +_msg_vga_init: ; 0xc4800 LB 0x2f + db 'Oracle VM VirtualBox Version 4.3.10 VGA BIOS', 00dh, 00ah, 000h +_vga_modes: ; 0xc482f LB 0x80 db 000h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h, 001h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h db 002h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h, 003h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h db 004h, 001h, 002h, 002h, 000h, 0b8h, 0ffh, 001h, 005h, 001h, 002h, 002h, 000h, 0b8h, 0ffh, 001h @@ -6791,11 +6791,11 @@ _vga_modes: ; 0xc482e LB 0x80 db 00fh, 001h, 003h, 001h, 000h, 0a0h, 0ffh, 000h, 010h, 001h, 004h, 004h, 000h, 0a0h, 0ffh, 002h db 011h, 001h, 003h, 001h, 000h, 0a0h, 0ffh, 002h, 012h, 001h, 004h, 004h, 000h, 0a0h, 0ffh, 002h db 013h, 001h, 005h, 008h, 000h, 0a0h, 0ffh, 003h, 06ah, 001h, 004h, 004h, 000h, 0a0h, 0ffh, 002h -_line_to_vpti: ; 0xc48ae LB 0x10 +_line_to_vpti: ; 0xc48af LB 0x10 db 017h, 017h, 018h, 018h, 004h, 005h, 006h, 007h, 00dh, 00eh, 011h, 012h, 01ah, 01bh, 01ch, 01dh -_dac_regs: ; 0xc48be LB 0x4 +_dac_regs: ; 0xc48bf LB 0x4 dd 0ff3f3f3fh -_video_param_table: ; 0xc48c2 LB 0x780 +_video_param_table: ; 0xc48c3 LB 0x780 db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h @@ -6916,7 +6916,7 @@ _video_param_table: ; 0xc48c2 LB 0x780 db 072h, 0f0h, 000h, 060h, 000h, 000h, 000h, 000h, 000h, 000h, 059h, 08dh, 057h, 032h, 000h, 057h db 073h, 0e3h, 0ffh, 000h, 001h, 002h, 003h, 004h, 005h, 014h, 007h, 038h, 039h, 03ah, 03bh, 03ch db 03dh, 03eh, 03fh, 001h, 000h, 00fh, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 005h, 00fh, 0ffh -_palette0: ; 0xc5042 LB 0xc0 +_palette0: ; 0xc5043 LB 0xc0 db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah @@ -6929,7 +6929,7 @@ _palette0: ; 0xc5042 LB 0xc0 db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah db 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 02ah, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh db 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh, 03fh -_palette1: ; 0xc5102 LB 0xc0 +_palette1: ; 0xc5103 LB 0xc0 db 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah, 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah db 000h, 02ah, 02ah, 015h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah db 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah, 000h, 02ah, 02ah, 015h, 000h, 02ah, 02ah, 02ah @@ -6942,7 +6942,7 @@ _palette1: ; 0xc5102 LB 0xc0 db 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh, 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh db 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh db 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh -_palette2: ; 0xc51c2 LB 0xc0 +_palette2: ; 0xc51c3 LB 0xc0 db 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah, 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah db 000h, 02ah, 02ah, 02ah, 000h, 02ah, 02ah, 02ah, 000h, 000h, 015h, 000h, 000h, 03fh, 000h, 02ah db 015h, 000h, 02ah, 03fh, 02ah, 000h, 015h, 02ah, 000h, 03fh, 02ah, 02ah, 015h, 02ah, 02ah, 03fh @@ -6955,7 +6955,7 @@ _palette2: ; 0xc51c2 LB 0xc0 db 015h, 015h, 000h, 015h, 015h, 02ah, 015h, 03fh, 000h, 015h, 03fh, 02ah, 03fh, 015h, 000h, 03fh db 015h, 02ah, 03fh, 03fh, 000h, 03fh, 03fh, 02ah, 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh db 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh -_palette3: ; 0xc5282 LB 0x300 +_palette3: ; 0xc5283 LB 0x300 db 000h, 000h, 000h, 000h, 000h, 02ah, 000h, 02ah, 000h, 000h, 02ah, 02ah, 02ah, 000h, 000h, 02ah db 000h, 02ah, 02ah, 015h, 000h, 02ah, 02ah, 02ah, 015h, 015h, 015h, 015h, 015h, 03fh, 015h, 03fh db 015h, 015h, 03fh, 03fh, 03fh, 015h, 015h, 03fh, 015h, 03fh, 03fh, 03fh, 015h, 03fh, 03fh, 03fh @@ -7004,12 +7004,12 @@ _palette3: ; 0xc5282 LB 0x300 db 00bh, 010h, 00bh, 00bh, 010h, 00ch, 00bh, 010h, 00dh, 00bh, 010h, 00fh, 00bh, 010h, 010h, 00bh db 00fh, 010h, 00bh, 00dh, 010h, 00bh, 00ch, 010h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h -_static_functionality: ; 0xc5582 LB 0x10 +_static_functionality: ; 0xc5583 LB 0x10 db 0ffh, 0e0h, 00fh, 000h, 000h, 000h, 000h, 007h, 002h, 008h, 0e7h, 00ch, 000h, 000h, 000h, 000h -_video_save_pointer_table: ; 0xc5592 LB 0x1c - db 0c2h, 048h, 000h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h +_video_save_pointer_table: ; 0xc5593 LB 0x1c + db 0c3h, 048h, 000h, 0c0h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h -_vgafont8: ; 0xc55ae LB 0x800 +_vgafont8: ; 0xc55af LB 0x800 db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07eh, 081h, 0a5h, 081h, 0bdh, 099h, 081h, 07eh db 07eh, 0ffh, 0dbh, 0ffh, 0c3h, 0e7h, 0ffh, 07eh, 06ch, 0feh, 0feh, 0feh, 07ch, 038h, 010h, 000h db 010h, 038h, 07ch, 0feh, 07ch, 038h, 010h, 000h, 038h, 07ch, 038h, 0feh, 0feh, 07ch, 038h, 07ch @@ -7138,7 +7138,7 @@ _vgafont8: ; 0xc55ae LB 0x800 db 000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h, 00fh, 00ch, 00ch, 00ch, 0ech, 06ch, 03ch, 01ch db 078h, 06ch, 06ch, 06ch, 06ch, 000h, 000h, 000h, 070h, 018h, 030h, 060h, 078h, 000h, 000h, 000h db 000h, 000h, 03ch, 03ch, 03ch, 03ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h -_vgafont14: ; 0xc5dae LB 0xe00 +_vgafont14: ; 0xc5daf LB 0xe00 db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 07eh, 081h, 0a5h, 081h, 081h, 0bdh, 099h, 081h, 07eh, 000h, 000h, 000h, 000h, 000h, 07eh, 0ffh db 0dbh, 0ffh, 0ffh, 0c3h, 0e7h, 0ffh, 07eh, 000h, 000h, 000h, 000h, 000h, 000h, 06ch, 0feh, 0feh @@ -7363,7 +7363,7 @@ _vgafont14: ; 0xc5dae LB 0xe00 db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 070h, 0d8h, 030h, 060h, 0c8h, 0f8h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 07ch, 07ch, 07ch, 07ch, 07ch, 07ch, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h -_vgafont16: ; 0xc6bae LB 0x1000 +_vgafont16: ; 0xc6baf LB 0x1000 db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 07eh, 081h, 0a5h, 081h, 081h, 0bdh, 099h, 081h, 081h, 07eh, 000h, 000h, 000h, 000h db 000h, 000h, 07eh, 0ffh, 0dbh, 0ffh, 0ffh, 0c3h, 0e7h, 0ffh, 0ffh, 07eh, 000h, 000h, 000h, 000h @@ -7620,7 +7620,7 @@ _vgafont16: ; 0xc6bae LB 0x1000 db 000h, 070h, 0d8h, 030h, 060h, 0c8h, 0f8h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 07ch, 07ch, 07ch, 07ch, 07ch, 07ch, 07ch, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h -_vgafont14alt: ; 0xc7bae LB 0x12d +_vgafont14alt: ; 0xc7baf LB 0x12d db 01dh, 000h, 000h, 000h, 000h, 024h, 066h, 0ffh, 066h, 024h, 000h, 000h, 000h, 000h, 000h, 022h db 000h, 063h, 063h, 063h, 022h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 02bh, 000h db 000h, 000h, 018h, 018h, 018h, 0ffh, 018h, 018h, 018h, 000h, 000h, 000h, 000h, 02dh, 000h, 000h @@ -7640,7 +7640,7 @@ _vgafont14alt: ; 0xc7bae LB 0x12d db 000h, 0fch, 066h, 066h, 07ch, 062h, 066h, 06fh, 066h, 066h, 0f3h, 000h, 000h, 000h, 0f1h, 000h db 000h, 018h, 018h, 018h, 0ffh, 018h, 018h, 018h, 000h, 0ffh, 000h, 000h, 000h, 0f6h, 000h, 000h db 018h, 018h, 000h, 000h, 0ffh, 000h, 000h, 018h, 018h, 000h, 000h, 000h, 000h -_vgafont16alt: ; 0xc7cdb LB 0x145 +_vgafont16alt: ; 0xc7cdc LB 0x144 db 01dh, 000h, 000h, 000h, 000h, 000h, 024h, 066h, 0ffh, 066h, 024h, 000h, 000h, 000h, 000h, 000h db 000h, 030h, 000h, 000h, 03ch, 066h, 0c3h, 0c3h, 0dbh, 0dbh, 0c3h, 0c3h, 066h, 03ch, 000h, 000h db 000h, 000h, 04dh, 000h, 000h, 0c3h, 0e7h, 0ffh, 0ffh, 0dbh, 0c3h, 0c3h, 0c3h, 0c3h, 0c3h, 000h @@ -7661,31 +7661,34 @@ _vgafont16alt: ; 0xc7cdb LB 0x145 db 09eh, 000h, 0fch, 066h, 066h, 07ch, 062h, 066h, 06fh, 066h, 066h, 066h, 0f3h, 000h, 000h, 000h db 000h, 0abh, 000h, 0c0h, 0c0h, 0c2h, 0c6h, 0cch, 018h, 030h, 060h, 0ceh, 09bh, 006h, 00ch, 01fh db 000h, 000h, 0ach, 000h, 0c0h, 0c0h, 0c2h, 0c6h, 0cch, 018h, 030h, 066h, 0ceh, 096h, 03eh, 006h - db 006h, 000h, 000h, 000h, 000h + db 006h, 000h, 000h, 000h _vbebios_copyright: ; 0xc7e20 LB 0x15 db 'VirtualBox VESA BIOS', 000h _vbebios_vendor_name: ; 0xc7e35 LB 0x13 db 'Oracle Corporation', 000h _vbebios_product_name: ; 0xc7e48 LB 0x21 db 'Oracle VM VirtualBox VBE Adapter', 000h -_vbebios_product_revision: ; 0xc7e69 LB 0x23 - db 'Oracle VM VirtualBox Version 4.3.8', 000h -_vbebios_info_string: ; 0xc7e8c LB 0x2b +_vbebios_product_revision: ; 0xc7e69 LB 0x24 + db 'Oracle VM VirtualBox Version 4.3.10', 000h +_vbebios_info_string: ; 0xc7e8d LB 0x2b db 'VirtualBox VBE Display Adapter enabled', 00dh, 00ah, 00dh, 00ah, 000h -_no_vbebios_info_string: ; 0xc7eb7 LB 0x29 +_no_vbebios_info_string: ; 0xc7eb8 LB 0x29 db 'No VirtualBox VBE support available!', 00dh, 00ah, 00dh, 00ah, 000h -section CONST progbits vstart=0x7ee0 align=1 ; size=0x0 class=DATA group=DGROUP + ; Padding 0x1 bytes at 0xc7ee1 + db 001h + +section CONST progbits vstart=0x7ee2 align=1 ; size=0x0 class=DATA group=DGROUP -section CONST2 progbits vstart=0x7ee0 align=1 ; size=0x0 class=DATA group=DGROUP +section CONST2 progbits vstart=0x7ee2 align=1 ; size=0x0 class=DATA group=DGROUP - ; Padding 0x120 bytes at 0xc7ee0 - db 001h, 000h, 000h, 000h, 000h, 001h, 000h, 000h, 000h, 000h, 000h, 000h, 02fh, 068h, 06fh, 06dh - db 065h, 02fh, 066h, 06dh, 033h, 02fh, 073h, 072h, 063h, 02fh, 076h, 062h, 06fh, 078h, 02dh, 034h - db 02eh, 033h, 02fh, 06fh, 075h, 074h, 02fh, 06ch, 069h, 06eh, 075h, 078h, 02eh, 061h, 06dh, 064h - db 036h, 034h, 02fh, 072h, 065h, 06ch, 065h, 061h, 073h, 065h, 02fh, 06fh, 062h, 06ah, 02fh, 056h - db 042h, 06fh, 078h, 056h, 067h, 061h, 042h, 069h, 06fh, 073h, 02fh, 056h, 042h, 06fh, 078h, 056h - db 067h, 061h, 042h, 069h, 06fh, 073h, 02eh, 073h, 079h, 06dh, 000h, 000h, 000h, 000h, 000h, 000h + ; Padding 0x11e bytes at 0xc7ee2 + db 000h, 000h, 000h, 000h, 001h, 000h, 000h, 000h, 000h, 000h, 000h, 02fh, 068h, 06fh, 06dh, 065h + db 02fh, 066h, 06dh, 033h, 02fh, 073h, 072h, 063h, 02fh, 076h, 062h, 06fh, 078h, 02dh, 034h, 02eh + db 033h, 02fh, 06fh, 075h, 074h, 02fh, 06ch, 069h, 06eh, 075h, 078h, 02eh, 061h, 06dh, 064h, 036h + db 034h, 02fh, 072h, 065h, 06ch, 065h, 061h, 073h, 065h, 02fh, 06fh, 062h, 06ah, 02fh, 056h, 042h + db 06fh, 078h, 056h, 067h, 061h, 042h, 069h, 06fh, 073h, 02fh, 056h, 042h, 06fh, 078h, 056h, 067h + db 061h, 042h, 069h, 06fh, 073h, 02eh, 073h, 079h, 06dh, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h @@ -7697,4 +7700,4 @@ section CONST2 progbits vstart=0x7ee0 align=1 ; size=0x0 class=DATA group=DGROUP db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h - db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 016h + db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 068h diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.md5sum b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.md5sum index 4f54140b9..cb2d80157 100644 --- a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.md5sum +++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative.md5sum @@ -1 +1 @@ -86355c5abda5dd1b0bf3f2f65828c6a1 *VBoxVgaBios.rom +25d0dc05c628f90ff6b5aa5e3987ba1f *VBoxVgaBios.rom diff --git a/src/VBox/Devices/Graphics/DevVGA.cpp b/src/VBox/Devices/Graphics/DevVGA.cpp index e55a4eda5..da28d9be4 100644 --- a/src/VBox/Devices/Graphics/DevVGA.cpp +++ b/src/VBox/Devices/Graphics/DevVGA.cpp @@ -5455,6 +5455,8 @@ static DECLCALLBACK(int) vgaR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint static DECLCALLBACK(int) vgaR3LoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) { #ifdef VBOX_WITH_HGSMI + PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE); + VBVAPause(pThis, (pThis->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) == 0); return vboxVBVALoadStateDone(pDevIns, pSSM); #else return VINF_SUCCESS; @@ -5474,6 +5476,9 @@ static DECLCALLBACK(void) vgaR3Reset(PPDMDEVINS pDevIns) char *pchEnd; LogFlow(("vgaReset\n")); + if (pThis->pVdma) + vboxVDMAReset(pThis->pVdma); + #ifdef VBOX_WITH_HGSMI VBVAReset(pThis); #endif /* VBOX_WITH_HGSMI */ @@ -5924,6 +5929,7 @@ static DECLCALLBACK(int) vgaR3Construct(PPDMDEVINS pDevIns, int iInstance, PCF pThis->IVBVACallbacks.pfnCrHgsmiControlCompleteAsync = vboxVDMACrHgsmiControlCompleteAsync; # endif #endif + pThis->IVBVACallbacks.pfnCrCtlSubmit = vboxCmdVBVACmdHostCtl; /* * We use our own critical section to avoid unncessary pointer indirections diff --git a/src/VBox/Devices/Graphics/DevVGA.h b/src/VBox/Devices/Graphics/DevVGA.h index f3617bb6e..aad2b43cc 100644 --- a/src/VBox/Devices/Graphics/DevVGA.h +++ b/src/VBox/Devices/Graphics/DevVGA.h @@ -292,7 +292,8 @@ typedef struct VGAState { # if defined(VBOX_WITH_HGSMI) && (defined(VBOX_WITH_VIDEOHWACCEL) || defined(VBOX_WITH_CRHGSMI)) /** LUN\#0: VBVA callbacks interface */ PDMIDISPLAYVBVACALLBACKS IVBVACallbacks; -# elif HC_ARCH_BITS == 32 +# endif +# if HC_ARCH_BITS == 32 uint32_t Padding0; # endif /** Pointer to base interface of the driver. */ @@ -624,6 +625,10 @@ int vboxVBVASaveStateDone (PPDMDEVINS pDevIns, PSSMHANDLE pSSM); int vboxVDMACrHgsmiCommandCompleteAsync(PPDMIDISPLAYVBVACALLBACKS pInterface, PVBOXVDMACMD_CHROMIUM_CMD pCmd, int rc); int vboxVDMACrHgsmiControlCompleteAsync(PPDMIDISPLAYVBVACALLBACKS pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCmd, int rc); # endif +int vboxCmdVBVACmdHostCtl(PPDMIDISPLAYVBVACALLBACKS pInterface, + struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, + PFNCRCTLCOMPLETION pfnCompletion, + void *pvCompletion); int vboxVBVASaveStateExec (PPDMDEVINS pDevIns, PSSMHANDLE pSSM); int vboxVBVALoadStateExec (PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t u32Version); @@ -633,17 +638,17 @@ int vboxVBVALoadStateDone (PPDMDEVINS pDevIns, PSSMHANDLE pSSM); typedef struct VBOXVDMAHOST *PVBOXVDMAHOST; int vboxVDMAConstruct(PVGASTATE pVGAState, uint32_t cPipeElements); int vboxVDMADestruct(PVBOXVDMAHOST pVdma); +int vboxVDMAReset(PVBOXVDMAHOST pVdma); void vboxVDMAControl(PVBOXVDMAHOST pVdma, PVBOXVDMA_CTL pCmd, uint32_t cbCmd); void vboxVDMACommand(PVBOXVDMAHOST pVdma, PVBOXVDMACBUF_DR pCmd, uint32_t cbCmd); int vboxVDMASaveStateExecPrep(struct VBOXVDMAHOST *pVdma, PSSMHANDLE pSSM); int vboxVDMASaveStateExecDone(struct VBOXVDMAHOST *pVdma, PSSMHANDLE pSSM); # endif /* VBOX_WITH_VDMA */ -int vboxCmdVBVAEnable(PVGASTATE pVGAState, VBVABUFFER *pVBVA); -int vboxCmdVBVADisable(PVGASTATE pVGAState); int vboxCmdVBVACmdSubmit(PVGASTATE pVGAState); int vboxCmdVBVACmdFlush(PVGASTATE pVGAState); void vboxCmdVBVACmdTimer(PVGASTATE pVGAState); +int vboxCmdVBVACmdCtl(PVGASTATE pVGAState, VBOXCMDVBVA_CTL *pCtl, uint32_t cbCtl); #endif /* VBOX_WITH_HGSMI */ diff --git a/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp b/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp index e7dccbb59..ed727b13e 100644 --- a/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp +++ b/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp @@ -1939,6 +1939,32 @@ static DECLCALLBACK(int) vbvaChannelHandler (void *pvHandler, uint16_t u16Channe switch (u16ChannelInfo) { + case VBVA_CMDVBVA_SUBMIT: + { + rc = vboxCmdVBVACmdSubmit(pVGAState); + break; + } + case VBVA_CMDVBVA_FLUSH: + { + rc =vboxCmdVBVACmdFlush(pVGAState); + break; + } + case VBVA_CMDVBVA_CTL: + { + if (cbBuffer < VBoxSHGSMIBufferHeaderSize() + sizeof (VBOXCMDVBVA_CTL)) + { + Log(("buffer too small\n")); +#ifdef DEBUG_misha + AssertMsgFailed(("buffer too small\n")); +#endif + rc = VERR_INVALID_PARAMETER; + break; + } + + VBOXCMDVBVA_CTL *pCtl = (VBOXCMDVBVA_CTL*)VBoxSHGSMIBufferData((PVBOXSHGSMIHEADER)pvBuffer); + rc = vboxCmdVBVACmdCtl(pVGAState, pCtl, cbBuffer - VBoxSHGSMIBufferHeaderSize()); + break; + } #ifdef VBOX_WITH_VDMA case VBVA_VDMA_CMD: { @@ -2252,54 +2278,6 @@ static DECLCALLBACK(int) vbvaChannelHandler (void *pvHandler, uint16_t u16Channe pCaps->rc = VINF_SUCCESS; } break; #endif - - case VBVA_CMDVBVA_ENABLE: - { - if (cbBuffer < sizeof (VBVAENABLE)) - { - rc = VERR_INVALID_PARAMETER; - break; - } - - VBVAENABLE *pEnable = (VBVAENABLE *)pvBuffer; - - if ((pEnable->u32Flags & (VBVA_F_ENABLE | VBVA_F_DISABLE)) == VBVA_F_ENABLE) - { - uint32_t u32Offset = pEnable->u32Offset; - VBVABUFFER *pVBVA = (VBVABUFFER *)HGSMIOffsetToPointerHost (pIns, u32Offset); - - if (pVBVA) - rc = vboxCmdVBVAEnable(pVGAState, pVBVA); - else - { - LogRel(("Invalid VBVABUFFER offset 0x%x!!!\n", - pEnable->u32Offset)); - rc = VERR_INVALID_PARAMETER; - } - } - else if ((pEnable->u32Flags & (VBVA_F_ENABLE | VBVA_F_DISABLE)) == VBVA_F_DISABLE) - { - rc = vboxCmdVBVADisable(pVGAState); - } - else - { - LogRel(("Invalid VBVA_ENABLE flags 0x%x!!!\n", pEnable->u32Flags)); - rc = VERR_INVALID_PARAMETER; - } - - pEnable->i32Result = rc; - break; - } - case VBVA_CMDVBVA_SUBMIT: - { - rc = vboxCmdVBVACmdSubmit(pVGAState); - break; - } - case VBVA_CMDVBVA_FLUSH: - { - rc =vboxCmdVBVACmdFlush(pVGAState); - break; - } case VBVA_SCANLINE_CFG: { if (cbBuffer < sizeof (VBVASCANLINECFG)) diff --git a/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp b/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp index bdec54a28..0e35fe5a3 100644 --- a/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp +++ b/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp @@ -20,12 +20,22 @@ #include #include #include +#include #include "DevVGA.h" #include "HGSMI/SHGSMIHost.h" #include "HGSMI/HGSMIHostHlp.h" #include +#include + +#ifdef DEBUG_misha +# define VBOXVDBG_MEMCACHE_DISABLE +#endif + +#ifndef VBOXVDBG_MEMCACHE_DISABLE +# include +#endif #ifdef DEBUG_misha #define WARN_BP() do { AssertFailed(); } while (0) @@ -37,127 +47,733 @@ WARN_BP(); \ } while (0) -#ifdef VBOX_VDMA_WITH_WORKERTHREAD -typedef enum +#define VBOXVDMATHREAD_STATE_TERMINATED 0 +#define VBOXVDMATHREAD_STATE_CREATED 1 +#define VBOXVDMATHREAD_STATE_TERMINATING 2 + +typedef struct VBOXVDMATHREAD +{ + RTTHREAD hWorkerThread; + RTSEMEVENT hEvent; + RTSEMEVENT hClientEvent; + volatile uint32_t u32State; +} VBOXVDMATHREAD, *PVBOXVDMATHREAD; + + +/* state transformations: + * + * submitter | processor + * + * LISTENING ---> PROCESSING + * + * */ +#define VBVAEXHOSTCONTEXT_STATE_LISTENING 0 +#define VBVAEXHOSTCONTEXT_STATE_PROCESSING 1 + +#define VBVAEXHOSTCONTEXT_ESTATE_DISABLED -1 +#define VBVAEXHOSTCONTEXT_ESTATE_PAUSED 0 +#define VBVAEXHOSTCONTEXT_ESTATE_ENABLED 1 + +typedef struct VBVAEXHOSTCONTEXT +{ + VBVABUFFER *pVBVA; + volatile int32_t i32State; + volatile int32_t i32EnableState; + volatile uint32_t u32cCtls; + /* critical section for accessing ctl lists */ + RTCRITSECT CltCritSect; + RTLISTANCHOR GuestCtlList; + RTLISTANCHOR HostCtlList; +#ifndef VBOXVDBG_MEMCACHE_DISABLE + RTMEMCACHE CtlCache; +#endif +} VBVAEXHOSTCONTEXT; + +typedef enum +{ + VBVAEXHOSTCTL_TYPE_UNDEFINED = 0, + VBVAEXHOSTCTL_TYPE_HH_INTERNAL_PAUSE, + VBVAEXHOSTCTL_TYPE_HH_INTERNAL_RESUME, + VBVAEXHOSTCTL_TYPE_HH_ENABLE, + VBVAEXHOSTCTL_TYPE_HH_TERM, + VBVAEXHOSTCTL_TYPE_HH_RESET, + VBVAEXHOSTCTL_TYPE_HH_SAVESTATE, + VBVAEXHOSTCTL_TYPE_HH_LOADSTATE, + VBVAEXHOSTCTL_TYPE_HH_BE_OPAQUE, + VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE, + VBVAEXHOSTCTL_TYPE_GH_ENABLE_DISABLE +} VBVAEXHOSTCTL_TYPE; + +struct VBVAEXHOSTCTL; + +typedef DECLCALLBACKPTR(void, PFNVBVAEXHOSTCTL_COMPLETE)(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvComplete); + +typedef struct VBVAEXHOSTCTL +{ + RTLISTNODE Node; + VBVAEXHOSTCTL_TYPE enmType; + union + { + struct + { + uint8_t * pu8Cmd; + uint32_t cbCmd; + } cmd; + + struct + { + PSSMHANDLE pSSM; + uint32_t u32Version; + } state; + } u; + PFNVBVAEXHOSTCTL_COMPLETE pfnComplete; + void *pvComplete; +} VBVAEXHOSTCTL; + +/* VBoxVBVAExHP**, i.e. processor functions, can NOT be called concurrently with each other, + * but can be called with other VBoxVBVAExS** (submitter) functions except Init/Start/Term aparently. + * Can only be called be the processor, i.e. the entity that acquired the processor state by direct or indirect call to the VBoxVBVAExHSCheckCommands + * see mor edetailed comments in headers for function definitions */ +typedef enum +{ + VBVAEXHOST_DATA_TYPE_NO_DATA = 0, + VBVAEXHOST_DATA_TYPE_CMD, + VBVAEXHOST_DATA_TYPE_HOSTCTL, + VBVAEXHOST_DATA_TYPE_GUESTCTL +} VBVAEXHOST_DATA_TYPE; +static VBVAEXHOST_DATA_TYPE VBoxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd); + +static void VBoxVBVAExHPDataCompleteCmd(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint32_t cbCmd); +static void VBoxVBVAExHPDataCompleteCtl(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL *pCtl, int rc); + +/* VBoxVBVAExHP**, i.e. processor functions, can NOT be called concurrently with each other, + * can be called concurrently with istelf as well as with other VBoxVBVAEx** functions except Init/Start/Term aparently */ +static int VBoxVBVAExHSCheckCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva); + +static int VBoxVBVAExHSInit(struct VBVAEXHOSTCONTEXT *pCmdVbva); +static int VBoxVBVAExHSEnable(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVABUFFER *pVBVA); +static int VBoxVBVAExHSDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva); +static void VBoxVBVAExHSTerm(struct VBVAEXHOSTCONTEXT *pCmdVbva); +static int VBoxVBVAExHSSaveState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM); +static int VBoxVBVAExHSLoadState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version); + +static VBVAEXHOSTCTL* VBoxVBVAExHCtlAlloc(VBVAEXHOSTCONTEXT *pCmdVbva) +{ +#ifndef VBOXVDBG_MEMCACHE_DISABLE + return (VBVAEXHOSTCTL*)RTMemCacheAlloc(pCmdVbva->CtlCache); +#else + return (VBVAEXHOSTCTL*)RTMemAlloc(sizeof (VBVAEXHOSTCTL)); +#endif +} + +static void VBoxVBVAExHCtlFree(VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL *pCtl) +{ +#ifndef VBOXVDBG_MEMCACHE_DISABLE + RTMemCacheFree(pCmdVbva->CtlCache, pCtl); +#else + RTMemFree(pCtl); +#endif +} + +static VBVAEXHOSTCTL* VBoxVBVAExHCtlCreate(VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL_TYPE enmType) +{ + VBVAEXHOSTCTL* pCtl = VBoxVBVAExHCtlAlloc(pCmdVbva); + if (!pCtl) + { + WARN(("VBoxVBVAExHCtlAlloc failed\n")); + return NULL; + } + + pCtl->enmType = enmType; + return pCtl; +} + +static int vboxVBVAExHSProcessorAcquire(struct VBVAEXHOSTCONTEXT *pCmdVbva) +{ + Assert(pCmdVbva->i32State >= VBVAEXHOSTCONTEXT_STATE_LISTENING); + + if (ASMAtomicCmpXchgS32(&pCmdVbva->i32State, VBVAEXHOSTCONTEXT_STATE_PROCESSING, VBVAEXHOSTCONTEXT_STATE_LISTENING)) + return VINF_SUCCESS; + return VERR_SEM_BUSY; +} + +static VBVAEXHOSTCTL* vboxVBVAExHPCheckCtl(struct VBVAEXHOSTCONTEXT *pCmdVbva, bool *pfHostCtl, bool fHostOnlyMode) +{ + Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); + + if(!fHostOnlyMode && !ASMAtomicUoReadU32(&pCmdVbva->u32cCtls)) + return NULL; + + int rc = RTCritSectEnter(&pCmdVbva->CltCritSect); + if (RT_SUCCESS(rc)) + { + VBVAEXHOSTCTL* pCtl = RTListGetFirst(&pCmdVbva->HostCtlList, VBVAEXHOSTCTL, Node); + if (pCtl) + *pfHostCtl = true; + else if (!fHostOnlyMode) + { + if (ASMAtomicUoReadS32(&pCmdVbva->i32EnableState) > VBVAEXHOSTCONTEXT_ESTATE_PAUSED) + { + pCtl = RTListGetFirst(&pCmdVbva->GuestCtlList, VBVAEXHOSTCTL, Node); + /* pCtl can not be null here since pCmdVbva->u32cCtls is not null, + * and there are no HostCtl commands*/ + Assert(pCtl); + *pfHostCtl = false; + } + } + + if (pCtl) + { + RTListNodeRemove(&pCtl->Node); + ASMAtomicDecU32(&pCmdVbva->u32cCtls); + } + + RTCritSectLeave(&pCmdVbva->CltCritSect); + + return pCtl; + } + else + WARN(("RTCritSectEnter failed %d\n", rc)); + + return NULL; +} + +static VBVAEXHOSTCTL* VBoxVBVAExHPCheckHostCtlOnDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva) +{ + bool fHostCtl; + return vboxVBVAExHPCheckCtl(pCmdVbva, &fHostCtl, true); +} + + +static bool vboxVBVAExHPCheckProcessCtlInternal(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL* pCtl) +{ + switch (pCtl->enmType) + { + case VBVAEXHOSTCTL_TYPE_HH_INTERNAL_PAUSE: + if (pCmdVbva->i32EnableState > VBVAEXHOSTCONTEXT_ESTATE_PAUSED) + ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_PAUSED); + return true; + case VBVAEXHOSTCTL_TYPE_HH_INTERNAL_RESUME: + if (pCmdVbva->i32EnableState == VBVAEXHOSTCONTEXT_ESTATE_PAUSED) + ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_ENABLED); + return true; + default: + return false; + } +} + +static void vboxVBVAExHPProcessorRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva) +{ + Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); + + ASMAtomicWriteS32(&pCmdVbva->i32State, VBVAEXHOSTCONTEXT_STATE_LISTENING); +} + +static void vboxVBVAExHPHgEventSet(struct VBVAEXHOSTCONTEXT *pCmdVbva) +{ + Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); + if (pCmdVbva->pVBVA) + ASMAtomicOrU32(&pCmdVbva->pVBVA->hostFlags.u32HostEvents, VBVA_F_STATE_PROCESSING); +} + +static void vboxVBVAExHPHgEventClear(struct VBVAEXHOSTCONTEXT *pCmdVbva) +{ + Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); + if (pCmdVbva->pVBVA) + ASMAtomicAndU32(&pCmdVbva->pVBVA->hostFlags.u32HostEvents, ~VBVA_F_STATE_PROCESSING); +} + +static int vboxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd) +{ + Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); + Assert(pCmdVbva->i32EnableState > VBVAEXHOSTCONTEXT_ESTATE_PAUSED); + + VBVABUFFER *pVBVA = pCmdVbva->pVBVA; + + uint32_t indexRecordFirst = pVBVA->indexRecordFirst; + uint32_t indexRecordFree = pVBVA->indexRecordFree; + + Log(("first = %d, free = %d\n", + indexRecordFirst, indexRecordFree)); + + if (indexRecordFirst == indexRecordFree) + { + /* No records to process. Return without assigning output variables. */ + return VINF_EOF; + } + + uint32_t cbRecordCurrent = ASMAtomicReadU32(&pVBVA->aRecords[indexRecordFirst].cbRecord); + + /* A new record need to be processed. */ + if (cbRecordCurrent & VBVA_F_RECORD_PARTIAL) + { + /* the record is being recorded, try again */ + return VINF_TRY_AGAIN; + } + + uint32_t cbRecord = cbRecordCurrent & ~VBVA_F_RECORD_PARTIAL; + + if (!cbRecord) + { + /* the record is being recorded, try again */ + return VINF_TRY_AGAIN; + } + + /* we should not get partial commands here actually */ + Assert(cbRecord); + + /* The size of largest contiguous chunk in the ring biffer. */ + uint32_t u32BytesTillBoundary = pVBVA->cbData - pVBVA->off32Data; + + /* The pointer to data in the ring buffer. */ + uint8_t *pSrc = &pVBVA->au8Data[pVBVA->off32Data]; + + /* Fetch or point the data. */ + if (u32BytesTillBoundary >= cbRecord) + { + /* The command does not cross buffer boundary. Return address in the buffer. */ + *ppCmd = pSrc; + *pcbCmd = cbRecord; + return VINF_SUCCESS; + } + + LogRel(("CmdVbva: cross-bound writes unsupported\n")); + return VERR_INVALID_STATE; +} + +static void VBoxVBVAExHPDataCompleteCmd(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint32_t cbCmd) +{ + VBVABUFFER *pVBVA = pCmdVbva->pVBVA; + pVBVA->off32Data = (pVBVA->off32Data + cbCmd) % pVBVA->cbData; + + pVBVA->indexRecordFirst = (pVBVA->indexRecordFirst + 1) % RT_ELEMENTS(pVBVA->aRecords); +} + +static void VBoxVBVAExHPDataCompleteCtl(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL *pCtl, int rc) +{ + if (pCtl->pfnComplete) + pCtl->pfnComplete(pCmdVbva, pCtl, rc, pCtl->pvComplete); + else + VBoxVBVAExHCtlFree(pCmdVbva, pCtl); +} + +static VBVAEXHOST_DATA_TYPE vboxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd) +{ + Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); + VBVAEXHOSTCTL*pCtl; + bool fHostClt; + + for(;;) + { + pCtl = vboxVBVAExHPCheckCtl(pCmdVbva, &fHostClt, false); + if (pCtl) + { + if (fHostClt) + { + if (!vboxVBVAExHPCheckProcessCtlInternal(pCmdVbva, pCtl)) + { + *ppCmd = (uint8_t*)pCtl; + *pcbCmd = sizeof (*pCtl); + return VBVAEXHOST_DATA_TYPE_HOSTCTL; + } + } + else + { + *ppCmd = (uint8_t*)pCtl; + *pcbCmd = sizeof (*pCtl); + return VBVAEXHOST_DATA_TYPE_GUESTCTL; + } + } + + if (ASMAtomicUoReadS32(&pCmdVbva->i32EnableState) <= VBVAEXHOSTCONTEXT_ESTATE_PAUSED) + return VBVAEXHOST_DATA_TYPE_NO_DATA; + + int rc = vboxVBVAExHPCmdGet(pCmdVbva, ppCmd, pcbCmd); + switch (rc) + { + case VINF_SUCCESS: + return VBVAEXHOST_DATA_TYPE_CMD; + case VINF_EOF: + return VBVAEXHOST_DATA_TYPE_NO_DATA; + case VINF_TRY_AGAIN: + RTThreadSleep(1); + continue; + default: + /* this is something really unexpected, i.e. most likely guest has written something incorrect to the VBVA buffer */ + WARN(("Warning: vboxVBVAExHCmdGet returned unexpected status %d\n", rc)); + return VBVAEXHOST_DATA_TYPE_NO_DATA; + } + } + + WARN(("Warning: VBoxVBVAExHCmdGet unexpected state\n")); + return VBVAEXHOST_DATA_TYPE_NO_DATA; +} + +static VBVAEXHOST_DATA_TYPE VBoxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd) +{ + VBVAEXHOST_DATA_TYPE enmType = vboxVBVAExHPDataGet(pCmdVbva, ppCmd, pcbCmd); + if (enmType == VBVAEXHOST_DATA_TYPE_NO_DATA) + { + vboxVBVAExHPHgEventClear(pCmdVbva); + vboxVBVAExHPProcessorRelease(pCmdVbva); + /* we need to prevent racing between us clearing the flag and command check/submission thread, i.e. + * 1. we check the queue -> and it is empty + * 2. submitter adds command to the queue + * 3. submitter checks the "processing" -> and it is true , thus it does not submit a notification + * 4. we clear the "processing" state + * 5. ->here we need to re-check the queue state to ensure we do not leak the notification of the above command + * 6. if the queue appears to be not-empty set the "processing" state back to "true" + **/ + int rc = vboxVBVAExHSProcessorAcquire(pCmdVbva); + if (RT_SUCCESS(rc)) + { + /* we are the processor now */ + enmType = vboxVBVAExHPDataGet(pCmdVbva, ppCmd, pcbCmd); + if (enmType == VBVAEXHOST_DATA_TYPE_NO_DATA) + { + vboxVBVAExHPProcessorRelease(pCmdVbva); + return VBVAEXHOST_DATA_TYPE_NO_DATA; + } + + vboxVBVAExHPHgEventSet(pCmdVbva); + } + } + + return enmType; +} + +DECLINLINE(bool) vboxVBVAExHSHasCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva) +{ + VBVABUFFER *pVBVA = pCmdVbva->pVBVA; + + if (pVBVA) + { + uint32_t indexRecordFirst = pVBVA->indexRecordFirst; + uint32_t indexRecordFree = pVBVA->indexRecordFree; + + if (indexRecordFirst != indexRecordFree) + return true; + } + + return !!ASMAtomicReadU32(&pCmdVbva->u32cCtls); +} + +/* Checks whether the new commands are ready for processing + * @returns + * VINF_SUCCESS - there are commands are in a queue, and the given thread is now the processor (i.e. typically it would delegate processing to a worker thread) + * VINF_EOF - no commands in a queue + * VINF_ALREADY_INITIALIZED - another thread already processing the commands + * VERR_INVALID_STATE - the VBVA is paused or pausing */ +static int VBoxVBVAExHSCheckCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva) +{ + int rc = vboxVBVAExHSProcessorAcquire(pCmdVbva); + if (RT_SUCCESS(rc)) + { + /* we are the processor now */ + if (vboxVBVAExHSHasCommands(pCmdVbva)) + { + vboxVBVAExHPHgEventSet(pCmdVbva); + return VINF_SUCCESS; + } + + vboxVBVAExHPProcessorRelease(pCmdVbva); + return VINF_EOF; + } + if (rc == VERR_SEM_BUSY) + return VINF_ALREADY_INITIALIZED; + return VERR_INVALID_STATE; +} + +static int VBoxVBVAExHSInit(struct VBVAEXHOSTCONTEXT *pCmdVbva) +{ + memset(pCmdVbva, 0, sizeof (*pCmdVbva)); + int rc = RTCritSectInit(&pCmdVbva->CltCritSect); + if (RT_SUCCESS(rc)) + { +#ifndef VBOXVDBG_MEMCACHE_DISABLE + rc = RTMemCacheCreate(&pCmdVbva->CtlCache, sizeof (VBVAEXHOSTCTL), + 0, /* size_t cbAlignment */ + UINT32_MAX, /* uint32_t cMaxObjects */ + NULL, /* PFNMEMCACHECTOR pfnCtor*/ + NULL, /* PFNMEMCACHEDTOR pfnDtor*/ + NULL, /* void *pvUser*/ + 0 /* uint32_t fFlags*/ + ); + if (RT_SUCCESS(rc)) +#endif + { + RTListInit(&pCmdVbva->GuestCtlList); + RTListInit(&pCmdVbva->HostCtlList); + pCmdVbva->i32State = VBVAEXHOSTCONTEXT_STATE_PROCESSING; + pCmdVbva->i32EnableState = VBVAEXHOSTCONTEXT_ESTATE_DISABLED; + return VINF_SUCCESS; + } +#ifndef VBOXVDBG_MEMCACHE_DISABLE + else + WARN(("RTMemCacheCreate failed %d\n", rc)); +#endif + } + else + WARN(("RTCritSectInit failed %d\n", rc)); + + return rc; +} + +DECLINLINE(bool) VBoxVBVAExHSIsEnabled(struct VBVAEXHOSTCONTEXT *pCmdVbva) +{ + return (ASMAtomicUoReadS32(&pCmdVbva->i32EnableState) >= VBVAEXHOSTCONTEXT_ESTATE_PAUSED); +} + +static int VBoxVBVAExHSEnable(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVABUFFER *pVBVA) +{ + if (VBoxVBVAExHSIsEnabled(pCmdVbva)) + return VINF_ALREADY_INITIALIZED; + + pCmdVbva->pVBVA = pVBVA; + pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0; + ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_ENABLED); + return VINF_SUCCESS; +} + +static int VBoxVBVAExHSDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva) +{ + if (!VBoxVBVAExHSIsEnabled(pCmdVbva)) + return VINF_SUCCESS; + + ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_DISABLED); + return VINF_SUCCESS; +} + +static void VBoxVBVAExHSTerm(struct VBVAEXHOSTCONTEXT *pCmdVbva) +{ + /* ensure the processor is stopped */ + Assert(pCmdVbva->i32State >= VBVAEXHOSTCONTEXT_STATE_LISTENING); + + /* ensure no one tries to submit the command */ + if (pCmdVbva->pVBVA) + pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0; + + Assert(RTListIsEmpty(&pCmdVbva->GuestCtlList)); + Assert(RTListIsEmpty(&pCmdVbva->HostCtlList)); + + RTCritSectDelete(&pCmdVbva->CltCritSect); + +#ifndef VBOXVDBG_MEMCACHE_DISABLE + RTMemCacheDestroy(pCmdVbva->CtlCache); +#endif + + memset(pCmdVbva, 0, sizeof (*pCmdVbva)); +} + +/* Saves state + * @returns - same as VBoxVBVAExHSCheckCommands, or failure on load state fail + */ +static int VBoxVBVAExHSSaveState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM) +{ + int rc; + + int32_t i32EnableState = ASMAtomicUoReadS32(&pCmdVbva->i32EnableState); + if (i32EnableState >= VBVAEXHOSTCONTEXT_ESTATE_PAUSED) + { + if (i32EnableState != VBVAEXHOSTCONTEXT_ESTATE_PAUSED) + { + WARN(("vbva not paused\n")); + return VERR_INVALID_STATE; + } + + rc = SSMR3PutU32(pSSM, (uint32_t)(((uint8_t*)pCmdVbva->pVBVA) - pu8VramBase)); + AssertRCReturn(rc, rc); + return VINF_SUCCESS; + } + + rc = SSMR3PutU32(pSSM, 0xffffffff); + AssertRCReturn(rc, rc); + + return VINF_SUCCESS; +} + +typedef enum +{ + VBVAEXHOSTCTL_SOURCE_GUEST = 0, + VBVAEXHOSTCTL_SOURCE_HOST_ANY, + VBVAEXHOSTCTL_SOURCE_HOST_ENABLED +} VBVAEXHOSTCTL_SOURCE; + + +static int VBoxVBVAExHCtlSubmit(VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete) +{ + if ((enmSource == VBVAEXHOSTCTL_SOURCE_HOST_ENABLED) && !VBoxVBVAExHSIsEnabled(pCmdVbva)) + { + WARN(("cmd vbva not enabled\n")); + return VERR_INVALID_STATE; + } + + pCtl->pfnComplete = pfnComplete; + pCtl->pvComplete = pvComplete; + + int rc = RTCritSectEnter(&pCmdVbva->CltCritSect); + if (RT_SUCCESS(rc)) + { + if (enmSource > VBVAEXHOSTCTL_SOURCE_GUEST) + { + if ((enmSource == VBVAEXHOSTCTL_SOURCE_HOST_ENABLED) && !VBoxVBVAExHSIsEnabled(pCmdVbva)) + { + WARN(("cmd vbva not enabled\n")); + RTCritSectLeave(&pCmdVbva->CltCritSect); + return VERR_INVALID_STATE; + } + RTListAppend(&pCmdVbva->HostCtlList, &pCtl->Node); + } + else + RTListAppend(&pCmdVbva->GuestCtlList, &pCtl->Node); + + ASMAtomicIncU32(&pCmdVbva->u32cCtls); + + RTCritSectLeave(&pCmdVbva->CltCritSect); + + rc = VBoxVBVAExHSCheckCommands(pCmdVbva); + } + else + WARN(("RTCritSectEnter failed %d\n", rc)); + + return rc; +} + + +/* Loads state + * @returns - same as VBoxVBVAExHSCheckCommands, or failure on load state fail + */ +static int VBoxVBVAExHSLoadState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version) +{ + AssertMsgFailed(("implement!\n")); + uint32_t u32; + int rc = SSMR3GetU32(pSSM, &u32); + AssertRCReturn(rc, rc); + if (u32 != 0xffffffff) + { + VBVABUFFER *pVBVA = (VBVABUFFER*)pu8VramBase + u32; + rc = VBoxVBVAExHSEnable(pCmdVbva, pVBVA); + AssertRCReturn(rc, rc); + return VBoxVBVAExHSCheckCommands(pCmdVbva); + } + + return VINF_SUCCESS; +} + +typedef struct VBOXVDMAHOST { - VBOXVDMAPIPE_STATE_CLOSED = 0, - VBOXVDMAPIPE_STATE_CREATED = 1, - VBOXVDMAPIPE_STATE_OPENNED = 2, - VBOXVDMAPIPE_STATE_CLOSING = 3 -} VBOXVDMAPIPE_STATE; + PHGSMIINSTANCE pHgsmi; + PVGASTATE pVGAState; + VBVAEXHOSTCONTEXT CmdVbva; + VBOXVDMATHREAD Thread; + VBOXCRCMD_SVRINFO CrSrvInfo; + VBVAEXHOSTCTL* pCurRemainingHostCtl; +#ifdef VBOX_VDMA_WITH_WATCHDOG + PTMTIMERR3 WatchDogTimer; +#endif +} VBOXVDMAHOST, *PVBOXVDMAHOST; -typedef struct VBOXVDMAPIPE +int VBoxVDMAThreadNotifyConstructSucceeded(PVBOXVDMATHREAD pThread) { - RTSEMEVENT hEvent; - /* critical section for accessing pipe properties */ - RTCRITSECT hCritSect; - VBOXVDMAPIPE_STATE enmState; - /* true iff the other end needs Event notification */ - bool bNeedNotify; -} VBOXVDMAPIPE, *PVBOXVDMAPIPE; + Assert(pThread->u32State == VBOXVDMATHREAD_STATE_TERMINATED); + pThread->u32State = VBOXVDMATHREAD_STATE_CREATED; + int rc = RTSemEventSignal(pThread->hClientEvent); + AssertRC(rc); + return VINF_SUCCESS; +} -typedef enum +int VBoxVDMAThreadNotifyConstructFailed(PVBOXVDMATHREAD pThread) { - VBOXVDMAPIPE_CMD_TYPE_UNDEFINED = 0, - VBOXVDMAPIPE_CMD_TYPE_DMACMD = 1, - VBOXVDMAPIPE_CMD_TYPE_DMACTL = 2 -} VBOXVDMAPIPE_CMD_TYPE; + Assert(pThread->u32State == VBOXVDMATHREAD_STATE_TERMINATED); + int rc = RTSemEventSignal(pThread->hClientEvent); + AssertRC(rc); + if (RT_SUCCESS(rc)) + return VINF_SUCCESS; + return rc; +} -typedef struct VBOXVDMAPIPE_CMD_BODY +DECLINLINE(bool) VBoxVDMAThreadIsTerminating(PVBOXVDMATHREAD pThread) { - VBOXVDMAPIPE_CMD_TYPE enmType; - union - { - PVBOXVDMACBUF_DR pDr; - PVBOXVDMA_CTL pCtl; - void *pvCmd; - } u; -}VBOXVDMAPIPE_CMD_BODY, *PVBOXVDMAPIPE_CMD_BODY; + return ASMAtomicUoReadU32(&pThread->u32State) == VBOXVDMATHREAD_STATE_TERMINATING; +} -typedef struct VBOXVDMAPIPE_CMD +int VBoxVDMAThreadCreate(PVBOXVDMATHREAD pThread, PFNRTTHREAD pfnThread, void *pvThread) { - HGSMILISTENTRY Entry; - VBOXVDMAPIPE_CMD_BODY Cmd; -} VBOXVDMAPIPE_CMD, *PVBOXVDMAPIPE_CMD; + int rc = RTSemEventCreate(&pThread->hEvent); + if (RT_SUCCESS(rc)) + { + rc = RTSemEventCreate(&pThread->hClientEvent); + if (RT_SUCCESS(rc)) + { + pThread->u32State = VBOXVDMATHREAD_STATE_TERMINATED; + rc = RTThreadCreate(&pThread->hWorkerThread, pfnThread, pvThread, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "VDMA"); + if (RT_SUCCESS(rc)) + { + rc = RTSemEventWait(pThread->hClientEvent, RT_INDEFINITE_WAIT); + if (RT_SUCCESS(rc)) + { + if (pThread->u32State == VBOXVDMATHREAD_STATE_CREATED) + return VINF_SUCCESS; + WARN(("thread routine failed the initialization\n")); + rc = VERR_INVALID_STATE; + } + else + WARN(("RTSemEventWait failed %d\n", rc)); -#define VBOXVDMAPIPE_CMD_FROM_ENTRY(_pE) ( (PVBOXVDMAPIPE_CMD)((uint8_t *)(_pE) - RT_OFFSETOF(VBOXVDMAPIPE_CMD, Entry)) ) + RTThreadWait(pThread->hWorkerThread, RT_INDEFINITE_WAIT, NULL); + } + else + WARN(("RTThreadCreate failed %d\n", rc)); -typedef struct VBOXVDMAPIPE_CMD_POOL -{ - HGSMILIST List; - uint32_t cCmds; - VBOXVDMAPIPE_CMD aCmds[1]; -} VBOXVDMAPIPE_CMD_POOL, *PVBOXVDMAPIPE_CMD_POOL; -#endif + RTSemEventDestroy(pThread->hClientEvent); + } + else + WARN(("RTSemEventCreate failed %d\n", rc)); + RTSemEventDestroy(pThread->hEvent); + } + else + WARN(("RTSemEventCreate failed %d\n", rc)); -/* state transformations: - * - * submitter | processor - * STOPPED - * | - * | - * > - * LISTENING ---> PROCESSING - * ^ _/ - * | _/ - * | _/ - * | _/ - * | _/ - * | _/ - * | / - * < > - * PAUSED - * - * */ -#define VBVAEXHOSTCONTEXT_STATE_STOPPED 0 -#define VBVAEXHOSTCONTEXT_STATE_LISTENING 1 -#define VBVAEXHOSTCONTEXT_STATE_PROCESSING 2 -#define VBVAEXHOSTCONTEXT_STATE_PAUSED 3 + return rc; +} -typedef struct VBVAEXHOSTCONTEXT +DECLINLINE(int) VBoxVDMAThreadEventNotify(PVBOXVDMATHREAD pThread) { - VBVABUFFER *pVBVA; - uint32_t cbCurData; - volatile uint32_t u32State; - volatile uint32_t u32Pause; - volatile uint32_t u32cOtherCommands; -} VBVAEXHOSTCONTEXT; - -/* VBoxVBVAExHP**, i.e. processor functions, can NOT be called concurrently with each other, - * but can be called with other VBoxVBVAExS** (submitter) functions except Init/Start/Term aparently. - * Can only be called be the processor, i.e. the entity that acquired the processor state by direct or indirect call to the VBoxVBVAExHSCheckCommands - * see mor edetailed comments in headers for function definitions */ -static bool VBoxVBVAExHPCmdCheckRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva); -static int VBoxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd); + int rc = RTSemEventSignal(pThread->hEvent); + AssertRC(rc); + return rc; +} -/* VBoxVBVAExHP**, i.e. processor functions, can NOT be called concurrently with each other, - * can be called concurrently with istelf as well as with other VBoxVBVAEx** functions except Init/Start/Term aparently */ -static int VBoxVBVAExHSCheckCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva); +DECLINLINE(int) VBoxVDMAThreadEventWait(PVBOXVDMATHREAD pThread, RTMSINTERVAL cMillies) +{ + int rc = RTSemEventWait(pThread->hEvent, cMillies); + AssertRC(rc); + return rc; +} -static void VBoxVBVAExHSInit(struct VBVAEXHOSTCONTEXT *pCmdVbva); -static int VBoxVBVAExHSEnable(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVABUFFER *pVBVA); -static int VBoxVBVAExHSDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva); -static void VBoxVBVAExHSTerm(struct VBVAEXHOSTCONTEXT *pCmdVbva); -static int VBoxVBVAExHSSaveState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM); -static int VBoxVBVAExHSLoadState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version); +void VBoxVDMAThreadMarkTerminating(PVBOXVDMATHREAD pThread) +{ + Assert(pThread->u32State == VBOXVDMATHREAD_STATE_CREATED); + ASMAtomicWriteU32(&pThread->u32State, VBOXVDMATHREAD_STATE_TERMINATING); +} -typedef struct VBOXVDMAHOST +void VBoxVDMAThreadTerm(PVBOXVDMATHREAD pThread) { - PHGSMIINSTANCE pHgsmi; - PVGASTATE pVGAState; - VBVAEXHOSTCONTEXT CmdVbva; -#ifdef VBOX_VDMA_WITH_WATCHDOG - PTMTIMERR3 WatchDogTimer; -#endif -#ifdef VBOX_VDMA_WITH_WORKERTHREAD - VBOXVDMAPIPE Pipe; - HGSMILIST PendingList; - RTTHREAD hWorkerThread; - VBOXVDMAPIPE_CMD_POOL CmdPool; -#endif -} VBOXVDMAHOST, *PVBOXVDMAHOST; + int rc; + if (ASMAtomicReadU32(&pThread->u32State) != VBOXVDMATHREAD_STATE_TERMINATING) + { + VBoxVDMAThreadMarkTerminating(pThread); + rc = VBoxVDMAThreadEventNotify(pThread); + AssertRC(rc); + } + rc = RTThreadWait(pThread->hWorkerThread, RT_INDEFINITE_WAIT, NULL); + AssertRC(rc); + RTSemEventDestroy(pThread->hClientEvent); + RTSemEventDestroy(pThread->hEvent); +} +static int vdmaVBVACtlSubmitSync(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource); #ifdef VBOX_WITH_CRHGSMI @@ -248,39 +864,301 @@ static int vboxVDMACrCtlPost(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd AssertRC(rc); if(RT_SUCCESS(rc)) { - rc = vboxVDMACrCtlPostAsync (pVGAState, pCmd, cbCmd, vboxVDMACrCtlCbSetEvent, (void*)hComplEvent); + rc = vboxVDMACrCtlPostAsync(pVGAState, pCmd, cbCmd, vboxVDMACrCtlCbSetEvent, (void*)hComplEvent); #ifdef DEBUG_misha AssertRC(rc); #endif if (RT_SUCCESS(rc)) { - rc = RTSemEventWaitNoResume(hComplEvent, RT_INDEFINITE_WAIT); - AssertRC(rc); - if(RT_SUCCESS(rc)) + rc = RTSemEventWaitNoResume(hComplEvent, RT_INDEFINITE_WAIT); + AssertRC(rc); + if(RT_SUCCESS(rc)) + { + RTSemEventDestroy(hComplEvent); + } + } + else + { + /* the command is completed */ + RTSemEventDestroy(hComplEvent); + } + } + return rc; +} + +typedef struct VDMA_VBVA_CTL_CYNC_COMPLETION +{ + int rc; + RTSEMEVENT hEvent; +} VDMA_VBVA_CTL_CYNC_COMPLETION; + +static DECLCALLBACK(void) vboxVDMACrHgcmSubmitSyncCompletion(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, int rc, void *pvCompletion) +{ + VDMA_VBVA_CTL_CYNC_COMPLETION *pData = (VDMA_VBVA_CTL_CYNC_COMPLETION*)pvCompletion; + pData->rc = rc; + rc = RTSemEventSignal(pData->hEvent); + if (!RT_SUCCESS(rc)) + WARN(("RTSemEventSignal failed %d\n", rc)); +} + +static int vboxVDMACrHgcmSubmitSync(struct VBOXVDMAHOST *pVdma, VBOXCRCMDCTL* pCtl, uint32_t cbCtl) +{ + VDMA_VBVA_CTL_CYNC_COMPLETION Data; + Data.rc = VERR_NOT_IMPLEMENTED; + int rc = RTSemEventCreate(&Data.hEvent); + if (!RT_SUCCESS(rc)) + { + WARN(("RTSemEventCreate failed %d\n", rc)); + return rc; + } + + PVGASTATE pVGAState = pVdma->pVGAState; + rc = pVGAState->pDrv->pfnCrHgcmCtlSubmit(pVGAState->pDrv, pCtl, cbCtl, vboxVDMACrHgcmSubmitSyncCompletion, &Data); + if (RT_SUCCESS(rc)) + { + rc = RTSemEventWait(Data.hEvent, RT_INDEFINITE_WAIT); + if (RT_SUCCESS(rc)) + { + rc = Data.rc; + if (!RT_SUCCESS(rc)) + { + WARN(("pfnCrHgcmCtlSubmit command failed %d\n", rc)); + } + + } + else + WARN(("RTSemEventWait failed %d\n", rc)); + } + else + WARN(("pfnCrHgcmCtlSubmit failed %d\n", rc)); + + + RTSemEventDestroy(Data.hEvent); + + return rc; +} + +static DECLCALLBACK(uint8_t*) vboxVDMACrHgcmHandleEnableRemainingHostCommand(HVBOXCRCMDCTL_REMAINING_HOST_COMMAND hClient, uint32_t *pcbCtl, int prevCmdRc) +{ + struct VBOXVDMAHOST *pVdma = hClient; + if (!pVdma->pCurRemainingHostCtl) + { + /* disable VBVA, all subsequent host commands will go HGCM way */ + VBoxVBVAExHSDisable(&pVdma->CmdVbva); + } + else + { + VBoxVBVAExHPDataCompleteCtl(&pVdma->CmdVbva, pVdma->pCurRemainingHostCtl, prevCmdRc); + } + + pVdma->pCurRemainingHostCtl = VBoxVBVAExHPCheckHostCtlOnDisable(&pVdma->CmdVbva); + if (pVdma->pCurRemainingHostCtl) + { + *pcbCtl = pVdma->pCurRemainingHostCtl->u.cmd.cbCmd; + return pVdma->pCurRemainingHostCtl->u.cmd.pu8Cmd; + } + + *pcbCtl = 0; + return NULL; +} + +static int vboxVDMACrHgcmHandleEnable(struct VBOXVDMAHOST *pVdma) +{ + VBOXCRCMDCTL_ENABLE Enable; + Enable.Hdr.enmType = VBOXCRCMDCTL_TYPE_ENABLE; + Enable.hRHCmd = pVdma; + Enable.pfnRHCmd = vboxVDMACrHgcmHandleEnableRemainingHostCommand; + + int rc = vboxVDMACrHgcmSubmitSync(pVdma, &Enable.Hdr, sizeof (Enable)); + Assert(!pVdma->pCurRemainingHostCtl); + if (RT_SUCCESS(rc)) + { + Assert(!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva)); + return VINF_SUCCESS; + } + + Assert(VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva)); + WARN(("vboxVDMACrHgcmSubmitSync failed %d\n", rc)); + + return rc; +} + +static int vdmaVBVAEnableProcess(struct VBOXVDMAHOST *pVdma, uint32_t u32Offset) +{ + if (VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva)) + { + WARN(("vdma VBVA is already enabled\n")); + return VERR_INVALID_STATE; + } + + VBVABUFFER *pVBVA = (VBVABUFFER *)HGSMIOffsetToPointerHost(pVdma->pHgsmi, u32Offset); + if (!pVBVA) + { + WARN(("invalid offset %d\n", u32Offset)); + return VERR_INVALID_PARAMETER; + } + + if (!pVdma->CrSrvInfo.pfnEnable) + { +#ifdef DEBUG_misha + WARN(("pfnEnable is NULL\n")); + return VERR_NOT_SUPPORTED; +#endif + } + + int rc = VBoxVBVAExHSEnable(&pVdma->CmdVbva, pVBVA); + if (RT_SUCCESS(rc)) + { + VBOXCRCMDCTL Ctl; + Ctl.enmType = VBOXCRCMDCTL_TYPE_DISABLE; + rc = vboxVDMACrHgcmSubmitSync(pVdma, &Ctl, sizeof (Ctl)); + if (RT_SUCCESS(rc)) + { + PVGASTATE pVGAState = pVdma->pVGAState; + VBOXCRCMD_SVRENABLE_INFO Info; + Info.hCltScr = pVGAState->pDrv; + Info.pfnCltScrUpdateBegin = pVGAState->pDrv->pfnVBVAUpdateBegin; + Info.pfnCltScrUpdateProcess = pVGAState->pDrv->pfnVBVAUpdateProcess; + Info.pfnCltScrUpdateEnd = pVGAState->pDrv->pfnVBVAUpdateEnd; + rc = pVdma->CrSrvInfo.pfnEnable(pVdma->CrSrvInfo.hSvr, &Info); + if (RT_SUCCESS(rc)) + return VINF_SUCCESS; + else + WARN(("pfnEnable failed %d\n", rc)); + + vboxVDMACrHgcmHandleEnable(pVdma); + } + else + WARN(("vboxVDMACrHgcmSubmitSync failed %d\n", rc)); + + VBoxVBVAExHSDisable(&pVdma->CmdVbva); + } + else + WARN(("VBoxVBVAExHSEnable failed %d\n", rc)); + + return rc; +} + +static int vdmaVBVADisableProcess(struct VBOXVDMAHOST *pVdma) +{ + if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva)) + { + Log(("vdma VBVA is already disabled\n")); + return VINF_SUCCESS; + } + + int rc = pVdma->CrSrvInfo.pfnDisable(pVdma->CrSrvInfo.hSvr); + if (RT_SUCCESS(rc)) + { + /* disable is a bit tricky + * we need to ensure the host ctl commands do not come out of order + * and do not come over HGCM channel until after it is enabled */ + rc = vboxVDMACrHgcmHandleEnable(pVdma); + if (RT_SUCCESS(rc)) + return rc; + + PVGASTATE pVGAState = pVdma->pVGAState; + VBOXCRCMD_SVRENABLE_INFO Info; + Info.hCltScr = pVGAState->pDrv; + Info.pfnCltScrUpdateBegin = pVGAState->pDrv->pfnVBVAUpdateBegin; + Info.pfnCltScrUpdateProcess = pVGAState->pDrv->pfnVBVAUpdateProcess; + Info.pfnCltScrUpdateEnd = pVGAState->pDrv->pfnVBVAUpdateEnd; + pVdma->CrSrvInfo.pfnEnable(pVdma->CrSrvInfo.hSvr, &Info); + } + else + WARN(("pfnDisable failed %d\n", rc)); + + return rc; +} + +static int vboxVDMACrHostCtlProcess(struct VBOXVDMAHOST *pVdma, VBVAEXHOSTCTL *pCmd) +{ + switch (pCmd->enmType) + { + case VBVAEXHOSTCTL_TYPE_HH_SAVESTATE: + if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva)) + { + WARN(("VBVAEXHOSTCTL_TYPE_HH_SAVESTATE for disabled vdma VBVA\n")); + return VERR_INVALID_STATE; + } + return pVdma->CrSrvInfo.pfnSaveState(pVdma->CrSrvInfo.hSvr, pCmd->u.state.pSSM); + case VBVAEXHOSTCTL_TYPE_HH_LOADSTATE: + if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva)) + { + WARN(("VBVAEXHOSTCTL_TYPE_HH_LOADSTATE for disabled vdma VBVA\n")); + return VERR_INVALID_STATE; + } + return pVdma->CrSrvInfo.pfnLoadState(pVdma->CrSrvInfo.hSvr, pCmd->u.state.pSSM, pCmd->u.state.u32Version); + case VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE: + if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva)) + { + WARN(("VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE for disabled vdma VBVA\n")); + return VERR_INVALID_STATE; + } + return pVdma->CrSrvInfo.pfnHostCtl(pVdma->CrSrvInfo.hSvr, pCmd->u.cmd.pu8Cmd, pCmd->u.cmd.cbCmd); + case VBVAEXHOSTCTL_TYPE_HH_TERM: + { + int rc = vdmaVBVADisableProcess(pVdma); + if (!RT_SUCCESS(rc)) + { + WARN(("vdmaVBVADisableProcess failed %d\n", rc)); + return rc; + } + + VBoxVDMAThreadMarkTerminating(&pVdma->Thread); + return VINF_SUCCESS; + } + case VBVAEXHOSTCTL_TYPE_HH_RESET: + { + int rc = vdmaVBVADisableProcess(pVdma); + if (!RT_SUCCESS(rc)) + { + WARN(("vdmaVBVADisableProcess failed %d\n", rc)); + return rc; + } + return VINF_SUCCESS; + } + default: + WARN(("unexpected host ctl type %d\n", pCmd->enmType)); + return VERR_INVALID_PARAMETER; + } +} + +static int vboxVDMACrGuestCtlProcess(struct VBOXVDMAHOST *pVdma, VBVAEXHOSTCTL *pCmd) +{ + switch (pCmd->enmType) + { + case VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE: + if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva)) + { + WARN(("VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE for disabled vdma VBVA\n")); + return VERR_INVALID_STATE; + } + return pVdma->CrSrvInfo.pfnGuestCtl(pVdma->CrSrvInfo.hSvr, pCmd->u.cmd.pu8Cmd, pCmd->u.cmd.cbCmd); + case VBVAEXHOSTCTL_TYPE_GH_ENABLE_DISABLE: + { + VBVAENABLE *pEnable = (VBVAENABLE *)pCmd->u.cmd.pu8Cmd; + Assert(pCmd->u.cmd.cbCmd == sizeof (VBVAENABLE)); + if ((pEnable->u32Flags & (VBVA_F_ENABLE | VBVA_F_DISABLE)) == VBVA_F_ENABLE) { - RTSemEventDestroy(hComplEvent); + uint32_t u32Offset = pEnable->u32Offset; + return vdmaVBVAEnableProcess(pVdma, u32Offset); } + + return vdmaVBVADisableProcess(pVdma); } - else - { - /* the command is completed */ - RTSemEventDestroy(hComplEvent); - } + default: + WARN(("unexpected ctl type %d\n", pCmd->enmType)); + return VERR_INVALID_PARAMETER; } - return rc; } -static void vboxVDMACrCmdNotifyPerform(struct VBOXVDMAHOST *pVdma) -{ - PVGASTATE pVGAState = pVdma->pVGAState; - pVGAState->pDrv->pfnCrCmdNotifyCmds(pVGAState->pDrv); -} /* * @returns * */ -static int vboxVDMACrCmdPreprocess(struct VBOXVDMAHOST *pVdma, uint8_t* pu8Cmd, uint32_t cbCmd) +static int vboxVDMACrCmdProcess(struct VBOXVDMAHOST *pVdma, uint8_t* pu8Cmd, uint32_t cbCmd) { if (*pu8Cmd == VBOXCMDVBVA_OPTYPE_NOP) return VINF_EOF; @@ -298,96 +1176,74 @@ static int vboxVDMACrCmdPreprocess(struct VBOXVDMAHOST *pVdma, uint8_t* pu8Cmd, switch (pCmd->u8OpCode) { case VBOXCMDVBVA_OPTYPE_NOPCMD: - pCmd->i8Result = 0; + pCmd->u.i8Result = 0; return VINF_EOF; default: return VINF_SUCCESS; } } -static DECLCALLBACK(int) vboxVDMACrCmdCltCmdGet(HVBOXCRCMDCLT hClt, PVBOXCMDVBVA_HDR *ppNextCmd, uint32_t *pcbNextCmd) +static DECLCALLBACK(int) vboxVDMACrCmdEnable(HVBOXCRCMDSVR hSvr, VBOXCRCMD_SVRENABLE_INFO *pInfo) { - struct VBOXVDMAHOST *pVdma = hClt; + return VINF_SUCCESS; +} - VBoxVBVAExHPCmdCheckRelease(&pVdma->CmdVbva); +static DECLCALLBACK(void) vboxVDMACrCmdDisable(HVBOXCRCMDSVR hSvr) +{ +} - uint32_t cbCmd; - uint8_t *pu8Cmd; +static DECLCALLBACK(int) vboxVDMACrCmdCtl(HVBOXCRCMDSVR hSvr, uint8_t* pCmd, uint32_t cbCmd) +{ + return VERR_NOT_SUPPORTED; +} - for(;;) +static DECLCALLBACK(int) vboxVDMACrCmdCmd(HVBOXCRCMDSVR hSvr, PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd) +{ + switch (pCmd->u8OpCode) { - int rc = VBoxVBVAExHPCmdGet(&pVdma->CmdVbva, &pu8Cmd, &cbCmd); - switch (rc) +#if 0 + case VBOXCMDVBVA_OPTYPE_BLT_OFFPRIMSZFMT_OR_ID: { - case VINF_SUCCESS: - { - rc = vboxVDMACrCmdPreprocess(pVdma, pu8Cmd, cbCmd); - switch (rc) - { - case VINF_SUCCESS: - *ppNextCmd = (PVBOXCMDVBVA_HDR)pu8Cmd; - *pcbNextCmd = cbCmd; - return VINF_SUCCESS; - case VINF_EOF: - continue; - default: - Assert(!RT_FAILURE(rc)); - return RT_FAILURE(rc) ? rc : VERR_INTERNAL_ERROR; - } - break; - } - case VINF_EOF: - return VINF_EOF; - case VINF_PERMISSION_DENIED: - /* processing was paused, processing state was released, only VBoxVBVAExHS*** calls are now allowed */ - return VINF_EOF; - case VINF_INTERRUPTED: - /* command processing was interrupted, processor state remains set. client can process any commands */ - vboxVDMACrCmdNotifyPerform(pVdma); - return VINF_EOF; - default: - Assert(!RT_FAILURE(rc)); - return RT_FAILURE(rc) ? rc : VERR_INTERNAL_ERROR; + crVBoxServerCrCmdBltProcess(pCmd, cbCmd); + break; } +#endif + default: + WARN(("unsupported command\n")); + pCmd->u.i8Result = -1; } - - WARN(("Warning: vboxVDMACrCmdCltCmdGet unexpected state\n")); - return VERR_INTERNAL_ERROR; -} - -static DECLCALLBACK(int) vboxVDMACrCmdCltDmGet(HVBOXCRCMDCLT hClt, uint32_t idScreen, struct VBVAINFOSCREEN *pScreen, void **ppvVram) -{ - struct VBOXVDMAHOST *pVdma = hClt; - PVGASTATE pVGAState = pVdma->pVGAState; - - return VBVAGetScreenInfo(pVGAState, idScreen, pScreen, ppvVram); + return VINF_SUCCESS; } static int vboxVDMACrCtlHgsmiSetup(struct VBOXVDMAHOST *pVdma) { - PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP pCmd; - pCmd = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP) vboxVDMACrCtlCreate (VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP, - sizeof (*pCmd)); + PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP pCmd = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP) + vboxVDMACrCtlCreate (VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP, sizeof (*pCmd)); + int rc = VERR_NO_MEMORY; if (pCmd) { - VBOXCRCMD_CLTINFO CltInfo; - CltInfo.hClient = pVdma; - CltInfo.pfnCmdGet = vboxVDMACrCmdCltCmdGet; - CltInfo.pfnDmGet = vboxVDMACrCmdCltDmGet; PVGASTATE pVGAState = pVdma->pVGAState; pCmd->pvVRamBase = pVGAState->vram_ptrR3; pCmd->cbVRam = pVGAState->vram_size; - pCmd->pCrCmdClientInfo = &CltInfo; - int rc = vboxVDMACrCtlPost(pVGAState, &pCmd->Hdr, sizeof (*pCmd)); - Assert(RT_SUCCESS(rc) || rc == VERR_NOT_SUPPORTED); + rc = vboxVDMACrCtlPost(pVGAState, &pCmd->Hdr, sizeof (*pCmd)); if (RT_SUCCESS(rc)) { rc = vboxVDMACrCtlGetRc(&pCmd->Hdr); + if (RT_SUCCESS(rc)) + pVdma->CrSrvInfo = pCmd->CrCmdServerInfo; + else if (rc != VERR_NOT_SUPPORTED) + WARN(("vboxVDMACrCtlGetRc returned %d\n", rc)); } + else + WARN(("vboxVDMACrCtlPost failed %d\n", rc)); + vboxVDMACrCtlRelease(&pCmd->Hdr); - return rc; } - return VERR_NO_MEMORY; + + if (!RT_SUCCESS(rc)) + memset(&pVdma->CrSrvInfo, 0, sizeof (pVdma->CrSrvInfo)); + + return rc; } static int vboxVDMACmdExecBpbTransfer(PVBOXVDMAHOST pVdma, const PVBOXVDMACMD_DMA_BPB_TRANSFER pTransfer, uint32_t cbBuffer); @@ -883,236 +1739,52 @@ static int vboxVDMACmdExec(PVBOXVDMAHOST pVdma, const uint8_t *pvBuffer, uint32_ return VERR_INVALID_STATE; } -#ifdef VBOX_VDMA_WITH_WORKERTHREAD - -int vboxVDMAPipeConstruct(PVBOXVDMAPIPE pPipe) +static DECLCALLBACK(int) vboxVDMAWorkerThread(RTTHREAD ThreadSelf, void *pvUser) { - int rc = RTSemEventCreate(&pPipe->hEvent); - AssertRC(rc); - if (RT_SUCCESS(rc)) - { - rc = RTCritSectInit(&pPipe->hCritSect); - AssertRC(rc); - if (RT_SUCCESS(rc)) - { - pPipe->enmState = VBOXVDMAPIPE_STATE_CREATED; - pPipe->bNeedNotify = true; - return VINF_SUCCESS; -// RTCritSectDelete(pPipe->hCritSect); - } - RTSemEventDestroy(pPipe->hEvent); - } - return rc; -} + PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)pvUser; + PVGASTATE pVGAState = pVdma->pVGAState; + VBVAEXHOSTCONTEXT *pCmdVbva = &pVdma->CmdVbva; + PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi; + uint8_t *pCmd; + uint32_t cbCmd; -int vboxVDMAPipeOpenServer(PVBOXVDMAPIPE pPipe) -{ - int rc = RTCritSectEnter(&pPipe->hCritSect); - AssertRC(rc); - if (RT_SUCCESS(rc)) + int rc = VBoxVDMAThreadNotifyConstructSucceeded(&pVdma->Thread); + if (!RT_SUCCESS(rc)) { - Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED); - switch (pPipe->enmState) - { - case VBOXVDMAPIPE_STATE_CREATED: - pPipe->enmState = VBOXVDMAPIPE_STATE_OPENNED; - pPipe->bNeedNotify = false; - rc = VINF_SUCCESS; - break; - case VBOXVDMAPIPE_STATE_OPENNED: - pPipe->bNeedNotify = false; - rc = VINF_ALREADY_INITIALIZED; - break; - default: - AssertBreakpoint(); - rc = VERR_INVALID_STATE; - break; - } - - RTCritSectLeave(&pPipe->hCritSect); + WARN(("VBoxVDMAThreadNotifyConstructSucceeded failed %d\n", rc)); + return rc; } - return rc; -} -int vboxVDMAPipeCloseServer(PVBOXVDMAPIPE pPipe) -{ - int rc = RTCritSectEnter(&pPipe->hCritSect); - AssertRC(rc); - if (RT_SUCCESS(rc)) + while (!VBoxVDMAThreadIsTerminating(&pVdma->Thread)) { - Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED - || pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSING); - switch (pPipe->enmState) + VBVAEXHOST_DATA_TYPE enmType = VBoxVBVAExHPDataGet(pCmdVbva, &pCmd, &cbCmd); + switch (enmType) { - case VBOXVDMAPIPE_STATE_CLOSING: - pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSED; - rc = VINF_SUCCESS; - break; - case VBOXVDMAPIPE_STATE_CLOSED: - rc = VINF_ALREADY_INITIALIZED; + case VBVAEXHOST_DATA_TYPE_CMD: + vboxVDMACrCmdProcess(pVdma, pCmd, cbCmd); + VBoxVBVAExHPDataCompleteCmd(pCmdVbva, cbCmd); + VBVARaiseIrqNoWait(pVGAState, 0); break; - default: - AssertBreakpoint(); - rc = VERR_INVALID_STATE; - break; - } - - RTCritSectLeave(&pPipe->hCritSect); - } - return rc; -} - -int vboxVDMAPipeCloseClient(PVBOXVDMAPIPE pPipe) -{ - int rc = RTCritSectEnter(&pPipe->hCritSect); - AssertRC(rc); - if (RT_SUCCESS(rc)) - { - bool bNeedNotify = false; - Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED - || pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED - || pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED); - switch (pPipe->enmState) - { - case VBOXVDMAPIPE_STATE_OPENNED: - pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSING; - bNeedNotify = pPipe->bNeedNotify; - pPipe->bNeedNotify = false; + case VBVAEXHOST_DATA_TYPE_HOSTCTL: + rc = vboxVDMACrHostCtlProcess(pVdma, (VBVAEXHOSTCTL*)pCmd); + VBoxVBVAExHPDataCompleteCtl(pCmdVbva, (VBVAEXHOSTCTL*)pCmd, rc); break; - case VBOXVDMAPIPE_STATE_CREATED: - pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSED; - pPipe->bNeedNotify = false; + case VBVAEXHOST_DATA_TYPE_GUESTCTL: + rc = vboxVDMACrGuestCtlProcess(pVdma, (VBVAEXHOSTCTL*)pCmd); + VBoxVBVAExHPDataCompleteCtl(pCmdVbva, (VBVAEXHOSTCTL*)pCmd, rc); break; - case VBOXVDMAPIPE_STATE_CLOSED: - rc = VINF_ALREADY_INITIALIZED; + case VBVAEXHOST_DATA_TYPE_NO_DATA: + rc = VBoxVDMAThreadEventWait(&pVdma->Thread, RT_INDEFINITE_WAIT); + AssertRC(rc); break; default: - AssertBreakpoint(); - rc = VERR_INVALID_STATE; - break; - } - - RTCritSectLeave(&pPipe->hCritSect); - - if (bNeedNotify) - { - rc = RTSemEventSignal(pPipe->hEvent); - AssertRC(rc); - } - } - return rc; -} - - -typedef DECLCALLBACK(bool) FNHVBOXVDMARWCB(PVBOXVDMAPIPE pPipe, void *pvCallback); -typedef FNHVBOXVDMARWCB *PFNHVBOXVDMARWCB; - -int vboxVDMAPipeModifyServer(PVBOXVDMAPIPE pPipe, PFNHVBOXVDMARWCB pfnCallback, void * pvCallback) -{ - int rc = RTCritSectEnter(&pPipe->hCritSect); - AssertRC(rc); - if (RT_SUCCESS(rc)) - { - do - { - Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED - || pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSING); - - if (pPipe->enmState >= VBOXVDMAPIPE_STATE_OPENNED) - { - bool bProcessing = pfnCallback(pPipe, pvCallback); - pPipe->bNeedNotify = !bProcessing; - if (bProcessing) - { - RTCritSectLeave(&pPipe->hCritSect); - rc = VINF_SUCCESS; - break; - } - else if (pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSING) - { - pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSED; - RTCritSectLeave(&pPipe->hCritSect); - rc = VINF_EOF; - break; - } - } - else - { - AssertBreakpoint(); - rc = VERR_INVALID_STATE; - RTCritSectLeave(&pPipe->hCritSect); - break; - } - - RTCritSectLeave(&pPipe->hCritSect); - - rc = RTSemEventWait(pPipe->hEvent, RT_INDEFINITE_WAIT); - AssertRC(rc); - if (!RT_SUCCESS(rc)) - break; - - rc = RTCritSectEnter(&pPipe->hCritSect); - AssertRC(rc); - if (!RT_SUCCESS(rc)) + WARN(("unexpected type %d\n", enmType)); break; - } while (1); - } - - return rc; -} - -int vboxVDMAPipeModifyClient(PVBOXVDMAPIPE pPipe, PFNHVBOXVDMARWCB pfnCallback, void * pvCallback) -{ - int rc = RTCritSectEnter(&pPipe->hCritSect); - AssertRC(rc); - if (RT_SUCCESS(rc)) - { - bool bNeedNotify = false; - Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED); - if (pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED) - { - bool bModified = pfnCallback(pPipe, pvCallback); - if (bModified) - { - bNeedNotify = pPipe->bNeedNotify; - pPipe->bNeedNotify = false; - } - } - else - rc = VERR_INVALID_STATE; - - RTCritSectLeave(&pPipe->hCritSect); - - if (bNeedNotify) - { - rc = RTSemEventSignal(pPipe->hEvent); - AssertRC(rc); } } - return rc; -} - -int vboxVDMAPipeDestruct(PVBOXVDMAPIPE pPipe) -{ - Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED - || pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED); - /* ensure the pipe is closed */ - vboxVDMAPipeCloseClient(pPipe); - - Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED); - - if (pPipe->enmState != VBOXVDMAPIPE_STATE_CLOSED) - return VERR_INVALID_STATE; - - int rc = RTCritSectDelete(&pPipe->hCritSect); - AssertRC(rc); - - rc = RTSemEventDestroy(pPipe->hEvent); - AssertRC(rc); return VINF_SUCCESS; } -#endif static void vboxVDMACommandProcess(PVBOXVDMAHOST pVdma, PVBOXVDMACBUF_DR pCmd, uint32_t cbCmd) { @@ -1181,87 +1853,6 @@ static void vboxVDMAControlProcess(PVBOXVDMAHOST pVdma, PVBOXVDMA_CTL pCmd) AssertRC(rc); } -#ifdef VBOX_VDMA_WITH_WORKERTHREAD -typedef struct -{ - struct VBOXVDMAHOST *pVdma; - VBOXVDMAPIPE_CMD_BODY Cmd; - bool bHasCmd; -} VBOXVDMACMD_PROCESS_CONTEXT, *PVBOXVDMACMD_PROCESS_CONTEXT; - -static DECLCALLBACK(bool) vboxVDMACommandProcessCb(PVBOXVDMAPIPE pPipe, void *pvCallback) -{ - PVBOXVDMACMD_PROCESS_CONTEXT pContext = (PVBOXVDMACMD_PROCESS_CONTEXT)pvCallback; - struct VBOXVDMAHOST *pVdma = pContext->pVdma; - HGSMILISTENTRY *pEntry = hgsmiListRemoveHead(&pVdma->PendingList); - if (pEntry) - { - PVBOXVDMAPIPE_CMD pPipeCmd = VBOXVDMAPIPE_CMD_FROM_ENTRY(pEntry); - Assert(pPipeCmd); - pContext->Cmd = pPipeCmd->Cmd; - hgsmiListPrepend(&pVdma->CmdPool.List, pEntry); - pContext->bHasCmd = true; - return true; - } - - pContext->bHasCmd = false; - return false; -} - -static DECLCALLBACK(int) vboxVDMAWorkerThread(RTTHREAD ThreadSelf, void *pvUser) -{ - PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)pvUser; - PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi; - VBOXVDMACMD_PROCESS_CONTEXT Context; - Context.pVdma = pVdma; - - int rc = vboxVDMAPipeOpenServer(&pVdma->Pipe); - AssertRC(rc); - if (RT_SUCCESS(rc)) - { - do - { - rc = vboxVDMAPipeModifyServer(&pVdma->Pipe, vboxVDMACommandProcessCb, &Context); - AssertRC(rc); - if (RT_SUCCESS(rc)) - { - switch (Context.Cmd.enmType) - { - case VBOXVDMAPIPE_CMD_TYPE_DMACMD: - { - PVBOXVDMACBUF_DR pDr = Context.Cmd.u.pDr; - vboxVDMACommandProcess(pVdma, pDr); - break; - } - case VBOXVDMAPIPE_CMD_TYPE_DMACTL: - { - PVBOXVDMA_CTL pCtl = Context.Cmd.u.pCtl; - vboxVDMAControlProcess(pVdma, pCtl); - break; - } - default: - AssertBreakpoint(); - break; - } - - if (rc == VINF_EOF) - { - rc = VINF_SUCCESS; - break; - } - } - else - break; - } while (1); - } - - /* always try to close the pipe to make sure the client side is notified */ - int tmpRc = vboxVDMAPipeCloseServer(&pVdma->Pipe); - AssertRC(tmpRc); - return rc; -} -#endif - #ifdef VBOX_VDMA_WITH_WATCHDOG static DECLCALLBACK(void) vboxVDMAWatchDogTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) { @@ -1301,41 +1892,27 @@ int vboxVDMAConstruct(PVGASTATE pVGAState, uint32_t cPipeElements) "VDMA WatchDog Timer", &pVdma->WatchDogTimer); AssertRC(rc); #endif -#ifdef VBOX_VDMA_WITH_WORKERTHREAD - hgsmiListInit(&pVdma->PendingList); - rc = vboxVDMAPipeConstruct(&pVdma->Pipe); - AssertRC(rc); + rc = VBoxVBVAExHSInit(&pVdma->CmdVbva); if (RT_SUCCESS(rc)) { - rc = RTThreadCreate(&pVdma->hWorkerThread, vboxVDMAWorkerThread, pVdma, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "VDMA"); - AssertRC(rc); + rc = VBoxVDMAThreadCreate(&pVdma->Thread, vboxVDMAWorkerThread, pVdma); if (RT_SUCCESS(rc)) { - hgsmiListInit(&pVdma->CmdPool.List); - pVdma->CmdPool.cCmds = cPipeElements; - for (uint32_t i = 0; i < cPipeElements; ++i) - { - hgsmiListAppend(&pVdma->CmdPool.List, &pVdma->CmdPool.aCmds[i].Entry); - } -# if 0 //def VBOX_WITH_CRHGSMI - int tmpRc = vboxVDMACrCtlHgsmiSetup(pVdma); -# endif -#endif pVGAState->pVdma = pVdma; - VBoxVBVAExHSInit(&pVdma->CmdVbva); #ifdef VBOX_WITH_CRHGSMI int rcIgnored = vboxVDMACrCtlHgsmiSetup(pVdma); NOREF(rcIgnored); /** @todo is this ignoring intentional? */ #endif return VINF_SUCCESS; -#ifdef VBOX_VDMA_WITH_WORKERTHREAD } + else + WARN(("VBoxVDMAThreadCreate faile %d\n", rc)); - int tmpRc = vboxVDMAPipeDestruct(&pVdma->Pipe); - AssertRC(tmpRc); + VBoxVBVAExHSTerm(&pVdma->CmdVbva); } + else + WARN(("VBoxVBVAExHSInit faile %d\n", rc)); RTMemFree(pVdma); -#endif } else rc = VERR_OUT_OF_RESOURCES; @@ -1343,46 +1920,34 @@ int vboxVDMAConstruct(PVGASTATE pVGAState, uint32_t cPipeElements) return rc; } -int vboxVDMADestruct(struct VBOXVDMAHOST *pVdma) +int vboxVDMAReset(struct VBOXVDMAHOST *pVdma) { -#ifdef VBOX_VDMA_WITH_WORKERTHREAD - /* @todo: implement*/ - AssertBreakpoint(); -#endif - VBoxVBVAExHSTerm(&pVdma->CmdVbva); - RTMemFree(pVdma); + VBVAEXHOSTCTL Ctl; + Ctl.enmType = VBVAEXHOSTCTL_TYPE_HH_RESET; + int rc = vdmaVBVACtlSubmitSync(pVdma, &Ctl, VBVAEXHOSTCTL_SOURCE_HOST_ANY); + if (!RT_SUCCESS(rc)) + { + WARN(("vdmaVBVACtlSubmitSync failed %d\n", rc)); + return rc; + } return VINF_SUCCESS; } -#ifdef VBOX_VDMA_WITH_WORKERTHREAD -typedef struct -{ - struct VBOXVDMAHOST *pVdma; - VBOXVDMAPIPE_CMD_BODY Cmd; - bool bQueued; -} VBOXVDMACMD_SUBMIT_CONTEXT, *PVBOXVDMACMD_SUBMIT_CONTEXT; - -DECLCALLBACK(bool) vboxVDMACommandSubmitCb(PVBOXVDMAPIPE pPipe, void *pvCallback) +int vboxVDMADestruct(struct VBOXVDMAHOST *pVdma) { - PVBOXVDMACMD_SUBMIT_CONTEXT pContext = (PVBOXVDMACMD_SUBMIT_CONTEXT)pvCallback; - struct VBOXVDMAHOST *pVdma = pContext->pVdma; - HGSMILISTENTRY *pEntry = hgsmiListRemoveHead(&pVdma->CmdPool.List); - Assert(pEntry); - if (pEntry) + VBVAEXHOSTCTL Ctl; + Ctl.enmType = VBVAEXHOSTCTL_TYPE_HH_TERM; + int rc = vdmaVBVACtlSubmitSync(pVdma, &Ctl, VBVAEXHOSTCTL_SOURCE_HOST_ANY); + if (!RT_SUCCESS(rc)) { - PVBOXVDMAPIPE_CMD pPipeCmd = VBOXVDMAPIPE_CMD_FROM_ENTRY(pEntry); - pPipeCmd->Cmd = pContext->Cmd; - VBoxSHGSMICommandMarkAsynchCompletion(pContext->Cmd.u.pvCmd); - pContext->bQueued = true; - hgsmiListAppend(&pVdma->PendingList, pEntry); - return true; + WARN(("vdmaVBVACtlSubmitSync failed %d\n", rc)); + return rc; } - - /* @todo: should we try to flush some commands here? */ - pContext->bQueued = false; - return false; + VBoxVDMAThreadTerm(&pVdma->Thread); + VBoxVBVAExHSTerm(&pVdma->CmdVbva); + RTMemFree(pVdma); + return VINF_SUCCESS; } -#endif int vboxVDMASaveStateExecPrep(struct VBOXVDMAHOST *pVdma, PSSMHANDLE pSSM) { @@ -1545,377 +2110,201 @@ void vboxVDMACommand(struct VBOXVDMAHOST *pVdma, PVBOXVDMACBUF_DR pCmd, uint32_t } /**/ -static int vboxVBVAExHSProcessorAcquire(struct VBVAEXHOSTCONTEXT *pCmdVbva) -{ - Assert(pCmdVbva->u32State != VBVAEXHOSTCONTEXT_STATE_STOPPED); - uint32_t oldState; - if (!ASMAtomicReadU32(&pCmdVbva->u32Pause)) +static int vdmaVBVACtlSubmit(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete) +{ + int rc = VBoxVBVAExHCtlSubmit(&pVdma->CmdVbva, pCtl, enmSource, pfnComplete, pvComplete); + if (RT_SUCCESS(rc)) { - if (ASMAtomicCmpXchgExU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_PROCESSING, VBVAEXHOSTCONTEXT_STATE_LISTENING, &oldState)) - return VINF_SUCCESS; - return oldState == VBVAEXHOSTCONTEXT_STATE_PROCESSING ? VERR_SEM_BUSY : VERR_INVALID_STATE; + if (rc == VINF_SUCCESS) + return VBoxVDMAThreadEventNotify(&pVdma->Thread); + else + Assert(rc == VINF_ALREADY_INITIALIZED); } - return VERR_INVALID_STATE; -} - -static bool vboxVBVAExHPCheckPause(struct VBVAEXHOSTCONTEXT *pCmdVbva) -{ - Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); - - if (!ASMAtomicReadU32(&pCmdVbva->u32Pause)) - return false; - - ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_PAUSED); - return true; -} - -static bool vboxVBVAExHPCheckOtherCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva) -{ - Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); - - return !!ASMAtomicUoReadU32(&pCmdVbva->u32cOtherCommands); -} - -static void vboxVBVAExHPProcessorRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva) -{ - Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); - - if (!vboxVBVAExHPCheckPause(pCmdVbva)) - ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_LISTENING); else - ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_PAUSED); -} - -static void vboxVBVAExHPHgEventSet(struct VBVAEXHOSTCONTEXT *pCmdVbva) -{ - Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); - - ASMAtomicOrU32(&pCmdVbva->pVBVA->hostFlags.u32HostEvents, VBVA_F_STATE_PROCESSING); -} - -static void vboxVBVAExHPHgEventClear(struct VBVAEXHOSTCONTEXT *pCmdVbva) -{ - Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); + WARN(("VBoxVBVAExHCtlSubmit failed %d\n", rc)); - ASMAtomicAndU32(&pCmdVbva->pVBVA->hostFlags.u32HostEvents, ~VBVA_F_STATE_PROCESSING); + return rc; } -static bool vboxVBVAExHPCmdCheckRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva) +static DECLCALLBACK(void) vboxCmdVBVACmdCtlGuestCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvContext) { - if (!pCmdVbva->cbCurData) - return false; - - VBVABUFFER *pVBVA = pCmdVbva->pVBVA; - pVBVA->off32Data = (pVBVA->off32Data + pCmdVbva->cbCurData) % pVBVA->cbData; - - pVBVA->indexRecordFirst = (pVBVA->indexRecordFirst + 1) % RT_ELEMENTS(pVBVA->aRecords); + PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)pvContext; + VBOXCMDVBVA_CTL *pGCtl = (VBOXCMDVBVA_CTL*)(pCtl->u.cmd.pu8Cmd - sizeof (VBOXCMDVBVA_CTL)); + AssertRC(rc); + pGCtl->i32Result = rc; - pCmdVbva->cbCurData = 0; + Assert(pVdma->pVGAState->fGuestCaps & VBVACAPS_COMPLETEGCMD_BY_IOREAD); + rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pGCtl); + AssertRC(rc); - return true; + VBoxVBVAExHCtlFree(pVbva, pCtl); } -static int vboxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd) +static int vdmaVBVACtlOpaqueSubmit(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL_SOURCE enmSource, uint8_t* pu8Cmd, uint32_t cbCmd, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete) { - Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); - - VBVABUFFER *pVBVA = pCmdVbva->pVBVA; - - uint32_t indexRecordFirst = pVBVA->indexRecordFirst; - uint32_t indexRecordFree = pVBVA->indexRecordFree; - - Log(("first = %d, free = %d\n", - indexRecordFirst, indexRecordFree)); - - if (indexRecordFirst == indexRecordFree) - { - /* No records to process. Return without assigning output variables. */ - return VINF_EOF; - } - - uint32_t cbRecordCurrent = ASMAtomicReadU32(&pVBVA->aRecords[indexRecordFirst].cbRecord); - - /* A new record need to be processed. */ - if (cbRecordCurrent & VBVA_F_RECORD_PARTIAL) - { - /* the record is being recorded, try again */ - return VINF_TRY_AGAIN; - } - - uint32_t cbRecord = cbRecordCurrent & ~VBVA_F_RECORD_PARTIAL; - - if (!cbRecord) + VBVAEXHOSTCTL* pHCtl = VBoxVBVAExHCtlCreate(&pVdma->CmdVbva, VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE); + if (!pHCtl) { - /* the record is being recorded, try again */ - return VINF_TRY_AGAIN; + WARN(("VBoxVBVAExHCtlCreate failed\n")); + return VERR_NO_MEMORY; } - /* we should not get partial commands here actually */ - Assert(cbRecord); - - /* The size of largest contiguous chunk in the ring biffer. */ - uint32_t u32BytesTillBoundary = pVBVA->cbData - pVBVA->off32Data; - - /* The pointer to data in the ring buffer. */ - uint8_t *pSrc = &pVBVA->au8Data[pVBVA->off32Data]; - - /* Fetch or point the data. */ - if (u32BytesTillBoundary >= cbRecord) + pHCtl->u.cmd.pu8Cmd = pu8Cmd; + pHCtl->u.cmd.cbCmd = cbCmd; + int rc = vdmaVBVACtlSubmit(pVdma, pHCtl, enmSource, pfnComplete, pvComplete); + if (!RT_SUCCESS(rc)) { - /* The command does not cross buffer boundary. Return address in the buffer. */ - *ppCmd = pSrc; - *pcbCmd = cbRecord; - pCmdVbva->cbCurData = cbRecord; - return VINF_SUCCESS; + WARN(("vdmaVBVACtlSubmit failed rc %d\n", rc)); + return rc;; } - - LogRel(("CmdVbva: cross-bound writes unsupported\n")); - return VERR_INVALID_STATE; -} - -/* Resumes command processing - * @returns - same as VBoxVBVAExHSCheckCommands - */ -static int vboxVBVAExHSResume(struct VBVAEXHOSTCONTEXT *pCmdVbva) -{ - Assert(pCmdVbva->u32State != VBVAEXHOSTCONTEXT_STATE_STOPPED); - - ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_LISTENING); - - return VBoxVBVAExHSCheckCommands(pCmdVbva); + return VINF_SUCCESS; } -/* pause the command processing. this will make the processor stop the command processing and release the processing state - * to resume the command processing the vboxVBVAExHSResume must be called */ -static void vboxVBVAExHSPause(struct VBVAEXHOSTCONTEXT *pCmdVbva) +static int vdmaVBVACtlOpaqueGuestSubmit(PVBOXVDMAHOST pVdma, VBOXCMDVBVA_CTL *pCtl, uint32_t cbCtl) { - Assert(pCmdVbva->u32State != VBVAEXHOSTCONTEXT_STATE_STOPPED); - - Assert(!pCmdVbva->u32Pause); - - ASMAtomicWriteU32(&pCmdVbva->u32Pause, 1); - - for(;;) - { - if (ASMAtomicCmpXchgU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_PAUSED, VBVAEXHOSTCONTEXT_STATE_LISTENING)) - break; - - if (ASMAtomicReadU32(&pCmdVbva->u32State) == VBVAEXHOSTCONTEXT_STATE_PAUSED) - break; - - RTThreadSleep(2); - } + Assert(cbCtl >= sizeof (VBOXCMDVBVA_CTL)); + VBoxSHGSMICommandMarkAsynchCompletion(pCtl); + int rc = vdmaVBVACtlOpaqueSubmit(pVdma, VBVAEXHOSTCTL_SOURCE_GUEST, (uint8_t*)(pCtl+1), cbCtl - sizeof (VBOXCMDVBVA_CTL), vboxCmdVBVACmdCtlGuestCompletion, pVdma); + if (RT_SUCCESS(rc)) + return VINF_SUCCESS; - pCmdVbva->u32Pause = 0; + WARN(("vdmaVBVACtlOpaqueSubmit failed %d\n", rc)); + pCtl->i32Result = rc; + rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCtl); + AssertRC(rc); + return VINF_SUCCESS; } -/* releases (completed) the command previously acquired by VBoxVBVAExHCmdGet - * for convenience can be called if no command is currently acquired - * in that case it will do nothing and return false. - * if the completion notification is needed returns true. */ -static bool VBoxVBVAExHPCmdCheckRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva) +static DECLCALLBACK(void) vboxCmdVBVACmdCtlHostCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvCompletion) { - Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); - - return vboxVBVAExHPCmdCheckRelease(pCmdVbva); + VBOXCRCMDCTL* pVboxCtl = (VBOXCRCMDCTL*)pCtl->u.cmd.pu8Cmd; + if (pVboxCtl->pfnInternal) + ((PFNCRCTLCOMPLETION)pVboxCtl->pfnInternal)(pVboxCtl, pCtl->u.cmd.cbCmd, rc, pvCompletion); + VBoxVBVAExHCtlFree(pVbva, pCtl); } -/* - * @returns - * VINF_SUCCESS - new command is obtained - * VINF_EOF - processor has completed all commands and release the processing state, only VBoxVBVAExHS*** calls are now allowed - * VINF_PERMISSION_DENIED - processing was paused, processing state was released, only VBoxVBVAExHS*** calls are now allowed - * VINF_INTERRUPTED - command processing was interrupted, processor state remains set. client can process any commands, - * and call VBoxVBVAExHPCmdGet again for further processing - * VERR_** - error happened, most likely guest corrupted VBVA data - * - */ -static int VBoxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd) +static int vdmaVBVACtlOpaqueHostSubmit(PVBOXVDMAHOST pVdma, struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, + PFNCRCTLCOMPLETION pfnCompletion, + void *pvCompletion) { - Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); - - for(;;) + pCmd->pfnInternal = (void(*)())pfnCompletion; + int rc = vdmaVBVACtlOpaqueSubmit(pVdma, VBVAEXHOSTCTL_SOURCE_HOST_ENABLED, (uint8_t*)pCmd, cbCmd, vboxCmdVBVACmdCtlHostCompletion, pvCompletion); + if (!RT_SUCCESS(rc)) { - if (vboxVBVAExHPCheckPause(pCmdVbva)) - return VINF_PERMISSION_DENIED; - if (vboxVBVAExHPCheckOtherCommands(pCmdVbva)) - return VINF_INTERRUPTED; - - int rc = vboxVBVAExHPCmdGet(pCmdVbva, ppCmd, pcbCmd); - switch (rc) + if (rc == VERR_INVALID_STATE) { - case VINF_SUCCESS: - return VINF_SUCCESS; - case VINF_EOF: - vboxVBVAExHPHgEventClear(pCmdVbva); - vboxVBVAExHPProcessorRelease(pCmdVbva); - /* we need to prevent racing between us clearing the flag and command check/submission thread, i.e. - * 1. we check the queue -> and it is empty - * 2. submitter adds command to the queue - * 3. submitter checks the "processing" -> and it is true , thus it does not submit a notification - * 4. we clear the "processing" state - * 5. ->here we need to re-check the queue state to ensure we do not leak the notification of the above command - * 6. if the queue appears to be not-empty set the "processing" state back to "true" - **/ - if (VBoxVBVAExHSCheckCommands(pCmdVbva) == VINF_SUCCESS) - continue; - return VINF_EOF; - case VINF_TRY_AGAIN: - RTThreadSleep(1); - continue; - default: - /* this is something really unexpected, i.e. most likely guest has written something incorrect to the VBVA buffer */ - if (RT_FAILURE(rc)) - return rc; + pCmd->pfnInternal = NULL; + PVGASTATE pVGAState = pVdma->pVGAState; + rc = pVGAState->pDrv->pfnCrHgcmCtlSubmit(pVGAState->pDrv, pCmd, cbCmd, pfnCompletion, pvCompletion); + if (!RT_SUCCESS(rc)) + WARN(("pfnCrHgsmiControlProcess failed %d\n", rc)); - WARN(("Warning: vboxVBVAExHCmdGet returned unexpected success status %d\n", rc)); - return VERR_INTERNAL_ERROR; + return rc; } + WARN(("vdmaVBVACtlOpaqueSubmit failed %d\n", rc)); + return rc; } - WARN(("Warning: VBoxVBVAExHCmdGet unexpected state\n")); - return VERR_INTERNAL_ERROR; + return VINF_SUCCESS; } -/* Checks whether the new commands are ready for processing - * @returns - * VINF_SUCCESS - there are commands are in a queue, and the given thread is now the processor (i.e. typically it would delegate processing to a worker thread) - * VINF_EOF - no commands in a queue - * VINF_ALREADY_INITIALIZED - another thread already processing the commands - * VERR_INVALID_STATE - the VBVA is paused or pausing */ -static int VBoxVBVAExHSCheckCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva) +static int vdmaVBVACtlEnableDisableSubmitInternal(PVBOXVDMAHOST pVdma, VBVAENABLE *pEnable, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete) { - if (ASMAtomicUoReadU32(&pCmdVbva->u32State) == VBVAEXHOSTCONTEXT_STATE_STOPPED) - return VINF_EOF; - - int rc = vboxVBVAExHSProcessorAcquire(pCmdVbva); - if (RT_SUCCESS(rc)) + VBVAEXHOSTCTL* pHCtl = VBoxVBVAExHCtlCreate(&pVdma->CmdVbva, VBVAEXHOSTCTL_TYPE_GH_ENABLE_DISABLE); + if (!pHCtl) { - /* we are the processor now */ - VBVABUFFER *pVBVA = pCmdVbva->pVBVA; - - uint32_t indexRecordFirst = pVBVA->indexRecordFirst; - uint32_t indexRecordFree = pVBVA->indexRecordFree; - - if (indexRecordFirst != indexRecordFree) - { - vboxVBVAExHPHgEventSet(pCmdVbva); - return VINF_SUCCESS; - } - - vboxVBVAExHPProcessorRelease(pCmdVbva); - return VINF_EOF; + WARN(("VBoxVBVAExHCtlCreate failed\n")); + return VERR_NO_MEMORY; } - if (rc == VERR_SEM_BUSY) - return VINF_ALREADY_INITIALIZED; - Assert(rc == VERR_INVALID_STATE); - return VERR_INVALID_STATE; -} - -static void VBoxVBVAExHSInit(struct VBVAEXHOSTCONTEXT *pCmdVbva) -{ - memset(pCmdVbva, 0, sizeof (*pCmdVbva)); -} - -static int VBoxVBVAExHSEnable(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVABUFFER *pVBVA) -{ - if (ASMAtomicUoReadU32(&pCmdVbva->u32State) != VBVAEXHOSTCONTEXT_STATE_STOPPED) - return VINF_ALREADY_INITIALIZED; - pCmdVbva->pVBVA = pVBVA; - pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0; - ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_LISTENING); + pHCtl->u.cmd.pu8Cmd = (uint8_t*)pEnable; + pHCtl->u.cmd.cbCmd = sizeof (*pEnable); + int rc = vdmaVBVACtlSubmit(pVdma, pHCtl, VBVAEXHOSTCTL_SOURCE_GUEST, pfnComplete, pvComplete); + if (!RT_SUCCESS(rc)) + { + WARN(("vdmaVBVACtlSubmit failed rc %d\n", rc)); + return rc;; + } return VINF_SUCCESS; } -static int VBoxVBVAExHSDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva) +static int vdmaVBVACtlEnableDisableSubmit(PVBOXVDMAHOST pVdma, VBOXCMDVBVA_CTL_ENABLE *pEnable) { - if (ASMAtomicUoReadU32(&pCmdVbva->u32State) == VBVAEXHOSTCONTEXT_STATE_STOPPED) - return VINF_SUCCESS; - - /* ensure no commands pending and one tries to submit them */ - int rc = vboxVBVAExHSProcessorAcquire(pCmdVbva); + VBoxSHGSMICommandMarkAsynchCompletion(&pEnable->Hdr); + int rc = vdmaVBVACtlEnableDisableSubmitInternal(pVdma, &pEnable->Enable, vboxCmdVBVACmdCtlGuestCompletion, pVdma); if (RT_SUCCESS(rc)) - { - pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0; - memset(pCmdVbva, 0, sizeof (*pCmdVbva)); return VINF_SUCCESS; - } - return VERR_INVALID_STATE; + + WARN(("vdmaVBVACtlEnableDisableSubmitInternal failed %d\n", rc)); + pEnable->Hdr.i32Result = rc; + rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, &pEnable->Hdr); + AssertRC(rc); + return VINF_SUCCESS; } -static void VBoxVBVAExHSTerm(struct VBVAEXHOSTCONTEXT *pCmdVbva) +static DECLCALLBACK(void) vdmaVBVACtlSubmitSyncCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvContext) { - /* ensure the processor is stopped */ - if (ASMAtomicUoReadU32(&pCmdVbva->u32State) == VBVAEXHOSTCONTEXT_STATE_STOPPED) - return; - - /* ensure no one tries to submit the command */ - vboxVBVAExHSPause(pCmdVbva); - pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0; - memset(pCmdVbva, 0, sizeof (*pCmdVbva)); + VDMA_VBVA_CTL_CYNC_COMPLETION *pData = (VDMA_VBVA_CTL_CYNC_COMPLETION*)pvContext; + pData->rc = rc; + rc = RTSemEventSignal(pData->hEvent); + if (!RT_SUCCESS(rc)) + WARN(("RTSemEventSignal failed %d\n", rc)); } -/* Saves state - * @returns - same as VBoxVBVAExHSCheckCommands, or failure on load state fail - */ -static int VBoxVBVAExHSSaveState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM) +static int vdmaVBVACtlSubmitSync(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource) { - int rc; - if (ASMAtomicUoReadU32(&pCmdVbva->u32State) != VBVAEXHOSTCONTEXT_STATE_STOPPED) + VDMA_VBVA_CTL_CYNC_COMPLETION Data; + Data.rc = VERR_NOT_IMPLEMENTED; + int rc = RTSemEventCreate(&Data.hEvent); + if (!RT_SUCCESS(rc)) { - vboxVBVAExHSPause(pCmdVbva); - rc = SSMR3PutU32(pSSM, (uint32_t)(((uint8_t*)pCmdVbva->pVBVA) - pu8VramBase)); - AssertRCReturn(rc, rc); - return vboxVBVAExHSResume(pCmdVbva); + WARN(("RTSemEventCreate failed %d\n", rc)); + return rc; } - rc = SSMR3PutU32(pSSM, 0xffffffff); - AssertRCReturn(rc, rc); - - return VINF_EOF; -} - -/* Loads state - * @returns - same as VBoxVBVAExHSCheckCommands, or failure on load state fail - */ -static int VBoxVBVAExHSLoadState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version) -{ - uint32_t u32; - int rc = SSMR3GetU32(pSSM, &u32); - AssertRCReturn(rc, rc); - if (u32 != 0xffffffff) + rc = vdmaVBVACtlSubmit(pVdma, pCtl, enmSource, vdmaVBVACtlSubmitSyncCompletion, &Data); + if (RT_SUCCESS(rc)) { - VBVABUFFER *pVBVA = (VBVABUFFER*)pu8VramBase + u32; - rc = VBoxVBVAExHSEnable(pCmdVbva, pVBVA); - AssertRCReturn(rc, rc); - return VBoxVBVAExHSCheckCommands(pCmdVbva); + rc = RTSemEventWait(Data.hEvent, RT_INDEFINITE_WAIT); + if (RT_SUCCESS(rc)) + { + rc = Data.rc; + if (!RT_SUCCESS(rc)) + WARN(("vdmaVBVACtlSubmitSyncCompletion returned %d\n", rc)); + } + else + WARN(("RTSemEventWait failed %d\n", rc)); } + else + WARN(("vdmaVBVACtlSubmit failed %d\n", rc)); + + RTSemEventDestroy(Data.hEvent); - return VINF_EOF; + return rc; } -int vboxCmdVBVAEnable(PVGASTATE pVGAState, VBVABUFFER *pVBVA) +static int vdmaVBVAPause(PVBOXVDMAHOST pVdma) { - struct VBOXVDMAHOST *pVdma = pVGAState->pVdma; - return VBoxVBVAExHSEnable(&pVdma->CmdVbva, pVBVA); + VBVAEXHOSTCTL Ctl; + Ctl.enmType = VBVAEXHOSTCTL_TYPE_HH_INTERNAL_PAUSE; + return vdmaVBVACtlSubmitSync(pVdma, &Ctl, VBVAEXHOSTCTL_SOURCE_HOST_ANY); } -int vboxCmdVBVADisable(PVGASTATE pVGAState) +static int vdmaVBVAResume(PVBOXVDMAHOST pVdma) { - struct VBOXVDMAHOST *pVdma = pVGAState->pVdma; - return VBoxVBVAExHSDisable(&pVdma->CmdVbva); + VBVAEXHOSTCTL Ctl; + Ctl.enmType = VBVAEXHOSTCTL_TYPE_HH_INTERNAL_RESUME; + return vdmaVBVACtlSubmitSync(pVdma, &Ctl, VBVAEXHOSTCTL_SOURCE_HOST_ANY); } -static int vboxCmdVBVACmdSubmitPerform(PVGASTATE pVGAState) +static int vboxVDMACmdSubmitPerform(struct VBOXVDMAHOST *pVdma) { - struct VBOXVDMAHOST *pVdma = pVGAState->pVdma; int rc = VBoxVBVAExHSCheckCommands(&pVdma->CmdVbva); switch (rc) { case VINF_SUCCESS: - return pVGAState->pDrv->pfnCrCmdNotifyCmds(pVGAState->pDrv); + return VBoxVDMAThreadEventNotify(&pVdma->Thread); case VINF_ALREADY_INITIALIZED: case VINF_EOF: case VERR_INVALID_STATE: @@ -1926,17 +2315,70 @@ static int vboxCmdVBVACmdSubmitPerform(PVGASTATE pVGAState) } } + +int vboxCmdVBVACmdHostCtl(PPDMIDISPLAYVBVACALLBACKS pInterface, + struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, + PFNCRCTLCOMPLETION pfnCompletion, + void *pvCompletion) +{ + PVGASTATE pVGAState = PPDMIDISPLAYVBVACALLBACKS_2_PVGASTATE(pInterface); + struct VBOXVDMAHOST *pVdma = pVGAState->pVdma; + return vdmaVBVACtlOpaqueHostSubmit(pVdma, pCmd, cbCmd, pfnCompletion, pvCompletion); +} + +int vboxCmdVBVACmdCtl(PVGASTATE pVGAState, VBOXCMDVBVA_CTL *pCtl, uint32_t cbCtl) +{ + struct VBOXVDMAHOST *pVdma = pVGAState->pVdma; + int rc = VINF_SUCCESS; + switch (pCtl->u32Type) + { + case VBOXCMDVBVACTL_TYPE_3DCTL: + return vdmaVBVACtlOpaqueGuestSubmit(pVdma, pCtl, cbCtl); + case VBOXCMDVBVACTL_TYPE_ENABLE: + if (cbCtl != sizeof (VBOXCMDVBVA_CTL_ENABLE)) + { + WARN(("incorrect enable size\n")); + rc = VERR_INVALID_PARAMETER; + break; + } + return vdmaVBVACtlEnableDisableSubmit(pVdma, (VBOXCMDVBVA_CTL_ENABLE*)pCtl); + default: + WARN(("unsupported type\n")); + rc = VERR_INVALID_PARAMETER; + break; + } + + pCtl->i32Result = rc; + rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCtl); + AssertRC(rc); + return VINF_SUCCESS; +} + int vboxCmdVBVACmdSubmit(PVGASTATE pVGAState) { - return vboxCmdVBVACmdSubmitPerform(pVGAState); + if (!VBoxVBVAExHSIsEnabled(&pVGAState->pVdma->CmdVbva)) + { + WARN(("vdma VBVA is disabled\n")); + return VERR_INVALID_STATE; + } + + return vboxVDMACmdSubmitPerform(pVGAState->pVdma); } int vboxCmdVBVACmdFlush(PVGASTATE pVGAState) { - return vboxCmdVBVACmdSubmitPerform(pVGAState); + WARN(("flush\n")); + if (!VBoxVBVAExHSIsEnabled(&pVGAState->pVdma->CmdVbva)) + { + WARN(("vdma VBVA is disabled\n")); + return VERR_INVALID_STATE; + } + return vboxVDMACmdSubmitPerform(pVGAState->pVdma); } void vboxCmdVBVACmdTimer(PVGASTATE pVGAState) { - vboxCmdVBVACmdSubmitPerform(pVGAState); + if (!VBoxVBVAExHSIsEnabled(&pVGAState->pVdma->CmdVbva)) + return; + vboxVDMACmdSubmitPerform(pVGAState->pVdma); } diff --git a/src/VBox/Devices/Makefile.kmk b/src/VBox/Devices/Makefile.kmk index 8c723378f..179a99887 100644 --- a/src/VBox/Devices/Makefile.kmk +++ b/src/VBox/Devices/Makefile.kmk @@ -371,10 +371,11 @@ if !defined(VBOX_ONLY_EXTPACKS) # Goes on almost to the end of the file. include $(PATH_SUB_CURRENT)/Network/lwip-new/Makefile.kmk endif Network/DevINIP.cpp_DEFS += VBOX_WITH_NEW_LWIP + VBoxDD_LWIP_INCS += Network # for lwipopts.h $(eval $(call def_vbox_lwip_private, \ VBoxDD, Network/lwip-new)) $(eval $(call def_vbox_lwip_flags, \ - Network/DevINIP.cpp, Network/lwip-new)) + VBoxDD, Network/DevINIP.cpp, Network/lwip-new)) endif endif # VBOX_WITH_INIP @@ -449,7 +450,7 @@ if !defined(VBOX_ONLY_EXTPACKS) # Goes on almost to the end of the file. ifdef VBOX_WITH_NEW_LWIP Storage/DrvVD.cpp_DEFS += VBOX_WITH_NEW_LWIP $(eval $(call def_vbox_lwip_flags, \ - Storage/DrvVD.cpp, Network/lwip-new)) + VBoxDD, Storage/DrvVD.cpp, Network/lwip-new)) else Storage/DrvVD.cpp_INCS = $(LWIP_INCS) endif diff --git a/src/VBox/Devices/Network/lwip-new/CHANGELOG b/src/VBox/Devices/Network/lwip-new/CHANGELOG index 68954d963..cf7728633 100644 --- a/src/VBox/Devices/Network/lwip-new/CHANGELOG +++ b/src/VBox/Devices/Network/lwip-new/CHANGELOG @@ -6,6 +6,10 @@ HISTORY ++ New features: + 2014-01-17: Jiri Engelthaler + * icmp, icmp6, opt.h: patch #8027: Completed HW checksuming for IPv4 and + IPv6 ICMP's + 2012-03-25: Simon Goldschmidt (idea by Mason) * posix/*: added posix-compatibility include files posix/netdb.h and posix/sys/socket.h which are a simple wrapper to the correct lwIP include files. @@ -80,6 +84,46 @@ HISTORY ++ Bugfixes: + 2014-01-08: Stathis Voukelatos + * memp_std.h: patch #7928 Fixed size calculation in MALLOC memory pool + creation macro + + 2014-01-18: Brian Fahs + * tcp_out.c: patch #8237: tcp_rexmit_rto fails to update pcb->unsent_oversize + when necessary + + 2014-01-17: Grant Erickson, Jay Logue, Simon Goldschmidt + * ipv6.c, netif.c: patch #7913 Enable Support for IPv6 Loopback + + 2014-01-16: Stathis Voukelatos + * netif.c: patch #7902 Fixed netif_poll() operation when LWIP_LOOPBACK_MAX_PBUFS > 0 + + 2014-01-14: "Freddie Chopin" + * snmp.h, mib2.c: fixed constness and spelling of sysdescr + + 2014-01-14: Simon Goldschmidt (patch by Thomas Faber) + * tcpip.c: patch #8241: Fix implicit declaration of ip_input with + LWIP_TCPIP_CORE_LOCKING_INPUT disabled + + 2014-01-14: chrysn + * timers.c: patch #8244 make timeouts usable reliably from outside of the + timeout routine + + 2014-01-10: Simon Goldschmidt + * ip_frag.c, ip6_frag.c: fixed bug #41041 Potential use-after-free in IPv6 reassembly + + 2014-01-10: Simon Goldschmidt + * memp.c: fixed bug #41188 Alignment error in memp_init() when MEMP_SEPARATE_POOLS==1 + + 2014-01-10: Simon Goldschmidt + * tcp.c: fixed bug #39898 tcp_fasttmr() possible lock due to infinte queue process loop + + 2013-06-29: Simon Goldschmidt + * inet.h, sockets.h: partially fixed bug #37585: IPv6 compatibility (in socket structs) + + 2013-06-29: Simon Goldschmidt + * inet6.h: bug #37585/task #12600: fixed struct in6_addr.s6_addr to conform to spec + 2013-04-24: patch by Liam * api_msg.c: patch #8008 Fix a potential null pointer dereference in assert diff --git a/src/VBox/Devices/Network/lwip-new/Makefile.kmk b/src/VBox/Devices/Network/lwip-new/Makefile.kmk index 396ec80a3..0a8bee545 100644 --- a/src/VBox/Devices/Network/lwip-new/Makefile.kmk +++ b/src/VBox/Devices/Network/lwip-new/Makefile.kmk @@ -15,13 +15,6 @@ # hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. # -# -# Recommended kmk flags: -# -# VBOX_WITH_NAT_SERVICE=1 -# VBOX_WITH_LWIP_NAT=1 -# - LWIP_INCS += \ src/include \ src/include/ipv4 \ @@ -101,9 +94,6 @@ LWIP_SOURCES += \ # src/netif/ppp/vj.c -define def_vbox_lwip_flags # VAR_BaseName, path/to/lwip/dir - $(strip $1)_INCS += $(foreach incdir, $(LWIP_INCS), $(strip $2)/$(incdir)) -endef define _def_vbox_lwip_use # VAR_BaseName, path/to/lwip/dir $(strip $1)_SOURCES += \ @@ -113,6 +103,25 @@ define _def_vbox_lwip_use # VAR_BaseName, path/to/lwip/dir # $(strip $2)/src/foo/bar.c_CFLAGS += -magic endef + +define def_vbox_lwip_flags # PROTO_BaseName, VAR_BaseName, path/to/lwip/dir + # add anything configured for the component via PROTO_BaseName + $(foreach suffix, INCS DEFS, + $(if $(value $(strip $1)_LWIP_$(suffix)), + $(eval # + $(strip $2)_$(suffix) += $(value $(strip $1)_LWIP_$(suffix)) + ))) + + # add lwip's own includes + $(strip $2)_INCS += $(foreach incdir, $(LWIP_INCS), $(strip $3)/$(incdir)) + + # disable lwip assertions for some build types + $(strip $2)_DEFS.release += LWIP_NOASSERT + $(strip $2)_DEFS.profile += LWIP_NOASSERT + $(strip $2)_DEFS.kprofile += LWIP_NOASSERT +endef + + ### ### Call this if you want to expose lwip to your component as a whole. ### In this case individual lwip files (added to _SOURCES of your @@ -123,9 +132,10 @@ endef ### define def_vbox_lwip_public # VAR_BaseName, path/to/lwip/dir $(eval $(call _def_vbox_lwip_use, $1, $2)) - $(eval $(call def_vbox_lwip_flags, $1, $2)) + $(eval $(call def_vbox_lwip_flags, $1, $1, $2)) endef + ### ### Call this if you want to expose lwip only to a few selected files. ### In this case each lwip file is configured with lwip includes etc @@ -137,7 +147,7 @@ endef define def_vbox_lwip_private # VAR_BaseName, path/to/lwip/dir $(eval $(call _def_vbox_lwip_use, $1, $2)) $(foreach file, $(LWIP_SOURCES), \ - $(eval $(call def_vbox_lwip_flags, $(strip $2)/$(file), $2))) + $(eval $(call def_vbox_lwip_flags, $1, $(strip $2)/$(file), $2))) endef diff --git a/src/VBox/Devices/Network/lwip-new/src/api/tcpip.c b/src/VBox/Devices/Network/lwip-new/src/api/tcpip.c index f959b5830..7d4afbfdf 100644 --- a/src/VBox/Devices/Network/lwip-new/src/api/tcpip.c +++ b/src/VBox/Devices/Network/lwip-new/src/api/tcpip.c @@ -46,6 +46,7 @@ #include "lwip/pbuf.h" #include "lwip/tcpip.h" #include "lwip/init.h" +#include "lwip/ip.h" #include "netif/etharp.h" #include "netif/ppp_oe.h" diff --git a/src/VBox/Devices/Network/lwip-new/src/core/ipv4/icmp.c b/src/VBox/Devices/Network/lwip-new/src/core/ipv4/icmp.c index 464d14e9b..85e67eb87 100644 --- a/src/VBox/Devices/Network/lwip-new/src/core/ipv4/icmp.c +++ b/src/VBox/Devices/Network/lwip-new/src/core/ipv4/icmp.c @@ -145,6 +145,7 @@ icmp_input(struct pbuf *p, struct netif *inp) LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n")); goto lenerr; } +#if CHECKSUM_CHECK_ICMP if (inet_chksum_pbuf(p) != 0) { LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n")); pbuf_free(p); @@ -152,6 +153,7 @@ icmp_input(struct pbuf *p, struct netif *inp) snmp_inc_icmpinerrors(); return; } +#endif #if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN if (pbuf_header(p, (PBUF_IP_HLEN + PBUF_LINK_HLEN))) { /* p is not big enough to contain link headers @@ -427,7 +429,9 @@ icmp_send_response(struct pbuf *p, u8_t type, u8_t code) /* calculate checksum */ icmphdr->chksum = 0; +#if CHECKSUM_GEN_ICMP icmphdr->chksum = inet_chksum(icmphdr, q->len); +#endif ICMP_STATS_INC(icmp.xmit); /* increase number of messages attempted to send */ snmp_inc_icmpoutmsgs(); diff --git a/src/VBox/Devices/Network/lwip-new/src/core/ipv4/ip4.c b/src/VBox/Devices/Network/lwip-new/src/core/ipv4/ip4.c index 4cb40fe25..ab051d4b0 100644 --- a/src/VBox/Devices/Network/lwip-new/src/core/ipv4/ip4.c +++ b/src/VBox/Devices/Network/lwip-new/src/core/ipv4/ip4.c @@ -879,11 +879,11 @@ err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, if (ip_addr_cmp(dest, &netif->ip_addr)) { /* Packet to self, enqueue it for loopback */ LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()")); - return netif_loop_output(netif, p, dest); + return netif_loop_output(netif, p); } #if LWIP_IGMP if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) { - netif_loop_output(netif, p, dest); + netif_loop_output(netif, p); } #endif /* LWIP_IGMP */ #endif /* ENABLE_LOOPBACK */ diff --git a/src/VBox/Devices/Network/lwip-new/src/core/ipv4/ip_frag.c b/src/VBox/Devices/Network/lwip-new/src/core/ipv4/ip_frag.c index 8d184345d..f68cc351b 100644 --- a/src/VBox/Devices/Network/lwip-new/src/core/ipv4/ip_frag.c +++ b/src/VBox/Devices/Network/lwip-new/src/core/ipv4/ip_frag.c @@ -481,7 +481,6 @@ ip_reass(struct pbuf *p) struct ip_reass_helper *iprh; u16_t offset, len; u8_t clen; - struct ip_reassdata *ipr_prev = NULL; IPFRAG_STATS_INC(ip_frag.recv); snmp_inc_ipreasmreqds(); @@ -527,7 +526,6 @@ ip_reass(struct pbuf *p) IPFRAG_STATS_INC(ip_frag.cachehit); break; } - ipr_prev = ipr; } if (ipr == NULL) { @@ -565,6 +563,7 @@ ip_reass(struct pbuf *p) /* find the right place to insert this pbuf */ /* @todo: trim pbufs if fragments are overlapping */ if (ip_reass_chain_frag_into_datagram_and_validate(ipr, p)) { + struct ip_reassdata *ipr_prev; /* the totally last fragment (flag more fragments = 0) was received at least * once AND all fragments are received */ ipr->datagram_len += IP_HLEN; @@ -579,7 +578,9 @@ ip_reass(struct pbuf *p) IPH_OFFSET_SET(fraghdr, 0); IPH_CHKSUM_SET(fraghdr, 0); /* @todo: do we need to set calculate the correct checksum? */ +#if CHECKSUM_GEN_IP IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN)); +#endif /* CHECKSUM_GEN_IP */ p = ipr->p; @@ -592,6 +593,14 @@ ip_reass(struct pbuf *p) pbuf_cat(p, r); r = iprh->next_pbuf; } + + /* find the previous entry in the linked list */ + for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr->next) { + if (ipr_prev->next == ipr) { + break; + } + } + /* release the sources allocate for the fragment queue entry */ ip_reass_dequeue_datagram(ipr, ipr_prev); @@ -811,7 +820,9 @@ ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest) IPH_OFFSET_SET(iphdr, htons(tmp)); IPH_LEN_SET(iphdr, htons(cop + IP_HLEN)); IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); +#endif /* CHECKSUM_GEN_IP */ #if IP_FRAG_USES_STATIC_BUF if (last) { diff --git a/src/VBox/Devices/Network/lwip-new/src/core/ipv6/icmp6.c b/src/VBox/Devices/Network/lwip-new/src/core/ipv6/icmp6.c index 09d598f82..28d6611d5 100644 --- a/src/VBox/Devices/Network/lwip-new/src/core/ipv6/icmp6.c +++ b/src/VBox/Devices/Network/lwip-new/src/core/ipv6/icmp6.c @@ -101,7 +101,7 @@ icmp6_input(struct pbuf *p, struct netif *inp) icmp6hdr = (struct icmp6_hdr *)p->payload; -#if LWIP_ICMP6_CHECKSUM_CHECK +#if CHECKSUM_CHECK_ICMP6 if (ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->tot_len, ip6_current_src_addr(), ip6_current_dest_addr()) != 0) { /* Checksum failed */ @@ -110,7 +110,7 @@ icmp6_input(struct pbuf *p, struct netif *inp) ICMP6_STATS_INC(icmp6.drop); return; } -#endif /* LWIP_ICMP6_CHECKSUM_CHECK */ +#endif /* CHECKSUM_CHECK_ICMP6 */ switch (icmp6hdr->type) { case ICMP6_TYPE_NA: /* Neighbor advertisement */ @@ -184,8 +184,10 @@ icmp6_input(struct pbuf *p, struct netif *inp) /* Set fields in reply. */ ((struct icmp6_echo_hdr *)(r->payload))->type = ICMP6_TYPE_EREP; ((struct icmp6_echo_hdr *)(r->payload))->chksum = 0; +#if CHECKSUM_GEN_ICMP6 ((struct icmp6_echo_hdr *)(r->payload))->chksum = ip6_chksum_pseudo(r, IP6_NEXTH_ICMP6, r->tot_len, reply_src, ip6_current_src_addr()); +#endif /* CHECKSUM_GEN_ICMP6 */ /* Send reply. */ ICMP6_STATS_INC(icmp6.xmit); @@ -218,8 +220,6 @@ void icmp6_proxy_input(struct pbuf *p, struct netif *inp) { struct icmp6_hdr *icmp6hdr; - struct pbuf * r; - ip6_addr_t * reply_src; ICMP6_STATS_INC(icmp6.recv); @@ -394,8 +394,10 @@ icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type) /* calculate checksum */ icmp6hdr->chksum = 0; +#if CHECKSUM_GEN_ICMP6 icmp6hdr->chksum = ip6_chksum_pseudo(q, IP6_NEXTH_ICMP6, q->tot_len, reply_src, reply_dest); +#endif /* CHECKSUM_GEN_ICMP6 */ ICMP6_STATS_INC(icmp6.xmit); ip6_output_if(q, reply_src, reply_dest, LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); diff --git a/src/VBox/Devices/Network/lwip-new/src/core/ipv6/ip6.c b/src/VBox/Devices/Network/lwip-new/src/core/ipv6/ip6.c index b890073d6..43a1d2164 100644 --- a/src/VBox/Devices/Network/lwip-new/src/core/ipv6/ip6.c +++ b/src/VBox/Devices/Network/lwip-new/src/core/ipv6/ip6.c @@ -947,10 +947,17 @@ ip6_output_if(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest, ip6_debug_print(p); #if ENABLE_LOOPBACK - /* TODO implement loopback for v6 - if (ip6_addr_cmp(dest, netif_ip6_addr(0))) { - return netif_loop_output(netif, p, dest); - }*/ + { + int i; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(dest, netif_ip6_addr(netif, i))) { + /* Packet to self, enqueue it for loopback */ + LWIP_DEBUGF(IP6_DEBUG, ("netif_loop_output()\n")); + return netif_loop_output(netif, p); + } + } + } #endif /* ENABLE_LOOPBACK */ #if LWIP_IPV6_FRAG /* don't fragment if interface has mtu set to 0 [loopif] */ @@ -959,7 +966,7 @@ ip6_output_if(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest, } #endif /* LWIP_IPV6_FRAG */ - LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()")); + LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()\n")); return netif->output_ip6(netif, p, dest); } diff --git a/src/VBox/Devices/Network/lwip-new/src/core/ipv6/mld6.c b/src/VBox/Devices/Network/lwip-new/src/core/ipv6/mld6.c index 6b45ca043..f91f7efaa 100644 --- a/src/VBox/Devices/Network/lwip-new/src/core/ipv6/mld6.c +++ b/src/VBox/Devices/Network/lwip-new/src/core/ipv6/mld6.c @@ -566,8 +566,10 @@ mld6_send(struct mld_group *group, u8_t type) mld_hdr->reserved = 0; ip6_addr_set(&(mld_hdr->multicast_address), &(group->group_address)); +#if CHECKSUM_GEN_ICMP6 mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, &(group->group_address)); +#endif /* CHECKSUM_GEN_ICMP6 */ /* Add hop-by-hop headers options: router alert with MLD value. */ ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD); diff --git a/src/VBox/Devices/Network/lwip-new/src/core/ipv6/nd6.c b/src/VBox/Devices/Network/lwip-new/src/core/ipv6/nd6.c index e0a063c2a..2eb74a7d3 100644 --- a/src/VBox/Devices/Network/lwip-new/src/core/ipv6/nd6.c +++ b/src/VBox/Devices/Network/lwip-new/src/core/ipv6/nd6.c @@ -888,8 +888,10 @@ nd6_send_ns(struct netif * netif, ip6_addr_t * target_addr, u8_t flags) target_addr = &multicast_address; } +#if CHECKSUM_GEN_ICMP6 ns_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, target_addr); +#endif /* CHECKSUM_GEN_ICMP6 */ /* Send the packet out. */ ND6_STATS_INC(nd6.xmit); @@ -960,8 +962,10 @@ nd6_send_na(struct netif * netif, ip6_addr_t * target_addr, u8_t flags) dest_addr = ip6_current_src_addr(); } +#if CHECKSUM_GEN_ICMP6 na_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, dest_addr); +#endif /* CHECKSUM_GEN_ICMP6 */ /* Send the packet out. */ ND6_STATS_INC(nd6.xmit); @@ -1027,8 +1031,10 @@ nd6_send_rs(struct netif * netif) SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); } +#if CHECKSUM_GEN_ICMP6 rs_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, &multicast_address); +#endif /* CHECKSUM_GEN_ICMP6 */ /* Send the packet out. */ ND6_STATS_INC(nd6.xmit); diff --git a/src/VBox/Devices/Network/lwip-new/src/core/memp.c b/src/VBox/Devices/Network/lwip-new/src/core/memp.c index 6d109797f..d2743736b 100644 --- a/src/VBox/Devices/Network/lwip-new/src/core/memp.c +++ b/src/VBox/Devices/Network/lwip-new/src/core/memp.c @@ -201,7 +201,7 @@ static const char *memp_desc[MEMP_MAX] = { * extern u8_t __attribute__((section(".onchip_mem"))) memp_memory_UDP_PCB_base[]; */ #define LWIP_MEMPOOL(name,num,size,desc) u8_t memp_memory_ ## name ## _base \ - [((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))]; + [LWIP_MEM_ALIGN_BUFFER((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))]; #include "lwip/memp_std.h" /** This array holds the base of each memory pool. */ @@ -213,7 +213,7 @@ static u8_t *const memp_bases[] = { #else /* MEMP_SEPARATE_POOLS */ /** This is the actual memory used by the pools (all pools in one big block). */ -static u8_t memp_memory[MEM_ALIGNMENT - 1 +static u8_t memp_memory[MEM_ALIGNMENT - 1 /* XXX: LWIP_MEM_ALIGN_BUFFER */ #define LWIP_MEMPOOL(name,num,size,desc) + ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) ) #include "lwip/memp_std.h" ]; @@ -334,7 +334,7 @@ memp_overflow_check_all(void) #endif /* !MEMP_SEPARATE_POOLS */ for (i = 0; i < MEMP_MAX; ++i) { #if MEMP_SEPARATE_POOLS - p = (struct memp *)(memp_bases[i]); + p = (struct memp *)LWIP_MEM_ALIGN(memp_bases[i]); #endif /* MEMP_SEPARATE_POOLS */ for (j = 0; j < memp_num[i]; ++j) { memp_overflow_check_element_overflow(p, i); @@ -346,7 +346,7 @@ memp_overflow_check_all(void) #endif /* !MEMP_SEPARATE_POOLS */ for (i = 0; i < MEMP_MAX; ++i) { #if MEMP_SEPARATE_POOLS - p = (struct memp *)(memp_bases[i]); + p = (struct memp *)LWIP_MEM_ALIGN(memp_bases[i]); #endif /* MEMP_SEPARATE_POOLS */ for (j = 0; j < memp_num[i]; ++j) { memp_overflow_check_element_underflow(p, i); @@ -370,7 +370,7 @@ memp_overflow_init(void) #endif /* !MEMP_SEPARATE_POOLS */ for (i = 0; i < MEMP_MAX; ++i) { #if MEMP_SEPARATE_POOLS - p = (struct memp *)(memp_bases[i]); + p = (struct memp *)LWIP_MEM_ALIGN(memp_bases[i]); #endif /* MEMP_SEPARATE_POOLS */ for (j = 0; j < memp_num[i]; ++j) { #if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 @@ -415,7 +415,7 @@ memp_init(void) VALGRIND_CREATE_MEMPOOL(&memp_tab[i], MEMP_VALGRIND_RED_ZONE, 0); #endif #if MEMP_SEPARATE_POOLS - memp = (struct memp*)memp_bases[i]; + memp = (struct memp*)LWIP_MEM_ALIGN(memp_bases[i]); #endif /* MEMP_SEPARATE_POOLS */ /* create a linked list of memp elements */ for (j = 0; j < memp_num[i]; ++j) { diff --git a/src/VBox/Devices/Network/lwip-new/src/core/netif.c b/src/VBox/Devices/Network/lwip-new/src/core/netif.c index 1004ed126..385711fe9 100644 --- a/src/VBox/Devices/Network/lwip-new/src/core/netif.c +++ b/src/VBox/Devices/Network/lwip-new/src/core/netif.c @@ -88,7 +88,19 @@ static u8_t netif_num; static err_t netif_null_output_ip6(struct netif *netif, struct pbuf *p, ip6_addr_t *ipaddr); #endif /* LWIP_IPV6 */ +#if LWIP_IPV6 +#define ipX_input(in, netif) (IP6H_V((const struct ip6_hdr *)in->payload) == 6) ? ip6_input(in, netif) : ip_input(in, netif) +#else +#define ipX_input(in, netif) ip_input(in, netif) +#endif + #if LWIP_HAVE_LOOPIF +static err_t netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, ip_addr_t* addr); +#if LWIP_IPV6 +static err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, ip6_addr_t* addr); +#endif + + static struct netif loop_netif; /** @@ -108,7 +120,10 @@ netif_loopif_init(struct netif *netif) netif->name[0] = 'l'; netif->name[1] = 'o'; - netif->output = netif_loop_output; + netif->output = netif_loop_output_ipv4; +#if LWIP_IPV6 + netif->output_ip6 = netif_loop_output_ipv6; +#endif return ERR_OK; } #endif /* LWIP_HAVE_LOOPIF */ @@ -127,6 +142,15 @@ netif_init(void) #else /* NO_SYS */ netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, tcpip_input); #endif /* NO_SYS */ + +#if LWIP_IPV6 + loop_netif.ip6_addr[0].addr[0] = 0; + loop_netif.ip6_addr[0].addr[1] = 0; + loop_netif.ip6_addr[0].addr[2] = 0; + loop_netif.ip6_addr[0].addr[3] = PP_HTONL(0x00000001UL); + loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID; +#endif /* LWIP_IPV6 */ + netif_set_up(&loop_netif); #endif /* LWIP_HAVE_LOOPIF */ @@ -655,13 +679,11 @@ void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_ * * @param netif the lwip network interface structure * @param p the (IP) packet to 'send' - * @param ipaddr the ip address to send the packet to (not used) * @return ERR_OK if the packet has been sent * ERR_MEM if the pbuf used to copy the packet couldn't be allocated */ err_t -netif_loop_output(struct netif *netif, struct pbuf *p, - ip_addr_t *ipaddr) +netif_loop_output(struct netif *netif, struct pbuf *p) { struct pbuf *r; err_t err; @@ -679,7 +701,6 @@ netif_loop_output(struct netif *netif, struct pbuf *p, #endif /* LWIP_HAVE_LOOPIF */ #endif /* LWIP_SNMP */ SYS_ARCH_DECL_PROTECT(lev); - LWIP_UNUSED_ARG(ipaddr); /* Allocate a new pbuf */ r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); @@ -741,6 +762,23 @@ netif_loop_output(struct netif *netif, struct pbuf *p, return ERR_OK; } +static err_t +netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, ip_addr_t* addr) +{ + LWIP_UNUSED_ARG(addr); + return netif_loop_output(netif, p); +} + +#if LWIP_IPV6 +static err_t +netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, ip6_addr_t* addr) +{ + LWIP_UNUSED_ARG(addr); + return netif_loop_output(netif, p); +} +#endif + + /** * Call netif_poll() in the main loop of your application. This is to prevent * reentering non-reentrant functions like tcp_input(). Packets passed to @@ -769,16 +807,22 @@ netif_poll(struct netif *netif) if (in != NULL) { struct pbuf *in_end = in; #if LWIP_LOOPBACK_MAX_PBUFS - u8_t clen = pbuf_clen(in); - /* adjust the number of pbufs on queue */ - LWIP_ASSERT("netif->loop_cnt_current underflow", - ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); - netif->loop_cnt_current -= clen; + u8_t clen = 1; #endif /* LWIP_LOOPBACK_MAX_PBUFS */ while (in_end->len != in_end->tot_len) { LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); in_end = in_end->next; +#if LWIP_LOOPBACK_MAX_PBUFS + clen++; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ } +#if LWIP_LOOPBACK_MAX_PBUFS + /* adjust the number of pbufs on queue */ + LWIP_ASSERT("netif->loop_cnt_current underflow", + ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); + netif->loop_cnt_current -= clen; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + /* 'in_end' now points to the last pbuf from 'in' */ if (in_end == netif->loop_last) { /* this was the last pbuf in the list */ @@ -798,7 +842,7 @@ netif_poll(struct netif *netif) snmp_add_ifinoctets(stats_if, in->tot_len); snmp_inc_ifinucastpkts(stats_if); /* loopback packets are always IP packets! */ - if (ip_input(in, netif) != ERR_OK) { + if (ipX_input(in, netif) != ERR_OK) { pbuf_free(in); } /* Don't reference the packet any more! */ diff --git a/src/VBox/Devices/Network/lwip-new/src/core/snmp/mib2.c b/src/VBox/Devices/Network/lwip-new/src/core/snmp/mib2.c index dcd3b62c1..fe1bf6d71 100644 --- a/src/VBox/Devices/Network/lwip-new/src/core/snmp/mib2.c +++ b/src/VBox/Devices/Network/lwip-new/src/core/snmp/mib2.c @@ -772,8 +772,8 @@ static const s32_t sysservices = SNMP_SYSSERVICES; /** mib-2.system.sysDescr */ static const u8_t sysdescr_len_default = 4; static const u8_t sysdescr_default[] = "lwIP"; -static u8_t* sysdescr_len_ptr = (u8_t*)&sysdescr_len_default; -static u8_t* sysdescr_ptr = (u8_t*)&sysdescr_default[0]; +static const u8_t* sysdescr_len_ptr = &sysdescr_len_default; +static const u8_t* sysdescr_ptr = &sysdescr_default[0]; /** mib-2.system.sysContact */ static const u8_t syscontact_len_default = 0; static const u8_t syscontact_default[] = ""; @@ -902,7 +902,7 @@ static u32_t snmpinpkts = 0, * @param src points to source * @param n number of octets to copy. */ -static void ocstrncpy(u8_t *dst, u8_t *src, u16_t n) +static void ocstrncpy(u8_t *dst, const u8_t *src, u16_t n) { u16_t i = n; while (i > 0) { @@ -918,7 +918,7 @@ static void ocstrncpy(u8_t *dst, u8_t *src, u16_t n) * @param src points to source * @param n number of sub identifiers to copy. */ -void objectidncpy(s32_t *dst, s32_t *src, u8_t n) +void objectidncpy(s32_t *dst, const s32_t *src, u8_t n) { u8_t i = n; while(i > 0) { @@ -933,7 +933,7 @@ void objectidncpy(s32_t *dst, s32_t *src, u8_t n) * @param str if non-NULL then copy str pointer * @param len points to string length, excluding zero terminator */ -void snmp_set_sysdesr(u8_t *str, u8_t *len) +void snmp_set_sysdescr(const u8_t *str, const u8_t *len) { if (str != NULL) { diff --git a/src/VBox/Devices/Network/lwip-new/src/core/stats.c b/src/VBox/Devices/Network/lwip-new/src/core/stats.c index 06fbe0f2c..ff97853fa 100644 --- a/src/VBox/Devices/Network/lwip-new/src/core/stats.c +++ b/src/VBox/Devices/Network/lwip-new/src/core/stats.c @@ -86,7 +86,7 @@ stats_display_proto(struct stats_proto *proto, const char *name) LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit)); } -#if IGMP_STATS +#if IGMP_STATS || MLD6_STATS void stats_display_igmp(struct stats_igmp *igmp, const char *name) { @@ -106,7 +106,7 @@ stats_display_igmp(struct stats_igmp *igmp, const char *name) LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave)); LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n\t", igmp->tx_report)); } -#endif /* IGMP_STATS */ +#endif /* IGMP_STATS || MLD6_STATS */ #if MEM_STATS || MEMP_STATS void diff --git a/src/VBox/Devices/Network/lwip-new/src/core/tcp.c b/src/VBox/Devices/Network/lwip-new/src/core/tcp.c index 7596562e3..ebf6f48d5 100644 --- a/src/VBox/Devices/Network/lwip-new/src/core/tcp.c +++ b/src/VBox/Devices/Network/lwip-new/src/core/tcp.c @@ -1005,7 +1005,12 @@ tcp_slowtmr_start: * (to the real destination - as done by proxy hanlder). */ /* Check if this PCB has stayed too long in SYN-RCVD */ - if (pcb->state == SYN_RCVD || pcb->state == SYN_RCVD_0) { + if (pcb->state == SYN_RCVD +#if LWIP_CONNECTION_PROXY + || pcb->state == SYN_RCVD_0 +#endif + ) + { if ((u32_t)(tcp_ticks - pcb->tmr) > TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) { ++pcb_remove; @@ -1154,6 +1159,8 @@ tcp_fasttmr_start: } } pcb = next; + } else { + pcb = pcb->next; } } } diff --git a/src/VBox/Devices/Network/lwip-new/src/core/tcp_out.c b/src/VBox/Devices/Network/lwip-new/src/core/tcp_out.c index 0fcd0f12a..9884efa2c 100644 --- a/src/VBox/Devices/Network/lwip-new/src/core/tcp_out.c +++ b/src/VBox/Devices/Network/lwip-new/src/core/tcp_out.c @@ -1262,11 +1262,16 @@ tcp_rexmit_rto(struct tcp_pcb *pcb) for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); /* concatenate unsent queue after unacked queue */ seg->next = pcb->unsent; +#if TCP_OVERSIZE && TCP_OVERSIZE_DBGCHECK + /* if last unsent changed, we need to update unsent_oversize */ + if (pcb->unsent == NULL) { + pcb->unsent_oversize = seg->oversize_left; + } +#endif /* TCP_OVERSIZE && TCP_OVERSIZE_DBGCHECK*/ /* unsent queue is the concatenated queue (of unacked, unsent) */ pcb->unsent = pcb->unacked; /* unacked queue is now empty */ pcb->unacked = NULL; - /* last unsent hasn't changed, no need to reset unsent_oversize */ /* increment number of retransmissions */ ++pcb->nrtx; diff --git a/src/VBox/Devices/Network/lwip-new/src/core/timers.c b/src/VBox/Devices/Network/lwip-new/src/core/timers.c index 02fef0fdd..601a905f2 100644 --- a/src/VBox/Devices/Network/lwip-new/src/core/timers.c +++ b/src/VBox/Devices/Network/lwip-new/src/core/timers.c @@ -79,7 +79,7 @@ static int tcpip_tcp_timer_active; #if LWIP_CONNECTION_PROXY /** global variable that shows if proxy timer is currently scheduled or not */ static int proxy_udp_timer_active; -#endif /* LWIP_TCP */ +#endif /* LWIP_CONNECTION_PROXY */ #if LWIP_TCP @@ -368,16 +368,34 @@ sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg) #endif /* LWIP_DEBUG_TIMERNAMES */ { struct sys_timeo *timeout, *t; +#if NO_SYS + u32_t now, diff; +#endif timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT); if (timeout == NULL) { LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL); return; } + +#if NO_SYS + now = sys_now(); + if (next_timeout == NULL) { + diff = 0; + timeouts_last_time = now; + } else { + diff = now - timeouts_last_time; + } +#endif + timeout->next = NULL; timeout->h = handler; timeout->arg = arg; +#if NO_SYS + timeout->time = msecs + diff; +#else timeout->time = msecs; +#endif #if LWIP_DEBUG_TIMERNAMES timeout->handler_name = handler_name; LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n", @@ -479,7 +497,7 @@ sys_check_timeouts(void) if (tmptimeout && (tmptimeout->time <= diff)) { /* timeout has expired */ had_one = 1; - timeouts_last_time = now; + timeouts_last_time += tmptimeout->time; diff -= tmptimeout->time; next_timeout = tmptimeout->next; handler = tmptimeout->h; diff --git a/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/autoip.h b/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/autoip.h index e62b72e8c..b9f18733f 100644 --- a/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/autoip.h +++ b/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/autoip.h @@ -94,6 +94,9 @@ struct autoip /** Set a struct autoip allocated by the application to work with */ void autoip_set_struct(struct netif *netif, struct autoip *autoip); +/** Remove a struct autoip previously set to the netif using autoip_set_struct() */ +#define autoip_remove_struct(netif) do { (netif)->autoip = NULL; } while (0) + /** Start AutoIP client */ err_t autoip_start(struct netif *netif); diff --git a/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/inet.h b/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/inet.h index 7bff49b59..a6d2eda48 100644 --- a/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/inet.h +++ b/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/inet.h @@ -40,9 +40,14 @@ extern "C" { #endif +/* If your port already typedef's in_addr_t, define IN_ADDR_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED) +typedef u32_t in_addr_t; +#endif /** For compatibility with BSD code */ struct in_addr { - u32_t s_addr; + in_addr_t s_addr; }; /** 255.255.255.255 */ @@ -89,6 +94,15 @@ struct in_addr { #define IN_LOOPBACKNET IP_LOOPBACKNET +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX +#endif +#if LWIP_IPV6 +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN IP6ADDR_STRLEN_MAX +#endif +#endif + #define inet_addr_from_ipaddr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) #define inet_addr_to_ipaddr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr)) /* ATTENTION: the next define only works because both s_addr and ip_addr_t are an u32_t effectively! */ diff --git a/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/ip4_addr.h b/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/ip4_addr.h index 923d4b066..af76856cf 100644 --- a/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/ip4_addr.h +++ b/src/VBox/Devices/Network/lwip-new/src/include/ipv4/lwip/ip4_addr.h @@ -228,6 +228,9 @@ u8_t ip4_addr_netmask_valid(u32_t netmask); #define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr)) #define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr)) +#define IP4ADDR_STRLEN_MAX 16 +#define IPADDR_STRLEN_MAX IP4ADDR_STRLEN_MAX + /** For backwards compatibility */ #define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr) diff --git a/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/inet6.h b/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/inet6.h index dbf98df01..8359521b5 100644 --- a/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/inet6.h +++ b/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/inet6.h @@ -58,7 +58,7 @@ struct in6_addr { u8_t u8_addr[16]; u32_t u32_addr[4]; } un; -#define s6_addr un.u32_addr +#define s6_addr un.u8_addr }; #define IN6ADDR_ANY_INIT {0,0,0,0} diff --git a/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/ip6_addr.h b/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/ip6_addr.h index 56da0d34b..4e5f4a25d 100644 --- a/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/ip6_addr.h +++ b/src/VBox/Devices/Network/lwip-new/src/include/ipv6/lwip/ip6_addr.h @@ -85,8 +85,6 @@ extern const ip6_addr_t ip6_addr_any; #define IP6_ADDR_ANY ((ip6_addr_t *)&ip6_addr_any) - - #if BYTE_ORDER == BIG_ENDIAN /** Set an IPv6 partial address given by byte-parts. */ #define IP6_ADDR(ip6addr, index, a,b,c,d) \ @@ -146,7 +144,6 @@ Little-endian version, stored in network order (no htonl). */ (dest)->addr[3] = (src) == NULL ? 0 : htonl((src)->addr[3]);}while(0) - /** * Determine if two IPv6 address are on the same network. * @@ -170,6 +167,10 @@ Little-endian version, stored in network order (no htonl). */ ((ip6addr)->addr[2] == 0) && \ ((ip6addr)->addr[3] == 0))) +#define ip6_addr_isloopback(ip6addr) (((ip6addr)->addr[0] == 0UL) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) #define ip6_addr_isglobal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xe0000000UL)) == PP_HTONL(0x20000000UL)) @@ -270,6 +271,8 @@ Little-endian version, stored in network order (no htonl). */ ipaddr != NULL ? IP6_ADDR_BLOCK7(ipaddr) : 0, \ ipaddr != NULL ? IP6_ADDR_BLOCK8(ipaddr) : 0)) +#define IP6ADDR_STRLEN_MAX 46 + int ip6addr_aton(const char *cp, ip6_addr_t *addr); /** returns ptr to static buffer; not reentrant! */ char *ip6addr_ntoa(const ip6_addr_t *addr); diff --git a/src/VBox/Devices/Network/lwip-new/src/include/lwip/debug.h b/src/VBox/Devices/Network/lwip-new/src/include/lwip/debug.h index 0fe041396..fe66d4e47 100644 --- a/src/VBox/Devices/Network/lwip-new/src/include/lwip/debug.h +++ b/src/VBox/Devices/Network/lwip-new/src/include/lwip/debug.h @@ -76,6 +76,8 @@ #endif /* LWIP_ERROR */ #ifdef LWIP_DEBUG +/* let VBox override it to use logging */ +#ifndef LWIP_DEBUGF /** print debug message only if debug message type is enabled... * AND is of correct type AND is at least LWIP_DBG_LEVEL */ @@ -90,8 +92,12 @@ } \ } \ } while(0) - +#endif /* !LWIP_DEBUGF */ #else /* LWIP_DEBUG */ +#ifdef LWIP_DEBUG +/* sanity check, this is going to fail with undefined variables anyway */ +#error LWIP_DEBUGF is defined without LWIP_DEBUG +#endif #define LWIP_DEBUGF(debug, message) #endif /* LWIP_DEBUG */ diff --git a/src/VBox/Devices/Network/lwip-new/src/include/lwip/memp_std.h b/src/VBox/Devices/Network/lwip-new/src/include/lwip/memp_std.h index 592a2824e..8e1c99c40 100644 --- a/src/VBox/Devices/Network/lwip-new/src/include/lwip/memp_std.h +++ b/src/VBox/Devices/Network/lwip-new/src/include/lwip/memp_std.h @@ -12,7 +12,7 @@ #ifndef LWIP_MALLOC_MEMPOOL /* This treats "malloc pools" just like any other pool. The pools are a little bigger to provide 'size' as the amount of user data. */ -#define LWIP_MALLOC_MEMPOOL(num, size) LWIP_MEMPOOL(POOL_##size, num, (size + sizeof(struct memp_malloc_helper)), "MALLOC_"#size) +#define LWIP_MALLOC_MEMPOOL(num, size) LWIP_MEMPOOL(POOL_##size, num, (size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper))), "MALLOC_"#size) #define LWIP_MALLOC_MEMPOOL_START #define LWIP_MALLOC_MEMPOOL_END #endif /* LWIP_MALLOC_MEMPOOL */ diff --git a/src/VBox/Devices/Network/lwip-new/src/include/lwip/netif.h b/src/VBox/Devices/Network/lwip-new/src/include/lwip/netif.h index 322d2d0ed..b2c8d87a7 100644 --- a/src/VBox/Devices/Network/lwip-new/src/include/lwip/netif.h +++ b/src/VBox/Devices/Network/lwip-new/src/include/lwip/netif.h @@ -359,7 +359,7 @@ void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_ #endif /* LWIP_IGMP */ #if ENABLE_LOOPBACK -err_t netif_loop_output(struct netif *netif, struct pbuf *p, ip_addr_t *dest_ip); +err_t netif_loop_output(struct netif *netif, struct pbuf *p); void netif_poll(struct netif *netif); #if !LWIP_NETIF_LOOPBACK_MULTITHREADING void netif_poll_all(void); diff --git a/src/VBox/Devices/Network/lwip-new/src/include/lwip/netifapi.h b/src/VBox/Devices/Network/lwip-new/src/include/lwip/netifapi.h index 33318efaf..648151b6b 100644 --- a/src/VBox/Devices/Network/lwip-new/src/include/lwip/netifapi.h +++ b/src/VBox/Devices/Network/lwip-new/src/include/lwip/netifapi.h @@ -96,6 +96,9 @@ err_t netifapi_netif_common ( struct netif *netif, #define netifapi_netif_set_default(n) netifapi_netif_common(n, netif_set_default, NULL) #define netifapi_dhcp_start(n) netifapi_netif_common(n, NULL, dhcp_start) #define netifapi_dhcp_stop(n) netifapi_netif_common(n, dhcp_stop, NULL) +#define netifapi_dhcp_inform(n) netifapi_netif_common(n, dhcp_inform, NULL) +#define netifapi_dhcp_renew(n) netifapi_netif_common(n, NULL, dhcp_renew) +#define netifapi_dhcp_release(n) netifapi_netif_common(n, NULL, dhcp_release) #define netifapi_autoip_start(n) netifapi_netif_common(n, NULL, autoip_start) #define netifapi_autoip_stop(n) netifapi_netif_common(n, NULL, autoip_stop) diff --git a/src/VBox/Devices/Network/lwip-new/src/include/lwip/opt.h b/src/VBox/Devices/Network/lwip-new/src/include/lwip/opt.h index 0da6fad50..1cec8d464 100644 --- a/src/VBox/Devices/Network/lwip-new/src/include/lwip/opt.h +++ b/src/VBox/Devices/Network/lwip-new/src/include/lwip/opt.h @@ -1880,6 +1880,13 @@ #define CHECKSUM_GEN_ICMP 1 #endif +/** + * CHECKSUM_GEN_ICMP6==1: Generate checksums in software for outgoing ICMP6 packets. + */ +#ifndef CHECKSUM_GEN_ICMP6 +#define CHECKSUM_GEN_ICMP6 1 +#endif + /** * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. */ @@ -1901,6 +1908,20 @@ #define CHECKSUM_CHECK_TCP 1 #endif +/** + * CHECKSUM_CHECK_ICMP==1: Check checksums in software for incoming ICMP packets. + */ +#ifndef CHECKSUM_CHECK_ICMP +#define CHECKSUM_CHECK_ICMP 1 +#endif + +/** + * CHECKSUM_CHECK_ICMP6==1: Check checksums in software for incoming ICMPv6 packets + */ +#ifndef CHECKSUM_CHECK_ICMP6 +#define CHECKSUM_CHECK_ICMP6 1 +#endif + /** * LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from * application buffers to pbufs. @@ -1957,13 +1978,6 @@ #define LWIP_ICMP6_HL 255 #endif -/** - * LWIP_ICMP6_CHECKSUM_CHECK==1: verify checksum on ICMPv6 packets - */ -#ifndef LWIP_ICMP6_CHECKSUM_CHECK -#define LWIP_ICMP6_CHECKSUM_CHECK 1 -#endif - /** * LWIP_IPV6_MLD==1: Enable multicast listener discovery protocol. */ diff --git a/src/VBox/Devices/Network/lwip-new/src/include/lwip/snmp.h b/src/VBox/Devices/Network/lwip-new/src/include/lwip/snmp.h index 2ed043dd5..7844cc11e 100644 --- a/src/VBox/Devices/Network/lwip-new/src/include/lwip/snmp.h +++ b/src/VBox/Devices/Network/lwip-new/src/include/lwip/snmp.h @@ -98,7 +98,7 @@ struct snmp_obj_id }; /* system */ -void snmp_set_sysdesr(u8_t* str, u8_t* len); +void snmp_set_sysdescr(const u8_t* str, const u8_t* len); void snmp_set_sysobjid(struct snmp_obj_id *oid); void snmp_get_sysobjid_ptr(struct snmp_obj_id **oid); void snmp_inc_sysuptime(void); @@ -231,7 +231,7 @@ void snmp_get_snmpenableauthentraps(u8_t *value); #else /* system */ -#define snmp_set_sysdesr(str, len) +#define snmp_set_sysdescr(str, len) #define snmp_set_sysobjid(oid); #define snmp_get_sysobjid_ptr(oid) #define snmp_inc_sysuptime() diff --git a/src/VBox/Devices/Network/lwip-new/src/include/lwip/sockets.h b/src/VBox/Devices/Network/lwip-new/src/include/lwip/sockets.h index 73461374b..853beea80 100644 --- a/src/VBox/Devices/Network/lwip-new/src/include/lwip/sockets.h +++ b/src/VBox/Devices/Network/lwip-new/src/include/lwip/sockets.h @@ -48,33 +48,54 @@ extern "C" { #endif +/* If your port already typedef's sa_family_t, define SA_FAMILY_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(sa_family_t) && !defined(SA_FAMILY_T_DEFINED) +typedef u8_t sa_family_t; +#endif +/* If your port already typedef's in_port_t, define IN_PORT_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(in_port_t) && !defined(IN_PORT_T_DEFINED) +typedef u16_t in_port_t; +#endif + /* members are in network byte order */ struct sockaddr_in { - u8_t sin_len; - u8_t sin_family; - u16_t sin_port; - struct in_addr sin_addr; + u8_t sin_len; + sa_family_t sin_family; + in_port_t sin_port; + struct in_addr sin_addr; #define SIN_ZERO_LEN 8 - char sin_zero[SIN_ZERO_LEN]; + char sin_zero[SIN_ZERO_LEN]; }; #if LWIP_IPV6 struct sockaddr_in6 { - u8_t sin6_len; /* length of this structure */ - u8_t sin6_family; /* AF_INET6 */ - u16_t sin6_port; /* Transport layer port # */ - u32_t sin6_flowinfo; /* IPv6 flow information */ - struct in6_addr sin6_addr; /* IPv6 address */ + u8_t sin6_len; /* length of this structure */ + sa_family_t sin6_family; /* AF_INET6 */ + in_port_t sin6_port; /* Transport layer port # */ + u32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ }; #endif /* LWIP_IPV6 */ struct sockaddr { - u8_t sa_len; - u8_t sa_family; + u8_t sa_len; + sa_family_t sa_family; #if LWIP_IPV6 - u8_t sa_data[22]; + char sa_data[22]; #else /* LWIP_IPV6 */ - u8_t sa_data[14]; + char sa_data[14]; +#endif /* LWIP_IPV6 */ +}; + +struct sockaddr_storage { + u8_t s2_len; + sa_family_t ss_family; + char s2_data1[2]; + u32_t s2_data2[3]; +#if LWIP_IPV6 + u32_t s2_data3[2]; #endif /* LWIP_IPV6 */ }; @@ -146,10 +167,12 @@ struct linger { #define PF_UNSPEC AF_UNSPEC #define IPPROTO_IP 0 +#define IPPROTO_ICMP 1 #define IPPROTO_TCP 6 #define IPPROTO_UDP 17 #if LWIP_IPV6 #define IPPROTO_IPV6 41 +#define IPPROTO_ICMPV6 58 #endif /* LWIP_IPV6 */ #define IPPROTO_UDPLITE 136 diff --git a/src/VBox/Devices/Network/lwip-new/vbox/VBoxLwipCore.cpp b/src/VBox/Devices/Network/lwip-new/vbox/VBoxLwipCore.cpp index db07f70c7..f848e7b9e 100644 --- a/src/VBox/Devices/Network/lwip-new/vbox/VBoxLwipCore.cpp +++ b/src/VBox/Devices/Network/lwip-new/vbox/VBoxLwipCore.cpp @@ -74,7 +74,7 @@ static DECLCALLBACK(void) lwipCoreUserCallback(void *pvArg) pUserClbk->pfn(pUserClbk->pvUser); /* wake up caller on EMT/main */ - lwip_sys_sem_signal(&g_LwipCore.LwipTcpIpSem); + sys_sem_signal(&g_LwipCore.LwipTcpIpSem); LogFlowFuncLeave(); } @@ -129,14 +129,14 @@ int vboxLwipCoreInitialize(PFNRT1 pfnCallback, void *pvCallbackArg) if (g_LwipCore.iLWIPInitiatorCounter == 0) { - lwipRc = lwip_sys_sem_new(&g_LwipCore.LwipTcpIpSem, 0); + lwipRc = sys_sem_new(&g_LwipCore.LwipTcpIpSem, 0); if (lwipRc != ERR_OK) { LogFlow(("%s: sys_sem_new error %d\n", __FUNCTION__, lwipRc)); goto done; } - lwip_tcpip_init(lwipCoreInitDone, &callback); + tcpip_init(lwipCoreInitDone, &callback); } else { @@ -148,7 +148,7 @@ int vboxLwipCoreInitialize(PFNRT1 pfnCallback, void *pvCallbackArg) } } - lwip_sys_sem_wait(&g_LwipCore.LwipTcpIpSem, 0); + sys_sem_wait(&g_LwipCore.LwipTcpIpSem); ++g_LwipCore.iLWIPInitiatorCounter; } done: @@ -211,7 +211,7 @@ void vboxLwipCoreFinalize(PFNRT1 pfnCallback, void *pvCallbackArg) } if (lwipRc == ERR_OK) - lwip_sys_sem_wait(&g_LwipCore.LwipTcpIpSem, 0); + sys_sem_wait(&g_LwipCore.LwipTcpIpSem); } LogFlowFuncLeave(); diff --git a/src/VBox/Devices/Network/lwip-new/vbox/include/lwip-log.h b/src/VBox/Devices/Network/lwip-new/vbox/include/lwip-log.h new file mode 100644 index 000000000..f66ca8de1 --- /dev/null +++ b/src/VBox/Devices/Network/lwip-new/vbox/include/lwip-log.h @@ -0,0 +1,93 @@ +/* -*- indent-tabs-mode: nil; -*- */ +#ifndef __VBOX_LWIP_LOG_H__ +#define __VBOX_LWIP_LOG_H__ + +#include + +#ifdef LWIP_DEBUG +/* + * All LWIP_DBG_* constants fit into a byte, so we use upper bits to + * encode the VBox log group. + * + * Mapping between FOO_DEBUG and LOG_GROUP_LWIP_FOO is straightforward + * except for IP4 where extra '4' was added to the group names to make + * it possible to specify lwip_ip4* instead of lwip_ip*, where the + * latter would enable both IP4 and IP6 logging. + * + * We ignore LWIP_DBG_STATE &c since in our scheme they would traslate + * into additional log groups and require combinatorial explosion. We + * probably can use LWIP_DBG_TYPES_ON for finer selection if need be + * (for internal debugging only, as it requires recompilation). + * + * Debug levels are mapped to RT debug levels so lwip's default level + * ends up as RT's level4. Non-default levels are currently not used + * much in lwip sources, so enable l4 to get the logs. + */ + +#define LWIP_DEBUGF_LOG_GROUP_SHIFT 8 +#define LWIP_DEBUGF_LOG_GROUP(_g) \ + (((_g) << LWIP_DEBUGF_LOG_GROUP_SHIFT) | LWIP_DBG_ON) + +#define API_LIB_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_API_LIB) +#define API_MSG_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_API_MSG) +#define ETHARP_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_ETHARP) +#define ICMP_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_ICMP) +#define IGMP_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_IGMP) +#define INET_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_INET) +#define IP_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_IP4) +#define IP_REASS_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_IP4_REASS) +#define IP6_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_IP6) +#define MEM_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_MEM) +#define MEMP_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_MEMP) +#define NETIF_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_NETIF) +#define PBUF_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_PBUF) +#define RAW_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_RAW) +#define SOCKETS_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_SOCKETS) +#define SYS_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_SYS) +#define TCP_CWND_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_TCP_CWND) +#define TCP_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_TCP) +#define TCP_FR_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_TCP_FR) +#define TCP_INPUT_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_TCP_INPUT) +#define TCP_OUTPUT_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_TCP_OUTPUT) +#define TCP_QLEN_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_TCP_QLEN) +#define TCP_RST_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_TCP_RST) +#define TCP_RTO_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_TCP_RTO) +#define TCP_WND_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_TCP_WND) +#define TCPIP_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_TCPIP) +#define TIMERS_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_TIMERS) +#define UDP_DEBUG LWIP_DEBUGF_LOG_GROUP(LOG_GROUP_LWIP_UDP) + +/* + * The following symbols are for debugging of modules that are not + * compiled in. They are listed here for reference but there're no + * log groups defined for them currently. + */ +#undef AUTOIP_DEBUG +#undef DHCP_DEBUG +#undef DNS_DEBUG +#undef PPP_DEBUG +#undef SLIP_DEBUG +#undef SNMP_MIB_DEBUG +#undef SNMP_MSG_DEBUG + +#ifdef LOG_ENABLED + +#define LWIP_DEBUGF(_when, _args) \ + do { \ + const VBOX_LOGGROUP _group = (_when) >> LWIP_DEBUGF_LOG_GROUP_SHIFT; \ + if (_group >= LOG_GROUP_DEFAULT) { \ + /* severe => l1; serious => l2; warning => l3; default => l4 */ \ + const unsigned int _level = \ + 1 << (LWIP_DBG_MASK_LEVEL+1 - ((_when) & LWIP_DBG_MASK_LEVEL)); \ + LogIt(LOG_INSTANCE, _level, _group, _args); \ + } \ + } while (0) + +#else /* !LOG_ENABLED */ + +#define LWIP_DEBUGF(_when, _args) do { } while (0) + +#endif /* !LOG_ENABLED */ + +#endif /* LWIP_DEBUG */ +#endif /* __VBOX_LWIP_LOG_H__ */ diff --git a/src/VBox/Devices/Network/lwip-new/vbox/include/lwip-namespace.h b/src/VBox/Devices/Network/lwip-new/vbox/include/lwip-namespace.h index f5e3f35f0..41c0ffeda 100644 --- a/src/VBox/Devices/Network/lwip-new/vbox/include/lwip-namespace.h +++ b/src/VBox/Devices/Network/lwip-new/vbox/include/lwip-namespace.h @@ -88,11 +88,14 @@ #define netif_set_netmask lwip_netif_set_netmask #define netif_set_up lwip_netif_set_up #if MEM_LIBC_MALLOC == 0 -#define mem_free lwip_mem_free +#if MEM_USE_POOLS == 0 #define mem_init lwip_mem_init +#define mem_trim lwip_mem_trim +#endif /* !MEM_USE_POOLS */ #define mem_malloc lwip_mem_malloc -#define mem_realloc lwip_mem_realloc -#endif +#define mem_calloc lwip_mem_calloc +#define mem_free lwip_mem_free +#endif /* !MEM_LIBC_MALLOC */ #define memp_free lwip_memp_free #define memp_init lwip_memp_init #define memp_malloc lwip_memp_malloc @@ -147,7 +150,7 @@ #define sys_sem_free lwip_sys_sem_free #define sys_sem_new lwip_sys_sem_new #define sys_sem_signal lwip_sys_sem_signal -#define lwip_sys_sem_wait lwip_sys_arch_sem_wait +#define lwip_sys_sem_wait sys_sem_wait #define sys_arch_sem_wait lwip_sys_arch_sem_wait #endif #define sys_timeout_debug lwip_sys_timeout_debug @@ -221,19 +224,4 @@ #define lwip_pbuf_init() #define lwip_etharp_init() -#ifndef htons -# define htons lwip_htons -#endif - -#ifndef ntohs -# define ntohs lwip_ntohs -#endif - -#ifndef htonl -# define htonl lwip_htonl -#endif - -#ifndef ntohl -# define ntohl lwip_ntohl -#endif #endif /* _VBOX_LWIP_NAMESPACE_H_ */ diff --git a/src/VBox/Devices/Network/lwip-new/vbox/include/lwipopts.h b/src/VBox/Devices/Network/lwip-new/vbox/include/lwipopts.h deleted file mode 100644 index befb1d2d3..000000000 --- a/src/VBox/Devices/Network/lwip-new/vbox/include/lwipopts.h +++ /dev/null @@ -1,222 +0,0 @@ -#ifndef VBOX_LWIP_OPTS_H_ -#define VBOX_LWIP_OPTS_H_ - -#include -#include /* This may include malloc.h (msc), which is something that has - * to be done before redefining any of the functions therein. */ -#include /* see LWIP_RAND() definition */ - -/* lwip/sockets.h assumes that if FD_SET is defined (in case of Innotek GCC - * its definition is dragged through iprt/types.h) then struct timeval is - * defined as well, but it's not the case. So include it manually. */ -#ifdef RT_OS_OS2 -# include -#endif - -/** Make lwIP use the libc malloc, or more precisely (see below) the IPRT - * memory allocation functions. */ -#define MEM_LIBC_MALLOC 1 - -/** Set proper memory alignment. */ -#if HC_ARCH_BITS == 64 -# define MEM_ALIGNMENT 8 -#else -#define MEM_ALIGNMENT 4 -#endif - -/* IP */ -#define IP_REASSEMBLY 1 -#define IP_REASS_MAX_PBUFS 128 - - - -/** Increase maximum TCP window size. */ -#define TCP_WND 32768 - -/** Increase TCP maximum segment size. */ -#define TCP_MSS 1460 - -/** Enable queueing of out-of-order segments. */ -#define TCP_QUEUE_OOSEQ 1 - -/** TCP sender buffer space (bytes). */ -#define TCP_SND_BUF (32 * TCP_MSS) - -/* TCP sender buffer space (pbufs). This must be at least = 2 * - TCP_SND_BUF/TCP_MSS for things to work. */ -#define TCP_SND_QUEUELEN 64 - -/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application - sends a lot of data out of ROM (or other static memory), this - should be set high. - - NB: This is for PBUF_ROM and PBUF_REF pbufs only! - - Number of PBUF_POOL pbufs is controlled by PBUF_POOL_SIZE that, - somewhat confusingly, breaks MEMP_NUM_* pattern. - - PBUF_RAM pbufs are allocated with mem_malloc (with MEM_LIBC_MALLOC - set to 1 this is just system malloc), not memp_malloc. */ -#define MEMP_NUM_PBUF (1024 * 4) - - -/* MEMP_NUM_MLD6_GROUP: Maximum number of IPv6 multicast groups that - can be joined. - - We need to be able to join solicited node multicast for each - address (potentially different) and two groups for DHCP6. All - routers multicast is hardcoded in ip6.c and does not require - explicit joining. Provide also for a few extra groups just in - case. */ -#define MEMP_NUM_MLD6_GROUP (LWIP_IPV6_NUM_ADDRESSES + /* dhcp6 */ 2 + /* extra */ 8) - - -/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP - segments. */ -#define MEMP_NUM_TCP_SEG (MEMP_NUM_TCP_PCB * TCP_SND_QUEUELEN / 2) - -/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP - connections. */ -#define MEMP_NUM_TCP_PCB 128 - -/* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used - for sequential API communication and incoming packets. Used in - src/api/tcpip.c. */ -#define MEMP_NUM_TCPIP_MSG_API 128 -#define MEMP_NUM_TCPIP_MSG_INPKT 1024 - -/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One - per active UDP "connection". */ -#define MEMP_NUM_UDP_PCB 32 - -/* Pbuf options */ -/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. - This is only for PBUF_POOL pbufs, primarily used by netif drivers. - - This should have been named with the MEMP_NUM_ prefix (cf. - MEMP_NUM_PBUF for PBUF_ROM and PBUF_REF) as it controls the size of - yet another memp_malloc() pool. */ -#define PBUF_POOL_SIZE (1024 * 4) - -/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. - Use default that is based on TCP_MSS and PBUF_LINK_HLEN. */ -#undef PBUF_POOL_BUFSIZE - -/** Turn on support for lightweight critical region protection. Leaving this - * off uses synchronization code in pbuf.c which is totally polluted with - * races. All the other lwip source files would fall back to semaphore-based - * synchronization, but pbuf.c is just broken, leading to incorrect allocation - * and as a result to assertions due to buffers being double freed. */ -#define SYS_LIGHTWEIGHT_PROT 1 - -/** Attempt to get rid of htons etc. macro issues. */ -#define LWIP_PREFIX_BYTEORDER_FUNCS - -#define LWIP_NOASSERT 0 - -#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 -#define LWIP_TCPIP_CORE_LOCKING 0 -#define LWIP_TCP 1 -#define LWIP_SOCKET 1 -#define LWIP_ARP 1 -#define ARP_PROXY 1 -#define LWIP_ETHERNET 1 -#define LWIP_COMPAT_SOCKETS 0 -#define LWIP_COMPAT_MUTEX 1 - -#define LWIP_IPV6 1 -#define LWIP_IPV6_FORWARD 1 -#define LWIP_ND6_PROXY 1 - -#define LWIP_ND6_ALLOW_RA_UPDATES (!LWIP_IPV6_FORWARD) -#define LWIP_IPV6_SEND_ROUTER_SOLICIT (!LWIP_IPV6_FORWARD) -/* IPv6 autoconfig we don't need in proxy, but it required for very seldom cases - * iSCSI over intnet with IPv6 - */ -#define LWIP_IPV6_AUTOCONFIG 1 -#if LWIP_IPV6_FORWARD /* otherwise use the default from lwip/opt.h */ -#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 0 -#endif - -#define LWIP_IPV6_FRAG 1 - -/** - * aka Slirp mode. - */ -#define LWIP_CONNECTION_PROXY 1 -#define IP_FORWARD 1 - -/* MEMP_NUM_SYS_TIMEOUT: the number of simultaneously active - timeouts. */ -#define MEMP_NUM_SYS_TIMEOUT 16 - - -/* this is required for IPv6 and IGMP needs */ -#define LWIP_RAND() RTRandU32() - -/* Debugging stuff. */ -#ifdef DEBUG -/* filter in debugging severity */ -# define DBG_TYPES_ON (LWIP_DBG_ON | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_FRESH | LWIP_DBG_HALT) -# define DBG_MIN_LEVEL 0 - -# define LWIP_DEBUG LWIP_DBG_ON -/* Ethernet & ARP debugging */ -# define ETHARP_DEBUG LWIP_DBG_ON -/* IPv4 debugging */ -# define IP_DEBUG LWIP_DBG_ON -# define IP_REASS_DEBUG LWIP_DBG_ON -/* IPv6 debugging */ -# define IP6_DEBUG LWIP_DBG_ON -/* ICMP debugging */ -# define ICMP_DEBUG LWIP_DBG_ON -/* TCP debugging */ -# define TCP_DEBUG LWIP_DBG_ON -# define TCP_INPUT_DEBUG LWIP_DBG_ON -# define TCP_FR_DEBUG LWIP_DBG_ON -# define TCP_RTO_DEBUG LWIP_DBG_ON -# define TCP_CWND_DEBUG LWIP_DBG_ON -# define TCP_WND_DEBUG LWIP_DBG_ON -# define TCP_OUTPUT_DEBUG LWIP_DBG_ON -# define TCP_RST_DEBUG LWIP_DBG_ON -# define TCP_QLEN_DEBUG LWIP_DBG_ON -/* RAW API debugging */ -/* API debugging */ -# define NETIF_DEBUG LWIP_DBG_ON -# define PBUF_DEBUG LWIP_DBG_ON -# define API_LIB_DEBUG LWIP_DBG_ON -# define API_MSG_DEBUG LWIP_DBG_ON -# define SOCKETS_DEBUG LWIP_DBG_ON - -# define INET_DEBUG LWIP_DBG_ON -# define RAW_DEBUG LWIP_DBG_ON -# define MEM_DEBUG LWIP_DBG_ON -# define MEMP_DEBUG LWIP_DBG_ON -# define SYS_DEBUG LWIP_DBG_ON - -# define UDP_DEBUG LWIP_DBG_ON -# define TCPIP_DEBUG LWIP_DBG_ON -# define DHCP_DEBUG LWIP_DBG_ON - -# define LWIP_PROXY_DEBUG LWIP_DBG_ON -/* Debug checks */ -# define TCP_OVERSIZE_DBGCHECK 1 -#endif /* DEBUG */ - -/* printf formatter definitions */ -#define U16_F "hu" -#define S16_F "hd" -#define X16_F "hx" -#define U32_F "lu" -#define S32_F "ld" -#define X32_F "lx" - -/* Redirect libc memory alloc functions to IPRT. */ -#define malloc(x) RTMemAlloc(x) -#define realloc(x,y) RTMemRealloc((x), (y)) -#define free(x) RTMemFree(x) - - -#include "lwip-namespace.h" - -#endif diff --git a/src/VBox/Devices/Network/lwipopts.h b/src/VBox/Devices/Network/lwipopts.h new file mode 100644 index 000000000..bc7193168 --- /dev/null +++ b/src/VBox/Devices/Network/lwipopts.h @@ -0,0 +1,177 @@ +#ifndef VBOX_LWIP_OPTS_H_ +#define VBOX_LWIP_OPTS_H_ + +#include +#include /* This may include malloc.h (msc), which is something that has + * to be done before redefining any of the functions therein. */ +#include /* see LWIP_RAND() definition */ + +/* lwip/sockets.h assumes that if FD_SET is defined (in case of Innotek GCC + * its definition is dragged through iprt/types.h) then struct timeval is + * defined as well, but it's not the case. So include it manually. */ +#ifdef RT_OS_OS2 +# include +#endif + +/** Make lwIP use the libc malloc, or more precisely (see below) the IPRT + * memory allocation functions. */ +#define MEM_LIBC_MALLOC 1 + +/** Set proper memory alignment. */ +#if HC_ARCH_BITS == 64 +# define MEM_ALIGNMENT 8 +#else +#define MEM_ALIGNMENT 4 +#endif + +/* IP */ +#define IP_REASSEMBLY 1 +#define IP_REASS_MAX_PBUFS 128 + + + +/** Increase maximum TCP window size. */ +#define TCP_WND 32768 + +/** Increase TCP maximum segment size. */ +#define TCP_MSS 1460 + +/** Enable queueing of out-of-order segments. */ +#define TCP_QUEUE_OOSEQ 1 + +/** TCP sender buffer space (bytes). */ +#define TCP_SND_BUF (32 * TCP_MSS) + +/* TCP sender buffer space (pbufs). This must be at least = 2 * + TCP_SND_BUF/TCP_MSS for things to work. */ +#define TCP_SND_QUEUELEN 64 + +/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application + sends a lot of data out of ROM (or other static memory), this + should be set high. + + NB: This is for PBUF_ROM and PBUF_REF pbufs only! + + Number of PBUF_POOL pbufs is controlled by PBUF_POOL_SIZE that, + somewhat confusingly, breaks MEMP_NUM_* pattern. + + PBUF_RAM pbufs are allocated with mem_malloc (with MEM_LIBC_MALLOC + set to 1 this is just system malloc), not memp_malloc. */ +#define MEMP_NUM_PBUF (1024 * 4) + + +/* MEMP_NUM_MLD6_GROUP: Maximum number of IPv6 multicast groups that + can be joined. + + We need to be able to join solicited node multicast for each + address (potentially different) and two groups for DHCP6. All + routers multicast is hardcoded in ip6.c and does not require + explicit joining. Provide also for a few extra groups just in + case. */ +#define MEMP_NUM_MLD6_GROUP (LWIP_IPV6_NUM_ADDRESSES + /* dhcp6 */ 2 + /* extra */ 8) + + +/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP + segments. */ +#define MEMP_NUM_TCP_SEG (MEMP_NUM_TCP_PCB * TCP_SND_QUEUELEN / 2) + +/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP + connections. */ +#define MEMP_NUM_TCP_PCB 128 + +/* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used + for sequential API communication and incoming packets. Used in + src/api/tcpip.c. */ +#define MEMP_NUM_TCPIP_MSG_API 128 +#define MEMP_NUM_TCPIP_MSG_INPKT 1024 + +/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + per active UDP "connection". */ +#define MEMP_NUM_UDP_PCB 32 + +/* Pbuf options */ +/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + This is only for PBUF_POOL pbufs, primarily used by netif drivers. + + This should have been named with the MEMP_NUM_ prefix (cf. + MEMP_NUM_PBUF for PBUF_ROM and PBUF_REF) as it controls the size of + yet another memp_malloc() pool. */ +#define PBUF_POOL_SIZE (1024 * 4) + +/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. + Use default that is based on TCP_MSS and PBUF_LINK_HLEN. */ +#undef PBUF_POOL_BUFSIZE + +/** Turn on support for lightweight critical region protection. Leaving this + * off uses synchronization code in pbuf.c which is totally polluted with + * races. All the other lwip source files would fall back to semaphore-based + * synchronization, but pbuf.c is just broken, leading to incorrect allocation + * and as a result to assertions due to buffers being double freed. */ +#define SYS_LIGHTWEIGHT_PROT 1 + +/** Attempt to get rid of htons etc. macro issues. */ +#undef LWIP_PREFIX_BYTEORDER_FUNCS + +#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 +#define LWIP_TCPIP_CORE_LOCKING 0 +#define LWIP_TCP 1 +#define LWIP_SOCKET 1 +#define LWIP_ARP 1 +#define ARP_PROXY 0 +#define LWIP_ETHERNET 1 +#define LWIP_COMPAT_SOCKETS 0 +#define LWIP_COMPAT_MUTEX 1 + +#define LWIP_IPV6 1 +#define LWIP_IPV6_FORWARD 0 +#define LWIP_ND6_PROXY 0 + +#define LWIP_ND6_ALLOW_RA_UPDATES (!LWIP_IPV6_FORWARD) +#define LWIP_IPV6_SEND_ROUTER_SOLICIT (!LWIP_IPV6_FORWARD) +/* IPv6 autoconfig we don't need in proxy, but it required for very seldom cases + * iSCSI over intnet with IPv6 + */ +#define LWIP_IPV6_AUTOCONFIG 1 +#if LWIP_IPV6_FORWARD /* otherwise use the default from lwip/opt.h */ +#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 0 +#endif + +#define LWIP_IPV6_FRAG 1 + +/** + * aka Slirp mode. + */ +#define LWIP_CONNECTION_PROXY 0 +#define IP_FORWARD 0 + +/* MEMP_NUM_SYS_TIMEOUT: the number of simultaneously active + timeouts. */ +#define MEMP_NUM_SYS_TIMEOUT 16 + + +/* this is required for IPv6 and IGMP needs */ +#define LWIP_RAND() RTRandU32() + +/* Debugging stuff. */ +#ifdef DEBUG +# define LWIP_DEBUG +# include "lwip-log.h" +#endif /* DEBUG */ + +/* printf formatter definitions */ +#define U16_F "hu" +#define S16_F "hd" +#define X16_F "hx" +#define U32_F "lu" +#define S32_F "ld" +#define X32_F "lx" + +/* Redirect libc memory alloc functions to IPRT. */ +#define malloc(x) RTMemAlloc(x) +#define realloc(x,y) RTMemRealloc((x), (y)) +#define free(x) RTMemFree(x) + + +#include "lwip-namespace.h" + +#endif diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.asm b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.asm index ef96042d3..068c36e71 100644 --- a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.asm +++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.asm @@ -965,7 +965,7 @@ section CONST progbits vstart=0xb0 align=1 ; size=0xcf8 class=DATA group=DGROUP section CONST2 progbits vstart=0xda8 align=1 ; size=0x3fa class=DATA group=DGROUP _bios_cvs_version_string: ; 0xf0da8 LB 0x12 - db 'VirtualBox 4.3.8', 000h, 000h + db 'VirtualBox 4.3.10', 000h _bios_prefix_string: ; 0xf0dba LB 0x8 db 'BIOS: ', 000h, 000h _isotag: ; 0xf0dc2 LB 0x6 @@ -16025,4 +16025,4 @@ dummy_iret: ; 0xfff53 LB 0x9d db 'XM' cpu_reset: ; 0xffff0 LB 0x10 jmp far 0f000h:0e05bh ; ea 5b e0 00 f0 - db 030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fch, 04fh + db 030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fch, 026h diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.md5sum b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.md5sum index d8860acb9..3de91992c 100644 --- a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.md5sum +++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.md5sum @@ -1 +1 @@ -57043783b40423d82ef1605eae6b1822 *VBoxPcBios.rom +bb8dc7f1c69895d10cad2dadc4306b6d *VBoxPcBios.rom diff --git a/src/VBox/Devices/Storage/DrvHostBase.cpp b/src/VBox/Devices/Storage/DrvHostBase.cpp index cca91d27a..5c588f20e 100644 --- a/src/VBox/Devices/Storage/DrvHostBase.cpp +++ b/src/VBox/Devices/Storage/DrvHostBase.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2011 Oracle Corporation + * Copyright (C) 2006-2014 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -872,7 +872,7 @@ static int drvHostBaseOpen(PDRVHOSTBASE pThis, PRTFILE pFileDevice, bool fReadOn else { strcpy(szName1, *pszVendor ? pszVendor : pszProduct); - RTStrPrintf(szName2, sizeof(szName2), "%s %s (#%u)", *pszVendor ? pszVendor : pszProduct, i); + RTStrPrintf(szName2, sizeof(szName2), "%s (#%u)", *pszVendor ? pszVendor : pszProduct, i); } } else diff --git a/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp b/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp index 8ee189c27..ca942b1e1 100644 --- a/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp +++ b/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp @@ -515,6 +515,9 @@ int vmmdevHGCMConnect (PVMMDEV pThis, VMMDevHGCMConnect *pHGCMConnect, RTGCPHYS pHGCMConnectCopy->loc.type = VMMDevHGCMLoc_LocalHost_Existing; rc = pThis->pHGCMDrv->pfnConnect (pThis->pHGCMDrv, pCmd, &pHGCMConnectCopy->loc, &pHGCMConnectCopy->u32ClientID); + + if (RT_FAILURE(rc)) + vmmdevHGCMRemoveCommand(pThis, pCmd); } else { @@ -554,6 +557,8 @@ static int vmmdevHGCMConnectSaved (PVMMDEV pThis, VMMDevHGCMConnect *pHGCMConnec { *pfHGCMCalled = true; } + /* else + * ... the caller will also execute vmmdevHGCMRemoveCommand() for us */ } else { @@ -580,6 +585,9 @@ int vmmdevHGCMDisconnect (PVMMDEV pThis, VMMDevHGCMDisconnect *pHGCMDisconnect, pCmd->paLinPtrs = NULL; rc = pThis->pHGCMDrv->pfnDisconnect (pThis->pHGCMDrv, pCmd, pHGCMDisconnect->u32ClientID); + + if (RT_FAILURE(rc)) + vmmdevHGCMRemoveCommand(pThis, pCmd); } else { @@ -614,6 +622,8 @@ static int vmmdevHGCMDisconnectSaved (PVMMDEV pThis, VMMDevHGCMDisconnect *pHGCM { *pfHGCMCalled = true; } + /* else + * ... the caller will also execute vmmdevHGCMRemoveCommand() for us */ } else { @@ -1735,6 +1745,8 @@ static int vmmdevHGCMCallSaved (PVMMDEV pThis, VMMDevHGCMCall *pHGCMCall, RTGCPH { *pfHGCMCalled = true; } + /* else + * ... the caller will also execute vmmdevHGCMRemoveCommand() for us */ } return rc; diff --git a/src/VBox/Frontends/VirtualBox/src/globals/UIExtraDataEventHandler.cpp b/src/VBox/Frontends/VirtualBox/src/globals/UIExtraDataEventHandler.cpp index 60d63aa5e..5128b76a4 100644 --- a/src/VBox/Frontends/VirtualBox/src/globals/UIExtraDataEventHandler.cpp +++ b/src/VBox/Frontends/VirtualBox/src/globals/UIExtraDataEventHandler.cpp @@ -95,9 +95,20 @@ public slots: Assert(!!vboxGlobal().settings()); } } -#ifdef Q_WS_MAC else if (vboxGlobal().isVMConsoleProcess()) { + /* Take care about HID LEDs sync */ + if (strKey == GUI_HidLedsSync) + { + /* If extra data GUI/HidLedsSync is not present in VM config or set + * to 1 then sync is enabled. Otherwise, it is disabled. */ + + /* (temporary disabled by default) */ + bool f = (strValue == "1") ? true : false; + emit sigHidLedsSyncStateChanged(f); + } + +#ifdef Q_WS_MAC /* Check for the currently running machine */ if (strId == vboxGlobal().managedVMUuid()) { @@ -108,8 +119,8 @@ public slots: emit sigDockIconAppearanceChange(f); } } - } #endif /* Q_WS_MAC */ + } } signals: @@ -117,6 +128,7 @@ signals: void sigGUILanguageChange(QString strLang); void sigSelectorShortcutsChanged(); void sigMachineShortcutsChanged(); + void sigHidLedsSyncStateChanged(bool fEnabled); #ifdef RT_OS_DARWIN void sigPresentationModeChange(bool fEnabled); void sigDockIconAppearanceChange(bool fEnabled); @@ -190,6 +202,10 @@ UIExtraDataEventHandler::UIExtraDataEventHandler() this, SIGNAL(sigMachineShortcutsChanged()), Qt::QueuedConnection); + connect(m_pHandler, SIGNAL(sigHidLedsSyncStateChanged(bool)), + this, SIGNAL(sigHidLedsSyncStateChanged(bool)), + Qt::QueuedConnection); + #ifdef Q_WS_MAC connect(m_pHandler, SIGNAL(sigPresentationModeChange(bool)), this, SIGNAL(sigPresentationModeChange(bool)), diff --git a/src/VBox/Frontends/VirtualBox/src/globals/UIExtraDataEventHandler.h b/src/VBox/Frontends/VirtualBox/src/globals/UIExtraDataEventHandler.h index 99a3df234..92a035a1d 100644 --- a/src/VBox/Frontends/VirtualBox/src/globals/UIExtraDataEventHandler.h +++ b/src/VBox/Frontends/VirtualBox/src/globals/UIExtraDataEventHandler.h @@ -38,6 +38,7 @@ signals: void sigGUILanguageChange(QString strLang); void sigSelectorShortcutsChanged(); void sigMachineShortcutsChanged(); + void sigHidLedsSyncStateChanged(bool fEnabled); #ifdef RT_OS_DARWIN void sigPresentationModeChange(bool fEnabled); void sigDockIconAppearanceChange(bool fEnabled); diff --git a/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.h b/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.h index c9b785a0e..e11f5366e 100644 --- a/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.h +++ b/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.h @@ -17,9 +17,19 @@ #ifndef ___darwin_VBoxCocoaApplication_h #define ___darwin_VBoxCocoaApplication_h +/* Qt includes: */ +#include + +/* GUI includes: */ #include "VBoxCocoaHelper.h" + ADD_COCOA_NATIVE_REF(UICocoaApplicationPrivate); ADD_COCOA_NATIVE_REF(NSAutoreleasePool); +ADD_COCOA_NATIVE_REF(NSString); +ADD_COCOA_NATIVE_REF(NSWindow); + +/* Forward declarations: */ +class QWidget; /** Event handler callback. * @returns true if handled, false if not. @@ -29,6 +39,9 @@ ADD_COCOA_NATIVE_REF(NSAutoreleasePool); */ typedef bool (*PFNVBOXCACALLBACK)(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser); +/** Native notification callback type for QWidget. */ +typedef void (*PfnNativeNotificationCallbackForQWidget)(const QString &strNativeNotificationName, QWidget *pWidget); + /* C++ singleton for our private NSApplication object */ class UICocoaApplication { @@ -39,11 +52,21 @@ public: void registerForNativeEvents(uint32_t fMask, PFNVBOXCACALLBACK pfnCallback, void *pvUser); void unregisterForNativeEvents(uint32_t fMask, PFNVBOXCACALLBACK pfnCallback, void *pvUser); + /** Register passed @a pWidget to native notification @a strNativeNotificationName, using @a pCallback as handler. */ + void registerToNativeNotification(const QString &strNativeNotificationName, QWidget *pWidget, PfnNativeNotificationCallbackForQWidget pCallback); + /** Unregister passed @a pWidget from native notification @a strNativeNotificationName. */ + void unregisterFromNativeNotification(const QString &strNativeNotificationName, QWidget *pWidget); + /** Redirects native notification @a pstrNativeNotificationName for window @a pWindow to registered listener. */ + void nativeNotificationProxy(NativeNSStringRef pstrNativeNotificationName, NativeNSWindowRef pWindow); + private: UICocoaApplication(); static UICocoaApplication *m_pInstance; NativeUICocoaApplicationPrivateRef m_pNative; NativeNSAutoreleasePoolRef m_pPool; + + /** Map of notification callbacks registered for corresponding QWidget(s). */ + QMap > m_callbacks; }; #endif /* ___darwin_VBoxCocoaApplication_h */ diff --git a/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.mm b/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.mm index c45147102..994e747e4 100644 --- a/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.mm +++ b/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.mm @@ -15,7 +15,7 @@ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. */ -/* Local includes */ +/* GUI includes: */ #include "UICocoaApplication.h" #include "VBoxUtils-darwin.h" @@ -67,6 +67,10 @@ - (void)sendEvent:(NSEvent *)theEvent; - (void)setCallback:(uint32_t)fMask :(PFNVBOXCACALLBACK)pfnCallback :(void *)pvUser; - (void)unsetCallback:(uint32_t)fMask :(PFNVBOXCACALLBACK)pfnCallback :(void *)pvUser; + +- (void)registerToNotification :(NSString*)pstrNotificationName :(NSWindow*)pWindow; +- (void)unregisterFromNotification :(NSString*)pstrNotificationName :(NSWindow*)pWindow; +- (void)notificationCallback :(NSNotification*)notification; @end /* @interface UICocoaApplicationPrivate */ @implementation UICocoaApplicationPrivate @@ -159,6 +163,45 @@ fNewMask |= pData->fMask; m_fMask = fNewMask; } + +/** Register @a pWindow to cocoa notification @a pstrNotificationName. */ +- (void) registerToNotification :(NSString*)pstrNotificationName :(NSWindow*)pWindow +{ + /* Register notification observer: */ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(notificationCallback:) + name:pstrNotificationName + object:pWindow]; +} + +/** Unregister @a pWindow from cocoa notification @a pstrNotificationName. */ +- (void) unregisterFromNotification :(NSString*)pstrNotificationName :(NSWindow*)pWindow +{ + /* Uninstall notification observer: */ + [[NSNotificationCenter defaultCenter] removeObserver:self + name:pstrNotificationName + object:pWindow]; +} + +/** Redirects cocoa @a notification to UICocoaApplication instance. */ +- (void) notificationCallback :(NSNotification*)notification +{ + /* Get current notification name: */ + NSString *pstrName = [notification name]; + + /* Define known notification names: */ + NSString *spstrWillEnterFullscreenNotification = @"NSWindowWillEnterFullScreenNotification"; + NSString *spstrDidEnterFullscreenNotification = @"NSWindowDidEnterFullScreenNotification"; + NSString *spstrWillExitFullscreenNotification = @"NSWindowWillExitFullScreenNotification"; + NSString *spstrDidExitFullscreenNotification = @"NSWindowDidExitFullScreenNotification"; + + /* Redirect known notifications to UICocoaApplication instance: */ + if ( [pstrName isEqualToString :spstrWillEnterFullscreenNotification] + || [pstrName isEqualToString :spstrDidEnterFullscreenNotification] + || [pstrName isEqualToString :spstrWillExitFullscreenNotification] + || [pstrName isEqualToString :spstrDidExitFullscreenNotification]) + UICocoaApplication::instance()->nativeNotificationProxy(pstrName, [notification object]); +} @end /* @implementation UICocoaApplicationPrivate */ /* C++ singleton for our private NSApplication object */ @@ -200,3 +243,52 @@ void UICocoaApplication::unregisterForNativeEvents(uint32_t fMask, PFNVBOXCACALL [m_pNative unsetCallback:fMask :pfnCallback :pvUser]; } +void UICocoaApplication::registerToNativeNotification(const QString &strNativeNotificationName, QWidget *pWidget, PfnNativeNotificationCallbackForQWidget pCallback) +{ + /* Make sure it is not registered yet: */ + AssertReturnVoid(!m_callbacks.contains(pWidget) || !m_callbacks[pWidget].contains(strNativeNotificationName)); + + /* Remember callback: */ + m_callbacks[pWidget][strNativeNotificationName] = pCallback; + + /* Register observer: */ + NativeNSStringRef pstrNativeNotificationName = darwinToNativeString(strNativeNotificationName.toLatin1().constData()); + NativeNSWindowRef pWindow = darwinToNativeWindow(pWidget); + [m_pNative registerToNotification :pstrNativeNotificationName :pWindow]; +} + +void UICocoaApplication::unregisterFromNativeNotification(const QString &strNativeNotificationName, QWidget *pWidget) +{ + /* Make sure it is registered yet: */ + AssertReturnVoid(m_callbacks.contains(pWidget) && m_callbacks[pWidget].contains(strNativeNotificationName)); + + /* Forget callback: */ + m_callbacks[pWidget].remove(strNativeNotificationName); + if (m_callbacks[pWidget].isEmpty()) + m_callbacks.remove(pWidget); + + /* Unregister observer: */ + NativeNSStringRef pstrNativeNotificationName = darwinToNativeString(strNativeNotificationName.toLatin1().constData()); + NativeNSWindowRef pWindow = darwinToNativeWindow(pWidget); + [m_pNative unregisterFromNotification :pstrNativeNotificationName :pWindow]; +} + +void UICocoaApplication::nativeNotificationProxy(NativeNSStringRef pstrNotificationName, NativeNSWindowRef pWindow) +{ + /* Get notification name: */ + QString strNotificationName = darwinFromNativeString(pstrNotificationName); + + /* Check if existing widget(s) have corresponding notification handler: */ + const QList &keys1 = m_callbacks.keys(); + for (int i = 0; i < keys1.size(); ++i) + { + QWidget *pWidget = keys1[i]; + if (darwinToNativeWindow(pWidget) == pWindow) + { + const QMap &callbacks = m_callbacks[pWidget]; + if (callbacks.contains(strNotificationName)) + callbacks[strNotificationName](strNotificationName, pWidget); + } + } +} + diff --git a/src/VBox/Frontends/VirtualBox/src/platform/darwin/VBoxUtils-darwin-cocoa.mm b/src/VBox/Frontends/VirtualBox/src/platform/darwin/VBoxUtils-darwin-cocoa.mm index f34c19717..6ce8db863 100644 --- a/src/VBox/Frontends/VirtualBox/src/platform/darwin/VBoxUtils-darwin-cocoa.mm +++ b/src/VBox/Frontends/VirtualBox/src/platform/darwin/VBoxUtils-darwin-cocoa.mm @@ -35,6 +35,10 @@ #include #include "DarwinKeyboard.h" +/** Easy way of dynamical call for 10.7 AppKit functionality we do not yet support. */ +#define NSWindowCollectionBehaviorFullScreenPrimary (1 << 7) +#define NSFullScreenWindowMask (1 << 14) + NativeNSWindowRef darwinToNativeWindowImpl(NativeNSViewRef pView) { NativeNSWindowRef window = NULL; @@ -92,6 +96,11 @@ NativeNSStringRef darwinToNativeString(const char* pcszString) return [NSString stringWithUTF8String: pcszString]; } +QString darwinFromNativeString(NativeNSStringRef pString) +{ + return [pString cStringUsingEncoding :NSASCIIStringEncoding]; +} + void darwinSetShowsToolbarButtonImpl(NativeNSWindowRef pWindow, bool fEnabled) { [pWindow setShowsToolbarButton:fEnabled]; @@ -176,6 +185,40 @@ void darwinMinaturizeWindow(NativeNSWindowRef pWindow) // [pWindow performMiniaturize:nil]; } +void darwinEnableFullscreenSupport(NativeNSWindowRef pWindow) +{ + [pWindow setCollectionBehavior :NSWindowCollectionBehaviorFullScreenPrimary]; +} + +void darwinEnableTransienceSupport(NativeNSWindowRef pWindow) +{ + [pWindow setCollectionBehavior :NSWindowCollectionBehaviorTransient]; +} + +void darwinToggleFullscreenMode(NativeNSWindowRef pWindow) +{ + /* Toggle native fullscreen mode for passed pWindow. This method is available since 10.7 only. + * To automatically sync this method subsequent calls we performing it on the main (GUI) thread. */ + if ([pWindow respondsToSelector: @selector(toggleFullScreen:)]) + [pWindow performSelectorOnMainThread: @selector(toggleFullScreen:) withObject: (id)nil waitUntilDone :NO]; +} + +bool darwinIsInFullscreenMode(NativeNSWindowRef pWindow) +{ + /* Check whether passed pWindow is in native fullscreen mode. */ + return [pWindow styleMask] & NSFullScreenWindowMask; +} + +bool darwinScreensHaveSeparateSpaces() +{ + /* Check whether screens have separate spaces. + * This method is available since 10.9 only. */ + if ([NSScreen respondsToSelector: @selector(screensHaveSeparateSpaces)]) + return [NSScreen performSelector: @selector(screensHaveSeparateSpaces)]; + else + return false; +} + void darwinSetDockIconMenu(QMenu* pMenu) { extern void qt_mac_set_dock_menu(QMenu *); diff --git a/src/VBox/Frontends/VirtualBox/src/platform/darwin/VBoxUtils-darwin.cpp b/src/VBox/Frontends/VirtualBox/src/platform/darwin/VBoxUtils-darwin.cpp index 1fe642432..a7aa965f6 100644 --- a/src/VBox/Frontends/VirtualBox/src/platform/darwin/VBoxUtils-darwin.cpp +++ b/src/VBox/Frontends/VirtualBox/src/platform/darwin/VBoxUtils-darwin.cpp @@ -138,6 +138,26 @@ void darwinMinaturizeWindow(QWidget *pWidget) return ::darwinMinaturizeWindow(::darwinToNativeWindow(pWidget)); } +void darwinEnableFullscreenSupport(QWidget *pWidget) +{ + return ::darwinEnableFullscreenSupport(::darwinToNativeWindow(pWidget)); +} + +void darwinEnableTransienceSupport(QWidget *pWidget) +{ + return ::darwinEnableTransienceSupport(::darwinToNativeWindow(pWidget)); +} + +void darwinToggleFullscreenMode(QWidget *pWidget) +{ + return ::darwinToggleFullscreenMode(::darwinToNativeWindow(pWidget)); +} + +bool darwinIsInFullscreenMode(QWidget *pWidget) +{ + return ::darwinIsInFullscreenMode(::darwinToNativeWindow(pWidget)); +} + void darwinInstallResizeDelegate(QWidget *pWidget) { ::darwinInstallResizeDelegate(::darwinToNativeWindow(pWidget)); diff --git a/src/VBox/Frontends/VirtualBox/src/platform/darwin/VBoxUtils-darwin.h b/src/VBox/Frontends/VirtualBox/src/platform/darwin/VBoxUtils-darwin.h index 3798cf8b4..ed75cd2db 100644 --- a/src/VBox/Frontends/VirtualBox/src/platform/darwin/VBoxUtils-darwin.h +++ b/src/VBox/Frontends/VirtualBox/src/platform/darwin/VBoxUtils-darwin.h @@ -49,6 +49,7 @@ RT_C_DECLS_BEGIN NativeNSWindowRef darwinToNativeWindowImpl(NativeNSViewRef pView); NativeNSViewRef darwinToNativeViewImpl(NativeNSWindowRef pWindow); NativeNSStringRef darwinToNativeString(const char* pcszString); +QString darwinFromNativeString(NativeNSStringRef pString); /******************************************************************************** * @@ -77,6 +78,11 @@ int darwinWindowToolBarHeight(NativeNSWindowRef pWindow); bool darwinIsToolbarVisible(NativeNSWindowRef pWindow); bool darwinIsWindowMaximized(NativeNSWindowRef pWindow); void darwinMinaturizeWindow(NativeNSWindowRef pWindow); +void darwinEnableFullscreenSupport(NativeNSWindowRef pWindow); +void darwinEnableTransienceSupport(NativeNSWindowRef pWindow); +void darwinToggleFullscreenMode(NativeNSWindowRef pWindow); +bool darwinIsInFullscreenMode(NativeNSWindowRef pWindow); +bool darwinScreensHaveSeparateSpaces(); bool darwinOpenFile(NativeNSStringRef pstrFile); @@ -238,6 +244,10 @@ int darwinWindowToolBarHeight(QWidget *pWidget); bool darwinIsToolbarVisible(QToolBar *pToolBar); bool darwinIsWindowMaximized(QWidget *pWidget); void darwinMinaturizeWindow(QWidget *pWidget); +void darwinEnableFullscreenSupport(QWidget *pWidget); +void darwinEnableTransienceSupport(QWidget *pWidget); +void darwinToggleFullscreenMode(QWidget *pWidget); +bool darwinIsInFullscreenMode(QWidget *pWidget); bool darwinOpenFile(const QString &strFile); QString darwinSystemLanguage(void); diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBuffer.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBuffer.cpp index d2c546eef..19e3babbe 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBuffer.cpp +++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBuffer.cpp @@ -283,6 +283,14 @@ STDMETHODIMP UIFrameBuffer::RequestResize(ULONG uScreenId, ULONG uPixelFormat, */ STDMETHODIMP UIFrameBuffer::NotifyUpdate(ULONG uX, ULONG uY, ULONG uWidth, ULONG uHeight) { + /* Retina screens with physical-to-logical scaling requires + * odd/even pixel updates to be taken into account, + * otherwise we have artifacts on the borders of incoming rectangle. */ + uX = qMax(0, (int)uX - 1); + uY = qMax(0, (int)uY - 1); + uWidth = qMin((int)m_width, (int)uWidth + 2); + uHeight = qMin((int)m_height, (int)uHeight + 2); + LogRel2(("UIFrameBuffer::NotifyUpdate: Origin=%lux%lu, Size=%lux%lu\n", (unsigned long)uX, (unsigned long)uY, (unsigned long)uWidth, (unsigned long)uHeight)); diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp index 968824127..670f6e4f4 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp +++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp @@ -1212,13 +1212,11 @@ bool UIKeyboardHandler::keyEventHandleNormal(int iKey, uint8_t uScan, int fFlags * we are updating the list of pressed keys and preparing scancodes: */ if ((fFlags & KeyPressed) || (m_pressedKeys[uScan] & uWhatPressed)) { - /* Check if the guest has the same view on the modifier keys - * (NumLock, CapsLock, ScrollLock) as the X server. - * If not, send KeyPress events to synchronize the state: */ -#if !defined(Q_WS_MAC) && !defined(Q_WS_WIN) - if (fFlags & KeyPressed) - fixModifierState(pCodes, puCodesCount); -#endif + /* If HID LEDs sync is disabled or not supported, check if the guest has the + * same view on the modifier keys (NumLock, CapsLock, ScrollLock) as the host. */ + if (!machineLogic()->isHidLedsSyncEnabled()) + if (fFlags & KeyPressed) + fixModifierState(pCodes, puCodesCount); /* Prepend 'extended' scancode if needed: */ if (fFlags & KeyExtended) diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachine.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachine.cpp index fb985cdc6..0e24a8690 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachine.cpp +++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachine.cpp @@ -22,9 +22,6 @@ #include "UIActionPoolRuntime.h" #include "UIMachineLogic.h" #include "UIMachineWindow.h" -#ifdef Q_WS_MAC -# include -#endif /* Q_WS_MAC */ /* Visual state interface: */ class UIVisualState : public QObject @@ -39,9 +36,6 @@ public: , m_type(type) , m_pSession(pSession) , m_pMachineLogic(0) -#ifdef Q_WS_MAC - , m_fadeToken(kCGDisplayFadeReservationInvalidToken) -#endif /* Q_WS_MAC */ { } @@ -65,26 +59,10 @@ public: UIMachineLogic* machineLogic() const { return m_pMachineLogic; } /* Method to prepare change one visual state to another: */ - bool prepareChange(UIVisualStateType previousVisualStateType) + bool prepareChange() { m_pMachineLogic = UIMachineLogic::create(this, m_pSession, visualStateType()); - bool fResult = m_pMachineLogic->checkAvailability(); -#ifdef Q_WS_MAC - /* If the new is or the old type was fullscreen we add the blending - * transition between the mode switches. - * TODO: make this more general. */ - if ( fResult - && ( visualStateType() == UIVisualStateType_Fullscreen - || previousVisualStateType == UIVisualStateType_Fullscreen)) - { - /* Fade to black */ - CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &m_fadeToken); - CGDisplayFade(m_fadeToken, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, true); - } -#else /* Q_WS_MAC */ - Q_UNUSED(previousVisualStateType); -#endif /* !Q_WS_MAC */ - return fResult; + return m_pMachineLogic->checkAvailability(); } /* Method to change one visual state to another: */ @@ -94,31 +72,12 @@ public: m_pMachineLogic->prepare(); } - /* Method to finish change one visual state to another: */ - void finishChange() - { -#ifdef Q_WS_MAC - /* If there is a valid fade token, fade back to normal color in any - * case. */ - if (m_fadeToken != kCGDisplayFadeReservationInvalidToken) - { - /* Fade back to the normal gamma */ - CGDisplayFade(m_fadeToken, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, false); - CGReleaseDisplayFadeReservation(m_fadeToken); - m_fadeToken = kCGDisplayFadeReservationInvalidToken; - } -#endif /* Q_WS_MAC */ - } - protected: /* Variables: */ UIVisualStateType m_type; UISession *m_pSession; UIMachineLogic *m_pMachineLogic; -#ifdef Q_WS_MAC - CGDisplayFadeReservationToken m_fadeToken; -#endif /* Q_WS_MAC */ }; UIMachine::UIMachine(UIMachine **ppSelf, const CSession &session) @@ -199,12 +158,9 @@ void UIMachine::sltChangeVisualState(UIVisualStateType newVisualStateType) /* Create new state: */ UIVisualState *pNewVisualState = new UIVisualState(this, m_pSession, newVisualStateType); - /* Get previous visual state type: */ - UIVisualStateType previousVisualStateType = m_pVisualState ? m_pVisualState->visualStateType() : UIVisualStateType_Normal; - /* First we have to check if the selected mode is available at all. * Only then we delete the old mode and switch to the new mode. */ - if (pNewVisualState->prepareChange(previousVisualStateType)) + if (pNewVisualState->prepareChange()) { /* Delete previous state: */ delete m_pVisualState; @@ -212,9 +168,6 @@ void UIMachine::sltChangeVisualState(UIVisualStateType newVisualStateType) /* Set the new mode as current mode: */ m_pVisualState = pNewVisualState; m_pVisualState->change(); - - /* Finish any setup: */ - m_pVisualState->finishChange(); } else { diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp index e7ced6db3..de3b11c9d 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp +++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp @@ -55,6 +55,7 @@ #include "UIConverter.h" #include "UIModalWindowManager.h" #include "UIMedium.h" +#include "UIExtraDataEventHandler.h" #ifdef Q_WS_MAC # include "DockIconPreview.h" # include "UIExtraDataEventHandler.h" @@ -398,6 +399,30 @@ void UIMachineLogic::notifyAbout3DOverlayVisibilityChange(bool fVisible) } } +void UIMachineLogic::sltChangeVisualStateToNormal() +{ + uisession()->setRequestedVisualState(UIVisualStateType_Invalid); + uisession()->changeVisualState(UIVisualStateType_Normal); +} + +void UIMachineLogic::sltChangeVisualStateToFullscreen() +{ + uisession()->setRequestedVisualState(UIVisualStateType_Invalid); + uisession()->changeVisualState(UIVisualStateType_Fullscreen); +} + +void UIMachineLogic::sltChangeVisualStateToSeamless() +{ + uisession()->setRequestedVisualState(UIVisualStateType_Invalid); + uisession()->changeVisualState(UIVisualStateType_Seamless); +} + +void UIMachineLogic::sltChangeVisualStateToScale() +{ + uisession()->setRequestedVisualState(UIVisualStateType_Invalid); + uisession()->changeVisualState(UIVisualStateType_Scale); +} + void UIMachineLogic::sltMachineStateChanged() { /* Get machine state: */ @@ -510,6 +535,11 @@ void UIMachineLogic::sltMouseCapabilityChanged() pAction->setChecked(false); } +void UIMachineLogic::sltHidLedsSyncStateChanged(bool fEnabled) +{ + m_isHidLedsSyncEnabled = fEnabled; +} + void UIMachineLogic::sltKeyboardLedsChanged() { /* Here we have to update host LED lock states using values provided by UISession: @@ -572,25 +602,29 @@ void UIMachineLogic::sltShowWindows() void UIMachineLogic::sltGuestMonitorChange(KGuestMonitorChangedEventType, ulong, QRect) { - /* Deliver event to all machine-windows: */ + LogRel(("UIMachineLogic: Guest-screen count changed.\n")); + + /* Make sure all machine-window(s) have proper geometry: */ foreach (UIMachineWindow *pMachineWindow, machineWindows()) - pMachineWindow->handleScreenCountChange(); + pMachineWindow->showInNecessaryMode(); } void UIMachineLogic::sltHostScreenCountChanged() { - /* Deliver event to all machine-windows: */ + LogRel(("UIMachineLogic: Host-screen count changed.\n")); + + /* Make sure all machine-window(s) have proper geometry: */ foreach (UIMachineWindow *pMachineWindow, machineWindows()) - pMachineWindow->handleScreenCountChange(); + pMachineWindow->showInNecessaryMode(); } void UIMachineLogic::sltHostScreenGeometryChanged() { - LogRelFlow(("UIMachineLogic: Host-screen geometry changed.\n")); + LogRel(("UIMachineLogic: Host-screen geometry changed.\n")); - /* Deliver event to all machine-windows: */ + /* Make sure all machine-window(s) have proper geometry: */ foreach (UIMachineWindow *pMachineWindow, machineWindows()) - pMachineWindow->handleScreenGeometryChange(); + pMachineWindow->showInNecessaryMode(); } UIMachineLogic::UIMachineLogic(QObject *pParent, UISession *pSession, UIVisualStateType visualStateType) @@ -618,7 +652,28 @@ UIMachineLogic::UIMachineLogic(QObject *pParent, UISession *pSession, UIVisualSt , m_DockIconPreviewMonitor(0) #endif /* Q_WS_MAC */ , m_pHostLedsState(NULL) + , m_isHidLedsSyncEnabled(false) { + /* Setup HID LEDs synchronization. */ +#if defined(Q_WS_MAC) || defined(Q_WS_WIN) + /* Read initial extradata value. */ + QString strHidLedsSyncSettings = session().GetMachine().GetExtraData(GUI_HidLedsSync); + + /* If extra data GUI/HidLedsSync is not present in VM config or set + * to 1 then sync is enabled. Otherwise, it is disabled. */ + + /* (temporary disabled by default) */ + if (strHidLedsSyncSettings == "1") + m_isHidLedsSyncEnabled = true; + else + m_isHidLedsSyncEnabled = false; + + /* Subscribe to GUI_HidLedsSync extradata changes in order to + * be able to enable or disable feature dynamically. */ + connect(gEDataEvents, SIGNAL(sigHidLedsSyncStateChanged(bool)), this, SLOT(sltHidLedsSyncStateChanged(bool))); +#else + m_isHidLedsSyncEnabled = false; +#endif } void UIMachineLogic::setMachineWindowsCreated(bool fIsWindowsCreated) @@ -691,14 +746,6 @@ void UIMachineLogic::retranslateUi() } } -bool UIMachineLogic::isHidLedsSyncEnabled() -{ - QString strHidLedsSyncSettings = session().GetMachine().GetExtraData(GUI_HidLedsSync); - if (strHidLedsSyncSettings == "1") - return true; - return false; -} - #ifdef Q_WS_MAC void UIMachineLogic::updateDockOverlay() { diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.h b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.h index d8b7104a7..69b84bdeb 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.h +++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.h @@ -97,11 +97,23 @@ public: /* API: 3D overlay visibility stuff: */ virtual void notifyAbout3DOverlayVisibilityChange(bool fVisible); + /** Performs HID LEDs sync. */ + bool isHidLedsSyncEnabled() { return m_isHidLedsSyncEnabled; }; + protected slots: /** Checks if some visual-state type was requested. */ virtual void sltCheckForRequestedVisualStateType() {} + /** Requests visual-state change to 'normal' (window). */ + virtual void sltChangeVisualStateToNormal(); + /** Requests visual-state change to 'fullscreen'. */ + virtual void sltChangeVisualStateToFullscreen(); + /** Requests visual-state change to 'seamless'. */ + virtual void sltChangeVisualStateToSeamless(); + /** Requests visual-state change to 'scale'. */ + virtual void sltChangeVisualStateToScale(); + /* Console callback handlers: */ virtual void sltMachineStateChanged(); virtual void sltAdditionsStateChanged(); @@ -132,7 +144,6 @@ protected: void setMouseHandler(UIMouseHandler *pMouseHandler); void addMachineWindow(UIMachineWindow *pMachineWindow); void retranslateUi(); - bool isHidLedsSyncEnabled(); #ifdef Q_WS_MAC bool isDockIconPreviewEnabled() const { return m_fIsDockIconEnabled; } void setDockIconPreviewEnabled(bool fIsDockIconPreviewEnabled) { m_fIsDockIconEnabled = fIsDockIconPreviewEnabled; } @@ -232,6 +243,7 @@ private slots: #endif /* RT_OS_DARWIN */ /* Handlers: Keyboard LEDs sync logic: */ + void sltHidLedsSyncStateChanged(bool fEnabled); void sltSwitchKeyboardLedsToGuestLeds(); void sltSwitchKeyboardLedsToPreviousLeds(); @@ -277,6 +289,7 @@ private: #endif /* Q_WS_MAC */ void *m_pHostLedsState; + bool m_isHidLedsSyncEnabled; /* Friend classes: */ friend class UIMachineWindow; diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp index 5eb78a0b7..9f396a217 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp +++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp @@ -375,7 +375,7 @@ UIMachineView::UIMachineView( UIMachineWindow *pMachineWindow , bool bAccelerate2DVideo #endif /* VBOX_WITH_VIDEOHWACCEL */ ) - : QAbstractScrollArea(pMachineWindow) + : QAbstractScrollArea(pMachineWindow->centralWidget()) , m_pMachineWindow(pMachineWindow) , m_uScreenId(uScreenId) , m_pFrameBuffer(0) diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.cpp index 08fa1b193..776589f1a 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.cpp +++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.cpp @@ -441,26 +441,6 @@ void UIMachineWindow::cleanupMachineView() m_pMachineView = 0; } -void UIMachineWindow::handleScreenCountChange() -{ - /* Ignore if window is minimized: */ - if (isMinimized()) - return; - - /* Make sure window is in necessary mode: */ - showInNecessaryMode(); -} - -void UIMachineWindow::handleScreenGeometryChange() -{ - /* Ignore if window is minimized: */ - if (isMinimized()) - return; - - /* Make sure window is in necessary mode: */ - showInNecessaryMode(); -} - void UIMachineWindow::updateAppearanceOf(int iElement) { /* Update window title: */ @@ -527,3 +507,19 @@ Qt::Alignment UIMachineWindow::viewAlignment(UIVisualStateType visualStateType) return 0; } +#ifdef Q_WS_MAC +void UIMachineWindow::handleNativeNotification(const QString &strNativeNotificationName, QWidget *pWidget) +{ + /* Handle arrived notification: */ + LogRel(("UIMachineWindow::handleNativeNotification: Notification '%s' received.\n", + strNativeNotificationName.toAscii().constData())); + if (UIMachineWindow *pMachineWindow = qobject_cast(pWidget)) + { + /* Redirect arrived notification: */ + LogRel(("UIMachineWindow::handleNativeNotification: Redirecting '%s' notification to corresponding machine-window...\n", + strNativeNotificationName.toAscii().constData())); + pMachineWindow->handleNativeNotification(strNativeNotificationName); + } +} +#endif /* Q_WS_MAC */ + diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.h b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.h index d41b37b4a..c942442f5 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.h +++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.h @@ -55,6 +55,7 @@ public: void cleanup(); /* Public getters: */ + ulong screenId() const { return m_uScreenId; } UIMachineView* machineView() const { return m_pMachineView; } UIMachineLogic* machineLogic() const { return m_pMachineLogic; } UISession* uisession() const; @@ -93,6 +94,12 @@ protected: #endif /* Q_WS_X11 */ void closeEvent(QCloseEvent *pEvent); +#ifdef Q_WS_MAC + /** Mac OS X: Handles native notifications. + * @param strNativeNotificationName Native notification name. */ + virtual void handleNativeNotification(const QString & /* strNativeNotificationName */) {} +#endif /* Q_WS_MAC */ + /* Prepare helpers: */ virtual void prepareSessionConnections(); virtual void prepareMainLayout(); @@ -113,10 +120,6 @@ protected: virtual void cleanupMainLayout() {} virtual void cleanupSessionConnections() {} - /* Visibility stuff: */ - void handleScreenCountChange(); - void handleScreenGeometryChange(); - /* Update stuff: */ virtual void updateAppearanceOf(int iElement); #ifdef VBOX_WITH_DEBUGGER_GUI @@ -128,6 +131,13 @@ protected: static Qt::WindowFlags windowFlags(UIVisualStateType visualStateType); static Qt::Alignment viewAlignment(UIVisualStateType visualStateType); +#ifdef Q_WS_MAC + /** Mac OS X: Handles native notifications. + * @param strNativeNotificationName Native notification name. + * @param pWidget Widget, notification related to. */ + static void handleNativeNotification(const QString &strNativeNotificationName, QWidget *pWidget); +#endif /* Q_WS_MAC */ + /* Variables: */ UIMachineLogic *m_pMachineLogic; UIMachineView *m_pMachineView; diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp index fde420563..309aa1aae 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp +++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp @@ -21,6 +21,7 @@ #include #include #include +#include /* GUI includes: */ #include "VBoxGlobal.h" @@ -425,6 +426,21 @@ void UIMouseHandler::sltMousePointerShapeChanged() } } +void UIMouseHandler::sltMaybeActivateHoveredWindow() +{ + /* Are we still have hovered window to activate? */ + if (m_pHoveredWindow && !m_pHoveredWindow->isActiveWindow()) + { + /* Activate it: */ + m_pHoveredWindow->activateWindow(); +#ifdef Q_WS_X11 + /* On X11 its not enough to just activate window if you + * want to raise it also, so we will make it separately: */ + m_pHoveredWindow->raise(); +#endif /* Q_WS_X11 */ + } +} + /* Mouse-handler constructor: */ UIMouseHandler::UIMouseHandler(UIMachineLogic *pMachineLogic) : QObject(pMachineLogic) @@ -547,13 +563,25 @@ bool UIMouseHandler::eventFilter(QObject *pWatched, QEvent *pEvent) case QEvent::MouseMove: case QEvent::MouseButtonRelease: { + /* Get mouse-event: */ + QMouseEvent *pOldMouseEvent = static_cast(pEvent); + + /* Check which viewport(s) we *probably* hover: */ + QWidgetList probablyHoveredViewports; + foreach (QWidget *pViewport, m_viewports) + { + QPoint posInViewport = pViewport->mapFromGlobal(pOldMouseEvent->globalPos()); + if (pViewport->geometry().adjusted(0, 0, 1, 1).contains(posInViewport)) + probablyHoveredViewports << pViewport; + } + /* Determine actually hovered viewport: */ + QWidget *pHoveredWidget = probablyHoveredViewports.isEmpty() ? 0 : + probablyHoveredViewports.contains(pWatchedWidget) ? pWatchedWidget : + probablyHoveredViewports.first(); + /* Check if we should propagate this event to another window: */ - QWidget *pHoveredWidget = QApplication::widgetAt(QCursor::pos()); if (pHoveredWidget && pHoveredWidget != pWatchedWidget && m_viewports.values().contains(pHoveredWidget)) { - /* Get current mouse-move event: */ - QMouseEvent *pOldMouseEvent = static_cast(pEvent); - /* Prepare redirected mouse-move event: */ QMouseEvent *pNewMouseEvent = new QMouseEvent(pOldMouseEvent->type(), pHoveredWidget->mapFromGlobal(pOldMouseEvent->globalPos()), @@ -584,13 +612,14 @@ bool UIMouseHandler::eventFilter(QObject *pWatched, QEvent *pEvent) m_windows.values().contains(pWatchedWidget->window()) && QApplication::activeWindow() != pWatchedWidget->window()) { - /* Activating hovered machine window: */ - pWatchedWidget->window()->activateWindow(); -#ifdef Q_WS_X11 - /* On X11 its not enough to just activate window if you - * want to raise it also, so we will make it separately: */ - pWatchedWidget->window()->raise(); -#endif /* Q_WS_X11 */ + /* Put request for hovered window activation in 300msec: */ + m_pHoveredWindow = pWatchedWidget->window(); + QTimer::singleShot(300, this, SLOT(sltMaybeActivateHoveredWindow())); + } + else + { + /* Revoke request for hovered window activation: */ + m_pHoveredWindow = 0; } /* This event should be also processed using next 'case': */ diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.h b/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.h index f94c9f5e4..b659a5820 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.h +++ b/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.h @@ -24,6 +24,7 @@ #include #include #include +#include /* GUI includes: */ #include "UIDefs.h" @@ -85,6 +86,9 @@ protected slots: /* Mouse pointer-shape-change handler: */ virtual void sltMousePointerShapeChanged(); + /** Activate hovered window if any. */ + void sltMaybeActivateHoveredWindow(); + protected: /* Mouse-handler constructor/destructor: */ @@ -125,6 +129,9 @@ protected: /* Registered machine-view-viewport(s): */ QMap m_viewports; + /** Hovered window to be activated. */ + QPointer m_pHoveredWindow; + /* Other mouse variables: */ QPoint m_lastMousePos; QPoint m_capturedMousePos; diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp index fcfffe0d5..8fbdd923b 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp +++ b/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp @@ -349,6 +349,16 @@ void UISession::powerUp() : "disabled")); #endif +/* Check if HID LEDs sync is enabled and add a log message about it. */ +#if defined(Q_WS_MAC) || defined(Q_WS_WIN) + if(uimachine()->machineLogic()->isHidLedsSyncEnabled()) + LogRel(("HID LEDs sync is enabled.\n")); + else + LogRel(("HID LEDs sync is disabled.\n")); +#else + LogRel(("HID LEDs sync is not supported on this platform.\n")); +#endif + #ifdef VBOX_GUI_WITH_PIDFILE vboxGlobal().createPidfile(); #endif @@ -654,38 +664,6 @@ void UISession::sltInstallGuestAdditionsFrom(const QString &strSource) } } -void UISession::sltChangeVisualStateToNormal() -{ - /* Reset requests: */ - setRequestedVisualState(UIVisualStateType_Invalid); - /* Request change: */ - m_pMachine->asyncChangeVisualState(UIVisualStateType_Normal); -} - -void UISession::sltChangeVisualStateToFullscreen() -{ - /* Reset requests: */ - setRequestedVisualState(UIVisualStateType_Invalid); - /* Request change: */ - m_pMachine->asyncChangeVisualState(UIVisualStateType_Fullscreen); -} - -void UISession::sltChangeVisualStateToSeamless() -{ - /* Reset requests: */ - setRequestedVisualState(UIVisualStateType_Invalid); - /* Request change: */ - m_pMachine->asyncChangeVisualState(UIVisualStateType_Seamless); -} - -void UISession::sltChangeVisualStateToScale() -{ - /* Reset requests: */ - setRequestedVisualState(UIVisualStateType_Invalid); - /* Request change: */ - m_pMachine->asyncChangeVisualState(UIVisualStateType_Scale); -} - void UISession::sltCloseRuntimeUI() { /* First, we have to hide any opened modal/popup widgets. @@ -842,11 +820,9 @@ void UISession::sltGuestMonitorChange(KGuestMonitorChangedEventType changeType, /* Ignore KGuestMonitorChangedEventType_NewOrigin change event: */ if (changeType == KGuestMonitorChangedEventType_NewOrigin) return; - /* Ignore KGuestMonitorChangedEventType_Disabled event if there is only one window visible: */ + /* Ignore KGuestMonitorChangedEventType_Disabled event for primary screen: */ AssertMsg(countOfVisibleWindows() > 0, ("All machine windows are hidden!")); - if ( changeType == KGuestMonitorChangedEventType_Disabled - && countOfVisibleWindows() == 1 - && isScreenVisible(uScreenId)) + if (changeType == KGuestMonitorChangedEventType_Disabled && uScreenId == 0) return; /* Process KGuestMonitorChangedEventType_Enabled change event: */ diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/UISession.h b/src/VBox/Frontends/VirtualBox/src/runtime/UISession.h index 6543c134e..27c8998e7 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/UISession.h +++ b/src/VBox/Frontends/VirtualBox/src/runtime/UISession.h @@ -255,15 +255,6 @@ public slots: private slots: - /** Requests visual-state change to 'normal' (window). */ - void sltChangeVisualStateToNormal(); - /** Requests visual-state change to 'fullscreen'. */ - void sltChangeVisualStateToFullscreen(); - /** Requests visual-state change to 'seamless'. */ - void sltChangeVisualStateToSeamless(); - /** Requests visual-state change to 'scale'. */ - void sltChangeVisualStateToScale(); - /* Handler: Close Runtime UI stuff: */ void sltCloseRuntimeUI(); diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineLogicFullscreen.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineLogicFullscreen.cpp index 3fffc3cf1..bb37d74fa 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineLogicFullscreen.cpp +++ b/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineLogicFullscreen.cpp @@ -29,11 +29,15 @@ #ifdef Q_WS_MAC # include "UIExtraDataEventHandler.h" # include "VBoxUtils.h" +# include "UIFrameBuffer.h" # include #endif /* Q_WS_MAC */ UIMachineLogicFullscreen::UIMachineLogicFullscreen(QObject *pParent, UISession *pSession) : UIMachineLogic(pParent, pSession, UIVisualStateType_Fullscreen) +#ifdef Q_WS_MAC + , m_fadeToken(kCGDisplayFadeReservationInvalidToken) +#endif /* Q_WS_MAC */ { /* Create multiscreen layout: */ m_pScreenLayout = new UIMultiScreenLayout(this); @@ -81,9 +85,9 @@ void UIMachineLogicFullscreen::maybeAdjustGuestScreenSize() { /* We should rebuild screen-layout: */ m_pScreenLayout->rebuild(); - /* And update machine-windows sizes finally: */ + /* Make sure all machine-window(s) have proper geometry: */ foreach (UIMachineWindow *pMachineWindow, machineWindows()) - pMachineWindow->handleScreenGeometryChange(); + pMachineWindow->showInNecessaryMode(); } int UIMachineLogicFullscreen::hostScreenForGuestScreen(int iScreenId) const @@ -96,6 +100,160 @@ bool UIMachineLogicFullscreen::hasHostScreenForGuestScreen(int iScreenId) const return m_pScreenLayout->hasHostScreenForGuestScreen(iScreenId); } +#ifdef RT_OS_DARWIN +void UIMachineLogicFullscreen::sltHandleNativeFullscreenWillEnter() +{ + /* Make sure this method is only used for ML and next: */ + AssertReturnVoid(vboxGlobal().osRelease() > MacOSXRelease_Lion); + + /* Get sender machine-window: */ + UIMachineWindow *pMachineWindow = qobject_cast(sender()); + AssertReturnVoid(pMachineWindow); + + /* Fade to black: */ + fadeToBlack(); +} + +void UIMachineLogicFullscreen::sltHandleNativeFullscreenDidEnter() +{ + /* Make sure this method is only used for ML and next: */ + AssertReturnVoid(vboxGlobal().osRelease() > MacOSXRelease_Lion); + + /* Get sender machine-window: */ + UIMachineWindow *pMachineWindow = qobject_cast(sender()); + AssertReturnVoid(pMachineWindow); + + /* Add machine-window to corresponding set: */ + m_fullscreenMachineWindows.insert(pMachineWindow); + AssertReturnVoid(m_fullscreenMachineWindows.contains(pMachineWindow)); + + /* Fade to normal if necessary: */ + QSet visibleMachineWindows; + foreach (UIMachineWindow *pMachineWindow, machineWindows()) + if (uisession()->isScreenVisible(pMachineWindow->screenId())) + visibleMachineWindows << pMachineWindow; + if ( !darwinScreensHaveSeparateSpaces() + || m_fullscreenMachineWindows == visibleMachineWindows) + fadeToNormal(); +} + +void UIMachineLogicFullscreen::sltHandleNativeFullscreenWillExit() +{ + /* Make sure this method is only used for ML and next: */ + AssertReturnVoid(vboxGlobal().osRelease() > MacOSXRelease_Lion); + + /* Get sender machine-window: */ + UIMachineWindow *pMachineWindow = qobject_cast(sender()); + AssertReturnVoid(pMachineWindow); + + /* Fade to black: */ + fadeToBlack(); +} + +void UIMachineLogicFullscreen::sltHandleNativeFullscreenDidExit() +{ + /* Make sure this method is only used for ML and next: */ + AssertReturnVoid(vboxGlobal().osRelease() > MacOSXRelease_Lion); + + /* Get sender machine-window: */ + UIMachineWindow *pMachineWindow = qobject_cast(sender()); + AssertReturnVoid(pMachineWindow); + + /* Remove machine-window from corresponding set: */ + bool fResult = m_fullscreenMachineWindows.remove(pMachineWindow); + AssertReturnVoid(fResult && !m_fullscreenMachineWindows.contains(pMachineWindow)); + Q_UNUSED(fResult); + + /* If that window was invalidated: */ + if (m_invalidFullscreenMachineWindows.contains(pMachineWindow)) + { + LogRel(("UIMachineLogicFullscreen::sltHandleNativeFullscreenDidExit: " + "Machine-window #%d exited invalidated fullscreen, revalidate it.\n", + (int)pMachineWindow->screenId())); + + /* Exclude window from invalidation list: */ + m_invalidFullscreenMachineWindows.remove(pMachineWindow); + + /* Revalidate 'fullscreen' window: */ + revalidateFullscreenWindow(pMachineWindow); + } + /* If there are no invalidated windows: */ + else if (m_invalidFullscreenMachineWindows.isEmpty()) + { + /* If there are 'fullscreen' windows: */ + if (!m_fullscreenMachineWindows.isEmpty()) + { + LogRel(("UIMachineLogicFullscreen::sltHandleNativeFullscreenDidExit: " + "Machine-window exited fullscreen, asking others to exit too...\n")); + + /* Ask window(s) to exit 'fullscreen' mode: */ + emit sigNotifyAboutNativeFullscreenShouldBeExited(); + } + /* If there are no 'fullscreen' windows: */ + else + { + LogRel(("UIMachineLogicFullscreen::sltHandleNativeFullscreenDidExit: " + "Machine-window(s) exited fullscreen, changing visual-state to requested...\n")); + + /* Change visual-state to requested: */ + UIVisualStateType type = uisession()->requestedVisualState(); + if (type == UIVisualStateType_Invalid) + type = UIVisualStateType_Normal; + uisession()->setRequestedVisualState(UIVisualStateType_Invalid); + uisession()->changeVisualState(type); + + /* Fade to normal: */ + fadeToNormal(); + } + } +} + +void UIMachineLogicFullscreen::sltChangeVisualStateToNormal() +{ + /* Base-class handling for Lion and previous: */ + if (vboxGlobal().osRelease() <= MacOSXRelease_Lion) + UIMachineLogic::sltChangeVisualStateToNormal(); + /* Special handling for ML and next: */ + else + { + /* Request 'normal' (window) visual-state: */ + uisession()->setRequestedVisualState(UIVisualStateType_Normal); + /* Ask window(s) to exit 'fullscreen' mode: */ + emit sigNotifyAboutNativeFullscreenShouldBeExited(); + } +} + +void UIMachineLogicFullscreen::sltChangeVisualStateToSeamless() +{ + /* Base-class handling for Lion and previous: */ + if (vboxGlobal().osRelease() <= MacOSXRelease_Lion) + UIMachineLogic::sltChangeVisualStateToSeamless(); + /* Special handling for ML and next: */ + else + { + /* Request 'seamless' visual-state: */ + uisession()->setRequestedVisualState(UIVisualStateType_Seamless); + /* Ask window(s) to exit 'fullscreen' mode: */ + emit sigNotifyAboutNativeFullscreenShouldBeExited(); + } +} + +void UIMachineLogicFullscreen::sltChangeVisualStateToScale() +{ + /* Base-class handling for Lion and previous: */ + if (vboxGlobal().osRelease() <= MacOSXRelease_Lion) + UIMachineLogic::sltChangeVisualStateToScale(); + /* Special handling for ML and next: */ + else + { + /* Request 'scale' visual-state: */ + uisession()->setRequestedVisualState(UIVisualStateType_Scale); + /* Ask window(s) to exit 'fullscreen' mode: */ + emit sigNotifyAboutNativeFullscreenShouldBeExited(); + } +} +#endif /* RT_OS_DARWIN */ + void UIMachineLogicFullscreen::sltMachineStateChanged() { /* Call to base-class: */ @@ -112,9 +270,9 @@ void UIMachineLogicFullscreen::sltMachineStateChanged() uisession()->forgetPreviousMachineState(); /* We should rebuild screen-layout: */ m_pScreenLayout->rebuild(); - /* We should update machine-windows sizes: */ + /* Make sure all machine-window(s) have proper geometry: */ foreach (UIMachineWindow *pMachineWindow, machineWindows()) - pMachineWindow->handleScreenGeometryChange(); + pMachineWindow->showInNecessaryMode(); } } @@ -123,35 +281,69 @@ void UIMachineLogicFullscreen::sltChangePresentationMode(bool /* fEnabled */) { setPresentationModeEnabled(true); } +#endif /* Q_WS_MAC */ void UIMachineLogicFullscreen::sltScreenLayoutChanged() { - setPresentationModeEnabled(true); + LogRel(("UIMachineLogicFullscreen: Multi-screen layout changed.\n")); + +#ifdef Q_WS_MAC + /* For Lion and previous: */ + if (vboxGlobal().osRelease() <= MacOSXRelease_Lion) + { + /* Make sure all machine-window(s) have proper geometry: */ + foreach (UIMachineWindow *pMachineWindow, machineWindows()) + pMachineWindow->showInNecessaryMode(); + /* Update 'presentation mode': */ + setPresentationModeEnabled(true); + } + /* Revalidate 'fullscreen' windows for ML and next: */ + else revalidateFullscreenWindows(); +#else /* !Q_WS_MAC */ + /* Make sure all machine-window(s) have proper geometry: */ + foreach (UIMachineWindow *pMachineWindow, machineWindows()) + pMachineWindow->showInNecessaryMode(); +#endif /* !Q_WS_MAC */ } -#endif /* Q_WS_MAC */ void UIMachineLogicFullscreen::sltGuestMonitorChange(KGuestMonitorChangedEventType changeType, ulong uScreenId, QRect screenGeo) { - LogRelFlow(("UIMachineLogicFullscreen: Guest-screen count changed.\n")); + LogRel(("UIMachineLogicFullscreen: Guest-screen count changed.\n")); /* Update multi-screen layout before any window update: */ if (changeType == KGuestMonitorChangedEventType_Enabled || changeType == KGuestMonitorChangedEventType_Disabled) m_pScreenLayout->rebuild(); +#ifdef Q_WS_MAC + /* Call to base-class for Lion and previous: */ + if (vboxGlobal().osRelease() <= MacOSXRelease_Lion) + UIMachineLogic::sltGuestMonitorChange(changeType, uScreenId, screenGeo); + /* Revalidate 'fullscreen' windows for ML and next: */ + else revalidateFullscreenWindows(); +#else /* !Q_WS_MAC */ /* Call to base-class: */ UIMachineLogic::sltGuestMonitorChange(changeType, uScreenId, screenGeo); +#endif /* !Q_WS_MAC */ } void UIMachineLogicFullscreen::sltHostScreenCountChanged() { - LogRelFlow(("UIMachineLogicFullscreen: Host-screen count changed.\n")); + LogRel(("UIMachineLogicFullscreen: Host-screen count changed.\n")); /* Update multi-screen layout before any window update: */ m_pScreenLayout->rebuild(); +#ifdef Q_WS_MAC + /* Call to base-class for Lion and previous: */ + if (vboxGlobal().osRelease() <= MacOSXRelease_Lion) + UIMachineLogic::sltHostScreenCountChanged(); + /* Revalidate 'fullscreen' windows for ML and next: */ + else revalidateFullscreenWindows(); +#else /* !Q_WS_MAC */ /* Call to base-class: */ UIMachineLogic::sltHostScreenCountChanged(); +#endif /* !Q_WS_MAC */ } void UIMachineLogicFullscreen::prepareActionGroups() @@ -180,19 +372,21 @@ void UIMachineLogicFullscreen::prepareActionConnections() /* "View" actions connections: */ connect(gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToNormal())); + this, SLOT(sltChangeVisualStateToNormal())); connect(gActionPool->action(UIActionIndexRuntime_Toggle_Seamless), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToSeamless())); + this, SLOT(sltChangeVisualStateToSeamless())); connect(gActionPool->action(UIActionIndexRuntime_Toggle_Scale), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToScale())); + this, SLOT(sltChangeVisualStateToScale())); } #ifdef Q_WS_MAC void UIMachineLogicFullscreen::prepareOtherConnections() { - /* Presentation mode connection: */ - connect(gEDataEvents, SIGNAL(sigPresentationModeChange(bool)), - this, SLOT(sltChangePresentationMode(bool))); + /* Make sure 'presentation mode' preference handling + * is updated at runtime for Lion and previous: */ + if (vboxGlobal().osRelease() <= MacOSXRelease_Lion) + connect(gEDataEvents, SIGNAL(sigPresentationModeChange(bool)), + this, SLOT(sltChangePresentationMode(bool))); } #endif /* Q_WS_MAC */ @@ -202,10 +396,13 @@ void UIMachineLogicFullscreen::prepareMachineWindows() if (isMachineWindowsCreated()) return; -#ifdef Q_WS_MAC // TODO: Is that "darwinSetFrontMostProcess" really need here? +#ifdef Q_WS_MAC /* We have to make sure that we are getting the front most process. * This is necessary for Qt versions > 4.3.3: */ - ::darwinSetFrontMostProcess(); + darwinSetFrontMostProcess(); + + /* Fade to black: */ + fadeToBlack(); #endif /* Q_WS_MAC */ /* Update the multi-screen layout: */ @@ -216,17 +413,41 @@ void UIMachineLogicFullscreen::prepareMachineWindows() addMachineWindow(UIMachineWindow::create(this, cScreenId)); /* Connect multi-screen layout change handler: */ - for (int i = 0; i < machineWindows().size(); ++i) - connect(m_pScreenLayout, SIGNAL(sigScreenLayoutChanged()), - static_cast(machineWindows()[i]), SLOT(sltShowInNecessaryMode())); - -#ifdef Q_WS_MAC - /* If the user change the screen, we have to decide again if the - * presentation mode should be changed. */ connect(m_pScreenLayout, SIGNAL(sigScreenLayoutChanged()), this, SLOT(sltScreenLayoutChanged())); - /* Note: Presentation mode has to be set *after* the windows are created. */ + +#ifdef Q_WS_MAC + /* Activate 'presentation mode': */ setPresentationModeEnabled(true); + + /* For Lion and previous fade to normal: */ + if (vboxGlobal().osRelease() <= MacOSXRelease_Lion) + fadeToNormal(); + + /* For ML and next: */ + if (vboxGlobal().osRelease() > MacOSXRelease_Lion) + { + /* Enable native fullscreen support: */ + foreach (UIMachineWindow *pMachineWindow, machineWindows()) + { + /* Logic => window signals: */ + connect(this, SIGNAL(sigNotifyAboutNativeFullscreenShouldBeEntered(UIMachineWindow*)), + pMachineWindow, SLOT(sltEnterNativeFullscreen(UIMachineWindow*))); + connect(this, SIGNAL(sigNotifyAboutNativeFullscreenShouldBeExited(UIMachineWindow*)), + pMachineWindow, SLOT(sltExitNativeFullscreen(UIMachineWindow*))); + /* Window => logic signals: */ + connect(pMachineWindow, SIGNAL(sigNotifyAboutNativeFullscreenWillEnter()), + this, SLOT(sltHandleNativeFullscreenWillEnter())); + connect(pMachineWindow, SIGNAL(sigNotifyAboutNativeFullscreenDidEnter()), + this, SLOT(sltHandleNativeFullscreenDidEnter())); + connect(pMachineWindow, SIGNAL(sigNotifyAboutNativeFullscreenWillExit()), + this, SLOT(sltHandleNativeFullscreenWillExit())); + connect(pMachineWindow, SIGNAL(sigNotifyAboutNativeFullscreenDidExit()), + this, SLOT(sltHandleNativeFullscreenDidExit())); + } + /* Revalidate 'fullscreen' windows: */ + revalidateFullscreenWindows(); + } #endif /* Q_WS_MAC */ /* Mark machine-window(s) created: */ @@ -249,15 +470,25 @@ void UIMachineLogicFullscreen::cleanupMachineWindows() if (!isMachineWindowsCreated()) return; +#ifdef Q_WS_MAC + /* For Lion and previous fade to black: */ + if (vboxGlobal().osRelease() <= MacOSXRelease_Lion) + fadeToBlack(); +#endif/* Q_WS_MAC */ + /* Mark machine-window(s) destroyed: */ setMachineWindowsCreated(false); - /* Cleanup machine-window(s): */ + /* Destroy machine-window(s): */ foreach (UIMachineWindow *pMachineWindow, machineWindows()) UIMachineWindow::destroy(pMachineWindow); #ifdef Q_WS_MAC + /* Deactivate 'presentation mode': */ setPresentationModeEnabled(false); + + /* Fade to normal: */ + fadeToNormal(); #endif/* Q_WS_MAC */ } @@ -265,11 +496,11 @@ void UIMachineLogicFullscreen::cleanupActionConnections() { /* "View" actions disconnections: */ disconnect(gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToNormal())); + this, SLOT(sltChangeVisualStateToNormal())); disconnect(gActionPool->action(UIActionIndexRuntime_Toggle_Seamless), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToSeamless())); + this, SLOT(sltChangeVisualStateToSeamless())); disconnect(gActionPool->action(UIActionIndexRuntime_Toggle_Scale), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToScale())); + this, SLOT(sltChangeVisualStateToScale())); /* Call to base-class: */ UIMachineLogic::cleanupActionConnections(); @@ -297,21 +528,162 @@ void UIMachineLogicFullscreen::cleanupActionGroups() #ifdef Q_WS_MAC void UIMachineLogicFullscreen::setPresentationModeEnabled(bool fEnabled) { - /* First check if we are on a screen which contains the Dock or the - * Menubar (which hasn't to be the same), only than the - * presentation mode have to be changed. */ - if ( fEnabled - && m_pScreenLayout->isHostTaskbarCovert()) + /* Should we enable it? */ + if (fEnabled) { - QString testStr = vboxGlobal().virtualBox().GetExtraData(GUI_PresentationModeEnabled).toLower(); - /* Default to false if it is an empty value */ - if (testStr.isEmpty() || testStr == "false") - SetSystemUIMode(kUIModeAllHidden, 0); + /* For Lion and previous: */ + if (vboxGlobal().osRelease() <= MacOSXRelease_Lion) + { + /* Check if we have screen which contains the Dock or the Menubar (which hasn't to be the same), + * only than the 'presentation mode' have to be changed. */ + if (m_pScreenLayout->isHostTaskbarCovert()) + { + /* Load 'presentation mode' preference: */ + QString strPresentationMode = vboxGlobal().virtualBox().GetExtraData(GUI_PresentationModeEnabled).toLower(); + /* Default to 'false' if it is an empty value: */ + if (strPresentationMode.isEmpty() || strPresentationMode == "false") + SetSystemUIMode(kUIModeAllHidden, 0); + else + SetSystemUIMode(kUIModeAllSuppressed, 0); + } + } + /* For ML and next: */ else + { + /* I am not sure we have to check anything here. + * Without 'presentation mode' native fullscreen works pretty bad, + * so we have to enable it anyway: */ SetSystemUIMode(kUIModeAllSuppressed, 0); + } + } + /* Should we disable it? */ + else SetSystemUIMode(kUIModeNormal, 0); +} + +void UIMachineLogicFullscreen::fadeToBlack() +{ + /* Make sure fade-token invalid: */ + if (m_fadeToken != kCGDisplayFadeReservationInvalidToken) + return; + + /* Acquire fade-token: */ + CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &m_fadeToken); + CGDisplayFade(m_fadeToken, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, true); +} + +void UIMachineLogicFullscreen::fadeToNormal() +{ + /* Make sure fade-token valid: */ + if (m_fadeToken == kCGDisplayFadeReservationInvalidToken) + return; + + /* Release fade-token: */ + CGDisplayFade(m_fadeToken, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, false); + CGReleaseDisplayFadeReservation(m_fadeToken); + m_fadeToken = kCGDisplayFadeReservationInvalidToken; +} + +void UIMachineLogicFullscreen::revalidateFullscreenWindow(UIMachineWindow *pMachineWindow) +{ + LogRel(("UIMachineLogicFullscreen::revalidateFullscreenWindow #%d begin.\n", pMachineWindow->screenId())); + + /* Make sure window is not already invalidated: */ + if (m_invalidFullscreenMachineWindows.contains(pMachineWindow)) + return; + + /* Ignore window if it is in 'fullscreen transition': */ + if (qobject_cast(pMachineWindow)->isInFullscreenTransition()) + return; + + /* Get screen ID: */ + ulong uScreenID = pMachineWindow->screenId(); + + /* Validate window which can't be fullscreen: */ + if (uScreenID != 0 && !darwinScreensHaveSeparateSpaces()) + { + /* Make sure window have proper geometry: */ + pMachineWindow->showInNecessaryMode(); } + /* Validate window which can be fullscreen: */ else - SetSystemUIMode(kUIModeNormal, 0); + { + /* Validate window which is not in fullscreen: */ + if (!darwinIsInFullscreenMode(pMachineWindow)) + { + /* If that window + * 1. should really be shown and + * 2. is mapped to some host-screen: */ + if ( uisession()->isScreenVisible(uScreenID) + && hasHostScreenForGuestScreen(uScreenID)) + { + LogRel(("UIMachineLogicFullscreen::revalidateFullscreenWindow: " + "Ask machine-window #%d to enter fullscreen.\n", (int)uScreenID)); + + /* Fade to black: */ + fadeToBlack(); + + /* Update 'presentation mode': */ + setPresentationModeEnabled(true); + + /* Make sure window have proper geometry and shown: */ + pMachineWindow->showInNecessaryMode(); + + /* Ask window to enter 'fullscreen' mode: */ + emit sigNotifyAboutNativeFullscreenShouldBeEntered(pMachineWindow); + } + /* If that window + * is shown while shouldn't: */ + else if (pMachineWindow->isVisible()) + { + /* Else make sure that window is hidden: */ + pMachineWindow->showInNecessaryMode(); + + /* Fade to normal: */ + fadeToNormal(); + } + } + /* Validate window which is in fullscreen: */ + else + { + /* Variables to compare: */ + const int iWantedHostScreenIndex = hostScreenForGuestScreen((int)uScreenID); + const int iCurrentHostScreenIndex = QApplication::desktop()->screenNumber(pMachineWindow); + const QSize frameBufferSize((int)uisession()->frameBuffer(uScreenID)->width(), (int)uisession()->frameBuffer(uScreenID)->height()); + const QSize screenSize = QApplication::desktop()->screenGeometry(iWantedHostScreenIndex).size(); + + /* If that window + * 1. shouldn't really be shown or + * 2. isn't mapped to some host-screen or + * 3. should be located on another host-screen than currently or + * 4. have another frame-buffer size than actually should. */ + if ( !uisession()->isScreenVisible(uScreenID) + || !hasHostScreenForGuestScreen(uScreenID) + || iWantedHostScreenIndex != iCurrentHostScreenIndex + || frameBufferSize != screenSize) + { + LogRel(("UIMachineLogicFullscreen::revalidateFullscreenWindow: " + "Ask machine-window #%d to exit fullscreen.\n", (int)uScreenID)); + + /* Fade to black: */ + fadeToBlack(); + + /* Mark window as invalidated: */ + m_invalidFullscreenMachineWindows << pMachineWindow; + + /* Ask window to exit 'fullscreen' mode: */ + emit sigNotifyAboutNativeFullscreenShouldBeExited(pMachineWindow); + } + } + } + + LogRel(("UIMachineLogicFullscreen::revalidateFullscreenWindow #%d end.\n", pMachineWindow->screenId())); +} + +void UIMachineLogicFullscreen::revalidateFullscreenWindows() +{ + /* Revalidate all fullscreen windows: */ + foreach (UIMachineWindow *pMachineWindow, machineWindows()) + revalidateFullscreenWindow(pMachineWindow); } #endif /* Q_WS_MAC */ diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineLogicFullscreen.h b/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineLogicFullscreen.h index a60b86d03..931a08f9a 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineLogicFullscreen.h +++ b/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineLogicFullscreen.h @@ -17,9 +17,14 @@ #ifndef ___UIMachineLogicFullscreen_h___ #define ___UIMachineLogicFullscreen_h___ -/* Local includes: */ +/* GUI includes: */ #include "UIMachineLogic.h" +/* Other includes: */ +#ifdef Q_WS_MAC +# include +#endif /* Q_WS_MAC */ + /* Forward declarations: */ class UIMultiScreenLayout; @@ -28,6 +33,14 @@ class UIMachineLogicFullscreen : public UIMachineLogic { Q_OBJECT; +#ifdef RT_OS_DARWIN +signals: + /** Mac OS X: Notifies listeners about native fullscreen mode should be entered on @a pMachineWindow. */ + void sigNotifyAboutNativeFullscreenShouldBeEntered(UIMachineWindow *pMachineWindow = 0); + /** Mac OS X: Notifies listeners about native fullscreen mode should be exited on @a pMachineWindow. */ + void sigNotifyAboutNativeFullscreenShouldBeExited(UIMachineWindow *pMachineWindow = 0); +#endif /* RT_OS_DARWIN */ + protected: /* Constructor/destructor: */ @@ -44,13 +57,34 @@ protected: private slots: +#ifdef RT_OS_DARWIN + /** Mac OS X: Handles native notification about 'fullscreen' will be entered. */ + void sltHandleNativeFullscreenWillEnter(); + /** Mac OS X: Handles native notification about 'fullscreen' entered. */ + void sltHandleNativeFullscreenDidEnter(); + /** Mac OS X: Handles native notification about 'fullscreen' will be exited. */ + void sltHandleNativeFullscreenWillExit(); + /** Mac OS X: Handles native notification about 'fullscreen' exited. */ + void sltHandleNativeFullscreenDidExit(); + + /** Mac OS X: Requests visual-state change from 'fullscreen' to 'normal' (window). */ + void sltChangeVisualStateToNormal(); + /** Mac OS X: Requests visual-state change from 'fullscreen' to 'seamless'. */ + void sltChangeVisualStateToSeamless(); + /** Mac OS X: Requests visual-state change from 'fullscreen' to 'scale'. */ + void sltChangeVisualStateToScale(); +#endif /* RT_OS_DARWIN */ + /* Handler: Console callback stuff: */ void sltMachineStateChanged(); #ifdef Q_WS_MAC void sltChangePresentationMode(bool fEnabled); - void sltScreenLayoutChanged(); #endif /* Q_WS_MAC */ + + /** Updates machine-window(s) location/size on screen-layout changes. */ + void sltScreenLayoutChanged(); + void sltGuestMonitorChange(KGuestMonitorChangedEventType changeType, ulong uScreenId, QRect screenGeo); void sltHostScreenCountChanged(); @@ -76,11 +110,31 @@ private: #ifdef Q_WS_MAC void setPresentationModeEnabled(bool fEnabled); + + /** Mac OS X: Performs fade to black if possible. */ + void fadeToBlack(); + /** Mac OS X: Performs fade to normal if possible. */ + void fadeToNormal(); + + /** Mac OS X: Revalidates 'fullscreen' mode for @a pMachineWindow. */ + void revalidateFullscreenWindow(UIMachineWindow *pMachineWindow); + /** Mac OS X: Revalidates 'fullscreen' mode for all windows. */ + void revalidateFullscreenWindows(); #endif /* Q_WS_MAC */ /* Variables: */ UIMultiScreenLayout *m_pScreenLayout; +#ifdef Q_WS_MAC + /** Mac OS X: Fade token. */ + CGDisplayFadeReservationToken m_fadeToken; + + /** Mac OS X: Contains machine-window(s) marked as 'fullscreen'. */ + QSet m_fullscreenMachineWindows; + /** Mac OS X: Contains machine-window(s) marked as 'invalid fullscreen'. */ + QSet m_invalidFullscreenMachineWindows; +#endif /* Q_WS_MAC */ + /* Friend classes: */ friend class UIMachineLogic; friend class UIMachineWindowFullscreen; diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineWindowFullscreen.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineWindowFullscreen.cpp index 3e0b4f7ef..5a92e6b88 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineWindowFullscreen.cpp +++ b/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineWindowFullscreen.cpp @@ -31,6 +31,10 @@ #include "UIMachineView.h" #include "UIMachineDefs.h" #include "UIMiniToolBar.h" +#ifdef Q_WS_MAC +# include "VBoxUtils-darwin.h" +# include "UICocoaApplication.h" +#endif /* Q_WS_MAC */ /* COM includes: */ #include "CSnapshot.h" @@ -39,9 +43,57 @@ UIMachineWindowFullscreen::UIMachineWindowFullscreen(UIMachineLogic *pMachineLog : UIMachineWindow(pMachineLogic, uScreenId) , m_pMainMenu(0) , m_pMiniToolBar(0) +#ifdef Q_WS_MAC + , m_fIsInFullscreenTransition(false) +#endif /* Q_WS_MAC */ { } +#ifdef Q_WS_MAC +void UIMachineWindowFullscreen::handleNativeNotification(const QString &strNativeNotificationName) +{ + /* Make sure this method is only used for ML and next: */ + AssertReturnVoid(vboxGlobal().osRelease() > MacOSXRelease_Lion); + + /* Log all arrived notifications: */ + LogRel(("UIMachineWindowFullscreen::handleNativeNotification: Notification '%s' received.\n", + strNativeNotificationName.toAscii().constData())); + + /* Handle 'NSWindowWillEnterFullScreenNotification' notification: */ + if (strNativeNotificationName == "NSWindowWillEnterFullScreenNotification") + { + LogRel(("UIMachineWindowFullscreen::handleNativeNotification: " + "Native fullscreen mode about to enter, notifying listener...\n")); + emit sigNotifyAboutNativeFullscreenWillEnter(); + } + /* Handle 'NSWindowDidEnterFullScreenNotification' notification: */ + else if (strNativeNotificationName == "NSWindowDidEnterFullScreenNotification") + { + /* Mark window transition complete: */ + m_fIsInFullscreenTransition = false; + LogRel(("UIMachineWindowFullscreen::handleNativeNotification: " + "Native fullscreen mode entered, notifying listener...\n")); + emit sigNotifyAboutNativeFullscreenDidEnter(); + } + /* Handle 'NSWindowWillExitFullScreenNotification' notification: */ + else if (strNativeNotificationName == "NSWindowWillExitFullScreenNotification") + { + LogRel(("UIMachineWindowFullscreen::handleNativeNotification: " + "Native fullscreen mode about to exit, notifying listener...\n")); + emit sigNotifyAboutNativeFullscreenWillExit(); + } + /* Handle 'NSWindowDidExitFullScreenNotification' notification: */ + else if (strNativeNotificationName == "NSWindowDidExitFullScreenNotification") + { + /* Mark window transition complete: */ + m_fIsInFullscreenTransition = false; + LogRel(("UIMachineWindowFullscreen::handleNativeNotification: " + "Native fullscreen mode exited, notifying listener...\n")); + emit sigNotifyAboutNativeFullscreenDidExit(); + } +} +#endif /* Q_WS_MAC */ + void UIMachineWindowFullscreen::sltMachineStateChanged() { /* Call to base-class: */ @@ -61,6 +113,63 @@ void UIMachineWindowFullscreen::sltPopupMainMenu() } } +#ifdef Q_WS_MAC +void UIMachineWindowFullscreen::sltEnterNativeFullscreen(UIMachineWindow *pMachineWindow) +{ + /* Make sure this slot is called only under ML and next: */ + AssertReturnVoid(vboxGlobal().osRelease() > MacOSXRelease_Lion); + + /* Make sure it is NULL or 'this' window passed: */ + if (pMachineWindow && pMachineWindow != this) + return; + + /* Make sure this window should be shown at all: */ + if (!uisession()->isScreenVisible(m_uScreenId)) + return; + + /* Make sure this window has fullscreen logic: */ + UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast(machineLogic()); + if (!pFullscreenLogic) + return; + + /* Make sure this window mapped to some host-screen: */ + if (!pFullscreenLogic->hasHostScreenForGuestScreen(m_uScreenId)) + return; + + /* Mark window 'transitioned to fullscreen': */ + m_fIsInFullscreenTransition = true; + + /* Enter native fullscreen mode if necessary: */ + if ( (darwinScreensHaveSeparateSpaces() || m_uScreenId == 0) + && !darwinIsInFullscreenMode(this)) + darwinToggleFullscreenMode(this); +} + +void UIMachineWindowFullscreen::sltExitNativeFullscreen(UIMachineWindow *pMachineWindow) +{ + /* Make sure this slot is called only under ML and next: */ + AssertReturnVoid(vboxGlobal().osRelease() > MacOSXRelease_Lion); + + /* Make sure it is NULL or 'this' window passed: */ + if (pMachineWindow && pMachineWindow != this) + return; + + /* Mark window 'transitioned from fullscreen': */ + m_fIsInFullscreenTransition = true; + + /* Exit native fullscreen mode if necessary: */ + if ( (darwinScreensHaveSeparateSpaces() || m_uScreenId == 0) + && darwinIsInFullscreenMode(this)) + darwinToggleFullscreenMode(this); +} +#endif /* Q_WS_MAC */ + +void UIMachineWindowFullscreen::sltRevokeFocus() +{ + /* Revoke stolen focus: */ + m_pMachineView->setFocus(); +} + void UIMachineWindowFullscreen::prepareMenu() { /* Call to base-class: */ @@ -87,6 +196,28 @@ void UIMachineWindowFullscreen::prepareVisualState() /* Prepare mini-toolbar: */ prepareMiniToolbar(); + +#ifdef Q_WS_MAC + /* Native fullscreen stuff on ML and next: */ + if (vboxGlobal().osRelease() > MacOSXRelease_Lion) + { + /* Enable fullscreen support for every screen which requires it: */ + if (darwinScreensHaveSeparateSpaces() || m_uScreenId == 0) + darwinEnableFullscreenSupport(this); + /* Enable transience support for other screens: */ + else + darwinEnableTransienceSupport(this); + /* Register to native fullscreen notifications: */ + UICocoaApplication::instance()->registerToNativeNotification("NSWindowWillEnterFullScreenNotification", this, + UIMachineWindow::handleNativeNotification); + UICocoaApplication::instance()->registerToNativeNotification("NSWindowDidEnterFullScreenNotification", this, + UIMachineWindow::handleNativeNotification); + UICocoaApplication::instance()->registerToNativeNotification("NSWindowWillExitFullScreenNotification", this, + UIMachineWindow::handleNativeNotification); + UICocoaApplication::instance()->registerToNativeNotification("NSWindowDidExitFullScreenNotification", this, + UIMachineWindow::handleNativeNotification); + } +#endif /* Q_WS_MAC */ } void UIMachineWindowFullscreen::prepareMiniToolbar() @@ -115,11 +246,14 @@ void UIMachineWindowFullscreen::prepareMiniToolbar() for (int i=0; i < actions.size(); ++i) menus << actions.at(i)->menu(); m_pMiniToolBar->addMenus(menus); +#ifndef RT_OS_DARWIN connect(m_pMiniToolBar, SIGNAL(sigMinimizeAction()), this, SLOT(showMinimized())); +#endif /* !RT_OS_DARWIN */ connect(m_pMiniToolBar, SIGNAL(sigExitAction()), gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen), SLOT(trigger())); connect(m_pMiniToolBar, SIGNAL(sigCloseAction()), gActionPool->action(UIActionIndexRuntime_Simple_Close), SLOT(trigger())); + connect(m_pMiniToolBar, SIGNAL(sigNotifyAboutFocusStolen()), this, SLOT(sltRevokeFocus())); } void UIMachineWindowFullscreen::cleanupMiniToolbar() @@ -137,6 +271,18 @@ void UIMachineWindowFullscreen::cleanupMiniToolbar() void UIMachineWindowFullscreen::cleanupVisualState() { +#ifdef Q_WS_MAC + /* Native fullscreen stuff on ML and next: */ + if (vboxGlobal().osRelease() > MacOSXRelease_Lion) + { + /* Unregister from native fullscreen notifications: */ + UICocoaApplication::instance()->unregisterFromNativeNotification("NSWindowWillEnterFullScreenNotification", this); + UICocoaApplication::instance()->unregisterFromNativeNotification("NSWindowDidEnterFullScreenNotification", this); + UICocoaApplication::instance()->unregisterFromNativeNotification("NSWindowWillExitFullScreenNotification", this); + UICocoaApplication::instance()->unregisterFromNativeNotification("NSWindowDidExitFullScreenNotification", this); + } +#endif /* Q_WS_MAC */ + /* Cleanup mini-toolbar: */ cleanupMiniToolbar(); @@ -162,8 +308,18 @@ void UIMachineWindowFullscreen::placeOnScreen() QRect workingArea = QApplication::desktop()->screenGeometry(iScreen); /* Move to the appropriate position: */ move(workingArea.topLeft()); +#ifdef Q_WS_MAC + /* Resize to the appropriate size on Lion and previous: */ + if (vboxGlobal().osRelease() <= MacOSXRelease_Lion) + resize(workingArea.size()); + /* Resize to the appropriate size on ML and next + * only if that screen has no own user-space: */ + else if (!darwinScreensHaveSeparateSpaces() && m_uScreenId != 0) + resize(workingArea.size()); +#else /* !Q_WS_MAC */ /* Resize to the appropriate size: */ resize(workingArea.size()); +#endif /* !Q_WS_MAC */ /* Adjust guest screen size if necessary: */ machineView()->maybeAdjustGuestScreenSize(); /* Move mini-toolbar into appropriate place: */ @@ -175,42 +331,42 @@ void UIMachineWindowFullscreen::placeOnScreen() void UIMachineWindowFullscreen::showInNecessaryMode() { - /* Should we show window?: */ - if (uisession()->isScreenVisible(m_uScreenId)) - { - /* Do we have the seamless logic? */ - if (UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast(machineLogic())) - { - /* Is this guest screen has own host screen? */ - if (pFullscreenLogic->hasHostScreenForGuestScreen(m_uScreenId)) - { - /* Make sure the window is maximized and placed on valid screen: */ - placeOnScreen(); - -#ifdef Q_WS_WIN - /* On Windows we should activate main window first, - * because entering fullscreen there doesn't means window will be auto-activated, - * so no window-activation event will be received - * and no keyboard-hook created otherwise... */ - if (m_uScreenId == 0) - setWindowState(windowState() | Qt::WindowActive); -#endif /* Q_WS_WIN */ - - /* Show in fullscreen mode: */ - showFullScreen(); - - /* Make sure the window is placed on valid screen again - * after window is shown & window's decorations applied. - * That is required (still?) due to X11 Window Geometry Rules. */ - placeOnScreen(); - - /* Return early: */ - return; - } - } - } - /* Hide in other cases: */ - hide(); + /* Make sure this window should be shown at all: */ + if (!uisession()->isScreenVisible(m_uScreenId)) + return hide(); + + /* Make sure this window has fullscreen logic: */ + UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast(machineLogic()); + if (!pFullscreenLogic) + return hide(); + + /* Make sure this window mapped to some host-screen: */ + if (!pFullscreenLogic->hasHostScreenForGuestScreen(m_uScreenId)) + return hide(); + + /* Make sure this window is not minimized: */ + if (isMinimized()) + return; + + /* Make sure this window is maximized and placed on valid screen: */ + placeOnScreen(); + +#ifdef Q_WS_MAC + /* ML and next using native stuff, so we can call for simple show(): */ + if (vboxGlobal().osRelease() > MacOSXRelease_Lion) show(); + /* Lion and previous using Qt stuff, so we should call for showFullScreen(): */ + else showFullScreen(); +#else /* !Q_WS_MAC */ + /* Show in fullscreen mode: */ + showFullScreen(); +#endif /* !Q_WS_MAC */ + +#ifdef Q_WS_X11 + /* Make sure the window is placed on valid screen again + * after window is shown & window's decorations applied. + * That is required (still?) due to X11 Window Geometry Rules. */ + placeOnScreen(); +#endif /* Q_WS_X11 */ } void UIMachineWindowFullscreen::updateAppearanceOf(int iElement) diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineWindowFullscreen.h b/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineWindowFullscreen.h index c1caf08d1..8b733590d 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineWindowFullscreen.h +++ b/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineWindowFullscreen.h @@ -30,22 +30,48 @@ class UIMachineWindowFullscreen : public UIMachineWindow { Q_OBJECT; +#ifdef RT_OS_DARWIN +signals: + /** Mac OS X: Notifies listener about native 'fullscreen' will be entered. */ + void sigNotifyAboutNativeFullscreenWillEnter(); + /** Mac OS X: Notifies listener about native 'fullscreen' entered. */ + void sigNotifyAboutNativeFullscreenDidEnter(); + /** Mac OS X: Notifies listener about native 'fullscreen' will be exited. */ + void sigNotifyAboutNativeFullscreenWillExit(); + /** Mac OS X: Notifies listener about native 'fullscreen' exited. */ + void sigNotifyAboutNativeFullscreenDidExit(); +#endif /* RT_OS_DARWIN */ + protected: /* Constructor: */ UIMachineWindowFullscreen(UIMachineLogic *pMachineLogic, ulong uScreenId); +#ifdef Q_WS_MAC + /** Mac OS X: Handles native notifications @a strNativeNotificationName for 'fullscreen' window. */ + void handleNativeNotification(const QString &strNativeNotificationName); + /** Mac OS X: Returns whether window is in 'fullscreen' transition. */ + bool isInFullscreenTransition() const { return m_fIsInFullscreenTransition; } +#endif /* Q_WS_MAC */ + private slots: /* Session event-handlers: */ void sltMachineStateChanged(); - /* Show in necessary mode: */ - void sltShowInNecessaryMode() { showInNecessaryMode(); } - /* Popup main-menu: */ void sltPopupMainMenu(); +#ifdef RT_OS_DARWIN + /** Mac OS X: Commands @a pMachineWindow to enter native 'fullscreen' mode if possible. */ + void sltEnterNativeFullscreen(UIMachineWindow *pMachineWindow); + /** Mac OS X: Commands @a pMachineWindow to exit native 'fullscreen' mode if possible. */ + void sltExitNativeFullscreen(UIMachineWindow *pMachineWindow); +#endif /* RT_OS_DARWIN */ + + /** Revokes keyboard-focus. */ + void sltRevokeFocus(); + private: /* Prepare helpers: */ @@ -69,6 +95,13 @@ private: QMenu *m_pMainMenu; UIRuntimeMiniToolBar *m_pMiniToolBar; +#ifdef Q_WS_MAC + /** Mac OS X: Reflects whether window is in 'fullscreen' transition. */ + bool m_fIsInFullscreenTransition; + /** Mac OS X: Allows 'fullscreen' API access: */ + friend class UIMachineLogicFullscreen; +#endif /* Q_WS_MAC */ + /* Factory support: */ friend class UIMachineWindow; }; diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineLogicNormal.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineLogicNormal.cpp index 040c6d8ff..2a3f79f2a 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineLogicNormal.cpp +++ b/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineLogicNormal.cpp @@ -98,11 +98,11 @@ void UIMachineLogicNormal::prepareActionConnections() /* "View" actions connections: */ connect(gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToFullscreen())); + this, SLOT(sltChangeVisualStateToFullscreen())); connect(gActionPool->action(UIActionIndexRuntime_Toggle_Seamless), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToSeamless())); + this, SLOT(sltChangeVisualStateToSeamless())); connect(gActionPool->action(UIActionIndexRuntime_Toggle_Scale), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToScale())); + this, SLOT(sltChangeVisualStateToScale())); /* "Device" actions connections: */ connect(gActionPool->action(UIActionIndexRuntime_Menu_SharedFolders)->menu(), SIGNAL(aboutToShow()), @@ -156,11 +156,11 @@ void UIMachineLogicNormal::cleanupActionConnections() { /* "View" actions disconnections: */ disconnect(gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToFullscreen())); + this, SLOT(sltChangeVisualStateToFullscreen())); disconnect(gActionPool->action(UIActionIndexRuntime_Toggle_Seamless), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToSeamless())); + this, SLOT(sltChangeVisualStateToSeamless())); disconnect(gActionPool->action(UIActionIndexRuntime_Toggle_Scale), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToScale())); + this, SLOT(sltChangeVisualStateToScale())); /* Call to base-class: */ UIMachineLogic::cleanupActionConnections(); diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp index 049e886bf..2aad2f1f1 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp +++ b/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp @@ -600,12 +600,16 @@ bool UIMachineWindowNormal::event(QEvent *pEvent) void UIMachineWindowNormal::showInNecessaryMode() { - /* Show window if we have to: */ - if (uisession()->isScreenVisible(m_uScreenId)) - show(); - /* Else hide window: */ - else - hide(); + /* Make sure this window should be shown at all: */ + if (!uisession()->isScreenVisible(m_uScreenId)) + return hide(); + + /* Make sure this window is not minimized: */ + if (isMinimized()) + return; + + /* Show in normal mode: */ + show(); } /** diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/scale/UIMachineLogicScale.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/scale/UIMachineLogicScale.cpp index b423ea4b1..832e11176 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/scale/UIMachineLogicScale.cpp +++ b/src/VBox/Frontends/VirtualBox/src/runtime/scale/UIMachineLogicScale.cpp @@ -75,11 +75,11 @@ void UIMachineLogicScale::prepareActionConnections() /* "View" actions connections: */ connect(gActionPool->action(UIActionIndexRuntime_Toggle_Scale), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToNormal())); + this, SLOT(sltChangeVisualStateToNormal())); connect(gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToFullscreen())); + this, SLOT(sltChangeVisualStateToFullscreen())); connect(gActionPool->action(UIActionIndexRuntime_Toggle_Seamless), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToSeamless())); + this, SLOT(sltChangeVisualStateToSeamless())); } void UIMachineLogicScale::prepareMachineWindows() @@ -125,11 +125,11 @@ void UIMachineLogicScale::cleanupActionConnections() { /* "View" actions disconnections: */ disconnect(gActionPool->action(UIActionIndexRuntime_Toggle_Scale), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToNormal())); + this, SLOT(sltChangeVisualStateToNormal())); disconnect(gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToFullscreen())); + this, SLOT(sltChangeVisualStateToFullscreen())); disconnect(gActionPool->action(UIActionIndexRuntime_Toggle_Seamless), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToSeamless())); + this, SLOT(sltChangeVisualStateToSeamless())); /* Call to base-class: */ UIMachineLogic::cleanupActionConnections(); diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/scale/UIMachineWindowScale.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/scale/UIMachineWindowScale.cpp index 340736523..891cd4ee2 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/scale/UIMachineWindowScale.cpp +++ b/src/VBox/Frontends/VirtualBox/src/runtime/scale/UIMachineWindowScale.cpp @@ -196,12 +196,16 @@ void UIMachineWindowScale::cleanupMenu() void UIMachineWindowScale::showInNecessaryMode() { - /* Show window if we have to: */ - if (uisession()->isScreenVisible(m_uScreenId)) - show(); - /* Else hide window: */ - else - hide(); + /* Make sure this window should be shown at all: */ + if (!uisession()->isScreenVisible(m_uScreenId)) + return hide(); + + /* Make sure this window is not minimized: */ + if (isMinimized()) + return; + + /* Show in normal mode: */ + show(); } bool UIMachineWindowScale::event(QEvent *pEvent) diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineLogicSeamless.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineLogicSeamless.cpp index 998705057..9eb85fbf3 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineLogicSeamless.cpp +++ b/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineLogicSeamless.cpp @@ -81,9 +81,9 @@ void UIMachineLogicSeamless::maybeAdjustGuestScreenSize() { /* We should rebuild screen-layout: */ m_pScreenLayout->rebuild(); - /* We should update machine-windows sizes: */ + /* Make sure all machine-window(s) have proper geometry: */ foreach (UIMachineWindow *pMachineWindow, machineWindows()) - pMachineWindow->handleScreenGeometryChange(); + pMachineWindow->showInNecessaryMode(); } int UIMachineLogicSeamless::hostScreenForGuestScreen(int iScreenId) const @@ -139,12 +139,19 @@ void UIMachineLogicSeamless::sltMachineStateChanged() uisession()->forgetPreviousMachineState(); /* We should rebuild screen-layout: */ m_pScreenLayout->rebuild(); - /* We should update machine-windows sizes: */ + /* Make sure all machine-window(s) have proper geometry: */ foreach (UIMachineWindow *pMachineWindow, machineWindows()) - pMachineWindow->handleScreenGeometryChange(); + pMachineWindow->showInNecessaryMode(); } } +void UIMachineLogicSeamless::sltScreenLayoutChanged() +{ + /* Make sure all machine-window(s) have proper geometry: */ + foreach (UIMachineWindow *pMachineWindow, machineWindows()) + pMachineWindow->showInNecessaryMode(); +} + void UIMachineLogicSeamless::sltGuestMonitorChange(KGuestMonitorChangedEventType changeType, ulong uScreenId, QRect screenGeo) { LogRelFlow(("UIMachineLogicSeamless: Guest-screen count changed.\n")); @@ -199,11 +206,11 @@ void UIMachineLogicSeamless::prepareActionConnections() /* "View" actions connections: */ connect(gActionPool->action(UIActionIndexRuntime_Toggle_Seamless), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToNormal())); + this, SLOT(sltChangeVisualStateToNormal())); connect(gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToFullscreen())); + this, SLOT(sltChangeVisualStateToFullscreen())); connect(gActionPool->action(UIActionIndexRuntime_Toggle_Scale), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToScale())); + this, SLOT(sltChangeVisualStateToScale())); } void UIMachineLogicSeamless::prepareMachineWindows() @@ -212,23 +219,22 @@ void UIMachineLogicSeamless::prepareMachineWindows() if (isMachineWindowsCreated()) return; -#ifdef Q_WS_MAC // TODO: Is that really need here? +#ifdef Q_WS_MAC /* We have to make sure that we are getting the front most process. * This is necessary for Qt versions > 4.3.3: */ - ::darwinSetFrontMostProcess(); + darwinSetFrontMostProcess(); #endif /* Q_WS_MAC */ /* Update the multi-screen layout: */ m_pScreenLayout->update(); - /* Create machine window(s): */ + /* Create machine-window(s): */ for (uint cScreenId = 0; cScreenId < session().GetMachine().GetMonitorCount(); ++cScreenId) addMachineWindow(UIMachineWindow::create(this, cScreenId)); /* Connect multi-screen layout change handler: */ - for (int i = 0; i < machineWindows().size(); ++i) - connect(m_pScreenLayout, SIGNAL(sigScreenLayoutChanged()), - static_cast(machineWindows()[i]), SLOT(sltShowInNecessaryMode())); + connect(m_pScreenLayout, SIGNAL(sigScreenLayoutChanged()), + this, SLOT(sltScreenLayoutChanged())); /* Mark machine-window(s) created: */ setMachineWindowsCreated(true); @@ -253,7 +259,7 @@ void UIMachineLogicSeamless::cleanupMachineWindows() /* Mark machine-window(s) destroyed: */ setMachineWindowsCreated(false); - /* Cleanup machine-window(s): */ + /* Destroy machine-window(s): */ foreach (UIMachineWindow *pMachineWindow, machineWindows()) UIMachineWindow::destroy(pMachineWindow); } @@ -262,11 +268,11 @@ void UIMachineLogicSeamless::cleanupActionConnections() { /* "View" actions disconnections: */ disconnect(gActionPool->action(UIActionIndexRuntime_Toggle_Seamless), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToNormal())); + this, SLOT(sltChangeVisualStateToNormal())); disconnect(gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToFullscreen())); + this, SLOT(sltChangeVisualStateToFullscreen())); disconnect(gActionPool->action(UIActionIndexRuntime_Toggle_Scale), SIGNAL(triggered(bool)), - uisession(), SLOT(sltChangeVisualStateToScale())); + this, SLOT(sltChangeVisualStateToScale())); /* Call to base-class: */ UIMachineLogic::cleanupActionConnections(); diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineLogicSeamless.h b/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineLogicSeamless.h index 8bebeddb0..e2cf3003a 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineLogicSeamless.h +++ b/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineLogicSeamless.h @@ -53,6 +53,9 @@ private slots: /* Handler: Console callback stuff: */ void sltMachineStateChanged(); + /** Updates machine-window(s) location/size on screen-layout changes. */ + void sltScreenLayoutChanged(); + void sltGuestMonitorChange(KGuestMonitorChangedEventType changeType, ulong uScreenId, QRect screenGeo); void sltHostScreenCountChanged(); diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineWindowSeamless.cpp b/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineWindowSeamless.cpp index bc87b27d9..4b3a8a71e 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineWindowSeamless.cpp +++ b/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineWindowSeamless.cpp @@ -70,6 +70,12 @@ void UIMachineWindowSeamless::sltPopupMainMenu() } } +void UIMachineWindowSeamless::sltRevokeFocus() +{ + /* Revoke stolen focus: */ + m_pMachineView->setFocus(); +} + void UIMachineWindowSeamless::prepareMenu() { /* Call to base-class: */ @@ -151,6 +157,7 @@ void UIMachineWindowSeamless::prepareMiniToolbar() gActionPool->action(UIActionIndexRuntime_Toggle_Seamless), SLOT(trigger())); connect(m_pMiniToolBar, SIGNAL(sigCloseAction()), gActionPool->action(UIActionIndexRuntime_Simple_Close), SLOT(trigger())); + connect(m_pMiniToolBar, SIGNAL(sigNotifyAboutFocusStolen()), this, SLOT(sltRevokeFocus())); } #endif /* !Q_WS_MAC */ @@ -213,28 +220,28 @@ void UIMachineWindowSeamless::placeOnScreen() void UIMachineWindowSeamless::showInNecessaryMode() { - /* Should we show window?: */ - if (uisession()->isScreenVisible(m_uScreenId)) - { - /* Do we have the seamless logic? */ - if (UIMachineLogicSeamless *pSeamlessLogic = qobject_cast(machineLogic())) - { - /* Is this guest screen has own host screen? */ - if (pSeamlessLogic->hasHostScreenForGuestScreen(m_uScreenId)) - { - /* Make sure the window is maximized and placed on valid screen: */ - placeOnScreen(); + /* Make sure this window should be shown at all: */ + if (!uisession()->isScreenVisible(m_uScreenId)) + return hide(); - /* Show in normal mode: */ - show(); + /* Make sure this window has seamless logic: */ + UIMachineLogicSeamless *pSeamlessLogic = qobject_cast(machineLogic()); + if (!pSeamlessLogic) + return hide(); - /* Return early: */ - return; - } - } - } - /* Hide in other cases: */ - hide(); + /* Make sure this window mapped to some host-screen: */ + if (!pSeamlessLogic->hasHostScreenForGuestScreen(m_uScreenId)) + return hide(); + + /* Make sure this window is not minimized: */ + if (isMinimized()) + return; + + /* Make sure this window is maximized and placed on valid screen: */ + placeOnScreen(); + + /* Show in normal mode: */ + show(); } #ifndef Q_WS_MAC diff --git a/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineWindowSeamless.h b/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineWindowSeamless.h index 007ee30e8..a7bfea8ac 100644 --- a/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineWindowSeamless.h +++ b/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineWindowSeamless.h @@ -42,12 +42,12 @@ private slots: void sltMachineStateChanged(); #endif /* !Q_WS_MAC */ - /* Show in necessary mode: */ - void sltShowInNecessaryMode() { showInNecessaryMode(); } - /* Popup main menu: */ void sltPopupMainMenu(); + /** Revokes keyboard-focus. */ + void sltRevokeFocus(); + private: /* Prepare helpers: */ diff --git a/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsInput.cpp b/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsInput.cpp index 59c4ac0d6..b2dd4949e 100644 --- a/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsInput.cpp +++ b/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsInput.cpp @@ -496,10 +496,13 @@ void UIHotKeyTableModel::sort(int iColumn, Qt::SortOrder order /* = Qt::Ascendin void UIHotKeyTableModel::applyFilter() { - /* Erase items first: */ - beginRemoveRows(QModelIndex(), 0, m_filteredShortcuts.size() - 1); - m_filteredShortcuts.clear(); - endRemoveRows(); + /* Erase items first if necessary: */ + if (!m_filteredShortcuts.isEmpty()) + { + beginRemoveRows(QModelIndex(), 0, m_filteredShortcuts.size() - 1); + m_filteredShortcuts.clear(); + endRemoveRows(); + } /* If filter is empty: */ if (m_strFilter.isEmpty()) @@ -520,8 +523,13 @@ void UIHotKeyTableModel::applyFilter() m_filteredShortcuts << item; } } - beginInsertRows(QModelIndex(), 0, m_filteredShortcuts.size() - 1); - endInsertRows(); + + /* Add items finally if necessary: */ + if (!m_filteredShortcuts.isEmpty()) + { + beginInsertRows(QModelIndex(), 0, m_filteredShortcuts.size() - 1); + endInsertRows(); + } } diff --git a/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.cpp b/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.cpp index 987d5276c..98c5ea58b 100644 --- a/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.cpp +++ b/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.cpp @@ -192,11 +192,6 @@ void UIRuntimeMiniToolBar::adjustGeometry() /* Simulate toolbar auto-hiding: */ simulateToolbarAutoHiding(); - - /* Due to [probably] Qt bug QMdiSubWindow still - * can receive focus even if focus policy is Qt::NoFocus, - * We should return the focus to our parent: */ - parentWidget()->setFocus(); } void UIRuntimeMiniToolBar::sltHandleToolbarResize() @@ -259,6 +254,8 @@ void UIRuntimeMiniToolBar::prepare() /* Prepare mini-toolbar: */ m_pToolbar = new UIMiniToolBar; { + /* Make sure we have no focus: */ + m_pToolbar->setFocusPolicy(Qt::NoFocus); /* Propagate known options to child: */ m_pToolbar->setAutoHide(m_fAutoHide); m_pToolbar->setAlignment(m_alignment); @@ -270,14 +267,16 @@ void UIRuntimeMiniToolBar::prepare() /* Configure child connections: */ connect(m_pToolbar, SIGNAL(sigResized()), this, SLOT(sltHandleToolbarResize())); connect(m_pToolbar, SIGNAL(sigAutoHideToggled()), this, SLOT(sltAutoHideToggled())); +#ifndef RT_OS_DARWIN connect(m_pToolbar, SIGNAL(sigMinimizeAction()), this, SIGNAL(sigMinimizeAction())); +#endif /* !RT_OS_DARWIN */ connect(m_pToolbar, SIGNAL(sigExitAction()), this, SIGNAL(sigExitAction())); connect(m_pToolbar, SIGNAL(sigCloseAction()), this, SIGNAL(sigCloseAction())); /* Add child to mdi-area: */ m_pEmbeddedToolbar = m_pMdiArea->addSubWindow(m_pToolbar, Qt::Window | Qt::FramelessWindowHint); /* Make sure we have no focus: */ - m_pToolbar->setFocusPolicy(Qt::NoFocus); m_pEmbeddedToolbar->setFocusPolicy(Qt::NoFocus); + m_pEmbeddedToolbar->installEventFilter(this); } /* Prepare hover-enter/leave timers: */ @@ -339,6 +338,19 @@ void UIRuntimeMiniToolBar::leaveEvent(QEvent*) m_pHoverLeaveTimer->start(); } +bool UIRuntimeMiniToolBar::eventFilter(QObject *pWatched, QEvent *pEvent) +{ + /* Due to Qt bug QMdiArea can + * 1. steal focus from current application focus-widget + * 3. and even request focus stealing if QMdiArea hidden yet. + * We have to notify listeners about such facts.. */ + if (pWatched && m_pEmbeddedToolbar && pWatched == m_pEmbeddedToolbar && + pEvent->type() == QEvent::FocusIn) + emit sigNotifyAboutFocusStolen(); + /* Call to base-class: */ + return QWidget::eventFilter(pWatched, pEvent); +} + void UIRuntimeMiniToolBar::updateAutoHideAnimationBounds() { /* Update animation: */ @@ -426,7 +438,9 @@ UIMiniToolBar::UIMiniToolBar() /* Variables: Contents stuff: */ , m_pAutoHideAction(0) , m_pLabel(0) +#ifndef RT_OS_DARWIN , m_pMinimizeAction(0) +#endif /* !RT_OS_DARWIN */ , m_pRestoreAction(0) , m_pCloseAction(0) /* Variables: Menu stuff: */ @@ -606,12 +620,14 @@ void UIMiniToolBar::prepare() /* Right label margin: */ m_margins << widgetForAction(addWidget(new QWidget)); +#ifndef RT_OS_DARWIN /* Minimize action: */ m_pMinimizeAction = new QAction(this); m_pMinimizeAction->setIcon(UIIconPool::iconSet(":/minimize_16px.png")); m_pMinimizeAction->setToolTip(tr("Minimize Window")); connect(m_pMinimizeAction, SIGNAL(triggered()), this, SIGNAL(sigMinimizeAction())); addAction(m_pMinimizeAction); +#endif /* !RT_OS_DARWIN */ /* Exit action: */ m_pRestoreAction = new QAction(this); diff --git a/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.h b/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.h index 7c3215ce4..26b85a4d6 100644 --- a/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.h +++ b/src/VBox/Frontends/VirtualBox/src/widgets/UIMiniToolBar.h @@ -53,7 +53,9 @@ class UIRuntimeMiniToolBar : public QWidget signals: /* Notifiers: Action stuff: */ +#ifndef RT_OS_DARWIN void sigMinimizeAction(); +#endif /* !RT_OS_DARWIN */ void sigExitAction(); void sigCloseAction(); @@ -61,6 +63,9 @@ signals: void sigHoverEnter(); void sigHoverLeave(); + /** Notifies listeners about we stole focus. */ + void sigNotifyAboutFocusStolen(); + public: /* Constructor/destructor: */ @@ -107,6 +112,10 @@ private: void enterEvent(QEvent *pEvent); void leaveEvent(QEvent *pEvent); + /** Filters @a pEvent if this object has been + * installed as an event-filter for the @a pWatched. */ + bool eventFilter(QObject *pWatched, QEvent *pEvent); + /* Helper: Hover stuff: */ void updateAutoHideAnimationBounds(); void simulateToolbarAutoHiding(); @@ -151,7 +160,9 @@ signals: /* Notifiers: Action stuff: */ void sigAutoHideToggled(); +#ifndef RT_OS_DARWIN void sigMinimizeAction(); +#endif /* !RT_OS_DARWIN */ void sigExitAction(); void sigCloseAction(); @@ -201,7 +212,9 @@ private: /* Variables: Contents stuff: */ QAction *m_pAutoHideAction; QLabel *m_pLabel; +#ifndef RT_OS_DARWIN QAction *m_pMinimizeAction; +#endif /* !RT_OS_DARWIN */ QAction *m_pRestoreAction; QAction *m_pCloseAction; diff --git a/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UIWizardNewVMPageBasic1.cpp b/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UIWizardNewVMPageBasic1.cpp index 40d264b1f..37f1607e8 100644 --- a/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UIWizardNewVMPageBasic1.cpp +++ b/src/VBox/Frontends/VirtualBox/src/wizards/newvm/UIWizardNewVMPageBasic1.cpp @@ -103,8 +103,8 @@ static const osTypePattern gs_OSTypePattern[] = { QRegExp("((Mac)|(Tig)|(Leop)|(os[ ]*x)).*32", Qt::CaseInsensitive), "MacOS" }, /* Code names for Linux distributions: */ - { QRegExp("((edgy)|(feisty)|(gutsy)|(hardy)|(intrepid)|(jaunty)|(karmic)|(lucid)|(maverick)|(natty)|(oneiric)|(precise)|(quantal)|(raring)).*64", Qt::CaseInsensitive), "Ubuntu_64" }, - { QRegExp("((edgy)|(feisty)|(gutsy)|(hardy)|(intrepid)|(jaunty)|(karmic)|(lucid)|(maverick)|(natty)|(oneiric)|(precise)|(quantal)|(raring)).*32", Qt::CaseInsensitive), "Ubuntu" }, + { QRegExp("((edgy)|(feisty)|(gutsy)|(hardy)|(intrepid)|(jaunty)|(karmic)|(lucid)|(maverick)|(natty)|(oneiric)|(precise)|(quantal)|(raring)|(saucy)|(trusty)).*64", Qt::CaseInsensitive), "Ubuntu_64" }, + { QRegExp("((edgy)|(feisty)|(gutsy)|(hardy)|(intrepid)|(jaunty)|(karmic)|(lucid)|(maverick)|(natty)|(oneiric)|(precise)|(quantal)|(raring)|(saucy)|(trusty)).*32", Qt::CaseInsensitive), "Ubuntu" }, { QRegExp("((sarge)|(etch)|(lenny)|(squeeze)|(wheezy)|(jessie)|(sid)).*64", Qt::CaseInsensitive), "Debian_64" }, { QRegExp("((sarge)|(etch)|(lenny)|(squeeze)|(wheezy)|(jessie)|(sid)).*32", Qt::CaseInsensitive), "Debian" }, { QRegExp("((moonshine)|(werewolf)|(sulphur)|(cambridge)|(leonidas)|(constantine)|(goddard)|(laughlin)|(lovelock)|(verne)|(beefy)|(spherical)).*64", Qt::CaseInsensitive), "Fedora_64" }, diff --git a/src/VBox/GuestHost/OpenGL/include/cr_server.h b/src/VBox/GuestHost/OpenGL/include/cr_server.h index 8efdef54a..b215d4cba 100644 --- a/src/VBox/GuestHost/OpenGL/include/cr_server.h +++ b/src/VBox/GuestHost/OpenGL/include/cr_server.h @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -232,7 +233,7 @@ typedef struct { GLboolean bVisible; /*guest window is visible*/ GLubyte u8Unused; /*redirect to FBO instead of real host window*/ GLboolean bFbDraw; /*GL_FRONT buffer is drawn to directly*/ - GLboolean fReserved; + GLboolean fIsDummyRefference; GLint cVisibleRects; /*count of visible rects*/ GLint *pVisibleRects; /*visible rects left, top, right, bottom*/ @@ -406,8 +407,6 @@ typedef struct { uint32_t fBlitterMode; CR_BLITTER Blitter; - VBOXCRCMD_CLTINFO CltInfo; - CR_SERVER_RPW RpwWorker; /** configuration options */ @@ -485,6 +484,8 @@ typedef struct { SPUDispatchTable TmpCtxDispatch; + VBOXCRCMD_SVRENABLE_INFO CrCmdClientInfo; + #ifdef VBOX_WITH_CRSERVER_DUMPER CR_RECORDER Recorder; CR_BLITTER RecorderBlitter; @@ -565,9 +566,13 @@ extern DECLEXPORT(void) crServerVBoxSetNotifyEventCB(PFNCRSERVERNOTIFYEVENT pfnC extern DECLEXPORT(int32_t) crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t cbCmd); extern DECLEXPORT(int32_t) crVBoxServerCrHgsmiCtl(struct VBOXVDMACMD_CHROMIUM_CTL *pCtl, uint32_t cbCtl); -extern DECLEXPORT(int32_t) crVBoxServerCrCmdNotifyCmds(); #endif +extern DECLEXPORT(int32_t) crVBoxServerHgcmEnable(HVBOXCRCMDCTL_REMAINING_HOST_COMMAND hRHCmd, PFNVBOXCRCMDCTL_REMAINING_HOST_COMMAND pfnRHCmd); +extern DECLEXPORT(int32_t) crVBoxServerHgcmDisable(); + +extern int crVBoxServerHostCtl(VBOXCRCMDCTL *pCtl, uint32_t cbCtl); + #ifdef __cplusplus } #endif diff --git a/src/VBox/GuestHost/OpenGL/include/cr_vreg.h b/src/VBox/GuestHost/OpenGL/include/cr_vreg.h index 353178d24..0f5786bea 100644 --- a/src/VBox/GuestHost/OpenGL/include/cr_vreg.h +++ b/src/VBox/GuestHost/OpenGL/include/cr_vreg.h @@ -63,6 +63,20 @@ DECLINLINE(void) VBoxRectScaled(const RTRECT *pRect, float xScale, float yScale, *pResult = *pRect; VBoxRectScale(pResult, xScale, yScale); } + +DECLINLINE(void) VBoxRectUnscale(PRTRECT pRect, float xScale, float yScale) +{ + pRect->xLeft = CR_FLOAT_RCAST(int32_t, pRect->xLeft / xScale); + pRect->yTop = CR_FLOAT_RCAST(int32_t, pRect->yTop / yScale); + pRect->xRight = CR_FLOAT_RCAST(int32_t, pRect->xRight / xScale); + pRect->yBottom = CR_FLOAT_RCAST(int32_t, pRect->yBottom / yScale); +} + +DECLINLINE(void) VBoxRectUnscaled(const RTRECT *pRect, float xScale, float yScale, PRTRECT pResult) +{ + *pResult = *pRect; + VBoxRectUnscale(pResult, xScale, yScale); +} #endif DECLINLINE(void) VBoxRectIntersect(PRTRECT pRect1, const RTRECT * pRect2) @@ -190,8 +204,8 @@ VBOXVREGDECL(int) VBoxVrListClone(const VBOXVR_LIST *pList, VBOXVR_LIST *pDstLis VBOXVREGDECL(int) VBoxVrListRectsIntersect(PVBOXVR_LIST pList, uint32_t cRects, const RTRECT * aRects, bool *pfChanged); VBOXVREGDECL(int) VBoxVrListIntersect(PVBOXVR_LIST pList, const VBOXVR_LIST *pList2, bool *pfChanged); -VBOXVREGDECL(int) VBoxVrInit(); -VBOXVREGDECL(void) VBoxVrTerm(); +VBOXVREGDECL(int) VBoxVrInit(void); +VBOXVREGDECL(void) VBoxVrTerm(void); typedef struct VBOXVR_LIST_ITERATOR { diff --git a/src/VBox/GuestHost/OpenGL/packer/pack_pixels.c b/src/VBox/GuestHost/OpenGL/packer/pack_pixels.c index 19f2a1d5b..2508643a9 100644 --- a/src/VBox/GuestHost/OpenGL/packer/pack_pixels.c +++ b/src/VBox/GuestHost/OpenGL/packer/pack_pixels.c @@ -143,7 +143,8 @@ void PACK_APIENTRY crPackBitmap(GLsizei width, GLsizei height, WRITE_DATA( 24, GLuint, noimagedata ); WRITE_DATA( 28, GLint, (GLint) (uintptr_t) bitmap); - crBitmapCopy(width, height, (GLubyte *)(data_ptr + 32), bitmap, unpack); + if (!noimagedata) + crBitmapCopy(width, height, (GLubyte *)(data_ptr + 32), bitmap, unpack); crHugePacket( CR_BITMAP_OPCODE, data_ptr ); crPackFree( data_ptr ); diff --git a/src/VBox/GuestHost/OpenGL/util/blitter.cpp b/src/VBox/GuestHost/OpenGL/util/blitter.cpp index 8dcf1cb67..a14c0916a 100644 --- a/src/VBox/GuestHost/OpenGL/util/blitter.cpp +++ b/src/VBox/GuestHost/OpenGL/util/blitter.cpp @@ -1575,7 +1575,7 @@ static int ctTdBltSdCreate(PCR_BLITTER pBlitter, uint32_t width, uint32_t height static int ctTdBltSdGet(PCR_TEXDATA pTex, uint32_t width, uint32_t height, PCR_TEXDATA *ppScaledCache) { - Assert(pTex->Flags.Entered); + Assert(CrBltIsEntered(pTex->pBlitter)); PCR_TEXDATA pScaledCache; diff --git a/src/VBox/GuestHost/OpenGL/util/htable.cpp b/src/VBox/GuestHost/OpenGL/util/htable.cpp index f84804f6e..bb9434c7a 100644 --- a/src/VBox/GuestHost/OpenGL/util/htable.cpp +++ b/src/VBox/GuestHost/OpenGL/util/htable.cpp @@ -65,7 +65,7 @@ int crHTableRealloc(PCRHTABLE pTbl, uint32_t cNewSize) void **pvNewData = (void**)RTMemAllocZ(sizeof (pTbl->paData[0]) * cNewSize); if (!pvNewData) { - WARN(("RTMemAllocZ failed for size (%d)", sizeof (pTbl->paData[0]) * cNewSize)); + WARN(("RTMemAllocZ failed for size (%d)", (int)(sizeof (pTbl->paData[0]) * cNewSize))); return VERR_NO_MEMORY; } memcpy(pvNewData, pTbl->paData, sizeof (pTbl->paData[0]) * pTbl->cSize); diff --git a/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp b/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp index 673699b2a..be095dc76 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp +++ b/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2012 Oracle Corporation + * Copyright (C) 2006-2014 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -138,11 +138,88 @@ static VBOXNETFLTGLOBALS g_VBoxNetFltGlobals; * It is used for tagging mbufs. */ static mbuf_tag_id_t g_idTag; -/** the offset of the struct ifnet::if_pcount variable. */ +/** The offset of the struct ifnet::if_pcount variable. + * @remarks Initial value is valid for Lion and earlier. We adjust it on attach + * for later releases. */ static unsigned g_offIfNetPCount = sizeof(void *) * (1 /*if_softc*/ + 1 /*if_name*/ + 2 /*if_link*/ + 2 /*if_addrhead*/ + 1 /*if_check_multi*/) + sizeof(u_long) /*if_refcnt*/; /** Macro for accessing ifnet::if_pcount. */ #define VBOX_GET_PCOUNT(pIfNet) ( *(int *)((uintptr_t)pIfNet + g_offIfNetPCount) ) +/** The size of area of ifnet structure we try to locate if_pcount in. */ +#define VBOXNETFLT_DARWIN_IFNET_SIZE 256 +/** Indicates whether g_offIfNetPCount has been adjusted already (no point in + * doing it more than once). */ +static bool g_fNetPCountFound = false; + + +/** + * Change the promiscuous setting and try spot the changed in @a pIfNet. + * + * @returns Offset of potential p_count field. + * @param pIfNet The interface we're attaching to. + * @param iPromisc Whether to enable (1) or disable (0) promiscuous mode. + * + * @note This implementation relies on if_pcount to be aligned on sizeof(int). + */ +static unsigned vboxNetFltDarwinSetAndDiff(ifnet_t pIfNet, int iPromisc) +{ + int aiSavedState[VBOXNETFLT_DARWIN_IFNET_SIZE / sizeof(int)]; + memcpy(aiSavedState, pIfNet, sizeof(aiSavedState)); + + ifnet_set_promiscuous(pIfNet, iPromisc); + + int const iDiff = iPromisc ? 1 : -1; + + /* + * We assume that ifnet structure will never have less members in front of if_pcount + * than it used to have in Lion. If this turns out to be false assumption we will + * have to start from zero offset. + */ + for (unsigned i = g_offIfNetPCount / sizeof(int); i < RT_ELEMENTS(aiSavedState); i++) + if (((int*)pIfNet)[i] - aiSavedState[i] == iDiff) + return i * sizeof(int); + + return 0; +} + + +/** + * Detect and adjust the offset of ifnet::if_pcount. + * + * @param pIfNet The interface we're attaching to. + */ +static void vboxNetFltDarwinDetectPCountOffset(ifnet_t pIfNet) +{ + if (g_fNetPCountFound) + return; + + /* + * It would be nice to use locking at this point, but it is not available via KPI. + * This is why we try several times. At each attempt we modify if_pcount four times + * to rule out false detections. + */ + unsigned offTry1, offTry2, offTry3, offTry4; + for (int iAttempt = 0; iAttempt < 3; iAttempt++) + { + offTry1 = vboxNetFltDarwinSetAndDiff(pIfNet, 1); + offTry2 = vboxNetFltDarwinSetAndDiff(pIfNet, 1); + offTry3 = vboxNetFltDarwinSetAndDiff(pIfNet, 0); + offTry4 = vboxNetFltDarwinSetAndDiff(pIfNet, 0); + if (offTry1 == offTry2 && offTry2 == offTry3 && offTry3 == offTry4) + { + if (g_offIfNetPCount != offTry1) + { + Log(("VBoxNetFltDarwinDetectPCountOffset: Adjusted if_pcount offset to %x from %x.\n", offTry1, g_offIfNetPCount)); + g_offIfNetPCount = offTry1; + g_fNetPCountFound = true; + } + break; + } + } + + if (g_offIfNetPCount != offTry1) + LogRel(("VBoxNetFlt: Failed to detect promiscuous count, all traffic may reach wire (%x != %x).\n", g_offIfNetPCount, offTry1)); +} /** @@ -955,6 +1032,9 @@ static int vboxNetFltDarwinAttachToInterface(PVBOXNETFLTINS pThis, bool fRedisco ASMAtomicUoWritePtr(&pThis->u.s.pIfNet, pIfNet); RTSpinlockReleaseNoInts(pThis->hSpinlock); + /* Adjust g_offIfNetPCount as it varies for different versions of xnu. */ + vboxNetFltDarwinDetectPCountOffset(pIfNet); + /* Prevent stuck-in-dock issue by associating interface receive thread with kernel thread. */ vboxNetFltSendDummy(pIfNet); diff --git a/src/VBox/HostServices/SharedOpenGL/Makefile.kmk b/src/VBox/HostServices/SharedOpenGL/Makefile.kmk index baf6c702e..971c1c9ae 100644 --- a/src/VBox/HostServices/SharedOpenGL/Makefile.kmk +++ b/src/VBox/HostServices/SharedOpenGL/Makefile.kmk @@ -264,6 +264,12 @@ VBoxOGLrenderspu_OBJCFLAGS.darwin = -Wno-shadow VBoxOGLrenderspu_SOURCES.darwin = \ render/renderspu_cocoa.c \ render/renderspu_cocoa_helper.m +ifdef VBOX_WITH_CRHGSMI +VBoxOGLrenderspu_DEFS += VBOX_WITH_CRHGSMI +endif +ifdef VBOX_WITH_VDMA +VBoxOGLrenderspu_DEFS += VBOX_WITH_VDMA +endif VBoxOGLrenderspu_LDFLAGS.darwin += -install_name $(VBOX_DYLD_EXECUTABLE_PATH)/VBoxOGLrenderspu.dylib VBoxOGLrenderspu_LIBS = \ $(PATH_STAGE_LIB)/VBoxOGLhostspuload$(VBOX_SUFF_LIB) \ diff --git a/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp b/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp index 4388fde94..77ddf197f 100644 --- a/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp +++ b/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp @@ -961,7 +961,7 @@ static void crScreenshotHandle(CRVBOXHGCMTAKESCREENSHOT *pScreenshot, uint32_t i /* * We differentiate between a function handler for the guest and one for the host. */ -static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) +static int svcHostCallPerform(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) { int rc = VINF_SUCCESS; @@ -979,10 +979,6 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa switch (u32Function) { - case SHCRGL_HOST_FN_CRCMD_NOTIFY_CMDS: - { - rc = crVBoxServerCrCmdNotifyCmds(); - } break; #ifdef VBOX_WITH_CRHGSMI case SHCRGL_HOST_FN_CRHGSMI_CMD: { @@ -1476,6 +1472,73 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa return rc; } +int crVBoxServerHostCtl(VBOXCRCMDCTL *pCtl, uint32_t cbCtl) +{ + if ((cbCtl - sizeof (VBOXCRCMDCTL)) % sizeof(VBOXHGCMSVCPARM)) + { + WARN(("invalid param size")); + return VERR_INVALID_PARAMETER; + } + uint32_t cParams = (cbCtl - sizeof (VBOXCRCMDCTL)) / sizeof (VBOXHGCMSVCPARM); + return svcHostCallPerform(pCtl->u32Function, cParams, (VBOXHGCMSVCPARM*)(pCtl + 1)); +} + +static DECLCALLBACK(int) svcHostCall(void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) +{ + switch (u32Function) + { + case SHCRGL_HOST_FN_CTL: + { + if (cParms != 1) + { + WARN(("cParams != 1")); + return VERR_INVALID_PARAMETER; + } + + if (paParms->type != VBOX_HGCM_SVC_PARM_PTR) + { + WARN(("invalid param type")); + return VERR_INVALID_PARAMETER; + } + + if (paParms->u.pointer.size < sizeof (VBOXCRCMDCTL)) + { + WARN(("invalid param size")); + return VERR_INVALID_PARAMETER; + } + + VBOXCRCMDCTL *pCtl = (VBOXCRCMDCTL*)paParms->u.pointer.addr; + switch (pCtl->enmType) + { + case VBOXCRCMDCTL_TYPE_HGCM: + { + return crVBoxServerHostCtl(pCtl, paParms->u.pointer.size); + } + case VBOXCRCMDCTL_TYPE_DISABLE: + { + if (paParms->u.pointer.size != sizeof (VBOXCRCMDCTL)) + WARN(("invalid param size")); + return crVBoxServerHgcmDisable(); + } + case VBOXCRCMDCTL_TYPE_ENABLE: + { + if (paParms->u.pointer.size != sizeof (VBOXCRCMDCTL_ENABLE)) + WARN(("invalid param size")); + VBOXCRCMDCTL_ENABLE *pEnable = (VBOXCRCMDCTL_ENABLE*)pCtl; + return crVBoxServerHgcmEnable(pEnable->hRHCmd, pEnable->pfnRHCmd); + } + default: + WARN(("invalid function")); + return VERR_INVALID_PARAMETER; + } + WARN(("should not be here!")); + return VERR_INTERNAL_ERROR; + } + default: + return svcHostCallPerform(u32Function, cParms, paParms); + } +} + extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable) { int rc = VINF_SUCCESS; diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h b/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h index 0b8b46432..677bcf0ee 100644 --- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h +++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h @@ -115,7 +115,7 @@ GLboolean crServerClientInBeginEnd(const CRClient *client); GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLint shareCtx, GLint preloadCtxID, int32_t internalID); GLint crServerDispatchWindowCreateEx(const char *dpyName, GLint visBits, GLint preloadWinID); -GLint crServerMuralInit(CRMuralInfo *mural, const char *dpyName, GLint visBits, GLint preloadWinID); +GLint crServerMuralInit(CRMuralInfo *mural, GLboolean fGuestWindow, GLint visBits, GLint preloadWinID); void crServerMuralTerm(CRMuralInfo *mural); GLboolean crServerMuralSize(CRMuralInfo *mural, GLint width, GLint height); void crServerMuralPosition(CRMuralInfo *mural, GLint x, GLint y); @@ -155,6 +155,8 @@ HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb); HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized(); HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb); +int CrFbRegionsClear(HCR_FRAMEBUFFER hFb); + #define CR_SERVER_FBO_BB_IDX(_mural) ((_mural)->iBbBuffer) #define CR_SERVER_FBO_FB_IDX(_mural) (((_mural)->iBbBuffer + 1) % ((_mural)->cBuffers)) @@ -425,7 +427,7 @@ typedef DECLCALLBACKPTR(bool, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB)(HCR_FRAMEBUF bool CrFbHas3DData(HCR_FRAMEBUFFER hFb); void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext); int CrFbResize(HCR_FRAMEBUFFER hFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM); -int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, uint32_t cRects, const RTRECT *pPrects, CR_BLITTER_IMG *pImg); +int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pPrects, CR_BLITTER_IMG *pImg); bool CrFbIsEnabled(HCR_FRAMEBUFFER hFb); int CrFbEntryCreateForTexId(HCR_FRAMEBUFFER hFb, GLuint idTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry); int CrFbEntryCreateForTexData(HCR_FRAMEBUFFER hFb, struct CR_TEXDATA *pTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry); diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c index 89b9c615b..1a7e360c6 100644 --- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c +++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c @@ -59,6 +59,8 @@ CRServer cr_server; int tearingdown = 0; /* can't be static */ +static DECLCALLBACK(int) crVBoxCrCmdCmd(HVBOXCRCMDSVR hSvr, PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd); + DECLINLINE(int32_t) crVBoxServerClientGet(uint32_t u32ClientID, CRClient **ppClient) { CRClient *pClient = NULL; @@ -161,7 +163,7 @@ static void crServerTearDown( void ) /* sync our state with renderspu, * do it before mural & context deletion to avoid deleting currently set murals/contexts*/ - cr_server.head_spu->dispatch_table.MakeCurrent(0, 0, 0); + cr_server.head_spu->dispatch_table.MakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID); /* Deallocate all semaphores */ crFreeHashtable(cr_server.semaphores, crFree); @@ -529,6 +531,38 @@ GLboolean crVBoxServerInit(void) return GL_TRUE; } +static int32_t crVBoxServerAddClientObj(uint32_t u32ClientID, CRClient **ppNewClient) +{ + CRClient *newClient; + + if (cr_server.numClients>=CR_MAX_CLIENTS) + { + if (ppNewClient) + *ppNewClient = NULL; + return VERR_MAX_THRDS_REACHED; + } + + newClient = (CRClient *) crCalloc(sizeof(CRClient)); + crDebug("crServer: AddClient u32ClientID=%d", u32ClientID); + + newClient->spu_id = 0; + newClient->currentCtxInfo = &cr_server.MainContextInfo; + newClient->currentContextNumber = -1; + newClient->conn = crNetAcceptClient(cr_server.protocol, NULL, + cr_server.tcpip_port, + cr_server.mtu, 0); + newClient->conn->u32ClientID = u32ClientID; + + cr_server.clients[cr_server.numClients++] = newClient; + + crServerAddToRunQueue(newClient); + + if (ppNewClient) + *ppNewClient = newClient; + + return VINF_SUCCESS; +} + int32_t crVBoxServerAddClient(uint32_t u32ClientID) { CRClient *newClient; @@ -744,6 +778,17 @@ extern DECLEXPORT(int32_t) crVBoxServerClientGetCaps(uint32_t u32ClientID, uint3 return VINF_SUCCESS; } +static int32_t crVBoxServerClientObjSetVersion(CRClient *pClient, uint32_t vMajor, uint32_t vMinor) +{ + pClient->conn->vMajor = vMajor; + pClient->conn->vMinor = vMinor; + + if (vMajor != CR_PROTOCOL_VERSION_MAJOR + || vMinor != CR_PROTOCOL_VERSION_MINOR) + return VERR_NOT_SUPPORTED; + return VINF_SUCCESS; +} + int32_t crVBoxServerClientSetVersion(uint32_t u32ClientID, uint32_t vMajor, uint32_t vMinor) { CRClient *pClient=NULL; @@ -760,15 +805,14 @@ int32_t crVBoxServerClientSetVersion(uint32_t u32ClientID, uint32_t vMajor, uint } if (!pClient) return VERR_INVALID_PARAMETER; - pClient->conn->vMajor = vMajor; - pClient->conn->vMinor = vMinor; + return crVBoxServerClientObjSetVersion(pClient, vMajor, vMinor); +} - if (vMajor != CR_PROTOCOL_VERSION_MAJOR - || vMinor != CR_PROTOCOL_VERSION_MINOR) - { - return VERR_NOT_SUPPORTED; - } - else return VINF_SUCCESS; +static int32_t crVBoxServerClientObjSetPID(CRClient *pClient, uint64_t pid) +{ + pClient->pid = pid; + + return VINF_SUCCESS; } int32_t crVBoxServerClientSetPID(uint32_t u32ClientID, uint64_t pid) @@ -787,9 +831,7 @@ int32_t crVBoxServerClientSetPID(uint32_t u32ClientID, uint64_t pid) } if (!pClient) return VERR_INVALID_PARAMETER; - pClient->pid = pid; - - return VINF_SUCCESS; + return crVBoxServerClientObjSetPID(pClient, pid); } int @@ -1004,7 +1046,7 @@ CRMuralInfo * crServerGetDummyMural(GLint visualBits) crWarning("crCalloc failed!"); return NULL; } - id = crServerMuralInit(pMural, "", visualBits, 0); + id = crServerMuralInit(pMural, GL_FALSE, visualBits, 0); if (id < 0) { crWarning("crServerMuralInit failed!"); @@ -2599,8 +2641,6 @@ DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version) if (version >= SHCROGL_SSM_VERSION_WITH_SCREEN_INFO) { - HCR_FRAMEBUFFER hFb; - rc = CrPMgrLoadState(pSSM, version); AssertRCReturn(rc, rc); } @@ -2885,10 +2925,37 @@ DECLEXPORT(int32_t) crVBoxServerSetScreenViewport(int sIndex, int32_t x, int32_t return VINF_SUCCESS; } +static void crVBoxServerDefaultContextSet() +{ + GLint spuWindow, spuCtx; + + if (cr_server.MainContextInfo.SpuContext) + { + CRMuralInfo *pMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits); + if (!pMural) + { + WARN(("dummy mural is NULL")); + spuCtx = CR_RENDER_DEFAULT_CONTEXT_ID; + spuWindow = CR_RENDER_DEFAULT_WINDOW_ID; + } + else + { + spuCtx = cr_server.MainContextInfo.SpuContext; + spuWindow = pMural->CreateInfo.realVisualBits; + } + } + else + { + spuCtx = CR_RENDER_DEFAULT_CONTEXT_ID; + spuWindow = CR_RENDER_DEFAULT_WINDOW_ID; + } + + cr_server.head_spu->dispatch_table.MakeCurrent(spuWindow, 0, spuCtx); +} #ifdef VBOX_WITH_CRHGSMI -static int32_t crVBoxServerCmdVbvaCrCmdProcess(struct VBOXCMDVBVA_CRCMD_CMD *pCmd) +static int32_t crVBoxServerCmdVbvaCrCmdProcess(struct VBOXCMDVBVA_CRCMD_CMD *pCmd, uint32_t cbCmd) { int32_t rc; uint32_t cBuffers = pCmd->cBuffers; @@ -2901,29 +2968,35 @@ static int32_t crVBoxServerCmdVbvaCrCmdProcess(struct VBOXCMDVBVA_CRCMD_CMD *pCm if (!g_pvVRamBase) { - crWarning("g_pvVRamBase is not initialized"); + WARN(("g_pvVRamBase is not initialized")); return VERR_INVALID_STATE; } if (!cBuffers) { - crWarning("zero buffers passed in!"); + WARN(("zero buffers passed in!")); return VERR_INVALID_PARAMETER; } cParams = cBuffers-1; + if (cbCmd != RT_OFFSETOF(VBOXCMDVBVA_CRCMD_CMD, aBuffers[cBuffers])) + { + WARN(("invalid buffer size")); + return VERR_INVALID_PARAMETER; + } + cbHdr = pCmd->aBuffers[0].cbBuffer; pHdr = VBOXCRHGSMI_PTR_SAFE(pCmd->aBuffers[0].offBuffer, cbHdr, CRVBOXHGSMIHDR); if (!pHdr) { - crWarning("invalid header buffer!"); + WARN(("invalid header buffer!")); return VERR_INVALID_PARAMETER; } if (cbHdr < sizeof (*pHdr)) { - crWarning("invalid header buffer size!"); + WARN(("invalid header buffer size!")); return VERR_INVALID_PARAMETER; } @@ -3187,24 +3260,110 @@ static int32_t crVBoxServerCmdVbvaCrCmdProcess(struct VBOXCMDVBVA_CRCMD_CMD *pCm return rc; } -static int32_t crVBoxServerCrCmdProcess(PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd) +static DECLCALLBACK(int) crVBoxCrCmdEnable(HVBOXCRCMDSVR hSvr, VBOXCRCMD_SVRENABLE_INFO *pInfo) +{ + cr_server.CrCmdClientInfo = *pInfo; + + crVBoxServerDefaultContextSet(); + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) crVBoxCrCmdDisable(HVBOXCRCMDSVR hSvr) +{ + cr_server.head_spu->dispatch_table.MakeCurrent(0, 0, 0); + + memset(&cr_server.CrCmdClientInfo, 0, sizeof (cr_server.CrCmdClientInfo)); + + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) crVBoxCrCmdHostCtl(HVBOXCRCMDSVR hSvr, uint8_t* pCmd, uint32_t cbCmd) { + return crVBoxServerHostCtl((VBOXCRCMDCTL*)pCmd, cbCmd); +} + +static DECLCALLBACK(int) crVBoxCrCmdGuestCtl(HVBOXCRCMDSVR hSvr, uint8_t* pCmd, uint32_t cbCmd) +{ + VBOXCMDVBVA_3DCTL *pCtl = (VBOXCMDVBVA_3DCTL*)pCmd; + if (cbCmd < sizeof (VBOXCMDVBVA_3DCTL)) + { + WARN(("invalid buffer size")); + return VERR_INVALID_PARAMETER; + } + + switch (pCtl->u32Type) + { + case VBOXCMDVBVA3DCTL_TYPE_CONNECT: + { + VBOXCMDVBVA_3DCTL_CONNECT *pConnect = (VBOXCMDVBVA_3DCTL_CONNECT*)pCtl; + + return VERR_NOT_SUPPORTED; + } + case VBOXCMDVBVA3DCTL_TYPE_DISCONNECT: + { + return VERR_NOT_SUPPORTED; + } + case VBOXCMDVBVA3DCTL_TYPE_CMD: + { + VBOXCMDVBVA_3DCTL_CMD *p3DCmd; + if (cbCmd < sizeof (VBOXCMDVBVA_3DCTL_CMD)) + { + WARN(("invalid size")); + return VERR_INVALID_PARAMETER; + } + + p3DCmd = (VBOXCMDVBVA_3DCTL_CMD*)pCmd; + + return crVBoxCrCmdCmd(NULL, &p3DCmd->Cmd, cbCmd - RT_OFFSETOF(VBOXCMDVBVA_3DCTL_CMD, Cmd)); + } + default: + WARN(("invalid function")); + return VERR_INVALID_PARAMETER; + } +} + +static DECLCALLBACK(int) crVBoxCrCmdSaveState(HVBOXCRCMDSVR hSvr, PSSMHANDLE pSSM) +{ + AssertFailed(); + return VERR_NOT_IMPLEMENTED; +} + +static DECLCALLBACK(int) crVBoxCrCmdLoadState(HVBOXCRCMDSVR hSvr, PSSMHANDLE pSSM, uint32_t u32Version) +{ + AssertFailed(); + return VERR_NOT_IMPLEMENTED; +} + + +static DECLCALLBACK(int) crVBoxCrCmdCmd(HVBOXCRCMDSVR hSvr, PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd) +{ + AssertFailed(); switch (pCmd->u8OpCode) { case VBOXCMDVBVA_OPTYPE_CRCMD: { - VBOXCMDVBVA_CRCMD *pCrCmdDr = (VBOXCMDVBVA_CRCMD*)pCmd; - VBOXCMDVBVA_CRCMD_CMD *pCrCmd = &pCrCmdDr->Cmd; - int rc = crVBoxServerCmdVbvaCrCmdProcess(pCrCmd); + VBOXCMDVBVA_CRCMD *pCrCmdDr; + VBOXCMDVBVA_CRCMD_CMD *pCrCmd; + int rc; + pCrCmdDr = (VBOXCMDVBVA_CRCMD*)pCmd; + pCrCmd = &pCrCmdDr->Cmd; + if (cbCmd < sizeof (VBOXCMDVBVA_CRCMD)) + { + WARN(("invalid buffer size")); + pCmd->u.i8Result = -1; + break; + } + rc = crVBoxServerCmdVbvaCrCmdProcess(pCrCmd, cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CRCMD, Cmd)); if (RT_SUCCESS(rc)) { /* success */ - pCmd->i8Result = 0; + pCmd->u.i8Result = 0; } else { - crWarning("crVBoxServerCmdVbvaCrCmdProcess failed, rc %d", rc); - pCmd->i8Result = -1; + WARN(("crVBoxServerCmdVbvaCrCmdProcess failed, rc %d", rc)); + pCmd->u.i8Result = -1; } break; } @@ -3215,34 +3374,11 @@ static int32_t crVBoxServerCrCmdProcess(PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd) } default: WARN(("unsupported command")); - pCmd->i8Result = -1; + pCmd->u.i8Result = -1; } return VINF_SUCCESS; } -int32_t crVBoxServerCrCmdNotifyCmds() -{ - PVBOXCMDVBVA_HDR pCmd = NULL; - uint32_t cbCmd; - - for (;;) - { - int rc = cr_server.CltInfo.pfnCmdGet(cr_server.CltInfo.hClient, &pCmd, &cbCmd); - if (rc == VINF_EOF) - return VINF_SUCCESS; - if (!RT_SUCCESS(rc)) - return rc; - - rc = crVBoxServerCrCmdProcess(pCmd, cbCmd); - if (!RT_SUCCESS(rc)) - return rc; - } - - /* should not be here! */ - AssertFailed(); - return VERR_INTERNAL_ERROR; -} - /* We moved all CrHgsmi command processing to crserverlib to keep the logic of dealing with CrHgsmi commands in one place. * * For now we need the notion of CrHgdmi commands in the crserver_lib to be able to complete it asynchronously once it is really processed. @@ -3272,7 +3408,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c if (!g_pvVRamBase) { - crWarning("g_pvVRamBase is not initialized"); + WARN(("g_pvVRamBase is not initialized")); crServerCrHgsmiCmdComplete(pCmd, VERR_INVALID_STATE); return VINF_SUCCESS; @@ -3280,7 +3416,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c if (!cBuffers) { - crWarning("zero buffers passed in!"); + WARN(("zero buffers passed in!")); crServerCrHgsmiCmdComplete(pCmd, VERR_INVALID_PARAMETER); return VINF_SUCCESS; @@ -3292,7 +3428,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c pHdr = VBOXCRHGSMI_PTR_SAFE(pCmd->aBuffers[0].offBuffer, cbHdr, CRVBOXHGSMIHDR); if (!pHdr) { - crWarning("invalid header buffer!"); + WARN(("invalid header buffer!")); crServerCrHgsmiCmdComplete(pCmd, VERR_INVALID_PARAMETER); return VINF_SUCCESS; @@ -3300,7 +3436,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c if (cbHdr < sizeof (*pHdr)) { - crWarning("invalid header buffer size!"); + WARN(("invalid header buffer size!")); crServerCrHgsmiCmdComplete(pCmd, VERR_INVALID_PARAMETER); return VINF_SUCCESS; @@ -3595,7 +3731,14 @@ int32_t crVBoxServerCrHgsmiCtl(struct VBOXVDMACMD_CHROMIUM_CTL *pCtl, uint32_t c PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP pSetup = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP)pCtl; g_pvVRamBase = (uint8_t*)pSetup->pvVRamBase; g_cbVRam = pSetup->cbVRam; - cr_server.CltInfo = *pSetup->pCrCmdClientInfo; + pSetup->CrCmdServerInfo.hSvr = NULL; + pSetup->CrCmdServerInfo.pfnEnable = crVBoxCrCmdEnable; + pSetup->CrCmdServerInfo.pfnDisable = crVBoxCrCmdDisable; + pSetup->CrCmdServerInfo.pfnCmd = crVBoxCrCmdCmd; + pSetup->CrCmdServerInfo.pfnHostCtl = crVBoxCrCmdHostCtl; + pSetup->CrCmdServerInfo.pfnGuestCtl = crVBoxCrCmdGuestCtl; + pSetup->CrCmdServerInfo.pfnSaveState = crVBoxCrCmdSaveState; + pSetup->CrCmdServerInfo.pfnLoadState = crVBoxCrCmdLoadState; rc = VINF_SUCCESS; break; } @@ -3628,4 +3771,39 @@ int32_t crVBoxServerCrHgsmiCtl(struct VBOXVDMACMD_CHROMIUM_CTL *pCtl, uint32_t c return rc; } +int32_t crVBoxServerHgcmEnable(HVBOXCRCMDCTL_REMAINING_HOST_COMMAND hRHCmd, PFNVBOXCRCMDCTL_REMAINING_HOST_COMMAND pfnRHCmd) +{ + int rc = VINF_SUCCESS; + uint8_t* pCtl; + uint32_t cbCtl; + + if (cr_server.numClients) + { + WARN(("cr_server.numClients(%d) is not NULL", cr_server.numClients)); + return VERR_INVALID_STATE; + } + + for (pCtl = pfnRHCmd(hRHCmd, &cbCtl, rc); pCtl; pCtl = pfnRHCmd(hRHCmd, &cbCtl, rc)) + { + rc = crVBoxCrCmdHostCtl(NULL, pCtl, cbCtl); + } + + crVBoxServerDefaultContextSet(); + + return VINF_SUCCESS; +} + +int32_t crVBoxServerHgcmDisable() +{ + if (cr_server.numClients) + { + WARN(("cr_server.numClients(%d) is not NULL", cr_server.numClients)); + return VERR_INVALID_STATE; + } + + cr_server.head_spu->dispatch_table.MakeCurrent(0, 0, 0); + + return VINF_SUCCESS; +} + #endif diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.cpp b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.cpp index e9ae9e78c..10cdf5cfb 100644 --- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.cpp +++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.cpp @@ -194,7 +194,6 @@ static int crServerRedirMuralDbSyncFb(CRMuralInfo *mural, HCR_FRAMEBUFFER hFb, C for (uint32_t i = 0; i < mural->cBuffers; ++i) { VBOXVR_TEXTURE Tex; - int rc; Tex.width = mural->width; Tex.height = mural->height; Tex.hwid = mural->aidColorTexs[i]; @@ -687,7 +686,8 @@ DECLEXPORT(int) crServerVBoxScreenshotGet(uint32_t u32Screen, uint32_t width, ui || pScreen->u32LineSize != pitch || pScreen->u16BitsPerPixel != 32) { - RTRECT Rect; + RTRECT SrcRect; + RTRECT DstRect; pScreenshot->Img.cbData = pScreen->u32LineSize * pScreen->u32Height; if (!pvBuffer) @@ -711,11 +711,15 @@ DECLEXPORT(int) crServerVBoxScreenshotGet(uint32_t u32Screen, uint32_t width, ui pScreenshot->Img.height = height; pScreenshot->Img.bpp = 32; pScreenshot->Img.pitch = pitch; - Rect.xLeft = 0; - Rect.yTop = 0; - Rect.xRight = pScreen->u32Width; - Rect.yBottom = pScreen->u32Height; - int rc = CrFbBltGetContents(hFb, &Rect, 1, &Rect, &pScreenshot->Img); + SrcRect.xLeft = 0; + SrcRect.yTop = 0; + SrcRect.xRight = pScreen->u32Width; + SrcRect.yBottom = pScreen->u32Height; + DstRect.xLeft = 0; + DstRect.yTop = 0; + DstRect.xRight = width; + DstRect.yBottom = height; + int rc = CrFbBltGetContents(hFb, &SrcRect, &DstRect, 1, &DstRect, &pScreenshot->Img); if (!RT_SUCCESS(rc)) { WARN(("CrFbBltGetContents failed %d", rc)); diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp index 49fa537cd..e1dca8288 100644 --- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp +++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp @@ -247,8 +247,8 @@ static void crFbBltImg(const CR_BLITTER_IMG *pSrc, const RTPOINT *pSrcDataPoint, int32_t srcY = pCopyRect->yTop - pSrcDataPoint->y; Assert(srcX >= 0); Assert(srcY >= 0); - Assert(srcX < pSrc->width); - Assert(srcY < pSrc->height); + Assert(srcX < (int32_t)pSrc->width); + Assert(srcY < (int32_t)pSrc->height); int32_t dstX = pCopyRect->xLeft - pDstDataPoint->x; int32_t dstY = pCopyRect->yTop - pDstDataPoint->y; @@ -258,7 +258,7 @@ static void crFbBltImg(const CR_BLITTER_IMG *pSrc, const RTPOINT *pSrcDataPoint, uint8_t *pu8Src = ((uint8_t*)pSrc->pvData) + pSrc->pitch * (!fSrcInvert ? srcY : pSrc->height - srcY - 1) + srcX * 4; uint8_t *pu8Dst = ((uint8_t*)pDst->pvData) + pDst->pitch * dstY + dstX * 4; - crFbBltMem(pu8Src, fSrcInvert ? -pSrc->pitch : pSrc->pitch, pu8Dst, pDst->pitch, pCopyRect->xRight - pCopyRect->xLeft, pCopyRect->yBottom - pCopyRect->yTop); + crFbBltMem(pu8Src, fSrcInvert ? -((int32_t)pSrc->pitch) : (int32_t)pSrc->pitch, pu8Dst, pDst->pitch, pCopyRect->xRight - pCopyRect->xLeft, pCopyRect->yBottom - pCopyRect->yTop); } static void crFbBltImgScaled(const CR_BLITTER_IMG *pSrc, const RTPOINT *pSrcDataPoint, bool fSrcInvert, const RTRECT *pCopyRect, const RTPOINT *pDstDataPoint, float strX, float strY, CR_BLITTER_IMG *pDst) @@ -267,8 +267,8 @@ static void crFbBltImgScaled(const CR_BLITTER_IMG *pSrc, const RTPOINT *pSrcData int32_t srcY = pCopyRect->yTop - pSrcDataPoint->y; Assert(srcX >= 0); Assert(srcY >= 0); - Assert(srcX < pSrc->width); - Assert(srcY < pSrc->height); + Assert(srcX < (int32_t)pSrc->width); + Assert(srcY < (int32_t)pSrc->height); RTPOINT ScaledDtsDataPoint; RTRECT ScaledCopyRect; @@ -315,10 +315,68 @@ static void crFbBltImgScaled(const CR_BLITTER_IMG *pSrc, const RTPOINT *pSrcData ScaledDstWidth, ScaledDstHeight, pu8Src, - fSrcInvert ? -pSrc->pitch : pSrc->pitch, + fSrcInvert ? -((int32_t)pSrc->pitch) : (int32_t)pSrc->pitch, pCopyRect->xRight - pCopyRect->xLeft, pCopyRect->yBottom - pCopyRect->yTop); } +static void crFbBltImgScaledRects(const CR_BLITTER_IMG *pSrc, const RTPOINT *pSrcDataPoint, bool fSrcInvert, const RTRECT *pCopyRect, const RTPOINT *pDstDataPoint, float strX, float strY, CR_BLITTER_IMG *pDst) +{ + int32_t srcX = pCopyRect->xLeft - pSrcDataPoint->x; + int32_t srcY = pCopyRect->yTop - pSrcDataPoint->y; + Assert(srcX >= 0); + Assert(srcY >= 0); + + RTRECT UnscaledCopyRect; + VBoxRectUnscaled(pCopyRect, strX, strY, &UnscaledCopyRect); + + srcX = CR_FLOAT_RCAST(int32_t, srcX / strX); + srcY = CR_FLOAT_RCAST(int32_t, srcY / strY); + + int32_t UnscaledSrcWidth = UnscaledCopyRect.xRight - UnscaledCopyRect.xLeft; + int32_t delta = (int32_t)pSrc->width - srcX - UnscaledSrcWidth; + if (delta < 0) + UnscaledSrcWidth += delta; + + if (UnscaledSrcWidth <= 0) + { + LOG(("UnscaledSrcWidth <= 0")); + if (UnscaledSrcWidth < 0) + WARN(("src width (%d) < 0", UnscaledSrcWidth)); + return; + } + + int32_t UnscaledSrcHeight = UnscaledCopyRect.yBottom - UnscaledCopyRect.yTop; + delta = (int32_t)pSrc->height - srcY - UnscaledSrcHeight; + if (delta < 0) + UnscaledSrcHeight += delta; + + if (UnscaledSrcHeight <= 0) + { + LOG(("UnscaledSrcHeight <= 0")); + if (UnscaledSrcHeight < 0) + WARN(("src height (%d) < 0", UnscaledSrcHeight)); + return; + } + + int32_t dstX = pCopyRect->xLeft - pDstDataPoint->x; + int32_t dstY = pCopyRect->yTop - pDstDataPoint->y; + Assert(dstX >= 0); + Assert(dstY >= 0); + + + uint8_t *pu8Src = ((uint8_t*)pSrc->pvData) + pSrc->pitch * (!fSrcInvert ? srcY : pSrc->height - srcY - 1) + srcX * 4; + uint8_t *pu8Dst = ((uint8_t*)pDst->pvData) + pDst->pitch * dstY + dstX * 4; + + CrBmpScale32(pu8Dst, pDst->pitch, + pCopyRect->xRight - pCopyRect->xLeft, + pCopyRect->yBottom - pCopyRect->yTop, + pu8Src, + fSrcInvert ? -pSrc->pitch : pSrc->pitch, + UnscaledSrcWidth, + UnscaledSrcHeight + ); +} + static void crFbImgFromScreenVram(const VBVAINFOSCREEN *pScreen, void *pvVram, CR_BLITTER_IMG *pImg) { pImg->pvData = pvVram; @@ -337,7 +395,7 @@ static void crFbImgFromFb(HCR_FRAMEBUFFER hFb, CR_BLITTER_IMG *pImg) crFbImgFromScreenVram(pScreen, pvVram, pImg); } -static int crFbBltGetContentsDirect(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg) +static int crFbBltGetContentsDirect(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg) { VBOXVR_LIST List; uint32_t c2DRects = 0; @@ -347,15 +405,17 @@ static int crFbBltGetContentsDirect(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, RTPOINT ScaledEntryPoint = {0}; VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter; - RTPOINT SrcPoint = {pSrcRect->xLeft, pSrcRect->yTop}; - float strX = ((float)pImg->width) / (pSrcRect->xRight - pSrcRect->xLeft); - float strY = ((float)pImg->height) / (pSrcRect->yBottom - pSrcRect->yTop); + int32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft; + int32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop; + int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft; + int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop; - RTPOINT ScaledSrcPoint; - ScaledSrcPoint.x = CR_FLOAT_RCAST(int32_t, strX * SrcPoint.x); - ScaledSrcPoint.y = CR_FLOAT_RCAST(int32_t, strY * SrcPoint.y); + RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop}; + float strX = ((float)dstWidth) / srcWidth; + float strY = ((float)dstHeight) / srcHeight; + bool fScale = (dstWidth != srcWidth || dstHeight != srcHeight); - RTPOINT ZeroPoint = {0, 0}; + const RTPOINT ZeroPoint = {0, 0}; VBoxVrListInit(&List); int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL); @@ -387,18 +447,24 @@ static int crFbBltGetContentsDirect(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, goto end; } - for (uint32_t i = 0; i < cRects; ++i) + for (uint32_t j = 0; j < cRegions; ++j) { - const RTRECT * pRect = &pRects[i]; - for (uint32_t j = 0; j < cRegions; ++j) + /* rects are in dst coordinates, + * while the pReg is in source coords + * convert */ + const RTRECT * pReg = &pRegions[j]; + RTRECT ScaledReg; + /* scale */ + VBoxRectScaled(pReg, strX, strY, &ScaledReg); + /* translate */ + VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop); + + for (uint32_t i = 0; i < cRects; ++i) { - const RTRECT * pReg = &pRegions[j]; - RTRECT Intersection; - VBoxRectIntersected(pRect, pReg, &Intersection); - if (VBoxRectIsZero(&Intersection)) - continue; + const RTRECT * pRect = &pRects[i]; - VBoxRectScale(&Intersection, strX, strY); + RTRECT Intersection; + VBoxRectIntersected(pRect, &ScaledReg, &Intersection); if (VBoxRectIsZero(&Intersection)) continue; @@ -454,8 +520,8 @@ static int crFbBltGetContentsDirect(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, width = CR_FLOAT_RCAST(uint32_t, strX * pVrTex->width); height = CR_FLOAT_RCAST(uint32_t, strY * pVrTex->height); - ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft); - ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop); + ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft) + pDstRect->xLeft; + ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop) + pDstRect->yTop; } rc = CrTdBltDataAcquireScaled(pTex, GL_BGRA, false, width, height, &pSrcImg); @@ -467,7 +533,7 @@ static int crFbBltGetContentsDirect(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS); - crFbBltImg(pSrcImg, &ScaledEntryPoint, fInvert, &Intersection, &ScaledSrcPoint, pImg); + crFbBltImg(pSrcImg, &ScaledEntryPoint, fInvert, &Intersection, &ZeroPoint, pImg); CrTdBltDataReleaseScaled(pTex, pSrcImg); } @@ -502,36 +568,34 @@ static int crFbBltGetContentsDirect(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, goto end; } - RTPOINT Pos = {0}; const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor); - uint32_t fbWidth = (pCompRect->xRight - pCompRect->xLeft); - uint32_t fbHeight = pCompRect->yBottom - pCompRect->yTop; - - uint32_t stretchedWidth = CR_FLOAT_RCAST(uint32_t, strX * fbWidth); - uint32_t stretchedHeight = CR_FLOAT_RCAST(uint32_t, strY * fbHeight); - CR_BLITTER_IMG FbImg; - bool fScale = fbWidth != stretchedWidth || fbHeight != stretchedHeight; - crFbImgFromFb(hFb, &FbImg); - for (uint32_t i = 0; i < cRects; ++i) + for (uint32_t j = 0; j < c2DRects; ++j) { - const RTRECT * pRect = &pRects[i]; - for (uint32_t j = 0; j < c2DRects; ++j) + const RTRECT * p2DRect = &p2DRects[j]; + RTRECT ScaledReg; + /* scale */ + VBoxRectScaled(p2DRect, strX, strY, &ScaledReg); + /* translate */ + VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop); + + for (uint32_t i = 0; i < cRects; ++i) { - const RTRECT * p2DRect = &p2DRects[j]; + const RTRECT * pRect = &pRects[i]; RTRECT Intersection; - VBoxRectIntersected(pRect, p2DRect, &Intersection); + + VBoxRectIntersected(pRect, &ScaledReg, &Intersection); if (VBoxRectIsZero(&Intersection)) continue; if (!fScale) - crFbBltImg(&FbImg, &ZeroPoint, false, &Intersection, &SrcPoint, pImg); + crFbBltImg(&FbImg, &DstPoint, false, &Intersection, &ZeroPoint, pImg); else - crFbBltImgScaled(&FbImg, &ZeroPoint, false, &Intersection, &SrcPoint, strX, strY, pImg); + crFbBltImgScaledRects(&FbImg, &DstPoint, false, &Intersection, &ZeroPoint, strX, strY, pImg); } } } @@ -549,10 +613,21 @@ end: return rc; } -static int crFbBltGetContentsScaleCPU(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg) +static int crFbBltGetContentsScaleCPU(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg) { - uint32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft; - uint32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop; + int32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft; + int32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop; + int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft; + int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop; + + RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop}; + float strX = ((float)dstWidth) / srcWidth; + float strY = ((float)dstHeight) / srcHeight; + + RTRECT DstRect; + VBoxRectUnscaled(pDstRect, strX, strY, &DstRect); + DstRect.xRight = DstRect.xLeft + srcWidth; + DstRect.yBottom = DstRect.yTop + srcHeight; /* destination is bigger than the source, do 3D data stretching with CPU */ CR_BLITTER_IMG Img; @@ -569,7 +644,7 @@ static int crFbBltGetContentsScaleCPU(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRec Img.bpp = pImg->bpp; Img.pitch = Img.width * 4; - int rc = CrFbBltGetContents(hFb, pSrcRect, cRects, pRects, &Img); + int rc = CrFbBltGetContents(hFb, pSrcRect, &DstRect, cRects, pRects, &Img); if (RT_SUCCESS(rc)) { CrBmpScale32((uint8_t *)pImg->pvData, @@ -588,21 +663,187 @@ static int crFbBltGetContentsScaleCPU(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRec } -int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg) +int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg) { uint32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft; uint32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop; - if ((srcWidth == pImg->width - && srcHeight == pImg->height) + uint32_t dstWidth = pDstRect->xRight - pDstRect->xLeft; + uint32_t dstHeight = pDstRect->yBottom - pDstRect->yTop; + if ((srcWidth == dstWidth + && srcHeight == dstHeight) || !CrFbHas3DData(hFb) - || (srcWidth * srcHeight > pImg->width * pImg->height)) + || (srcWidth * srcHeight > dstWidth * dstHeight)) { - return crFbBltGetContentsDirect(hFb, pSrcRect, cRects, pRects, pImg); + return crFbBltGetContentsDirect(hFb, pSrcRect, pDstRect, cRects, pRects, pImg); } - return crFbBltGetContentsScaleCPU(hFb, pSrcRect, cRects, pRects, pImg); + return crFbBltGetContentsScaleCPU(hFb, pSrcRect, pDstRect, cRects, pRects, pImg); } +#if 0 +static int crFbBltPutContentsVram(HCR_FRAMEBUFFER hFb, const RTPOINT *pDstPoint, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg, float strX, float strY) +{ + const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor); + const RTPOINT ZeroPoint = {0}; + + uint32_t fbWidth = (pCompRect->xRight - pCompRect->xLeft); + uint32_t fbHeight = pCompRect->yBottom - pCompRect->yTop; + + uint32_t stretchedWidth = CR_FLOAT_RCAST(uint32_t, strX * fbWidth); + uint32_t stretchedHeight = CR_FLOAT_RCAST(uint32_t, strY * fbHeight); + + CR_BLITTER_IMG FbImg; + + bool fScale = fbWidth != stretchedWidth || fbHeight != stretchedHeight; + + crFbImgFromFb(hFb, &FbImg); + + RTRECT Intersection; + + for (uint32_t i = 0; i < cRects; ++i) + { + const RTRECT * pRect = &pRects[i]; + VBoxRectIntersected(pRect, pCompRect, &Intersection); + + if (VBoxRectIsZero(&Intersection)) + continue; + + if (!fScale) + crFbBltImg(pImg, pDstPoint, false, &Intersection, &ZeroPoint, &FbImg); + else + crFbBltImgScaled(pImg, pDstPoint, false, &Intersection, &ZeroPoint, strX, strY, &FbImg); + } + + return VINF_SUCCESS; +} + +int CrFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg) +{ + RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop}; + float strX = ((float)pImg->width) / (pDstRect->xRight - pDstRect->xLeft); + float strY = ((float)pImg->height) / (pDstRect->yBottom - pDstRect->yTop); + + int rc = CrFbEntryRegionsAdd(hFb, NULL, const RTPOINT *pPos, cRects, pRects, true) + if (!hFb->cUpdating) + { + WARN(("not updating\n")); + return VERR_INVALID_STATE; + } +} + +int CrFbBltPutContentsNe(HCR_FRAMEBUFFER hFb, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg) +{ + uint32_t cCompRects; + const RTRECT *pCompRects; + int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cCompRects, NULL, NULL, &pCompRects); + if (!RT_SUCCESS(rc)) + { + WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc)); + return rc; + } + + bool fRegChanged = false; + for (uint32_t i = 0; i < cCompRects; ++i) + { + const RTRECT *pCompRect = pCompRects[i]; + for (uint32_t j = 0; j < cRects; ++j) + { + const RTRECT *pRect = pRects[j]; + if (VBoxRectIsIntersect(pCompRect, pRect)) + { + fRegChanged = true; + break; + } + } + } + + if (fRegChanged) + { + rc = CrFbUpdateBegin(hFb); + if (RT_SUCCESS(rc)) + { + rc = CrFbBltPutContents(hFb, pDstRect, cRects, pRects, pImg); + if (!RT_SUCCESS(rc)) + WARN(("CrFbBltPutContents failed rc %d", rc)); + CrFbUpdateEnd(hFb); + } + else + WARN(("CrFbUpdateBegin failed rc %d", rc)); + + return rc; + } + + return crFbBltPutContentsVram(HCR_FRAMEBUFFER hFb, const RTPOINT *pDstPoint, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg, float strX, float strY); + + const RTPOINT ZeroPoint = {0, 0}; + + c2DRects = VBoxVrListRectsCount(&List); + if (c2DRects) + { + if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT)) + { + if (g_CrPresenter.pvTmpBuf2) + RTMemFree(g_CrPresenter.pvTmpBuf2); + + g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT); + g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2); + if (!g_CrPresenter.pvTmpBuf2) + { + WARN(("RTMemAlloc failed!")); + g_CrPresenter.cbTmpBuf2 = 0; + rc = VERR_NO_MEMORY; + goto end; + } + } + + RTRECT *p2DRects = (RTRECT *)g_CrPresenter.pvTmpBuf2; + + rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects); + if (!RT_SUCCESS(rc)) + { + WARN(("VBoxVrListRectsGet failed, rc %d", rc)); + goto end; + } + + RTPOINT Pos = {0}; + const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor); + + CR_BLITTER_IMG FbImg; + + crFbImgFromFb(hFb, &FbImg); + + for (uint32_t i = 0; i < cRects; ++i) + { + const RTRECT * pRect = &pRects[i]; + for (uint32_t j = 0; j < c2DRects; ++j) + { + const RTRECT * p2DRect = &p2DRects[j]; + RTRECT Intersection; + VBoxRectIntersected(pRect, p2DRect, &Intersection); + if (VBoxRectIsZero(&Intersection)) + continue; + + if (!fScale) + crFbBltImg(&FbImg, &ZeroPoint, false, &Intersection, &SrcPoint, pImg); + else + crFbBltImgScaled(&FbImg, &ZeroPoint, false, &Intersection, &SrcPoint, strX, strY, pImg); + } + } + } + +end: + + if (pEnteredTex) + CrTdBltLeave(pEnteredTex); + + if (pEnteredBlitter) + CrBltLeave(pEnteredBlitter); + + VBoxVrListClear(&List); + + return rc; +} +#endif int CrFbResize(CR_FRAMEBUFFER *pFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM) { @@ -3583,7 +3824,7 @@ HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idScreen) static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i) { - for (;i < cr_server.screenCount; ++i) + for (;i < (uint32_t)cr_server.screenCount; ++i) { HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i); if (hFb) @@ -3595,7 +3836,7 @@ static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i) static HCR_FRAMEBUFFER crPMgrFbGetNextInitialized(uint32_t i) { - for (;i < cr_server.screenCount; ++i) + for (;i < (uint32_t)cr_server.screenCount; ++i) { HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i); if (hFb) @@ -3943,7 +4184,7 @@ int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap) /*helper function that calls CrFbUpdateEnd for all framebuffers being updated */ void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap) { - for (uint32_t i = 0; i < cr_server.screenCount; ++i) + for (uint32_t i = 0; i < (uint32_t)cr_server.screenCount; ++i) { if (!CrFBmIsSet(pMap, i)) continue; @@ -4412,12 +4653,12 @@ int32_t crVBoxServerCrCmdBltProcess(PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd) if (u8Flags & (VBOXCMDVBVA_OPF_ALLOC_DSTPRIMARY | VBOXCMDVBVA_OPF_ALLOC_SRCPRIMARY)) { VBOXCMDVBVA_BLT_PRIMARY *pBlt = (VBOXCMDVBVA_BLT_PRIMARY*)pCmd; - uint8_t u8PrimaryID = pBlt->Hdr.u8PrimaryID; + uint8_t u8PrimaryID = pBlt->Hdr.u.u8PrimaryID; HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u8PrimaryID); if (!hFb) { WARN(("request to present on disabled framebuffer, ignore")); - pCmd->i8Result = -1; + pCmd->u.i8Result = -1; return VINF_SUCCESS; } @@ -4435,7 +4676,7 @@ int32_t crVBoxServerCrCmdBltProcess(PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd) { WARN(("RTMemAlloc failed!")); g_CrPresenter.cbTmpBuf = 0; - pCmd->i8Result = -1; + pCmd->u.i8Result = -1; return VINF_SUCCESS; } } @@ -4455,23 +4696,24 @@ int32_t crVBoxServerCrCmdBltProcess(PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd) if (u8Flags & VBOXCMDVBVA_OPF_ALLOC_DSTID) { /* TexPresent */ - texId = pBlt->alloc.id; + texId = pBlt->alloc.u.id; } else { - VBOXCMDVBVAOFFSET offVRAM = pBlt->alloc.offVRAM; + VBOXCMDVBVAOFFSET offVRAM = pBlt->alloc.u.offVRAM; const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb); uint32_t cbScreen = pScreen->u32LineSize * pScreen->u32Height; if (offVRAM >= g_cbVRam || offVRAM + cbScreen >= g_cbVRam) { WARN(("invalid param")); - pCmd->i8Result = -1; + pCmd->u.i8Result = -1; return VINF_SUCCESS; } uint8_t *pu8Buf = g_pvVRamBase + offVRAM; texId = 0; +// cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr); /*todo: notify VGA device to perform updates */ } @@ -4481,7 +4723,7 @@ int32_t crVBoxServerCrCmdBltProcess(PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd) { /* blit from one primary to another primary, wow */ WARN(("not implemented")); - pCmd->i8Result = -1; + pCmd->u.i8Result = -1; return VINF_SUCCESS; } } @@ -4491,38 +4733,43 @@ int32_t crVBoxServerCrCmdBltProcess(PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd) /* blit from primary to non-primary */ if (u8Flags & VBOXCMDVBVA_OPF_ALLOC_DSTID) { - uint32_t texId = pBlt->alloc.id; + uint32_t texId = pBlt->alloc.u.id; WARN(("not implemented")); - pCmd->i8Result = -1; + pCmd->u.i8Result = -1; return VINF_SUCCESS; } else { - VBOXCMDVBVAOFFSET offVRAM = pBlt->alloc.offVRAM; + VBOXCMDVBVAOFFSET offVRAM = pBlt->alloc.u.offVRAM; const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb); uint32_t cbScreen = pScreen->u32LineSize * pScreen->u32Height; if (offVRAM >= g_cbVRam || offVRAM + cbScreen >= g_cbVRam) { WARN(("invalid param")); - pCmd->i8Result = -1; + pCmd->u.i8Result = -1; return VINF_SUCCESS; } uint8_t *pu8Buf = g_pvVRamBase + offVRAM; - RTRECT Rect; - Rect.xLeft = pBlt->Pos.x; - Rect.yTop = pBlt->Pos.y; - Rect.xRight = Rect.xLeft + pScreen->u32Width; - Rect.yBottom = Rect.yTop + pScreen->u32Height; + RTRECT SrcRect; + SrcRect.xLeft = 0; + SrcRect.yTop = 0; + SrcRect.xRight = pScreen->u32Width; + SrcRect.yBottom = pScreen->u32Height; + RTRECT DstRect; + DstRect.xLeft = pBlt->Pos.x; + DstRect.yTop = pBlt->Pos.y; + DstRect.xRight = DstRect.xLeft + pScreen->u32Width; + DstRect.yBottom = DstRect.yTop + pScreen->u32Height; CR_BLITTER_IMG Img; crFbImgFromScreenVram(pScreen, pu8Buf, &Img); - int rc = CrFbBltGetContents(hFb, &Rect, cRects, pRects, &Img); + int rc = CrFbBltGetContents(hFb, &SrcRect, &DstRect, cRects, pRects, &Img); if (!RT_SUCCESS(rc)) { WARN(("CrFbBltGetContents failed %d", rc)); - pCmd->i8Result = -1; + pCmd->u.i8Result = -1; return VINF_SUCCESS; } } @@ -4531,10 +4778,10 @@ int32_t crVBoxServerCrCmdBltProcess(PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd) else { WARN(("not implemented")); - pCmd->i8Result = -1; + pCmd->u.i8Result = -1; return VINF_SUCCESS; } - pCmd->i8Result = 0; + pCmd->u.i8Result = 0; return VINF_SUCCESS; } diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_stream.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_stream.c index bfadeda92..29670790a 100644 --- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_stream.c +++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_stream.c @@ -281,6 +281,28 @@ crServerDeleteClient( CRClient *client ) pNode->next = cr_server.pCleanupClient; cr_server.pCleanupClient = pNode; } + + if (!cr_server.numClients) + { + /* if no clients, the guest driver may be unloaded, + * and thus the visible regions situation might not be under control anymore, + * so cleanup the 3D framebuffer data here + * @todo: what really should happen is that guest driver on unload + * posts some request to host that would copy the current framebuffer 3D data to the 2D buffer + * (i.e. to the memory used by the standard IFramebuffer API) */ + HCR_FRAMEBUFFER hFb; + for (hFb = CrPMgrFbGetFirstEnabled(); hFb; hFb = CrPMgrFbGetNextEnabled(hFb)) + { + int rc = CrFbUpdateBegin(hFb); + if (RT_SUCCESS(rc)) + { + CrFbRegionsClear(hFb); + CrFbUpdateEnd(hFb); + } + else + WARN(("CrFbUpdateBegin failed %d", rc)); + } + } } /** diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c index b74c6224f..693512557 100644 --- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c +++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c @@ -18,26 +18,43 @@ crServerDispatchWindowCreate(const char *dpyName, GLint visBits) return crServerDispatchWindowCreateEx(dpyName, visBits, -1); } -GLint crServerMuralInit(CRMuralInfo *mural, const char *dpyName, GLint visBits, GLint preloadWinID) +GLint crServerMuralInit(CRMuralInfo *mural, GLboolean fGuestWindow, GLint visBits, GLint preloadWinID) { CRMuralInfo *defaultMural; GLint dims[2]; GLint windowID = -1; - GLint spuWindow; - int rc; + GLint spuWindow = 0; GLint realVisBits = visBits; + const char *dpyName = ""; crMemset(mural, 0, sizeof (*mural)); if (cr_server.fVisualBitsDefault) realVisBits = cr_server.fVisualBitsDefault; - /* - * Have first SPU make a new window. - */ - spuWindow = cr_server.head_spu->dispatch_table.WindowCreate( dpyName, realVisBits ); - if (spuWindow < 0) { - return spuWindow; +#ifdef RT_OS_DARWIN + if (fGuestWindow) + { + CRMuralInfo *dummy = crServerGetDummyMural(visBits); + if (!dummy) + { + WARN(("crServerGetDummyMural failed")); + return -1; + } + spuWindow = dummy->spuWindow; + mural->fIsDummyRefference = GL_TRUE; + } + else +#endif + { + /* + * Have first SPU make a new window. + */ + spuWindow = cr_server.head_spu->dispatch_table.WindowCreate( dpyName, realVisBits ); + if (spuWindow < 0) { + return spuWindow; + } + mural->fIsDummyRefference = GL_FALSE; } /* get initial window size */ @@ -121,7 +138,7 @@ GLint crServerDispatchWindowCreateEx(const char *dpyName, GLint visBits, GLint p return -1; } - windowID = crServerMuralInit(mural, dpyName, visBits, preloadWinID); + windowID = crServerMuralInit(mural, GL_TRUE, visBits, preloadWinID); if (windowID < 0) { crWarning("crServerMuralInit failed!"); @@ -181,7 +198,7 @@ void crServerMuralTerm(CRMuralInfo *mural) * which might lead to muralFBO (offscreen rendering) gl entities being created in a scope of that context */ cr_server.head_spu->dispatch_table.MakeCurrent(dummyMural->spuWindow, 0, cr_server.MainContextInfo.SpuContext); cr_server.currentWindow = -1; - cr_server.currentMural = NULL; + cr_server.currentMural = dummyMural; } else { @@ -202,7 +219,10 @@ void crServerMuralTerm(CRMuralInfo *mural) } } - cr_server.head_spu->dispatch_table.WindowDestroy( mural->spuWindow ); + if (!mural->fIsDummyRefference) + cr_server.head_spu->dispatch_table.WindowDestroy( mural->spuWindow ); + + mural->spuWindow = 0; if (mural->pVisibleRects) { diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu_wgl.c b/src/VBox/HostServices/SharedOpenGL/render/renderspu_wgl.c index 1175b29f6..1bd745a80 100644 --- a/src/VBox/HostServices/SharedOpenGL/render/renderspu_wgl.c +++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu_wgl.c @@ -1232,13 +1232,42 @@ GLboolean renderspu_SystemVBoxCreateWindow( VisualInfo *visual, GLboolean showIt return GL_TRUE; } +static void renderspuWindowRgnApply(WindowInfo *window) +{ + HRGN hRgn = window->hRgn; + if (hRgn) + { + /* note: according to the docs, SetWindowRgn owns the regions after it is called, + * and the regions will be freed automatically when needed, + * i.e. the caller should not do that. + * this is why we need to make a copy of the regions to be passed in */ + + int result; + hRgn = CreateRectRgn(0, 0, 0, 0); + if (!hRgn) + { + WARN(("CreateRectRgn failed")); + return; + } + + result = CombineRgn(hRgn, window->hRgn, NULL, RGN_COPY); + if (result == ERROR) + { + WARN(("CombineRgn failed")); + return; + } + } + + SetWindowRgn(window->hWnd, hRgn, true); +} + /* Either show or hide the render SPU's window. */ void renderspu_SystemShowWindow( WindowInfo *window, GLboolean showIt ) { if (showIt) { crDebug("SHOW renderspu_SystemShowWindow: %x", window->hWnd); - SetWindowRgn(window->hWnd, window->hRgn, true); + renderspuWindowRgnApply(window); } else { @@ -1246,7 +1275,9 @@ void renderspu_SystemShowWindow( WindowInfo *window, GLboolean showIt ) crDebug("HIDE renderspu_SystemShowWindow: %x", window->hWnd); hRgn = CreateRectRgn(0, 0, 0, 0); SetWindowRgn(window->hWnd, hRgn, true); - DeleteObject(hRgn); + /* note: according to the docs, SetWindowRgn owns the regions after it is called, + * and the regions will be freed automatically when needed, + * i.e. the caller should not do that */ } window->visible = showIt; } @@ -1571,12 +1602,12 @@ void renderspu_SystemWindowVisibleRegion(WindowInfo *window, GLint cRects, const DeleteObject(hTmpRgn); } + window->hRgn = hRgn; + if (window->visible) - SetWindowRgn(window->hWnd, hRgn, true); + renderspuWindowRgnApply(window); crDebug("Render SPU: SetWindowRgn (%x, cRects=%i)", window->hWnd, cRects); - - window->hRgn = hRgn; } static void renderspuHandleWindowMessages( HWND hWnd ) diff --git a/src/VBox/Installer/darwin/VirtualBox_mpkg/Localizable.strings b/src/VBox/Installer/darwin/VirtualBox_mpkg/Localizable.strings index 68313701f..0a2e8eeef 100644 --- a/src/VBox/Installer/darwin/VirtualBox_mpkg/Localizable.strings +++ b/src/VBox/Installer/darwin/VirtualBox_mpkg/Localizable.strings @@ -9,8 +9,8 @@ 'choiceVBoxCLI_title' = '@VBOX_PRODUCT@ Command Line Utilities'; 'choiceVBoxCLI_msg' = 'Installs the @VBOX_PRODUCT@ command line utilities into /usr/bin.'; -'RUNNING_VMS_TLE' = "Running VirtualBox VMs detected!"; -'RUNNING_VMS_MSG' = "The installer has detected running Virtual Machines. Please shutdown all running VirtualBox machines and then restart the installation."; +'RUNNING_VMS_TLE' = "Running VirtualBox virtual machines detected!"; +'RUNNING_VMS_MSG' = "The installer has detected running virtual machines. Please shut down all running VirtualBox machines and then restart the installation."; 'UNSUPPORTED_HW_MACHINE_TLE' = "Unsupported hardware architecture detected!"; 'UNSUPPORTED_HW_MACHINE_MSG' = "The installer has detected an unsupported architecture. VirtualBox only runs on the x86 and amd64 architectures."; diff --git a/src/VBox/Installer/darwin/VirtualBox_mpkg/distribution.dist b/src/VBox/Installer/darwin/VirtualBox_mpkg/distribution.dist index 82cd3297f..3749e3589 100644 --- a/src/VBox/Installer/darwin/VirtualBox_mpkg/distribution.dist +++ b/src/VBox/Installer/darwin/VirtualBox_mpkg/distribution.dist @@ -1,7 +1,7 @@