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/. */
7 #include "DrawTargetWebglInternal.h"
8 #include "SourceSurfaceWebgl.h"
10 namespace mozilla::gfx
{
12 SourceSurfaceWebgl::SourceSurfaceWebgl(DrawTargetWebgl
* aDT
)
13 : mFormat(aDT
->GetFormat()),
14 mSize(aDT
->GetSize()),
16 mSharedContext(aDT
->mSharedContext
) {}
18 SourceSurfaceWebgl::SourceSurfaceWebgl(
19 const RefPtr
<SharedContextWebgl
>& aSharedContext
)
20 : mSharedContext(aSharedContext
) {}
22 SourceSurfaceWebgl::~SourceSurfaceWebgl() {
24 // Signal that the texture handle is not being used now.
25 mHandle
->ClearSurface();
29 // Read back the contents of the target or texture handle for data use.
30 inline bool SourceSurfaceWebgl::EnsureData() {
35 // Assume that the target changed, so there should be a texture handle
36 // holding a copy. Try to read data from the copy since we can't read
38 if (!mHandle
|| !mSharedContext
) {
41 mData
= mSharedContext
->ReadSnapshot(mHandle
);
43 mData
= mDT
->ReadSnapshot();
48 uint8_t* SourceSurfaceWebgl::GetData() {
52 return mData
->GetData();
55 int32_t SourceSurfaceWebgl::Stride() {
59 return mData
->Stride();
62 bool SourceSurfaceWebgl::Map(MapType aType
, MappedSurface
* aMappedSurface
) {
66 return mData
->Map(aType
, aMappedSurface
);
69 void SourceSurfaceWebgl::Unmap() {
75 // Handler for when the owner DrawTargetWebgl is about to modify its internal
76 // framebuffer, and so this snapshot must be copied into a new texture, if
77 // possible, or read back into data, if necessary, to preserve this particular
78 // version of the framebuffer.
79 void SourceSurfaceWebgl::DrawTargetWillChange(bool aNeedHandle
) {
81 // Only try to copy into a new texture handle if we don't already have data.
82 // However, we still might need to immediately draw this snapshot to a WebGL
83 // target, which would require a subsequent upload, so also copy into a new
84 // handle even if we already have data in that case since it is faster than
86 if ((!mData
|| aNeedHandle
) && !mHandle
) {
87 // Prefer copying the framebuffer to a texture if possible.
88 mHandle
= mDT
->CopySnapshot();
90 // Link this surface to the handle.
91 mHandle
->SetSurface(this);
93 // If that fails, then try to just read the data to a surface.
100 // Handler for when the owner DrawTargetWebgl is itself being destroyed and
101 // needs to transfer ownership of its internal backing texture to the snapshot.
102 void SourceSurfaceWebgl::GiveTexture(RefPtr
<TextureHandle
> aHandle
) {
103 // If we get here, then the target still points to this surface as its
104 // snapshot and needs to hand off its backing texture before it is destroyed.
106 MOZ_ASSERT(!mHandle
);
107 mHandle
= aHandle
.forget();
108 mHandle
->SetSurface(this);
112 void SourceSurfaceWebgl::SetHandle(TextureHandle
* aHandle
) {
113 MOZ_ASSERT(!mHandle
);
114 mFormat
= aHandle
->GetFormat();
115 mSize
= aHandle
->GetSize();
117 mHandle
->SetSurface(this);
120 // Handler for when the owner DrawTargetWebgl is destroying the cached texture
121 // handle that has been allocated for this snapshot.
122 void SourceSurfaceWebgl::OnUnlinkTexture(SharedContextWebgl
* aContext
) {
123 // If we get here, then we must have copied a snapshot, which only happens
124 // if the target changed.
126 // If the snapshot was mapped before the target changed, we may have read
127 // data instead of holding a copied texture handle. If subsequently we then
128 // try to draw with this snapshot, we might have allocated an external texture
129 // handle in the texture cache that still links to this snapshot and can cause
130 // us to end up here inside OnUnlinkTexture.
131 MOZ_ASSERT(mHandle
|| mData
);
133 mData
= aContext
->ReadSnapshot(mHandle
);
138 already_AddRefed
<SourceSurface
> SourceSurfaceWebgl::ExtractSubrect(
139 const IntRect
& aRect
) {
140 // Ensure we have a texture source available to extract from.
141 if (!(mDT
|| (mHandle
&& mSharedContext
)) || aRect
.IsEmpty() ||
142 !GetRect().Contains(aRect
)) {
145 RefPtr
<TextureHandle
> subHandle
;
146 RefPtr
<SharedContextWebgl
> sharedContext
;
148 // If this is still a snapshot linked to a target, then copy from the
150 subHandle
= mDT
->CopySnapshot(aRect
);
154 sharedContext
= mDT
->mSharedContext
;
156 // Otherwise, we have a handle, but we need to verify it is still linked to
158 sharedContext
= mSharedContext
;
159 if (!sharedContext
) {
162 // Try to copy directly from the handle using the context.
163 subHandle
= sharedContext
->CopySnapshot(aRect
, mHandle
);
168 RefPtr
<SourceSurfaceWebgl
> surface
= new SourceSurfaceWebgl(sharedContext
);
169 surface
->SetHandle(subHandle
);
170 return surface
.forget();
173 } // namespace mozilla::gfx