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