From b1e2dfd641e69c269c1b4d25efa69c6879e93f75 Mon Sep 17 00:00:00 2001 From: JerryShih Date: Thu, 22 Dec 2016 17:22:37 +0800 Subject: [PATCH] Bug 1321144 - add WebRender TextureHost related classes. r=sotaro? Add TextureSourceWebRenderOGL for WR GL composition. Use BindTextureSource/UnbindTextureSource() to provide the TextureSource for WR external image rendering. Currently,only ImageHost supports these functions. MozReview-Commit-ID: d5EvPUmlpq --- gfx/layers/composite/CompositableHost.h | 14 ++- gfx/layers/composite/ImageHost.cpp | 32 ++++-- gfx/layers/composite/ImageHost.h | 3 +- gfx/layers/composite/TextureHost.h | 9 +- gfx/layers/moz.build | 2 + gfx/layers/wr/TextureHostWebRenderOGL.cpp | 130 +++++++++++++++++++++ gfx/layers/wr/TextureHostWebRenderOGL.h | 132 ++++++++++++++++++++++ 7 files changed, 311 insertions(+), 11 deletions(-) create mode 100644 gfx/layers/wr/TextureHostWebRenderOGL.cpp create mode 100644 gfx/layers/wr/TextureHostWebRenderOGL.h diff --git a/gfx/layers/composite/CompositableHost.h b/gfx/layers/composite/CompositableHost.h index 977be0bd1f4a..c1d21abc1afe 100644 --- a/gfx/layers/composite/CompositableHost.h +++ b/gfx/layers/composite/CompositableHost.h @@ -241,7 +241,19 @@ public: /// is is destroyed. virtual void CleanupResources() {} - virtual void BindTextureSource() {} + // Used for WR + // This call will call the Lock() function and return a TextureSource for WR + // composition. + virtual TextureSource* BindTextureSource() + { + MOZ_RELEASE_ASSERT(true, "No implementation for BindTextureSource()"); + + return nullptr; + } + virtual void UnbindTextureSource() + { + MOZ_RELEASE_ASSERT(true, "No implementation for UnindTextureSource()"); + } protected: TextureInfo mTextureInfo; diff --git a/gfx/layers/composite/ImageHost.cpp b/gfx/layers/composite/ImageHost.cpp index 34271ecc4619..dd8d1a568095 100644 --- a/gfx/layers/composite/ImageHost.cpp +++ b/gfx/layers/composite/ImageHost.cpp @@ -434,14 +434,20 @@ ImageHost::Composite(LayerComposite* aLayer, mBias); } -void +TextureSource* ImageHost::BindTextureSource() { int imageIndex = ChooseImageIndex(); if (imageIndex < 0) { - return; + return nullptr; } + mBias = UpdateBias(GetCompositor()->GetCompositionTime(), + mImages[imageIndex].mTimeStamp, + uint32_t(imageIndex + 1) < mImages.Length() ? + mImages[imageIndex + 1].mTimeStamp :TimeStamp(), + mBias); + if (uint32_t(imageIndex) + 1 < mImages.Length()) { GetCompositor()->CompositeUntil(mImages[imageIndex + 1].mTimeStamp + TimeDuration::FromMilliseconds(BIAS_TIME_MS)); } @@ -450,13 +456,23 @@ ImageHost::BindTextureSource() img->mTextureHost->SetCompositor(GetCompositor()); SetCurrentTextureHost(img->mTextureHost); - // XXX Add TextureSource binding + // XXX: handle the lock failed in UnbindTextureSource() + if (!Lock()) { + MOZ_RELEASE_ASSERT(false, "ImageHost::BindTextureSource() locks failed"); + return nullptr; + } + if (!mCurrentTextureHost->BindTextureSource(mCurrentTextureSource)) { + MOZ_RELEASE_ASSERT(false, "ImageHost::BindTextureSource() binds textureSource failed"); + return nullptr; + } - mBias = UpdateBias( - GetCompositor()->GetCompositionTime(), mImages[imageIndex].mTimeStamp, - uint32_t(imageIndex + 1) < mImages.Length() ? - mImages[imageIndex + 1].mTimeStamp : TimeStamp(), - mBias); + return mCurrentTextureSource.get(); +} + +void +ImageHost::UnbindTextureSource() +{ + Unlock(); } void diff --git a/gfx/layers/composite/ImageHost.h b/gfx/layers/composite/ImageHost.h index 6e4b321e3ea5..2f6536b5a7c9 100644 --- a/gfx/layers/composite/ImageHost.h +++ b/gfx/layers/composite/ImageHost.h @@ -91,7 +91,8 @@ public: virtual void CleanupResources() override; - virtual void BindTextureSource() override; + virtual TextureSource* BindTextureSource() override; + virtual void UnbindTextureSource() override; int32_t GetFrameID() { diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index c224d8777284..0ecfd83041d4 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -49,6 +49,7 @@ class ISurfaceAllocator; class TextureHostOGL; class TextureReadLock; class TextureSourceOGL; +class TextureSourceWebRenderOGL; class TextureSourceD3D9; class TextureSourceD3D11; class TextureSourceBasic; @@ -116,10 +117,16 @@ public: /** * Cast to a TextureSource for for each backend.. */ - virtual TextureSourceOGL* AsSourceOGL() { + virtual TextureSourceOGL* AsSourceOGL() + { gfxCriticalNote << "Failed to cast " << Name() << " into a TextureSourceOGL"; return nullptr; } + virtual TextureSourceWebRenderOGL* AsSourceWebRenderOGL() + { + gfxCriticalNote << "Failed to cast " << Name() << " into a TextureSourceWebRenderOGL"; + return nullptr; + } virtual TextureSourceD3D9* AsSourceD3D9() { return nullptr; } virtual TextureSourceD3D11* AsSourceD3D11() { return nullptr; } virtual TextureSourceBasic* AsSourceBasic() { return nullptr; } diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index 57557e888b13..953a8e8a294e 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -202,6 +202,7 @@ EXPORTS.mozilla.layers += [ 'RenderTrace.h', 'TextureWrapperImage.h', 'TransactionIdAllocator.h', + 'wr/TextureHostWebRenderOGL.h', 'wr/WebRenderBridgeChild.h', 'wr/WebRenderBridgeParent.h', 'wr/WebRenderCompositorOGL.h', @@ -381,6 +382,7 @@ UNIFIED_SOURCES += [ 'RenderTrace.cpp', 'RotatedBuffer.cpp', 'TextureWrapperImage.cpp', + 'wr/TextureHostWebRenderOGL.cpp', 'wr/WebRenderBridgeChild.cpp', 'wr/WebRenderBridgeParent.cpp', 'wr/WebRenderCanvasLayer.cpp', diff --git a/gfx/layers/wr/TextureHostWebRenderOGL.cpp b/gfx/layers/wr/TextureHostWebRenderOGL.cpp new file mode 100644 index 000000000000..fbca3b6bfd8c --- /dev/null +++ b/gfx/layers/wr/TextureHostWebRenderOGL.cpp @@ -0,0 +1,130 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- +* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "TextureHostWebRenderOGL.h" + +#include "WebRenderCompositorOGL.h" + +namespace mozilla { +namespace layers { + +WebRenderCompositorOGL* AssertWebRenderCompositorOGL(Compositor* aCompositor) +{ + WebRenderCompositorOGL* compositor = + aCompositor ? aCompositor->AsWebRenderCompositorOGL() : nullptr; + MOZ_ASSERT(!!compositor); + + return compositor; +} + +bool +TextureImageTextureSourceWebRenderOGL::Update(gfx::DataSourceSurface* aSurface, + nsIntRegion* aDestRegion, + gfx::IntPoint* aSrcOffset) +{ + GLContext *gl = mCompositor->gl(); + MOZ_ASSERT(gl); + if (!gl || !gl->MakeCurrent()) { + NS_WARNING("trying to update TextureImageTextureSourceWebRenderOGL without a GLContext"); + return false; + } + if (!aSurface) { + gfxCriticalError() << "Invalid surface for WebRenderOGL update"; + return false; + } + MOZ_ASSERT(aSurface); + + IntSize size = aSurface->GetSize(); + if (!mTexImage || + (mTexImage->GetSize() != size && !aSrcOffset) || + mTexImage->GetContentType() != gfx::ContentForFormat(aSurface->GetFormat())) { + if (mFlags & TextureFlags::DISALLOW_BIGIMAGE) { + GLint maxTextureSize; + gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &maxTextureSize); + if (size.width > maxTextureSize || size.height > maxTextureSize) { + NS_WARNING("Texture exceeds maximum texture size, refusing upload"); + return false; + } + // Explicitly use CreateBasicTextureImage instead of CreateTextureImage, + // because CreateTextureImage might still choose to create a tiled + // texture image. + mTexImage = CreateBasicTextureImage(gl, size, + gfx::ContentForFormat(aSurface->GetFormat()), + LOCAL_GL_CLAMP_TO_EDGE, + FlagsToGLFlags(mFlags)); + } else { + // XXX - clarify which size we want to use. IncrementalContentHost will + // require the size of the destination surface to be different from + // the size of aSurface. + // See bug 893300 (tracks the implementation of ContentHost for new textures). + mTexImage = CreateTextureImage(gl, + size, + gfx::ContentForFormat(aSurface->GetFormat()), + LOCAL_GL_CLAMP_TO_EDGE, + FlagsToGLFlags(mFlags), + SurfaceFormatToImageFormat(aSurface->GetFormat())); + } + + if (aDestRegion && + !aSrcOffset && + !aDestRegion->IsEqual(gfx::IntRect(0, 0, size.width, size.height))) { + // UpdateFromDataSource will ignore our specified aDestRegion since the texture + // hasn't been allocated with glTexImage2D yet. Call Resize() to force the + // allocation (full size, but no upload), and then we'll only upload the pixels + // we care about below. + mTexImage->Resize(size); + } + } + + mTexImage->UpdateFromDataSource(aSurface, aDestRegion, aSrcOffset); + + return true; +} + +void +TextureImageTextureSourceWebRenderOGL::SetCompositor(Compositor* aCompositor) +{ + WebRenderCompositorOGL* glCompositor = AssertWebRenderCompositorOGL(aCompositor); + if (!glCompositor) { + DeallocateDeviceData(); + return; + } + if (mCompositor != glCompositor) { + DeallocateDeviceData(); + mCompositor = glCompositor; + } +} + +gfx::IntSize +TextureImageTextureSourceWebRenderOGL::GetSize() const +{ + if (mTexImage) { + if (mIterating) { + return mTexImage->GetTileRect().Size(); + } + return mTexImage->GetSize(); + } + NS_WARNING("Trying to query the size of an empty TextureSource."); + return gfx::IntSize(0, 0); +} + +gfx::SurfaceFormat +TextureImageTextureSourceWebRenderOGL::GetFormat() const +{ + if (mTexImage) { + return mTexImage->GetTextureFormat(); + } + NS_WARNING("Trying to query the format of an empty TextureSource."); + return gfx::SurfaceFormat::UNKNOWN; +} + +gfx::IntRect +TextureImageTextureSourceWebRenderOGL::GetTileRect() +{ + return mTexImage->GetTileRect(); +} + +} // namespace layers +} // namespace mozilla diff --git a/gfx/layers/wr/TextureHostWebRenderOGL.h b/gfx/layers/wr/TextureHostWebRenderOGL.h new file mode 100644 index 000000000000..34673bd5c5fd --- /dev/null +++ b/gfx/layers/wr/TextureHostWebRenderOGL.h @@ -0,0 +1,132 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef MOZILLA_GFX_TEXTUREHOSTWEBRENDEROGL_H +#define MOZILLA_GFX_TEXTUREHOSTWEBRENDEROGL_H + +#include // for size_t +#include // for uint64_t +#include "GLContextTypes.h" // for GLContext +#include "GLTextureImage.h" // for TextureImage +#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc +#include "mozilla/Attributes.h" // for override +#include "mozilla/RefPtr.h" // for RefPtr +#include "mozilla/gfx/Point.h" // for IntSize, IntPoint +#include "mozilla/gfx/Types.h" // for SurfaceFormat, etc +#include "mozilla/layers/CompositorTypes.h" // for TextureFlags +#include "mozilla/layers/TextureHost.h" // for TextureHost, etc +#include "nsRegionFwd.h" // for nsIntRegion + +namespace mozilla { +namespace layers { + +class Compositor; +class TextureImageTextureSourceWebRenderOGL; + +class TextureSourceWebRenderOGL +{ +public: + TextureSourceWebRenderOGL() {} + virtual ~TextureSourceWebRenderOGL() {} + + virtual gl::TextureImage* GetTextureImage() = 0; + + virtual TextureImageTextureSourceWebRenderOGL* AsTextureImageTextureSource() { return nullptr; } +}; + +/** + * A TextureSourceWebRenderOGL backed by a TextureImage. + */ +class TextureImageTextureSourceWebRenderOGL final : public DataTextureSource + , public TextureSourceWebRenderOGL + , public BigImageIterator +{ +public: + explicit TextureImageTextureSourceWebRenderOGL(WebRenderCompositorOGL *aCompositor, + TextureFlags aFlags = TextureFlags::DEFAULT) + : mCompositor(aCompositor) + , mFlags(aFlags) + , mIterating(false) + { + } + + virtual const char* Name() const override + { + return "TextureImageTextureSourceWebRenderOGL"; + } + + virtual TextureImageTextureSourceWebRenderOGL* AsTextureImageTextureSource() override + { + return this; + } + + virtual gl::TextureImage* GetTextureImage() override + { + return mTexImage.get(); + } + + // DataTextureSource + virtual bool Update(gfx::DataSourceSurface* aSurface, + nsIntRegion* aDestRegion = nullptr, + gfx::IntPoint* aSrcOffset = nullptr) override; + // + + // TextureSource + virtual void DeallocateDeviceData() override + { + mTexImage = nullptr; + SetUpdateSerial(0); + } + + virtual TextureSourceWebRenderOGL* AsSourceWebRenderOGL() override + { + return this; + } + + virtual gfx::IntSize GetSize() const override; + + virtual gfx::SurfaceFormat GetFormat() const override; + + virtual void SetCompositor(Compositor* aCompositor) override; + // + + // BigImageIterator + virtual BigImageIterator* AsBigImageIterator() override { return this; } + + virtual void BeginBigImageIteration() override + { + mTexImage->BeginBigImageIteration(); + mIterating = true; + } + + virtual void EndBigImageIteration() override + { + mIterating = false; + } + + virtual gfx::IntRect GetTileRect() override; + + virtual size_t GetTileCount() override + { + return mTexImage->GetTileCount(); + } + + virtual bool NextTile() override + { + return mTexImage->NextTile(); + } + // + +private: + RefPtr mTexImage; + RefPtr mCompositor; + TextureFlags mFlags; + bool mIterating; +}; + +} // namespace layers +} // namespace mozilla + +#endif /* MOZILLA_GFX_TEXTUREOGL_H */