Bug 1179935, introduce complex viewport projections to Compositor, remove PrepareViewport; r=mstange
authorVladimir Vukicevic <vladimir@pobox.com>
Tue, 19 May 2015 13:51:26 -0400
changeset 255273 fa2405094adb717e25c9cc73375609a5a38e9f81
parent 255272 29726d5ce4fbbade85b48bbc835f3b637ec11f9f
child 255274 5aa264987ee6646f457cfb9be9dc241669bb9cfa
push id14308
push userkwierso@gmail.com
push dateThu, 30 Jul 2015 03:22:19 +0000
treeherderfx-team@785f60f45b98 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1179935
milestone42.0a1
Bug 1179935, introduce complex viewport projections to Compositor, remove PrepareViewport; r=mstange --- gfx/layers/Compositor.h | 10 --- gfx/layers/basic/BasicCompositor.h | 2 - gfx/layers/composite/TextureHost.h | 34 +++++++- gfx/layers/d3d11/CompositorD3D11.cpp | 47 +++++++--- gfx/layers/d3d11/CompositorD3D11.h | 4 +- gfx/layers/d3d9/CompositorD3D9.h | 2 +- gfx/layers/opengl/CompositingRenderTargetOGL.cpp | 23 +++-- gfx/layers/opengl/CompositingRenderTargetOGL.h | 2 + gfx/layers/opengl/CompositorOGL.cpp | 104 +++++++++++++---------- gfx/layers/opengl/CompositorOGL.h | 6 +- 10 files changed, 145 insertions(+), 89 deletions(-)
gfx/layers/Compositor.h
gfx/layers/basic/BasicCompositor.h
gfx/layers/composite/TextureHost.h
gfx/layers/d3d11/CompositorD3D11.cpp
gfx/layers/d3d11/CompositorD3D11.h
gfx/layers/d3d9/CompositorD3D9.h
gfx/layers/opengl/CompositingRenderTargetOGL.cpp
gfx/layers/opengl/CompositingRenderTargetOGL.h
gfx/layers/opengl/CompositorOGL.cpp
gfx/layers/opengl/CompositorOGL.h
--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -380,26 +380,16 @@ public:
   /**
    * Post-rendering stuff if the rendering is done outside of this Compositor
    * e.g., by Composer2D.
    * aTransform is the transform from user space to window space.
    */
   virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) = 0;
 
   /**
-   * Setup the viewport and projection matrix for rendering to a target of the
-   * given dimensions. The size and transform here will override those set in
-   * BeginFrame. BeginFrame sets a size and transform for the default render
-   * target, usually the screen. Calling this method prepares the compositor to
-   * render using a different viewport (that is, size and transform), usually
-   * associated with a new render target.
-   */
-  virtual void PrepareViewport(const gfx::IntSize& aSize) = 0;
-
-  /**
    * Whether textures created by this compositor can receive partial updates.
    */
   virtual bool SupportsPartialTextureUpdate() = 0;
 
   void SetDiagnosticTypes(DiagnosticTypes aDiagnostics)
   {
     mDiagnosticTypes = aDiagnostics;
   }
--- a/gfx/layers/basic/BasicCompositor.h
+++ b/gfx/layers/basic/BasicCompositor.h
@@ -105,18 +105,16 @@ public:
   virtual int32_t GetMaxTextureSize() const override;
   virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) override { }
   
   virtual void SetScreenRenderOffset(const ScreenPoint& aOffset) override {
   }
 
   virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) override { }
 
-  virtual void PrepareViewport(const gfx::IntSize& aSize) override { }
-
 #ifdef MOZ_DUMP_PAINTING
   virtual const char* Name() const override { return "Basic"; }
 #endif // MOZ_DUMP_PAINTING
 
   virtual LayersBackend GetBackendType() const override {
     return LayersBackend::LAYERS_BASIC;
   }
 
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -711,39 +711,71 @@ private:
  */
 class CompositingRenderTarget: public TextureSource
 {
 public:
 
   explicit CompositingRenderTarget(const gfx::IntPoint& aOrigin)
     : mClearOnBind(false)
     , mOrigin(aOrigin)
+    , mHasComplexProjection(false)
   {}
   virtual ~CompositingRenderTarget() {}
 
 #ifdef MOZ_DUMP_PAINTING
   virtual already_AddRefed<gfx::DataSourceSurface> Dump(Compositor* aCompositor) { return nullptr; }
 #endif
 
   /**
    * Perform a clear when recycling a non opaque surface.
    * The clear is deferred to when the render target is bound.
    */
   void ClearOnBind() {
     mClearOnBind = true;
   }
 
-  const gfx::IntPoint& GetOrigin() { return mOrigin; }
+  const gfx::IntPoint& GetOrigin() const { return mOrigin; }
   gfx::IntRect GetRect() { return gfx::IntRect(GetOrigin(), GetSize()); }
 
+  /**
+   * If a Projection matrix is set, then it is used for rendering to
+   * this render target instead of generating one.  If no explicit
+   * projection is set, Compositors are expected to generate an
+   * orthogonal maaping that maps 0..1 to the full size of the render
+   * target.
+   */
+  bool HasComplexProjection() const { return mHasComplexProjection; }
+  void ClearProjection() { mHasComplexProjection = false; }
+  void SetProjection(const gfx::Matrix4x4& aNewMatrix, bool aEnableDepthBuffer,
+                     float aZNear, float aZFar)
+  {
+    mProjectionMatrix = aNewMatrix;
+    mEnableDepthBuffer = aEnableDepthBuffer;
+    mZNear = aZNear;
+    mZFar = aZFar;
+    mHasComplexProjection = true;
+  }
+  void GetProjection(gfx::Matrix4x4& aMatrix, bool& aEnableDepth, float& aZNear, float& aZFar)
+  {
+    MOZ_ASSERT(mHasComplexProjection);
+    aMatrix = mProjectionMatrix;
+    aEnableDepth = mEnableDepthBuffer;
+    aZNear = mZNear;
+    aZFar = mZFar;
+  }
 protected:
   bool mClearOnBind;
 
 private:
   gfx::IntPoint mOrigin;
+
+  gfx::Matrix4x4 mProjectionMatrix;
+  float mZNear, mZFar;
+  bool mHasComplexProjection;
+  bool mEnableDepthBuffer;
 };
 
 /**
  * Creates a TextureHost that can be used with any of the existing backends
  * Not all SurfaceDescriptor types are supported
  */
 already_AddRefed<TextureHost>
 CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc,
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -532,19 +532,30 @@ CompositorD3D11::CreateRenderTargetFromS
 }
 
 void
 CompositorD3D11::SetRenderTarget(CompositingRenderTarget* aRenderTarget)
 {
   MOZ_ASSERT(aRenderTarget);
   CompositingRenderTargetD3D11* newRT =
     static_cast<CompositingRenderTargetD3D11*>(aRenderTarget);
-  mCurrentRT = newRT;
-  mCurrentRT->BindRenderTarget(mContext);
-  PrepareViewport(newRT->GetSize());
+  if (mCurrentRT != newRT) {
+    mCurrentRT = newRT;
+    mCurrentRT->BindRenderTarget(mContext);
+  }
+
+  if (newRT->HasComplexProjection()) {
+    gfx::Matrix4x4 projection;
+    bool depthEnable;
+    float zNear, zFar;
+    newRT->GetProjection(projection, depthEnable, zNear, zFar);
+    PrepareViewport(newRT->GetSize(), projection, zNear, zFar);
+  } else {
+    PrepareViewport(newRT->GetSize());
+  }
 }
 
 void
 CompositorD3D11::SetPSForEffect(Effect* aEffect, MaskType aMaskType, gfx::SurfaceFormat aFormat)
 {
   switch (aEffect->mType) {
   case EffectTypes::SOLID_COLOR:
     mContext->PSSetShader(mAttachments->mSolidColorShader[aMaskType], nullptr, 0);
@@ -1102,36 +1113,44 @@ CompositorD3D11::EndFrame()
   }
 
   mCurrentRT = nullptr;
 }
 
 void
 CompositorD3D11::PrepareViewport(const gfx::IntSize& aSize)
 {
-  D3D11_VIEWPORT viewport;
-  viewport.MaxDepth = 1.0f;
-  viewport.MinDepth = 0.0f;
-  viewport.Width = aSize.width;
-  viewport.Height = aSize.height;
-  viewport.TopLeftX = 0;
-  viewport.TopLeftY = 0;
-
-  mContext->RSSetViewports(1, &viewport);
-
   // This view matrix translates coordinates from 0..width and 0..height to
   // -1..1 on the X axis, and -1..1 on the Y axis (flips the Y coordinate)
   Matrix viewMatrix = Matrix::Translation(-1.0, 1.0);
   viewMatrix.PreScale(2.0f / float(aSize.width), 2.0f / float(aSize.height));
   viewMatrix.PreScale(1.0f, -1.0f);
 
   Matrix4x4 projection = Matrix4x4::From2D(viewMatrix);
   projection._33 = 0.0f;
 
-  memcpy(&mVSConstants.projection, &projection, sizeof(mVSConstants.projection));
+  PrepareViewport(aSize, projection, 0.0f, 1.0f);
+}
+
+void
+CompositorD3D11::PrepareViewport(const gfx::IntSize& aSize,
+                                 const gfx::Matrix4x4& aProjection,
+                                 float aZNear, float aZFar)
+{
+  D3D11_VIEWPORT viewport;
+  viewport.MaxDepth = aZFar;
+  viewport.MinDepth = aZNear;
+  viewport.Width = aSize.width;
+  viewport.Height = aSize.height;
+  viewport.TopLeftX = 0;
+  viewport.TopLeftY = 0;
+
+  mContext->RSSetViewports(1, &viewport);
+
+  memcpy(&mVSConstants.projection, &aProjection._11, sizeof(mVSConstants.projection));
 }
 
 void
 CompositorD3D11::EnsureSize()
 {
   IntRect rect;
   mWidget->GetClientBounds(rect);
 
--- a/gfx/layers/d3d11/CompositorD3D11.h
+++ b/gfx/layers/d3d11/CompositorD3D11.h
@@ -124,17 +124,19 @@ public:
    * e.g., by Composer2D
    */
   virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) override {}
 
   /**
    * Setup the viewport and projection matrix for rendering
    * to a window of the given dimensions.
    */
-  virtual void PrepareViewport(const gfx::IntSize& aSize) override;
+  virtual void PrepareViewport(const gfx::IntSize& aSize);
+  virtual void PrepareViewport(const gfx::IntSize& aSize, const gfx::Matrix4x4& aProjection,
+                               float aZNear, float aZFar);
 
   virtual bool SupportsPartialTextureUpdate() override { return true; }
 
 #ifdef MOZ_DUMP_PAINTING
   virtual const char* Name() const override { return "Direct3D 11"; }
 #endif
 
   virtual LayersBackend GetBackendType() const override {
--- a/gfx/layers/d3d9/CompositorD3D9.h
+++ b/gfx/layers/d3d9/CompositorD3D9.h
@@ -66,17 +66,17 @@ public:
                           const gfx::Rect& aRenderBounds,
                           gfx::Rect *aClipRectOut = nullptr,
                           gfx::Rect *aRenderBoundsOut = nullptr) override;
 
   virtual void EndFrame() override;
 
   virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) override {}
 
-  virtual void PrepareViewport(const gfx::IntSize& aSize) override;
+  virtual void PrepareViewport(const gfx::IntSize& aSize);
 
   virtual bool SupportsPartialTextureUpdate() override{ return true; }
 
 #ifdef MOZ_DUMP_PAINTING
   virtual const char* Name() const override { return "Direct3D9"; }
 #endif
 
   virtual LayersBackend GetBackendType() const override {
--- a/gfx/layers/opengl/CompositingRenderTargetOGL.cpp
+++ b/gfx/layers/opengl/CompositingRenderTargetOGL.cpp
@@ -28,18 +28,24 @@ CompositingRenderTargetOGL::BindTexture(
   MOZ_ASSERT(mTextureHandle != 0);
   mGL->fActiveTexture(aTextureUnit);
   mGL->fBindTexture(aTextureTarget, mTextureHandle);
 }
 
 void
 CompositingRenderTargetOGL::BindRenderTarget()
 {
+  bool needsClear = false;
+
   if (mInitParams.mStatus != InitParams::INITIALIZED) {
     InitializeImpl();
+    if (mInitParams.mInit == INIT_MODE_CLEAR) {
+      needsClear = true;
+      mClearOnBind = false;
+    }
   } else {
     MOZ_ASSERT(mInitParams.mStatus == InitParams::INITIALIZED);
     GLuint fbo = mFBO == 0 ? mGL->GetDefaultFramebuffer() : mFBO;
     mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fbo);
     GLenum result = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
     if (result != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
       // The main framebuffer (0) of non-offscreen contexts
       // might be backed by a EGLSurface that needs to be renewed.
@@ -53,24 +59,24 @@ CompositingRenderTargetOGL::BindRenderTa
                          "GLContext=%p, IsOffscreen()=%d, mFBO=%d, aFBOTextureTarget=0x%x, "
                          "aRect.width=%d, aRect.height=%d",
                          result, mGL, mGL->IsOffscreen(), mFBO, mInitParams.mFBOTextureTarget,
                          mInitParams.mSize.width, mInitParams.mSize.height);
         NS_WARNING(msg.get());
       }
     }
 
-    mCompositor->PrepareViewport(mInitParams.mSize);
+    needsClear = mClearOnBind;
   }
 
-  if (mClearOnBind) {
+  if (needsClear) {
     mGL->fScissor(0, 0, mInitParams.mSize.width, mInitParams.mSize.height);
     mGL->fClearColor(0.0, 0.0, 0.0, 0.0);
-    mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
-    mClearOnBind = false;
+    mGL->fClearDepth(0.0);
+    mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
   }
 }
 
 #ifdef MOZ_DUMP_PAINTING
 already_AddRefed<DataSourceSurface>
 CompositingRenderTargetOGL::Dump(Compositor* aCompositor)
 {
   MOZ_ASSERT(mInitParams.mStatus == InitParams::INITIALIZED);
@@ -99,21 +105,12 @@ CompositingRenderTargetOGL::InitializeIm
   if (result != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
     nsAutoCString msg;
     msg.AppendPrintf("Framebuffer not complete -- error 0x%x, aFBOTextureTarget 0x%x, mFBO %d, mTextureHandle %d, aRect.width %d, aRect.height %d",
                       result, mInitParams.mFBOTextureTarget, mFBO, mTextureHandle, mInitParams.mSize.width, mInitParams.mSize.height);
     NS_ERROR(msg.get());
   }
 
   mInitParams.mStatus = InitParams::INITIALIZED;
-
-  mCompositor->PrepareViewport(mInitParams.mSize);
-  mGL->fScissor(0, 0, mInitParams.mSize.width, mInitParams.mSize.height);
-  if (mInitParams.mInit == INIT_MODE_CLEAR) {
-    mGL->fClearColor(0.0, 0.0, 0.0, 0.0);
-    mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
-    mClearOnBind = false;
-  }
-
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/opengl/CompositingRenderTargetOGL.h
+++ b/gfx/layers/opengl/CompositingRenderTargetOGL.h
@@ -34,16 +34,18 @@ namespace gfx {
 namespace layers {
 
 class TextureSource;
 
 class CompositingRenderTargetOGL : public CompositingRenderTarget
 {
   typedef mozilla::gl::GLContext GLContext;
 
+  friend class CompositorOGL;
+
   // For lazy initialisation of the GL stuff
   struct InitParams
   {
     InitParams() : mStatus(NO_PARAMS) {}
     InitParams(const gfx::IntSize& aSize,
                GLenum aFBOTextureTarget,
                SurfaceInitMode aInit)
       : mStatus(READY)
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -439,53 +439,64 @@ CompositorOGL::BindAndDrawQuadWithTextur
                                             aTexCoordRect,
                                             &layerRects,
                                             &textureRects);
 
   BindAndDrawQuads(aProg, rects, layerRects, textureRects);
 }
 
 void
-CompositorOGL::PrepareViewport(const gfx::IntSize& aSize)
+CompositorOGL::PrepareViewport(CompositingRenderTargetOGL* aRenderTarget)
 {
+  MOZ_ASSERT(aRenderTarget);
+  const gfx::IntSize& size = aRenderTarget->mInitParams.mSize;
+
   // Set the viewport correctly.
-  mGLContext->fViewport(0, 0, aSize.width, aSize.height);
+  mGLContext->fViewport(0, 0, size.width, size.height);
 
-  mViewportSize = aSize;
+  mViewportSize = size;
 
-  // We flip the view matrix around so that everything is right-side up; we're
-  // drawing directly into the window's back buffer, so this keeps things
-  // looking correct.
-  // XXX: We keep track of whether the window size changed, so we could skip
-  // this update if it hadn't changed since the last call.
+  if (!aRenderTarget->HasComplexProjection()) {
+    // We flip the view matrix around so that everything is right-side up; we're
+    // drawing directly into the window's back buffer, so this keeps things
+    // looking correct.
+    // XXX: We keep track of whether the window size changed, so we could skip
+    // this update if it hadn't changed since the last call.
 
-  // Matrix to transform (0, 0, aWidth, aHeight) to viewport space (-1.0, 1.0,
-  // 2, 2) and flip the contents.
-  Matrix viewMatrix;
-  if (mGLContext->IsOffscreen() && !gIsGtest) {
-    // In case of rendering via GL Offscreen context, disable Y-Flipping
-    viewMatrix.PreTranslate(-1.0, -1.0);
-    viewMatrix.PreScale(2.0f / float(aSize.width), 2.0f / float(aSize.height));
+    // Matrix to transform (0, 0, aWidth, aHeight) to viewport space (-1.0, 1.0,
+    // 2, 2) and flip the contents.
+    Matrix viewMatrix;
+    if (mGLContext->IsOffscreen() && !gIsGtest) {
+      // In case of rendering via GL Offscreen context, disable Y-Flipping
+      viewMatrix.PreTranslate(-1.0, -1.0);
+      viewMatrix.PreScale(2.0f / float(size.width), 2.0f / float(size.height));
+    } else {
+      viewMatrix.PreTranslate(-1.0, 1.0);
+      viewMatrix.PreScale(2.0f / float(size.width), 2.0f / float(size.height));
+      viewMatrix.PreScale(1.0f, -1.0f);
+    }
+
+    MOZ_ASSERT(mCurrentRenderTarget, "No destination");
+    // If we're drawing directly to the window then we want to offset
+    // drawing by the render offset.
+    if (!mTarget && mCurrentRenderTarget->IsWindow()) {
+      viewMatrix.PreTranslate(mRenderOffset.x, mRenderOffset.y);
+    }
+
+    Matrix4x4 matrix3d = Matrix4x4::From2D(viewMatrix);
+    matrix3d._33 = 0.0f;
+    mProjMatrix = matrix3d;
+    mGLContext->fDepthRange(0.0f, 1.0f);
   } else {
-    viewMatrix.PreTranslate(-1.0, 1.0);
-    viewMatrix.PreScale(2.0f / float(aSize.width), 2.0f / float(aSize.height));
-    viewMatrix.PreScale(1.0f, -1.0f);
+    // XXX take into account mRenderOffset
+    bool depthEnable;
+    float zNear, zFar;
+    aRenderTarget->GetProjection(mProjMatrix, depthEnable, zNear, zFar);
+    mGLContext->fDepthRange(zNear, zFar);
   }
-
-  MOZ_ASSERT(mCurrentRenderTarget, "No destination");
-  // If we're drawing directly to the window then we want to offset
-  // drawing by the render offset.
-  if (!mTarget && mCurrentRenderTarget->IsWindow()) {
-    viewMatrix.PreTranslate(mRenderOffset.x, mRenderOffset.y);
-  }
-
-  Matrix4x4 matrix3d = Matrix4x4::From2D(viewMatrix);
-  matrix3d._33 = 0.0f;
-
-  mProjMatrix = matrix3d;
 }
 
 already_AddRefed<CompositingRenderTarget>
 CompositorOGL::CreateRenderTarget(const IntRect &aRect, SurfaceInitMode aInit)
 {
   MOZ_ASSERT(aRect.width != 0 && aRect.height != 0, "Trying to create a render target of invalid size");
 
   if (aRect.width * aRect.height == 0) {
@@ -536,20 +547,24 @@ CompositorOGL::CreateRenderTargetFromSou
 void
 CompositorOGL::SetRenderTarget(CompositingRenderTarget *aSurface)
 {
   MOZ_ASSERT(aSurface);
   CompositingRenderTargetOGL* surface
     = static_cast<CompositingRenderTargetOGL*>(aSurface);
   if (mCurrentRenderTarget != surface) {
     mCurrentRenderTarget = surface;
-    mContextStateTracker.PopOGLSection(gl(), "Frame");
+    if (mCurrentRenderTarget) {
+      mContextStateTracker.PopOGLSection(gl(), "Frame");
+    }
     mContextStateTracker.PushOGLSection(gl(), "Frame");
     surface->BindRenderTarget();
   }
+
+  PrepareViewport(mCurrentRenderTarget);
 }
 
 CompositingRenderTarget*
 CompositorOGL::GetCurrentRenderTarget() const
 {
   return mCurrentRenderTarget;
 }
 
@@ -640,33 +655,34 @@ CompositorOGL::BeginFrame(const nsIntReg
 
   mPixelsPerFrame = width * height;
   mPixelsFilled = 0;
 
 #if MOZ_WIDGET_ANDROID
   TexturePoolOGL::Fill(gl());
 #endif
 
-  mCurrentRenderTarget =
-    CompositingRenderTargetOGL::RenderTargetForWindow(this,
-                                                      IntSize(width, height));
-  mCurrentRenderTarget->BindRenderTarget();
-
-  mContextStateTracker.PushOGLSection(gl(), "Frame");
-#ifdef DEBUG
-  mWindowRenderTarget = mCurrentRenderTarget;
-#endif
-
   // Default blend function implements "OVER"
   mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
                                  LOCAL_GL_ONE, LOCAL_GL_ONE);
   mGLContext->fEnable(LOCAL_GL_BLEND);
 
+  // Make sure SCISSOR is enabled before setting the render target, since the RT
+  // assumes scissor is enabled while it does clears.
   mGLContext->fEnable(LOCAL_GL_SCISSOR_TEST);
 
+  RefPtr<CompositingRenderTargetOGL> rt =
+    CompositingRenderTargetOGL::RenderTargetForWindow(this,
+                                                      IntSize(width, height));
+  SetRenderTarget(rt);
+
+#ifdef DEBUG
+  mWindowRenderTarget = mCurrentRenderTarget;
+#endif
+
   if (aClipRectOut && !aClipRectIn) {
     aClipRectOut->SetRect(0, 0, width, height);
   }
 
   // If the Android compositor is being used, this clear will be done in
   // DrawWindowUnderlay. Make sure the bits used here match up with those used
   // in mobile/android/base/gfx/LayerRenderer.java
 #ifndef MOZ_WIDGET_ANDROID
--- a/gfx/layers/opengl/CompositorOGL.h
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -178,16 +178,17 @@ struct CompositorOGLVRObjects {
 
 // If you want to make this class not final, first remove calls to virtual
 // methods (Destroy) that are made in the destructor.
 class CompositorOGL final : public Compositor
 {
   typedef mozilla::gl::GLContext GLContext;
 
   friend class GLManagerCompositor;
+  friend class CompositingRenderTargetOGL;
 
   std::map<ShaderConfigOGL, ShaderProgramOGL*> mPrograms;
 public:
   explicit CompositorOGL(nsIWidget *aWidget, int aSurfaceWidth = -1, int aSurfaceHeight = -1,
                          bool aUseExternalSurfaceSize = false);
 
 protected:
   virtual ~CompositorOGL();
@@ -256,19 +257,16 @@ public:
   virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) override;
 
   virtual void SetScreenRenderOffset(const ScreenPoint& aOffset) override {
     mRenderOffset = aOffset;
   }
 
   virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) override;
 
-  virtual void PrepareViewport(const gfx::IntSize& aSize) override;
-
-
 #ifdef MOZ_DUMP_PAINTING
   virtual const char* Name() const override { return "OGL"; }
 #endif // MOZ_DUMP_PAINTING
 
   virtual LayersBackend GetBackendType() const override {
     return LayersBackend::LAYERS_OPENGL;
   }
 
@@ -323,16 +321,18 @@ private:
   void DestroyVR(GLContext *gl);
 
   void DrawVRDistortion(const gfx::Rect& aRect,
                         const gfx::Rect& aClipRect,
                         const EffectChain& aEffectChain,
                         gfx::Float aOpacity,
                         const gfx::Matrix4x4& aTransform);
 
+  void PrepareViewport(CompositingRenderTargetOGL *aRenderTarget);
+
   /** Widget associated with this compositor */
   nsIWidget *mWidget;
   gfx::IntSize mWidgetSize;
   nsRefPtr<GLContext> mGLContext;
   UniquePtr<GLBlitTextureImageHelper> mBlitTextureImageHelper;
   gfx::Matrix4x4 mProjMatrix;
 
   /** The size of the surface we are rendering to */