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_TEXTUREOGL_H
8 #define MOZILLA_GFX_TEXTUREOGL_H
9 
10 #include <stddef.h>  // for size_t
11 #include <stdint.h>  // for uint64_t
12 #include "CompositableHost.h"
13 #include "GLContextTypes.h"  // for GLContext
14 #include "GLDefs.h"          // for GLenum, LOCAL_GL_CLAMP_TO_EDGE, etc
15 #include "GLTextureImage.h"  // for TextureImage
16 #include "gfxTypes.h"
17 #include "mozilla/GfxMessageUtils.h"         // for gfxContentType
18 #include "mozilla/Assertions.h"              // for MOZ_ASSERT, etc
19 #include "mozilla/Attributes.h"              // for override
20 #include "mozilla/RefPtr.h"                  // for RefPtr
21 #include "mozilla/gfx/Matrix.h"              // for Matrix4x4
22 #include "mozilla/gfx/Point.h"               // for IntSize, IntPoint
23 #include "mozilla/gfx/Types.h"               // for SurfaceFormat, etc
24 #include "mozilla/layers/CompositorOGL.h"    // for CompositorOGL
25 #include "mozilla/layers/CompositorTypes.h"  // for TextureFlags
26 #include "mozilla/layers/LayersSurfaces.h"   // for SurfaceDescriptor
27 #include "mozilla/layers/TextureHost.h"      // for TextureHost, etc
28 #include "mozilla/mozalloc.h"                // for operator delete, etc
29 #include "mozilla/webrender/RenderThread.h"
30 #include "nsCOMPtr.h"         // for already_AddRefed
31 #include "nsDebug.h"          // for NS_WARNING
32 #include "nsISupportsImpl.h"  // for TextureImage::Release, etc
33 #include "nsRegionFwd.h"      // for nsIntRegion
34 
35 #ifdef MOZ_WIDGET_ANDROID
36 #  include "AndroidSurfaceTexture.h"
37 #  include "mozilla/java/GeckoSurfaceTextureWrappers.h"
38 #endif
39 
40 namespace mozilla {
41 namespace gfx {
42 class DataSourceSurface;
43 }  // namespace gfx
44 
45 namespace layers {
46 
47 class Compositor;
48 class CompositorOGL;
49 class TextureImageTextureSourceOGL;
50 class GLTextureSource;
51 
52 void ApplySamplingFilterToBoundTexture(gl::GLContext* aGL,
53                                        gfx::SamplingFilter aSamplingFilter,
54                                        GLuint aTarget = LOCAL_GL_TEXTURE_2D);
55 
56 already_AddRefed<TextureHost> CreateTextureHostOGL(
57     const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator,
58     LayersBackend aBackend, TextureFlags aFlags);
59 
60 /*
61  * TextureHost implementations for the OpenGL backend.
62  *
63  * Note that it is important to be careful about the ownership model with
64  * the OpenGL backend, due to some widget limitation on Linux: before
65  * the nsBaseWidget associated with our OpenGL context has been completely
66  * deleted, every resource belonging to the OpenGL context MUST have been
67  * released. At the moment the teardown sequence happens in the middle of
68  * the nsBaseWidget's destructor, meaning that at a given moment we must be
69  * able to easily find and release all the GL resources.
70  * The point is: be careful about the ownership model and limit the number
71  * of objects sharing references to GL resources to make the tear down
72  * sequence as simple as possible.
73  */
74 
75 /**
76  * TextureSourceOGL provides the necessary API for CompositorOGL to composite
77  * a TextureSource.
78  */
79 class TextureSourceOGL {
80  public:
TextureSourceOGL()81   TextureSourceOGL()
82       : mCachedSamplingFilter(gfx::SamplingFilter::GOOD),
83         mHasCachedSamplingFilter(false) {}
84 
85   virtual bool IsValid() const = 0;
86 
87   virtual void BindTexture(GLenum aTextureUnit,
88                            gfx::SamplingFilter aSamplingFilter) = 0;
89 
90   // To be overridden in textures that need this. This method will be called
91   // when the compositor has used the texture to draw. This allows us to set
92   // a fence with glFenceSync which we can wait on later to ensure the GPU
93   // is done with the draw calls using that texture. We would like to be able
94   // to simply use glFinishObjectAPPLE, but this returns earlier than
95   // expected with nvidia drivers.
MaybeFenceTexture()96   virtual void MaybeFenceTexture() {}
97 
98   virtual gfx::IntSize GetSize() const = 0;
99 
GetTextureTarget()100   virtual GLenum GetTextureTarget() const { return LOCAL_GL_TEXTURE_2D; }
101 
102   virtual gfx::SurfaceFormat GetFormat() const = 0;
103 
104   virtual GLenum GetWrapMode() const = 0;
105 
GetTextureTransform()106   virtual gfx::Matrix4x4 GetTextureTransform() { return gfx::Matrix4x4(); }
107 
AsTextureImageTextureSource()108   virtual TextureImageTextureSourceOGL* AsTextureImageTextureSource() {
109     return nullptr;
110   }
111 
AsGLTextureSource()112   virtual GLTextureSource* AsGLTextureSource() { return nullptr; }
113 
SetSamplingFilter(gl::GLContext * aGL,gfx::SamplingFilter aSamplingFilter)114   void SetSamplingFilter(gl::GLContext* aGL,
115                          gfx::SamplingFilter aSamplingFilter) {
116     if (mHasCachedSamplingFilter && mCachedSamplingFilter == aSamplingFilter) {
117       return;
118     }
119     mHasCachedSamplingFilter = true;
120     mCachedSamplingFilter = aSamplingFilter;
121     ApplySamplingFilterToBoundTexture(aGL, aSamplingFilter, GetTextureTarget());
122   }
123 
ClearCachedFilter()124   void ClearCachedFilter() { mHasCachedSamplingFilter = false; }
125 
126  private:
127   gfx::SamplingFilter mCachedSamplingFilter;
128   bool mHasCachedSamplingFilter;
129 };
130 
131 /**
132  * A TextureSource backed by a TextureImage.
133  *
134  * Depending on the underlying TextureImage, may support texture tiling, so
135  * make sure to check AsBigImageIterator() and use the texture accordingly.
136  *
137  * This TextureSource can be used without a TextureHost and manage it's own
138  * GL texture(s).
139  */
140 class TextureImageTextureSourceOGL final : public DataTextureSource,
141                                            public TextureSourceOGL,
142                                            public BigImageIterator {
143  public:
144   explicit TextureImageTextureSourceOGL(
145       CompositorOGL* aCompositor, TextureFlags aFlags = TextureFlags::DEFAULT);
146 
Name()147   const char* Name() const override { return "TextureImageTextureSourceOGL"; }
148   // DataTextureSource
149 
150   bool Update(gfx::DataSourceSurface* aSurface,
151               nsIntRegion* aDestRegion = nullptr,
152               gfx::IntPoint* aSrcOffset = nullptr) override;
153 
154   void EnsureBuffer(const gfx::IntSize& aSize, gfxContentType aContentType);
155 
AsTextureImageTextureSource()156   TextureImageTextureSourceOGL* AsTextureImageTextureSource() override {
157     return this;
158   }
159 
160   // TextureSource
161 
162   void DeallocateDeviceData() override;
163 
AsSourceOGL()164   TextureSourceOGL* AsSourceOGL() override { return this; }
165 
166   void BindTexture(GLenum aTextureUnit,
167                    gfx::SamplingFilter aSamplingFilter) override;
168 
169   gfx::IntSize GetSize() const override;
170 
171   gfx::SurfaceFormat GetFormat() const override;
172 
IsValid()173   bool IsValid() const override { return !!mTexImage; }
174 
175   void SetTextureSourceProvider(TextureSourceProvider* aProvider) override;
176 
GetWrapMode()177   GLenum GetWrapMode() const override { return mTexImage->GetWrapMode(); }
178 
179   // BigImageIterator
180 
AsBigImageIterator()181   BigImageIterator* AsBigImageIterator() override { return this; }
182 
BeginBigImageIteration()183   void BeginBigImageIteration() override {
184     mTexImage->BeginBigImageIteration();
185     mIterating = true;
186   }
187 
EndBigImageIteration()188   void EndBigImageIteration() override { mIterating = false; }
189 
190   gfx::IntRect GetTileRect() override;
191 
GetTileCount()192   size_t GetTileCount() override { return mTexImage->GetTileCount(); }
193 
NextTile()194   bool NextTile() override { return mTexImage->NextTile(); }
195 
196  protected:
197   ~TextureImageTextureSourceOGL();
198 
199   RefPtr<gl::TextureImage> mTexImage;
200   RefPtr<gl::GLContext> mGL;
201   RefPtr<CompositorOGL> mCompositor;
202   TextureFlags mFlags;
203   bool mIterating;
204 };
205 
206 /**
207  * A texture source for GL textures.
208  *
209  * It does not own any GL texture, and attaches its shared handle to one of
210  * the compositor's temporary textures when binding.
211  *
212  * The shared texture handle is owned by the TextureHost.
213  */
214 class GLTextureSource : public DataTextureSource, public TextureSourceOGL {
215  public:
216   GLTextureSource(TextureSourceProvider* aProvider, GLuint aTextureHandle,
217                   GLenum aTarget, gfx::IntSize aSize,
218                   gfx::SurfaceFormat aFormat);
219 
220   virtual ~GLTextureSource();
221 
Name()222   const char* Name() const override { return "GLTextureSource"; }
223 
AsGLTextureSource()224   GLTextureSource* AsGLTextureSource() override { return this; }
225 
AsSourceOGL()226   TextureSourceOGL* AsSourceOGL() override { return this; }
227 
228   void BindTexture(GLenum activetex,
229                    gfx::SamplingFilter aSamplingFilter) override;
230 
231   bool IsValid() const override;
232 
GetSize()233   gfx::IntSize GetSize() const override { return mSize; }
234 
GetFormat()235   gfx::SurfaceFormat GetFormat() const override { return mFormat; }
236 
GetTextureTarget()237   GLenum GetTextureTarget() const override { return mTextureTarget; }
238 
GetWrapMode()239   GLenum GetWrapMode() const override { return LOCAL_GL_CLAMP_TO_EDGE; }
240 
241   void DeallocateDeviceData() override;
242 
243   void SetTextureSourceProvider(TextureSourceProvider* aProvider) override;
244 
SetSize(gfx::IntSize aSize)245   void SetSize(gfx::IntSize aSize) { mSize = aSize; }
246 
SetFormat(gfx::SurfaceFormat aFormat)247   void SetFormat(gfx::SurfaceFormat aFormat) { mFormat = aFormat; }
248 
GetTextureHandle()249   GLuint GetTextureHandle() const { return mTextureHandle; }
250 
gl()251   gl::GLContext* gl() const { return mGL; }
252 
253   bool Update(gfx::DataSourceSurface* aSurface,
254               nsIntRegion* aDestRegion = nullptr,
255               gfx::IntPoint* aSrcOffset = nullptr) override {
256     return false;
257   }
258 
259  protected:
260   void DeleteTextureHandle();
261 
262   RefPtr<gl::GLContext> mGL;
263   RefPtr<CompositorOGL> mCompositor;
264   GLuint mTextureHandle;
265   GLenum mTextureTarget;
266   gfx::IntSize mSize;
267   gfx::SurfaceFormat mFormat;
268 };
269 
270 // This texture source try to wrap "aSurface" in ctor for compositor direct
271 // access. Since we can't know the timing for gpu buffer access, the surface
272 // should be alive until the ~ClientStorageTextureSource(). And if we try to
273 // update the surface we mapped before, we need to call Sync() to make sure
274 // the surface is not used by compositor.
275 class DirectMapTextureSource : public GLTextureSource {
276  public:
277   DirectMapTextureSource(TextureSourceProvider* aProvider,
278                          gfx::DataSourceSurface* aSurface);
279   ~DirectMapTextureSource();
280 
281   bool Update(gfx::DataSourceSurface* aSurface,
282               nsIntRegion* aDestRegion = nullptr,
283               gfx::IntPoint* aSrcOffset = nullptr) override;
284 
IsDirectMap()285   bool IsDirectMap() override { return true; }
286 
287   // If aBlocking is false, check if this texture is no longer being used
288   // by the GPU - if aBlocking is true, this will block until the GPU is
289   // done with it.
290   bool Sync(bool aBlocking) override;
291 
292   void MaybeFenceTexture() override;
293 
294  private:
295   bool UpdateInternal(gfx::DataSourceSurface* aSurface,
296                       nsIntRegion* aDestRegion, gfx::IntPoint* aSrcOffset,
297                       bool aInit);
298 
299   GLsync mSync;
300 };
301 
302 class GLTextureHost : public TextureHost {
303  public:
304   GLTextureHost(TextureFlags aFlags, GLuint aTextureHandle, GLenum aTarget,
305                 GLsync aSync, gfx::IntSize aSize, bool aHasAlpha);
306 
307   virtual ~GLTextureHost();
308 
309   // We don't own anything.
DeallocateDeviceData()310   void DeallocateDeviceData() override {}
311 
312   void SetTextureSourceProvider(TextureSourceProvider* aProvider) override;
313 
314   bool Lock() override;
315 
Unlock()316   void Unlock() override {}
317 
318   gfx::SurfaceFormat GetFormat() const override;
319 
BindTextureSource(CompositableTextureSourceRef & aTexture)320   bool BindTextureSource(CompositableTextureSourceRef& aTexture) override {
321     aTexture = mTextureSource;
322     return !!aTexture;
323   }
324 
GetAsSurface()325   already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override {
326     return nullptr;  // XXX - implement this (for MOZ_DUMP_PAINTING)
327   }
328 
329   gl::GLContext* gl() const;
330 
GetSize()331   gfx::IntSize GetSize() const override { return mSize; }
332 
Name()333   const char* Name() override { return "GLTextureHost"; }
334 
335  protected:
336   const GLuint mTexture;
337   const GLenum mTarget;
338   GLsync mSync;
339   const gfx::IntSize mSize;
340   const bool mHasAlpha;
341   RefPtr<GLTextureSource> mTextureSource;
342 };
343 
344 ////////////////////////////////////////////////////////////////////////
345 // SurfaceTexture
346 
347 #ifdef MOZ_WIDGET_ANDROID
348 
349 class SurfaceTextureSource : public TextureSource, public TextureSourceOGL {
350  public:
351   SurfaceTextureSource(TextureSourceProvider* aProvider,
352                        java::GeckoSurfaceTexture::Ref& aSurfTex,
353                        gfx::SurfaceFormat aFormat, GLenum aTarget,
354                        GLenum aWrapMode, gfx::IntSize aSize,
355                        bool aIgnoreTransform);
356 
Name()357   const char* Name() const override { return "SurfaceTextureSource"; }
358 
AsSourceOGL()359   TextureSourceOGL* AsSourceOGL() override { return this; }
360 
361   void BindTexture(GLenum activetex,
362                    gfx::SamplingFilter aSamplingFilter) override;
363 
364   bool IsValid() const override;
365 
GetSize()366   gfx::IntSize GetSize() const override { return mSize; }
367 
GetFormat()368   gfx::SurfaceFormat GetFormat() const override { return mFormat; }
369 
370   gfx::Matrix4x4 GetTextureTransform() override;
371 
GetTextureTarget()372   GLenum GetTextureTarget() const override { return mTextureTarget; }
373 
GetWrapMode()374   GLenum GetWrapMode() const override { return mWrapMode; }
375 
376   void DeallocateDeviceData() override;
377 
378   void SetTextureSourceProvider(TextureSourceProvider* aProvider) override;
379 
gl()380   gl::GLContext* gl() const { return mGL; }
381 
382  protected:
383   RefPtr<gl::GLContext> mGL;
384   mozilla::java::GeckoSurfaceTexture::GlobalRef mSurfTex;
385   const gfx::SurfaceFormat mFormat;
386   const GLenum mTextureTarget;
387   const GLenum mWrapMode;
388   const gfx::IntSize mSize;
389   const bool mIgnoreTransform;
390 };
391 
392 class SurfaceTextureHost : public TextureHost {
393  public:
394   SurfaceTextureHost(TextureFlags aFlags,
395                      mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
396                      gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
397                      bool aContinuousUpdate, bool aIgnoreTransform);
398 
399   virtual ~SurfaceTextureHost();
400 
401   void PrepareTextureSource(CompositableTextureSourceRef& aTexture) override;
402 
403   void DeallocateDeviceData() override;
404 
405   void SetTextureSourceProvider(TextureSourceProvider* aProvider) override;
406 
407   bool Lock() override;
408 
409   gfx::SurfaceFormat GetFormat() const override;
410 
411   void NotifyNotUsed() override;
412 
BindTextureSource(CompositableTextureSourceRef & aTexture)413   bool BindTextureSource(CompositableTextureSourceRef& aTexture) override {
414     aTexture = mTextureSource;
415     return !!aTexture;
416   }
417 
GetAsSurface()418   already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override {
419     return nullptr;  // XXX - implement this (for MOZ_DUMP_PAINTING)
420   }
421 
422   gl::GLContext* gl() const;
423 
GetSize()424   gfx::IntSize GetSize() const override { return mSize; }
425 
Name()426   const char* Name() override { return "SurfaceTextureHost"; }
427 
AsSurfaceTextureHost()428   SurfaceTextureHost* AsSurfaceTextureHost() override { return this; }
429 
430   void CreateRenderTexture(
431       const wr::ExternalImageId& aExternalImageId) override;
432 
433   uint32_t NumSubTextures() override;
434 
435   void PushResourceUpdates(wr::TransactionBuilder& aResources,
436                            ResourceUpdateOp aOp,
437                            const Range<wr::ImageKey>& aImageKeys,
438                            const wr::ExternalImageId& aExtID) override;
439 
440   void PushDisplayItems(wr::DisplayListBuilder& aBuilder,
441                         const wr::LayoutRect& aBounds,
442                         const wr::LayoutRect& aClip, wr::ImageRendering aFilter,
443                         const Range<wr::ImageKey>& aImageKeys,
444                         const bool aPreferCompositorSurface) override;
445 
446  protected:
447   bool EnsureAttached();
448 
449   mozilla::java::GeckoSurfaceTexture::GlobalRef mSurfTex;
450   const gfx::IntSize mSize;
451   const gfx::SurfaceFormat mFormat;
452   bool mContinuousUpdate;
453   const bool mIgnoreTransform;
454   RefPtr<CompositorOGL> mCompositor;
455   RefPtr<SurfaceTextureSource> mTextureSource;
456 };
457 
458 #endif  // MOZ_WIDGET_ANDROID
459 
460 ////////////////////////////////////////////////////////////////////////
461 // EGLImage
462 
463 class EGLImageTextureSource : public TextureSource, public TextureSourceOGL {
464  public:
465   EGLImageTextureSource(TextureSourceProvider* aProvider, EGLImage aImage,
466                         gfx::SurfaceFormat aFormat, GLenum aTarget,
467                         GLenum aWrapMode, gfx::IntSize aSize);
468 
Name()469   const char* Name() const override { return "EGLImageTextureSource"; }
470 
AsSourceOGL()471   TextureSourceOGL* AsSourceOGL() override { return this; }
472 
473   void BindTexture(GLenum activetex,
474                    gfx::SamplingFilter aSamplingFilter) override;
475 
476   bool IsValid() const override;
477 
GetSize()478   gfx::IntSize GetSize() const override { return mSize; }
479 
GetFormat()480   gfx::SurfaceFormat GetFormat() const override { return mFormat; }
481 
482   gfx::Matrix4x4 GetTextureTransform() override;
483 
GetTextureTarget()484   GLenum GetTextureTarget() const override { return mTextureTarget; }
485 
GetWrapMode()486   GLenum GetWrapMode() const override { return mWrapMode; }
487 
488   // We don't own anything.
DeallocateDeviceData()489   void DeallocateDeviceData() override {}
490 
491   void SetTextureSourceProvider(TextureSourceProvider* aProvider) override;
492 
gl()493   gl::GLContext* gl() const { return mGL; }
494 
495  protected:
496   RefPtr<gl::GLContext> mGL;
497   RefPtr<CompositorOGL> mCompositor;
498   const EGLImage mImage;
499   const gfx::SurfaceFormat mFormat;
500   const GLenum mTextureTarget;
501   const GLenum mWrapMode;
502   const gfx::IntSize mSize;
503 };
504 
505 class EGLImageTextureHost final : public TextureHost {
506  public:
507   EGLImageTextureHost(TextureFlags aFlags, EGLImage aImage, EGLSync aSync,
508                       gfx::IntSize aSize, bool hasAlpha);
509 
510   virtual ~EGLImageTextureHost();
511 
512   // We don't own anything.
DeallocateDeviceData()513   void DeallocateDeviceData() override {}
514 
515   void SetTextureSourceProvider(TextureSourceProvider* aProvider) override;
516 
517   bool Lock() override;
518 
519   void Unlock() override;
520 
521   gfx::SurfaceFormat GetFormat() const override;
522 
BindTextureSource(CompositableTextureSourceRef & aTexture)523   bool BindTextureSource(CompositableTextureSourceRef& aTexture) override {
524     aTexture = mTextureSource;
525     return !!aTexture;
526   }
527 
GetAsSurface()528   already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override {
529     return nullptr;  // XXX - implement this (for MOZ_DUMP_PAINTING)
530   }
531 
532   gl::GLContext* gl() const;
533 
GetSize()534   gfx::IntSize GetSize() const override { return mSize; }
535 
Name()536   const char* Name() override { return "EGLImageTextureHost"; }
537 
538   void CreateRenderTexture(
539       const wr::ExternalImageId& aExternalImageId) override;
540 
541   void PushResourceUpdates(wr::TransactionBuilder& aResources,
542                            ResourceUpdateOp aOp,
543                            const Range<wr::ImageKey>& aImageKeys,
544                            const wr::ExternalImageId& aExtID) override;
545 
546   void PushDisplayItems(wr::DisplayListBuilder& aBuilder,
547                         const wr::LayoutRect& aBounds,
548                         const wr::LayoutRect& aClip, wr::ImageRendering aFilter,
549                         const Range<wr::ImageKey>& aImageKeys,
550                         const bool aPreferCompositorSurface) override;
551 
552  protected:
553   const EGLImage mImage;
554   const EGLSync mSync;
555   const gfx::IntSize mSize;
556   const bool mHasAlpha;
557   RefPtr<EGLImageTextureSource> mTextureSource;
558 };
559 
560 }  // namespace layers
561 }  // namespace mozilla
562 
563 #endif /* MOZILLA_GFX_TEXTUREOGL_H */
564