Bug 1383907 - Enable WebVR reftests on macOS; r?kip, jgilbert draft
authorDaosheng Mu <daoshengmu@gmail.com>
Fri, 25 Aug 2017 00:30:31 +0800
changeset 664553 c7b1cd3ec017a351831bb0abf738d70656d17601
parent 660422 d8e238b811d3dc74515065ae8cab6c74baf0295f
child 731467 eede6bdba27a2ca06413aea726c8a47b6a36bc82
push id79719
push userbmo:dmu@mozilla.com
push dateThu, 14 Sep 2017 01:44:35 +0000
reviewerskip, jgilbert
bugs1383907
milestone57.0a1
Bug 1383907 - Enable WebVR reftests on macOS; r?kip, jgilbert MozReview-Commit-ID: 2OpA95QWI4d
dom/vr/test/reftest/reftest.list
gfx/vr/gfxVRPuppet.cpp
gfx/vr/moz.build
--- a/dom/vr/test/reftest/reftest.list
+++ b/dom/vr/test/reftest/reftest.list
@@ -1,8 +1,10 @@
 # WebVR Reftests
 default-preferences pref(dom.vr.puppet.enabled,true) pref(dom.vr.test.enabled,true) pref(dom.vr.require-gesture,false) pref(dom.vr.puppet.submitframe,1)
 
-# VR SubmitFrame is only implemented for D3D11 now.
+# VR SubmitFrame is only implemented for D3D11 and MacOSX now.
 # We need to continue to investigate why these reftests can be run well in local,
-# but will be suspended until terminating on reftest debug build.
-skip-if(!winWidget||!layersGPUAccelerated||isDebugBuild) == draw_rect.html wrapper.html?draw_rect.png
-skip-if(!winWidget||!layersGPUAccelerated||isDebugBuild) == change_size.html wrapper.html?change_size.png
+# but will be suspended until terminating on reftest D3D11 debug build.
+skip-if(Android||gtkWidget||(winWidget&&isDebugBuild)||!layersGPUAccelerated) == draw_rect.html wrapper.html?draw_rect.png
+# On MacOSX platform, getting different color interpolation result.
+# For lower resolution Mac hardware, we need to adjust it to fuzzy-if(cocoaWidget,1,1200).
+fuzzy-if(cocoaWidget,1,600) skip-if(Android||gtkWidget||(winWidget&&isDebugBuild)||!layersGPUAccelerated) == change_size.html wrapper.html?change_size.png
--- a/gfx/vr/gfxVRPuppet.cpp
+++ b/gfx/vr/gfxVRPuppet.cpp
@@ -2,22 +2,26 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #if defined(XP_WIN)
 #include "CompositorD3D11.h"
 #include "TextureD3D11.h"
 #include "mozilla/gfx/DeviceManagerDx.h"
-#endif // XP_WIN
+#elif defined(XP_MACOSX)
+#include "mozilla/gfx/MacIOSurface.h"
+#endif
 
 #include "mozilla/Base64.h"
 #include "mozilla/gfx/DataSurfaceHelpers.h"
+#include "gfxPrefs.h"
 #include "gfxUtils.h"
 #include "gfxVRPuppet.h"
+#include "VRManager.h"
 
 #include "mozilla/dom/GamepadEventTypes.h"
 #include "mozilla/dom/GamepadBinding.h"
 
 // See CompositorD3D11Shaders.h
 namespace mozilla {
 namespace layers {
 struct ShaderBytes { const void* mData; size_t mLength; };
@@ -33,29 +37,19 @@ using namespace mozilla::layers;
 
 // Reminder: changing the order of these buttons may break web content
 static const uint64_t kPuppetButtonMask[] = {
   1,
   2,
   4,
   8
 };
-
 static const uint32_t kNumPuppetButtonMask = sizeof(kPuppetButtonMask) /
                                              sizeof(uint64_t);
-
-static const uint32_t kPuppetAxes[] = {
-  0,
-  1,
-  2
-};
-
-static const uint32_t kNumPuppetAxis = sizeof(kPuppetAxes) /
-                                       sizeof(uint32_t);
-
+static const uint32_t kNumPuppetAxis = 3;
 static const uint32_t kNumPuppetHaptcs = 1;
 
 VRDisplayPuppet::VRDisplayPuppet()
  : VRDisplayHost(VRDeviceType::Puppet)
  , mIsPresenting(false)
 {
   MOZ_COUNT_CTOR_INHERITED(VRDisplayPuppet, VRDisplayHost);
 
@@ -373,17 +367,17 @@ VRDisplayPuppet::SubmitFrame(TextureSour
       VRSubmitFrameResultInfo result;
       result.mFormat = SurfaceFormat::B8G8R8A8;
       // If the original texture size is not pow of 2, CopyResource() will add padding,
       // so the size is adjusted. We have to get the correct size by (mapInfo.RowPitch /
       // the format size).
       result.mWidth = mapInfo.RowPitch / 4;
       result.mHeight = desc.Height;
       result.mFrameNum = mDisplayInfo.mFrameId;
-      nsCString rawString(Substring((char*)srcData, mapInfo.RowPitch * desc.Height));
+      nsCString rawString(Substring(srcData, mapInfo.RowPitch * desc.Height));
 
       if (Base64Encode(rawString, result.mBase64Image) != NS_OK) {
         MOZ_ASSERT(false, "Failed to encode base64 images.");
       }
       mContext->Unmap(mappedTexture, 0);
       // Dispatch the base64 encoded string to the DOM side. Then, it will be decoded
       // and convert to a PNG image there.
       vm->DispatchSubmitFrameResult(mDisplayInfo.mDisplayID, result);
@@ -469,22 +463,76 @@ VRDisplayPuppet::SubmitFrame(TextureSour
 #elif defined(XP_MACOSX)
 
 bool
 VRDisplayPuppet::SubmitFrame(MacIOSurface* aMacIOSurface,
                              const IntSize& aSize,
                              const gfx::Rect& aLeftEyeRect,
                              const gfx::Rect& aRightEyeRect)
 {
-  if (!mIsPresenting) {
+  if (!mIsPresenting || !aMacIOSurface) {
     return false;
   }
 
-  // TODO: Bug 1343730, Need to block until the next simulated
-  // vblank interval and capture frames for use in reftests.
+  VRManager* vm = VRManager::Get();
+  MOZ_ASSERT(vm);
+
+  switch (gfxPrefs::VRPuppetSubmitFrame()) {
+    case 0:
+      // The VR frame is not displayed.
+      break;
+    case 1:
+    {
+      // The frames are submitted to VR compositor are decoded
+      // into a base64Image and dispatched to the DOM side.
+      RefPtr<SourceSurface> surf = aMacIOSurface->GetAsSurface();
+      RefPtr<DataSourceSurface> dataSurf = surf ? surf->GetDataSurface() :
+                                           nullptr;
+      if (dataSurf) {
+        // Ideally, we should convert the srcData to a PNG image and decode it
+        // to a Base64 string here, but the GPU process does not have the privilege to
+        // access the image library. So, we have to convert the RAW image data
+        // to a base64 string and forward it to let the content process to
+        // do the image conversion.
+        DataSourceSurface::MappedSurface map;
+        if (!dataSurf->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
+          MOZ_ASSERT(false, "Read DataSourceSurface fail.");
+          return false;
+        }
+        const uint8_t* srcData = map.mData;
+        const auto& surfSize = dataSurf->GetSize();
+        VRSubmitFrameResultInfo result;
+        result.mFormat = SurfaceFormat::B8G8R8A8;
+        result.mWidth = surfSize.width;
+        result.mHeight = surfSize.height;
+        result.mFrameNum = mDisplayInfo.mFrameId;
+        // If the original texture size is not pow of 2, the data will not be tightly strided.
+        // We have to copy the pixels by rows.
+        nsCString rawString;
+        for (int32_t i = 0; i < surfSize.height; i++) {
+          rawString += Substring((const char*)(srcData) + i * map.mStride,
+                                  surfSize.width * 4);
+        }
+        dataSurf->Unmap();
+
+        if (Base64Encode(rawString, result.mBase64Image) != NS_OK) {
+          MOZ_ASSERT(false, "Failed to encode base64 images.");
+        }
+        // Dispatch the base64 encoded string to the DOM side. Then, it will be decoded
+        // and convert to a PNG image there.
+        vm->DispatchSubmitFrameResult(mDisplayInfo.mDisplayID, result);
+      }
+      break;
+    }
+    case 2:
+    {
+      MOZ_ASSERT(false, "No support for showing VR frames on MacOSX yet.");
+      break;
+    }
+  }
 
   return false;
 }
 
 #endif
 
 void
 VRDisplayPuppet::NotifyVSync()
@@ -702,17 +750,17 @@ VRSystemManagerPuppet::HandleAxisMove(ui
   if (controller->GetAxisMove(aAxis) != aValue) {
     NewAxisMove(aControllerIdx, aAxis, aValue);
     controller->SetAxisMove(aAxis, aValue);
   }
 }
 
 void
 VRSystemManagerPuppet::HandlePoseTracking(uint32_t aControllerIdx,
-                                          const GamepadPoseState& aPose,
+                                          const dom::GamepadPoseState& aPose,
                                           VRControllerHost* aController)
 {
   MOZ_ASSERT(aController);
   if (aPose != aController->GetPose()) {
     aController->SetPose(aPose);
     NewPoseState(aControllerIdx, aPose);
   }
 }
--- a/gfx/vr/moz.build
+++ b/gfx/vr/moz.build
@@ -19,30 +19,30 @@ LOCAL_INCLUDES += [
     '/dom/base',
     '/gfx/layers/d3d11',
     '/gfx/thebes',
 ]
 
 UNIFIED_SOURCES += [
     'gfxVR.cpp',
     'gfxVROSVR.cpp',
-    'gfxVRPuppet.cpp',
     'ipc/VRLayerChild.cpp',
     'ipc/VRLayerParent.cpp',
     'ipc/VRManagerChild.cpp',
     'ipc/VRManagerParent.cpp',
     'VRDisplayClient.cpp',
     'VRDisplayPresentation.cpp',
     'VRManager.cpp',
 ]
 
 # VRDisplayHost includes MacIOSurface.h which includes Mac headers
 # which define Size and Points types in the root namespace that
 # often conflict with our own types.
 SOURCES += [
+    'gfxVRPuppet.cpp',
     'VRDisplayHost.cpp',
 ]
 
 # Build OpenVR on Windows, Linux, and macOS desktop targets
 if CONFIG['OS_TARGET'] in ('WINNT', 'Linux', 'Darwin'):
     DIRS += [
         'openvr',
     ]