1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef MOZILLA_GFX_COMPOSITINGRENDERTARGETOGL_H
8 #define MOZILLA_GFX_COMPOSITINGRENDERTARGETOGL_H
9 
10 #include "GLContextTypes.h"             // for GLContext
11 #include "GLDefs.h"                     // for GLenum, LOCAL_GL_FRAMEBUFFER, etc
12 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
13 #include "mozilla/Attributes.h"         // for override
14 #include "mozilla/RefPtr.h"             // for RefPtr, already_AddRefed
15 #include "mozilla/gfx/Point.h"          // for IntSize, IntSizeTyped
16 #include "mozilla/gfx/Types.h"          // for SurfaceFormat, etc
17 #include "mozilla/layers/Compositor.h"  // for SurfaceInitMode, etc
18 #include "mozilla/layers/TextureHost.h"    // for CompositingRenderTarget
19 #include "mozilla/layers/CompositorOGL.h"  // for CompositorOGL
20 #include "mozilla/mozalloc.h"              // for operator new
21 #include "nsAString.h"
22 #include "nsCOMPtr.h"  // for already_AddRefed
23 #include "nsDebug.h"   // for NS_ERROR, NS_WARNING
24 #include "nsString.h"  // for nsAutoCString
25 
26 namespace mozilla {
27 namespace gl {
28 class BindableTexture;
29 }  // namespace gl
30 namespace gfx {
31 class DataSourceSurface;
32 }  // namespace gfx
33 
34 namespace layers {
35 
36 class TextureSource;
37 
38 class CompositingRenderTargetOGL : public CompositingRenderTarget {
39   typedef mozilla::gl::GLContext GLContext;
40 
41   friend class CompositorOGL;
42 
43   enum class GLResourceOwnership : uint8_t {
44     // Framebuffer and texture will be deleted when the RenderTarget is
45     // destroyed.
46     OWNED_BY_RENDER_TARGET,
47 
48     // Framebuffer and texture are only used by the RenderTarget, but never
49     // deleted.
50     EXTERNALLY_OWNED
51   };
52 
53   struct InitParams {
54     GLenum mFBOTextureTarget;
55     SurfaceInitMode mInitMode;
56   };
57 
58  public:
59   ~CompositingRenderTargetOGL();
60 
Name()61   const char* Name() const override { return "CompositingRenderTargetOGL"; }
62 
63   /**
64    * Create a render target around the default FBO, for rendering straight to
65    * the window.
66    */
CreateForWindow(CompositorOGL * aCompositor,const gfx::IntSize & aSize)67   static already_AddRefed<CompositingRenderTargetOGL> CreateForWindow(
68       CompositorOGL* aCompositor, const gfx::IntSize& aSize) {
69     RefPtr<CompositingRenderTargetOGL> result = new CompositingRenderTargetOGL(
70         aCompositor, gfx::IntRect(gfx::IntPoint(), aSize), gfx::IntPoint(),
71         aSize, GLResourceOwnership::EXTERNALLY_OWNED, 0, 0, Nothing());
72     return result.forget();
73   }
74 
75   static already_AddRefed<CompositingRenderTargetOGL>
CreateForNewFBOAndTakeOwnership(CompositorOGL * aCompositor,GLuint aTexture,GLuint aFBO,const gfx::IntRect & aRect,const gfx::IntPoint & aClipSpaceOrigin,const gfx::IntSize & aPhySize,GLenum aFBOTextureTarget,SurfaceInitMode aInit)76   CreateForNewFBOAndTakeOwnership(CompositorOGL* aCompositor, GLuint aTexture,
77                                   GLuint aFBO, const gfx::IntRect& aRect,
78                                   const gfx::IntPoint& aClipSpaceOrigin,
79                                   const gfx::IntSize& aPhySize,
80                                   GLenum aFBOTextureTarget,
81                                   SurfaceInitMode aInit) {
82     RefPtr<CompositingRenderTargetOGL> result = new CompositingRenderTargetOGL(
83         aCompositor, aRect, aClipSpaceOrigin, aPhySize,
84         GLResourceOwnership::OWNED_BY_RENDER_TARGET, aTexture, aFBO,
85         Some(InitParams{aFBOTextureTarget, aInit}));
86     return result.forget();
87   }
88 
89   static already_AddRefed<CompositingRenderTargetOGL>
CreateForExternallyOwnedFBO(CompositorOGL * aCompositor,GLuint aFBO,const gfx::IntRect & aRect,const gfx::IntPoint & aClipSpaceOrigin)90   CreateForExternallyOwnedFBO(CompositorOGL* aCompositor, GLuint aFBO,
91                               const gfx::IntRect& aRect,
92                               const gfx::IntPoint& aClipSpaceOrigin) {
93     RefPtr<CompositingRenderTargetOGL> result = new CompositingRenderTargetOGL(
94         aCompositor, aRect, aClipSpaceOrigin, aRect.Size(),
95         GLResourceOwnership::EXTERNALLY_OWNED, 0, aFBO, Nothing());
96     return result.forget();
97   }
98 
99   void BindTexture(GLenum aTextureUnit, GLenum aTextureTarget);
100 
101   /**
102    * Call when we want to draw into our FBO
103    */
104   void BindRenderTarget();
105 
IsWindow()106   bool IsWindow() { return mFBO == 0; }
107 
108   GLuint GetFBO() const;
109 
GetTextureHandle()110   GLuint GetTextureHandle() const {
111     MOZ_ASSERT(!mNeedInitialization);
112     return mTextureHandle;
113   }
114 
115   // TextureSourceOGL
AsSourceOGL()116   TextureSourceOGL* AsSourceOGL() override {
117     // XXX - Bug 900770
118     MOZ_ASSERT(
119         false,
120         "CompositingRenderTargetOGL should not be used as a TextureSource");
121     return nullptr;
122   }
GetSize()123   gfx::IntSize GetSize() const override { return mSize; }
124 
125   // The point that DrawGeometry's aClipRect is relative to. Will be (0, 0) for
126   // root render targets and equal to GetOrigin() for non-root render targets.
GetClipSpaceOrigin()127   gfx::IntPoint GetClipSpaceOrigin() const { return mClipSpaceOrigin; }
128 
GetFormat()129   gfx::SurfaceFormat GetFormat() const override {
130     // XXX - Should it be implemented ? is the above assert true ?
131     MOZ_ASSERT(false, "Not implemented");
132     return gfx::SurfaceFormat::UNKNOWN;
133   }
134 
135   // In render target coordinates, i.e. the same space as GetOrigin().
136   // NOT relative to mClipSpaceOrigin!
SetClipRect(const Maybe<gfx::IntRect> & aRect)137   void SetClipRect(const Maybe<gfx::IntRect>& aRect) { mClipRect = aRect; }
GetClipRect()138   const Maybe<gfx::IntRect>& GetClipRect() const { return mClipRect; }
139 
140 #ifdef MOZ_DUMP_PAINTING
141   already_AddRefed<gfx::DataSourceSurface> Dump(
142       Compositor* aCompositor) override;
143 #endif
144 
GetInitSize()145   const gfx::IntSize& GetInitSize() const { return mSize; }
GetPhysicalSize()146   const gfx::IntSize& GetPhysicalSize() const { return mPhySize; }
147 
148  protected:
CompositingRenderTargetOGL(CompositorOGL * aCompositor,const gfx::IntRect & aRect,const gfx::IntPoint & aClipSpaceOrigin,const gfx::IntSize & aPhySize,GLResourceOwnership aGLResourceOwnership,GLuint aTexure,GLuint aFBO,const Maybe<InitParams> & aNeedInitialization)149   CompositingRenderTargetOGL(CompositorOGL* aCompositor,
150                              const gfx::IntRect& aRect,
151                              const gfx::IntPoint& aClipSpaceOrigin,
152                              const gfx::IntSize& aPhySize,
153                              GLResourceOwnership aGLResourceOwnership,
154                              GLuint aTexure, GLuint aFBO,
155                              const Maybe<InitParams>& aNeedInitialization)
156       : CompositingRenderTarget(aRect.TopLeft()),
157         mNeedInitialization(aNeedInitialization),
158         mSize(aRect.Size()),
159         mPhySize(aPhySize),
160         mCompositor(aCompositor),
161         mGL(aCompositor->gl()),
162         mClipSpaceOrigin(aClipSpaceOrigin),
163         mGLResourceOwnership(aGLResourceOwnership),
164         mTextureHandle(aTexure),
165         mFBO(aFBO) {
166     MOZ_ASSERT(mGL);
167   }
168 
169   /**
170    * Actually do the initialisation.
171    * We do this lazily so that when we first set this render target on the
172    * compositor we do not have to re-bind the FBO after unbinding it, or
173    * alternatively leave the FBO bound after creation. Note that we leave our
174    * FBO bound, and so calling this method is only suitable when about to use
175    * this render target.
176    */
177   void Initialize(GLenum aFBOTextureTarget);
178 
179   /**
180    * Some() between construction and Initialize, if initialization was
181    * requested.
182    */
183   Maybe<InitParams> mNeedInitialization;
184 
185   /*
186    * Users of render target would draw in logical size, but it is
187    * actually drawn to a surface in physical size.  GL surfaces have
188    * a limitation on their size, a smaller surface would be
189    * allocated for the render target if the caller requests in a
190    * size too big.
191    */
192   gfx::IntSize mSize;     // Logical size, the expected by callers.
193   gfx::IntSize mPhySize;  // Physical size, the real size of the surface.
194 
195   /**
196    * There is temporary a cycle between the compositor and the render target,
197    * each having a strong ref to the other. The compositor's reference to
198    * the target is always cleared at the end of a frame.
199    */
200   RefPtr<CompositorOGL> mCompositor;
201   RefPtr<GLContext> mGL;
202   Maybe<gfx::IntRect> mClipRect;
203   gfx::IntPoint mClipSpaceOrigin;
204   GLResourceOwnership mGLResourceOwnership;
205   GLuint mTextureHandle;
206   GLuint mFBO;
207 };
208 
209 }  // namespace layers
210 }  // namespace mozilla
211 
212 #endif /* MOZILLA_GFX_SURFACEOGL_H */
213