diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /dom/canvas/SourceSurfaceWebgl.cpp | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/canvas/SourceSurfaceWebgl.cpp')
-rw-r--r-- | dom/canvas/SourceSurfaceWebgl.cpp | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/dom/canvas/SourceSurfaceWebgl.cpp b/dom/canvas/SourceSurfaceWebgl.cpp new file mode 100644 index 0000000000..b7793e3173 --- /dev/null +++ b/dom/canvas/SourceSurfaceWebgl.cpp @@ -0,0 +1,172 @@ +/* -*- 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 "DrawTargetWebglInternal.h" +#include "SourceSurfaceWebgl.h" + +namespace mozilla::gfx { + +SourceSurfaceWebgl::SourceSurfaceWebgl(DrawTargetWebgl* aDT) + : mFormat(aDT->GetFormat()), + mSize(aDT->GetSize()), + mDT(aDT), + mSharedContext(aDT->mSharedContext) {} + +SourceSurfaceWebgl::SourceSurfaceWebgl( + const RefPtr<TextureHandle>& aHandle, + const RefPtr<DrawTargetWebgl::SharedContext>& aSharedContext) + : mFormat(aHandle->GetFormat()), + mSize(aHandle->GetSize()), + mSharedContext(aSharedContext), + mHandle(aHandle) { + mHandle->SetSurface(this); +} + +SourceSurfaceWebgl::~SourceSurfaceWebgl() { + if (mHandle) { + // Signal that the texture handle is not being used now. + mHandle->SetSurface(nullptr); + } +} + +// Read back the contents of the target or texture handle for data use. +inline bool SourceSurfaceWebgl::EnsureData() { + if (mData) { + return true; + } + if (!mDT) { + // Assume that the target changed, so there should be a texture handle + // holding a copy. Try to read data from the copy since we can't read + // from the target. + if (!mHandle || !mSharedContext) { + return false; + } + mData = mSharedContext->ReadSnapshot(mHandle); + } else { + mData = mDT->ReadSnapshot(); + } + return !!mData; +} + +uint8_t* SourceSurfaceWebgl::GetData() { + if (!EnsureData()) { + return nullptr; + } + return mData->GetData(); +} + +int32_t SourceSurfaceWebgl::Stride() { + if (!EnsureData()) { + return 0; + } + return mData->Stride(); +} + +bool SourceSurfaceWebgl::Map(MapType aType, MappedSurface* aMappedSurface) { + if (!EnsureData()) { + return false; + } + return mData->Map(aType, aMappedSurface); +} + +void SourceSurfaceWebgl::Unmap() { + if (mData) { + mData->Unmap(); + } +} + +// Handler for when the owner DrawTargetWebgl is about to modify its internal +// framebuffer, and so this snapshot must be copied into a new texture, if +// possible, or read back into data, if necessary, to preserve this particular +// version of the framebuffer. +void SourceSurfaceWebgl::DrawTargetWillChange(bool aNeedHandle) { + MOZ_ASSERT(mDT); + // Only try to copy into a new texture handle if we don't already have data. + // However, we still might need to immediately draw this snapshot to a WebGL + // target, which would require a subsequent upload, so also copy into a new + // handle even if we already have data in that case since it is faster than + // uploading. + if ((!mData || aNeedHandle) && !mHandle) { + // Prefer copying the framebuffer to a texture if possible. + mHandle = mDT->CopySnapshot(); + if (mHandle) { + // Link this surface to the handle. + mHandle->SetSurface(this); + } else { + // If that fails, then try to just read the data to a surface. + EnsureData(); + } + } + mDT = nullptr; +} + +// Handler for when the owner DrawTargetWebgl is itself being destroyed and +// needs to transfer ownership of its internal backing texture to the snapshot. +void SourceSurfaceWebgl::GiveTexture(RefPtr<TextureHandle> aHandle) { + // If we get here, then the target still points to this surface as its + // snapshot and needs to hand off its backing texture before it is destroyed. + MOZ_ASSERT(mDT); + MOZ_ASSERT(!mHandle); + mHandle = aHandle.forget(); + mHandle->SetSurface(this); + mDT = nullptr; +} + +// Handler for when the owner DrawTargetWebgl is destroying the cached texture +// handle that has been allocated for this snapshot. +void SourceSurfaceWebgl::OnUnlinkTexture( + DrawTargetWebgl::SharedContext* aContext) { + // If we get here, then we must have copied a snapshot, which only happens + // if the target changed. + MOZ_ASSERT(!mDT); + // If the snapshot was mapped before the target changed, we may have read + // data instead of holding a copied texture handle. If subsequently we then + // try to draw with this snapshot, we might have allocated an external texture + // handle in the texture cache that still links to this snapshot and can cause + // us to end up here inside OnUnlinkTexture. + MOZ_ASSERT(mHandle || mData); + if (!mData) { + mData = aContext->ReadSnapshot(mHandle); + } + mHandle = nullptr; +} + +already_AddRefed<SourceSurface> SourceSurfaceWebgl::ExtractSubrect( + const IntRect& aRect) { + // Ensure we have a texture source available to extract from. + if (!(mDT || (mHandle && mSharedContext)) || aRect.IsEmpty() || + !GetRect().Contains(aRect)) { + return nullptr; + } + RefPtr<TextureHandle> subHandle; + RefPtr<DrawTargetWebgl::SharedContext> sharedContext; + if (mDT) { + // If this is still a snapshot linked to a target, then copy from the + // target. + subHandle = mDT->CopySnapshot(aRect); + if (!subHandle) { + return nullptr; + } + sharedContext = mDT->mSharedContext; + } else { + // Otherwise, we have a handle, but we need to verify it is still linked to + // a valid context. + sharedContext = mSharedContext; + if (!sharedContext) { + return nullptr; + } + // Try to copy directly from the handle using the context. + subHandle = sharedContext->CopySnapshot(aRect, mHandle); + if (!subHandle) { + return nullptr; + } + } + RefPtr<SourceSurface> surface = + new SourceSurfaceWebgl(subHandle, sharedContext); + return surface.forget(); +} + +} // namespace mozilla::gfx |