Bug 1188700, [webvr] Fix VR distortion compositing in d3d11/gl to take into account rendertarget size and transform; r=kip
authorVladimir Vukicevic <vladimir@pobox.com>
Wed, 29 Jul 2015 14:39:47 -0400
changeset 286922 cef69a78f01614d31fdb7705816f7dc8fd807d62
parent 286921 616cd074d5815f9ee4e126f2b17866fab5718d2a
child 286923 572e4ffbc46d7365f922f8392f5d8e3caa4d607f
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskip
bugs1188700
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1188700, [webvr] Fix VR distortion compositing in d3d11/gl to take into account rendertarget size and transform; r=kip
gfx/layers/composite/ContainerLayerComposite.cpp
gfx/layers/d3d11/CompositorD3D11.cpp
gfx/layers/opengl/CompositorOGLVR.cpp
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -285,29 +285,29 @@ ContainerRenderVR(ContainerT* aContainer
   // XXX should DrawQuad handle this on its own?  Is there a time where we wouldn't want
   // to do this? (e.g. something like Cardboard would not require distortion so will fill
   // the entire rect)
   EffectChain solidEffect(aContainer);
   solidEffect.mPrimaryEffect = new EffectSolidColor(Color(0.0, 0.0, 0.0, 1.0));
   aManager->GetCompositor()->DrawQuad(rect, rect, solidEffect, 1.0, gfx::Matrix4x4());
 
   // draw the temporary surface with VR distortion to the original destination
-  gfx::Matrix4x4 scaleTransform = aContainer->GetEffectiveTransform();
   EffectChain vrEffect(aContainer);
   bool skipDistortion = vrRendering || PR_GetEnv("MOZ_GFX_VR_NO_DISTORTION");
   if (skipDistortion) {
     vrEffect.mPrimaryEffect = new EffectRenderTarget(surface);
-    scaleTransform.PreScale(rtBounds.width / float(surfaceRect.width),
-                            rtBounds.height / float(surfaceRect.height),
-                            1.0f);
   } else {
     vrEffect.mPrimaryEffect = new EffectVRDistortion(aHMD, surface);
-    // no need to scale, because the VRDistortion effect will sample from surface
   }
 
+  gfx::Matrix4x4 scaleTransform = aContainer->GetEffectiveTransform();
+  scaleTransform.PreScale(rtBounds.width / float(surfaceRect.width),
+                          rtBounds.height / float(surfaceRect.height),
+                          1.0f);
+
   // XXX we shouldn't use visibleRect here -- the VR distortion needs to know the
   // full rect, not just the visible one.  Luckily, right now, VR distortion is only
   // rendered when the element is fullscreen, so the visibleRect will be right anyway.
   aManager->GetCompositor()->DrawQuad(rect, clipRect, vrEffect, opacity,
                                       scaleTransform);
 
   DUMP("<<< ContainerRenderVR [%p]\n", aContainer);
 }
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -634,17 +634,16 @@ CompositorD3D11::DrawVRDistortion(const 
   }
 
   HRESULT hr;
 
   EffectVRDistortion* vrEffect =
     static_cast<EffectVRDistortion*>(aEffectChain.mPrimaryEffect.get());
 
   TextureSourceD3D11* source = vrEffect->mTexture->AsSourceD3D11();
-  gfx::IntSize size = vrEffect->mRenderTarget->GetSize(); // XXX source->GetSize()
 
   VRHMDInfo* hmdInfo = vrEffect->mHMD;
   VRHMDType hmdType = hmdInfo->GetType();
 
   if (!mAttachments->mVRDistortionVS[hmdType] ||
       !mAttachments->mVRDistortionPS[hmdType])
   {
     NS_WARNING("No VS/PS for hmd type for VR distortion!");
@@ -702,31 +701,33 @@ CompositorD3D11::DrawVRDistortion(const 
   mContext->IASetInputLayout(mAttachments->mVRDistortionInputLayout[hmdType]);
   mContext->VSSetShader(mAttachments->mVRDistortionVS[hmdType], nullptr, 0);
   mContext->PSSetShader(mAttachments->mVRDistortionPS[hmdType], nullptr, 0);
 
   // This is the source texture SRV for the pixel shader
   ID3D11ShaderResourceView* srView = source->GetShaderResourceView();
   mContext->PSSetShaderResources(0, 1, &srView);
 
-  gfx::IntSize vpSizeInt = mCurrentRT->GetSize();
-  gfx::Size vpSize(vpSizeInt.width, vpSizeInt.height);
+  Rect destRect = aTransform.TransformBounds(aRect);
+  gfx::IntSize preDistortionSize = vrEffect->mRenderTarget->GetSize(); // XXX source->GetSize()
+  gfx::Size vpSize = destRect.Size();
+
   ID3D11Buffer* vbuffer;
   UINT vsize, voffset;
 
   for (uint32_t eye = 0; eye < 2; eye++) {
     gfx::IntRect eyeViewport;
-    eyeViewport.x = eye * size.width / 2;
+    eyeViewport.x = eye * preDistortionSize.width / 2;
     eyeViewport.y = 0;
-    eyeViewport.width = size.width / 2;
-    eyeViewport.height = size.height;
+    eyeViewport.width = preDistortionSize.width / 2;
+    eyeViewport.height = preDistortionSize.height;
 
     hmdInfo->FillDistortionConstants(eye,
-                                     size, eyeViewport,
-                                     vpSize, aRect,
+                                     preDistortionSize, eyeViewport,
+                                     vpSize, destRect,
                                      shaderConstants);
 
     // D3D has clip space top-left as -1,1 so we need to flip the Y coordinate offset here
     shaderConstants.destinationScaleAndOffset[1] = - shaderConstants.destinationScaleAndOffset[1];
 
     // XXX I really want to write a templated helper for these next 4 lines
     D3D11_MAPPED_SUBRESOURCE resource;
     hr = mContext->Map(mAttachments->mVRDistortionConstants, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
--- a/gfx/layers/opengl/CompositorOGLVR.cpp
+++ b/gfx/layers/opengl/CompositorOGLVR.cpp
@@ -225,18 +225,16 @@ CompositorOGL::DrawVRDistortion(const gf
 
   GLenum textureTarget = LOCAL_GL_TEXTURE_2D;
   if (vrEffect->mRenderTarget)
     textureTarget = mFBOTextureTarget;
 
   RefPtr<CompositingRenderTargetOGL> surface =
     static_cast<CompositingRenderTargetOGL*>(vrEffect->mRenderTarget.get());
 
-  gfx::IntSize size = surface->GetInitSize(); // XXX source->GetSize()
-
   VRHMDInfo* hmdInfo = vrEffect->mHMD;
   VRDistortionConstants shaderConstants;
 
   if (hmdInfo->GetConfiguration() != mVR.mConfiguration) {
     for (uint32_t eye = 0; eye < 2; eye++) {
       const gfx::VRDistortionMesh& mesh = hmdInfo->GetDistortionMesh(eye);
       gl()->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mVR.mDistortionVertices[eye]);
       gl()->fBufferData(LOCAL_GL_ARRAY_BUFFER,
@@ -277,42 +275,43 @@ CompositorOGL::DrawVRDistortion(const gf
   gl()->fEnableVertexAttribArray(mVR.mATexCoord0);
   gl()->fEnableVertexAttribArray(mVR.mATexCoord1);
   gl()->fEnableVertexAttribArray(mVR.mATexCoord2);
   gl()->fEnableVertexAttribArray(mVR.mAGenericAttribs);
 
   surface->BindTexture(LOCAL_GL_TEXTURE0, mFBOTextureTarget);
   gl()->fUniform1i(mVR.mUTexture[programIndex], 0);
 
-  gfx::IntSize vpSizeInt = mCurrentRenderTarget->GetInitSize();
-  gfx::Size vpSize(vpSizeInt.width, vpSizeInt.height);
+  Rect destRect = aTransform.TransformBounds(aRect);
+  gfx::IntSize preDistortionSize = surface->GetInitSize(); // XXX source->GetSize()
+  gfx::Size vpSize = destRect.Size();
 
   for (uint32_t eye = 0; eye < 2; eye++) {
     gfx::IntRect eyeViewport;
-    eyeViewport.x = eye * size.width / 2;
+    eyeViewport.x = eye * preDistortionSize.width / 2;
     eyeViewport.y = 0;
-    eyeViewport.width = size.width / 2;
-    eyeViewport.height = size.height;
+    eyeViewport.width = preDistortionSize.width / 2;
+    eyeViewport.height = preDistortionSize.height;
 
     hmdInfo->FillDistortionConstants(eye,
-                                     size, eyeViewport,
-                                     vpSize, aRect,
+                                     preDistortionSize, eyeViewport,
+                                     vpSize, destRect,
                                      shaderConstants);
 
     float height = 1.0f;
     float texScaleAndOffset[4] = { shaderConstants.eyeToSourceScaleAndOffset[0],
                                    shaderConstants.eyeToSourceScaleAndOffset[1],
                                    shaderConstants.eyeToSourceScaleAndOffset[2],
                                    shaderConstants.eyeToSourceScaleAndOffset[3] };
     if (textureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) {
-      texScaleAndOffset[0] *= size.width;
-      texScaleAndOffset[1] *= size.height;
-      texScaleAndOffset[2] *= size.width;
-      texScaleAndOffset[3] *= size.height;
-      height = size.height;
+      texScaleAndOffset[0] *= preDistortionSize.width;
+      texScaleAndOffset[1] *= preDistortionSize.height;
+      texScaleAndOffset[2] *= preDistortionSize.width;
+      texScaleAndOffset[3] *= preDistortionSize.height;
+      height = preDistortionSize.height;
     }
 
     gl()->fUniform4fv(mVR.mUVRDestionatinScaleAndOffset[programIndex], 1, shaderConstants.destinationScaleAndOffset);
     gl()->fUniform4fv(mVR.mUVREyeToSource[programIndex], 1, texScaleAndOffset);
     gl()->fUniform1f(mVR.mUHeight[programIndex], height);
 
     gl()->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mVR.mDistortionVertices[eye]);