diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /dom/canvas/SourceSurfaceWebgl.cpp | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/canvas/SourceSurfaceWebgl.cpp')
-rw-r--r-- | dom/canvas/SourceSurfaceWebgl.cpp | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/dom/canvas/SourceSurfaceWebgl.cpp b/dom/canvas/SourceSurfaceWebgl.cpp new file mode 100644 index 0000000000..21a5045eaa --- /dev/null +++ b/dom/canvas/SourceSurfaceWebgl.cpp @@ -0,0 +1,173 @@ +/* -*- 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<SharedContextWebgl>& aSharedContext) + : mSharedContext(aSharedContext) {} + +SourceSurfaceWebgl::~SourceSurfaceWebgl() { + if (mHandle) { + // Signal that the texture handle is not being used now. + mHandle->ClearSurface(); + } +} + +// 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; +} + +void SourceSurfaceWebgl::SetHandle(TextureHandle* aHandle) { + MOZ_ASSERT(!mHandle); + mFormat = aHandle->GetFormat(); + mSize = aHandle->GetSize(); + mHandle = aHandle; + mHandle->SetSurface(this); +} + +// Handler for when the owner DrawTargetWebgl is destroying the cached texture +// handle that has been allocated for this snapshot. +void SourceSurfaceWebgl::OnUnlinkTexture(SharedContextWebgl* 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<SharedContextWebgl> 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<SourceSurfaceWebgl> surface = new SourceSurfaceWebgl(sharedContext); + surface->SetHandle(subHandle); + return surface.forget(); +} + +} // namespace mozilla::gfx |