summaryrefslogtreecommitdiffstats
path: root/gfx/layers/ipc/SharedRGBImage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/ipc/SharedRGBImage.cpp')
-rw-r--r--gfx/layers/ipc/SharedRGBImage.cpp156
1 files changed, 156 insertions, 0 deletions
diff --git a/gfx/layers/ipc/SharedRGBImage.cpp b/gfx/layers/ipc/SharedRGBImage.cpp
new file mode 100644
index 0000000000..392cb09610
--- /dev/null
+++ b/gfx/layers/ipc/SharedRGBImage.cpp
@@ -0,0 +1,156 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 "SharedRGBImage.h"
+#include "ImageTypes.h" // for ImageFormat::SHARED_RGB, etc
+#include "mozilla/ipc/Shmem.h" // for Shmem
+#include "gfx2DGlue.h" // for ImageFormatToSurfaceFormat, etc
+#include "gfxPlatform.h" // for gfxPlatform, gfxImageFormat
+#include "mozilla/gfx/Point.h" // for IntSIze
+#include "mozilla/layers/BufferTexture.h"
+#include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator, etc
+#include "mozilla/layers/ImageClient.h" // for ImageClient
+#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
+#include "mozilla/layers/TextureClient.h" // for BufferTextureClient, etc
+#include "mozilla/layers/TextureClientRecycleAllocator.h" // for ITextureClientAllocationHelper
+#include "mozilla/layers/ImageBridgeChild.h" // for ImageBridgeChild
+#include "mozilla/mozalloc.h" // for operator delete, etc
+#include "nsDebug.h" // for NS_WARNING, NS_ASSERTION
+#include "nsISupportsImpl.h" // for Image::AddRef, etc
+#include "nsProxyRelease.h"
+#include "nsRect.h" // for mozilla::gfx::IntRect
+
+// Just big enough for a 1080p RGBA32 frame
+#define MAX_FRAME_SIZE (16 * 1024 * 1024)
+
+namespace mozilla {
+namespace layers {
+
+class TextureClientForRawBufferAccessAllocationHelper
+ : public ITextureClientAllocationHelper {
+ public:
+ TextureClientForRawBufferAccessAllocationHelper(gfx::SurfaceFormat aFormat,
+ gfx::IntSize aSize,
+ TextureFlags aTextureFlags)
+ : ITextureClientAllocationHelper(aFormat, aSize, BackendSelector::Content,
+ aTextureFlags, ALLOC_DEFAULT) {}
+
+ bool IsCompatible(TextureClient* aTextureClient) override {
+ bool ret = aTextureClient->GetFormat() == mFormat &&
+ aTextureClient->GetSize() == mSize;
+ return ret;
+ }
+
+ already_AddRefed<TextureClient> Allocate(
+ KnowsCompositor* aAllocator) override {
+ return TextureClient::CreateForRawBufferAccess(
+ aAllocator, mFormat, mSize, gfx::BackendType::NONE, mTextureFlags);
+ }
+};
+
+SharedRGBImage::SharedRGBImage(ImageClient* aCompositable)
+ : Image(nullptr, ImageFormat::SHARED_RGB), mCompositable(aCompositable) {
+ MOZ_COUNT_CTOR(SharedRGBImage);
+}
+
+SharedRGBImage::SharedRGBImage(TextureClientRecycleAllocator* aRecycleAllocator)
+ : Image(nullptr, ImageFormat::SHARED_RGB),
+ mRecycleAllocator(aRecycleAllocator) {
+ MOZ_COUNT_CTOR(SharedRGBImage);
+}
+
+SharedRGBImage::~SharedRGBImage() {
+ MOZ_COUNT_DTOR(SharedRGBImage);
+ NS_ReleaseOnMainThread("SharedRGBImage::mSourceSurface",
+ mSourceSurface.forget());
+}
+
+TextureClientRecycleAllocator* SharedRGBImage::RecycleAllocator() {
+ static const uint32_t MAX_POOLED_VIDEO_COUNT = 5;
+
+ if (!mRecycleAllocator && mCompositable) {
+ if (!mCompositable->HasTextureClientRecycler()) {
+ // Initialize TextureClientRecycler
+ mCompositable->GetTextureClientRecycler()->SetMaxPoolSize(
+ MAX_POOLED_VIDEO_COUNT);
+ }
+ mRecycleAllocator = mCompositable->GetTextureClientRecycler();
+ }
+ return mRecycleAllocator;
+}
+
+bool SharedRGBImage::Allocate(gfx::IntSize aSize, gfx::SurfaceFormat aFormat) {
+ mSize = aSize;
+
+ TextureFlags flags =
+ mCompositable ? mCompositable->GetTextureFlags() : TextureFlags::DEFAULT;
+ {
+ TextureClientForRawBufferAccessAllocationHelper helper(aFormat, aSize,
+ flags);
+ mTextureClient = RecycleAllocator()->CreateOrRecycle(helper);
+ }
+
+ return !!mTextureClient;
+}
+
+gfx::IntSize SharedRGBImage::GetSize() const { return mSize; }
+
+TextureClient* SharedRGBImage::GetTextureClient(
+ KnowsCompositor* aKnowsCompositor) {
+ return mTextureClient.get();
+}
+
+static void ReleaseTextureClient(void* aData) {
+ RELEASE_MANUALLY(static_cast<TextureClient*>(aData));
+}
+
+static gfx::UserDataKey sTextureClientKey;
+
+already_AddRefed<gfx::SourceSurface> SharedRGBImage::GetAsSourceSurface() {
+ NS_ASSERTION(NS_IsMainThread(), "Must be main thread");
+
+ if (mSourceSurface) {
+ RefPtr<gfx::SourceSurface> surface(mSourceSurface);
+ return surface.forget();
+ }
+
+ RefPtr<gfx::SourceSurface> surface;
+ {
+ // We are 'borrowing' the DrawTarget and retaining a permanent reference to
+ // the underlying data (via the surface). It is in this instance since we
+ // know that the TextureClient is always wrapping a BufferTextureData and
+ // therefore it won't go away underneath us.
+ BufferTextureData* decoded_buffer =
+ mTextureClient->GetInternalData()->AsBufferTextureData();
+ RefPtr<gfx::DrawTarget> drawTarget = decoded_buffer->BorrowDrawTarget();
+
+ if (!drawTarget) {
+ return nullptr;
+ }
+
+ surface = drawTarget->Snapshot();
+ if (!surface) {
+ return nullptr;
+ }
+
+ // The surface may outlive the owning TextureClient. So, we need to ensure
+ // that the surface keeps the TextureClient alive via a reference held in
+ // user data. The TextureClient's DrawTarget only has a weak reference to
+ // the surface, so we won't create any cycles by just referencing the
+ // TextureClient.
+ if (!surface->GetUserData(&sTextureClientKey)) {
+ surface->AddUserData(&sTextureClientKey, mTextureClient,
+ ReleaseTextureClient);
+ ADDREF_MANUALLY(mTextureClient);
+ }
+ }
+
+ mSourceSurface = surface;
+ return surface.forget();
+}
+
+} // namespace layers
+} // namespace mozilla