Bug 1269337 - Implement physical and logical size for GL render target. r=mattwoodrow
authorThinker K.F. Li <thinker@codemud.net>
Mon, 28 Nov 2016 02:14:00 +0100
changeset 324656 e0418e43a56a778989013b446643bd45e2578708
parent 324655 ea44d42c5517077e717d29a0a57d88bd3558126b
child 324657 fcb1d52e5a8213fcfe7e9e5ebfef908122e835c4
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersmattwoodrow
bugs1269337
milestone53.0a1
Bug 1269337 - Implement physical and logical size for GL render target. r=mattwoodrow
gfx/layers/opengl/CompositingRenderTargetOGL.h
gfx/layers/opengl/CompositorOGL.cpp
gfx/layers/opengl/CompositorOGL.h
--- a/gfx/layers/opengl/CompositingRenderTargetOGL.h
+++ b/gfx/layers/opengl/CompositingRenderTargetOGL.h
@@ -41,30 +41,40 @@ class CompositingRenderTargetOGL : publi
 
   friend class CompositorOGL;
 
   // For lazy initialisation of the GL stuff
   struct InitParams
   {
     InitParams() : mStatus(NO_PARAMS) {}
     InitParams(const gfx::IntSize& aSize,
+               const gfx::IntSize& aPhySize,
                GLenum aFBOTextureTarget,
                SurfaceInitMode aInit)
       : mStatus(READY)
       , mSize(aSize)
+      , mPhySize(aPhySize)
       , mFBOTextureTarget(aFBOTextureTarget)
       , mInit(aInit)
     {}
 
     enum {
       NO_PARAMS,
       READY,
       INITIALIZED
     } mStatus;
-    gfx::IntSize mSize;
+    /*
+     * Users of render target would draw in logical size, but it is
+     * actually drawn to a surface in physical size.  GL surfaces have
+     * a limitation on their size, a smaller surface would be
+     * allocated for the render target if the caller requests in a
+     * size too big.
+     */
+    gfx::IntSize mSize; // Logical size, the expected by callers.
+    gfx::IntSize mPhySize; // Physical size, the real size of the surface.
     GLenum mFBOTextureTarget;
     SurfaceInitMode mInit;
   };
 
 public:
   CompositingRenderTargetOGL(CompositorOGL* aCompositor, const gfx::IntPoint& aOrigin,
                              GLuint aTexure, GLuint aFBO)
     : CompositingRenderTarget(aOrigin)
@@ -86,34 +96,35 @@ public:
    * the window.
    */
   static already_AddRefed<CompositingRenderTargetOGL>
   RenderTargetForWindow(CompositorOGL* aCompositor,
                         const gfx::IntSize& aSize)
   {
     RefPtr<CompositingRenderTargetOGL> result
       = new CompositingRenderTargetOGL(aCompositor, gfx::IntPoint(), 0, 0);
-    result->mInitParams = InitParams(aSize, 0, INIT_MODE_NONE);
+    result->mInitParams = InitParams(aSize, aSize, 0, INIT_MODE_NONE);
     result->mInitParams.mStatus = InitParams::INITIALIZED;
     return result.forget();
   }
 
   /**
    * Some initialisation work on the backing FBO and texture.
    * We do this lazily so that when we first set this render target on the
    * compositor we do not have to re-bind the FBO after unbinding it, or
    * alternatively leave the FBO bound after creation.
    */
   void Initialize(const gfx::IntSize& aSize,
+                  const gfx::IntSize& aPhySize,
                   GLenum aFBOTextureTarget,
                   SurfaceInitMode aInit)
   {
     MOZ_ASSERT(mInitParams.mStatus == InitParams::NO_PARAMS, "Initialized twice?");
     // postpone initialization until we actually want to use this render target
-    mInitParams = InitParams(aSize, aFBOTextureTarget, aInit);
+    mInitParams = InitParams(aSize, aPhySize, aFBOTextureTarget, aInit);
   }
 
   void BindTexture(GLenum aTextureUnit, GLenum aTextureTarget);
 
   /**
    * Call when we want to draw into our FBO
    */
   void BindRenderTarget();
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -463,20 +463,23 @@ CompositorOGL::GetTextureCoordinates(gfx
 
   return textureRect;
 }
 
 void
 CompositorOGL::PrepareViewport(CompositingRenderTargetOGL* aRenderTarget)
 {
   MOZ_ASSERT(aRenderTarget);
+  // Logical surface size.
   const gfx::IntSize& size = aRenderTarget->mInitParams.mSize;
+  // Physical surface size.
+  const gfx::IntSize& phySize = aRenderTarget->mInitParams.mPhySize;
 
   // Set the viewport correctly.
-  mGLContext->fViewport(0, 0, size.width, size.height);
+  mGLContext->fViewport(0, 0, phySize.width, phySize.height);
 
   mViewportSize = size;
 
   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
@@ -526,20 +529,22 @@ CompositorOGL::CreateRenderTarget(const 
 
   if (!gl()) {
     // CompositingRenderTargetOGL does not work without a gl context.
     return nullptr;
   }
 
   GLuint tex = 0;
   GLuint fbo = 0;
-  CreateFBOWithTexture(aRect, false, 0, &fbo, &tex);
+  IntRect rect = aRect;
+  IntSize FBOSize;
+  CreateFBOWithTexture(rect, false, 0, &fbo, &tex, &FBOSize);
   RefPtr<CompositingRenderTargetOGL> surface
     = new CompositingRenderTargetOGL(this, aRect.TopLeft(), tex, fbo);
-  surface->Initialize(aRect.Size(), mFBOTextureTarget, aInit);
+  surface->Initialize(aRect.Size(), FBOSize, mFBOTextureTarget, aInit);
   return surface.forget();
 }
 
 already_AddRefed<CompositingRenderTarget>
 CompositorOGL::CreateRenderTargetFromSource(const IntRect &aRect,
                                             const CompositingRenderTarget *aSource,
                                             const IntPoint &aSourcePoint)
 {
@@ -564,16 +569,17 @@ CompositorOGL::CreateRenderTargetFromSou
   } else {
     CreateFBOWithTexture(sourceRect, true, 0,
                          &fbo, &tex);
   }
 
   RefPtr<CompositingRenderTargetOGL> surface
     = new CompositingRenderTargetOGL(this, aRect.TopLeft(), tex, fbo);
   surface->Initialize(aRect.Size(),
+                      sourceRect.Size(),
                       mFBOTextureTarget,
                       INIT_MODE_NONE);
   return surface.forget();
 }
 
 void
 CompositorOGL::SetRenderTarget(CompositingRenderTarget *aSurface)
 {
@@ -694,26 +700,30 @@ CompositorOGL::BeginFrame(const nsIntReg
     aClipRectOut->SetRect(0, 0, width, height);
   }
 
   mGLContext->fClearColor(mClearColor.r, mClearColor.g, mClearColor.b, mClearColor.a);
   mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
 }
 
 void
-CompositorOGL::CreateFBOWithTexture(const gfx::IntRect& aRect, bool aCopyFromSource,
+CompositorOGL::CreateFBOWithTexture(const gfx::IntRect& aRect,
+                                    bool aCopyFromSource,
                                     GLuint aSourceFrameBuffer,
-                                    GLuint *aFBO, GLuint *aTexture)
+                                    GLuint *aFBO, GLuint *aTexture,
+                                    gfx::IntSize* aAllocSize)
 {
-  *aTexture = CreateTexture(aRect, aCopyFromSource, aSourceFrameBuffer);
+  *aTexture = CreateTexture(aRect, aCopyFromSource, aSourceFrameBuffer,
+                            aAllocSize);
   mGLContext->fGenFramebuffers(1, aFBO);
 }
 
 GLuint
-CompositorOGL::CreateTexture(const IntRect& aRect, bool aCopyFromSource, GLuint aSourceFrameBuffer)
+CompositorOGL::CreateTexture(const IntRect& aRect, bool aCopyFromSource,
+                             GLuint aSourceFrameBuffer, IntSize* aAllocSize)
 {
   // we're about to create a framebuffer backed by textures to use as an intermediate
   // surface. What to do if its size (as given by aRect) would exceed the
   // maximum texture size supported by the GL? The present code chooses the compromise
   // of just clamping the framebuffer's size to the max supported size.
   // This gives us a lower resolution rendering of the intermediate surface (children layers).
   // See bug 827170 for a discussion.
   IntRect clampedRect = aRect;
@@ -796,16 +806,21 @@ CompositorOGL::CreateTexture(const IntRe
   mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_MAG_FILTER,
                              LOCAL_GL_LINEAR);
   mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_WRAP_S,
                              LOCAL_GL_CLAMP_TO_EDGE);
   mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_WRAP_T,
                              LOCAL_GL_CLAMP_TO_EDGE);
   mGLContext->fBindTexture(mFBOTextureTarget, 0);
 
+  if (aAllocSize) {
+    aAllocSize->width = clampedRect.width;
+    aAllocSize->height = clampedRect.height;
+  }
+
   return tex;
 }
 
 ShaderConfigOGL
 CompositorOGL::GetShaderConfigFor(Effect *aEffect,
                                   MaskType aMask,
                                   gfx::CompositionOp aOp,
                                   bool aColorMatrix,
--- a/gfx/layers/opengl/CompositorOGL.h
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -340,19 +340,22 @@ private:
    * Create a FBO backed by a texture.
    * Note that the texture target type will be
    * of the type returned by FBOTextureTarget; different
    * shaders are required to sample from the different
    * texture types.
    */
   void CreateFBOWithTexture(const gfx::IntRect& aRect, bool aCopyFromSource,
                             GLuint aSourceFrameBuffer,
-                            GLuint *aFBO, GLuint *aTexture);
+                            GLuint *aFBO, GLuint *aTexture,
+                            gfx::IntSize* aAllocSize = nullptr);
 
-  GLuint CreateTexture(const gfx::IntRect& aRect, bool aCopyFromSource, GLuint aSourceFrameBuffer);
+  GLuint CreateTexture(const gfx::IntRect& aRect, bool aCopyFromSource,
+                       GLuint aSourceFrameBuffer,
+                       gfx::IntSize* aAllocSize = nullptr);
 
   gfx::Point3D GetLineCoefficients(const gfx::Point& aPoint1,
                                    const gfx::Point& aPoint2);
 
   void ActivateProgram(ShaderProgramOGL *aProg);
 
   void CleanupResources();