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