Bug 1685225 - Use state bits to determine the color for non-native theme meter chunks...
[gecko.git] / gfx / 2d / SourceSurfaceCapture.cpp
blob227c0ddf34b670762a5115800e82961df61112b4
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 "SourceSurfaceCapture.h"
8 #include "DrawCommand.h"
9 #include "DrawTargetCapture.h"
10 #include "MainThreadUtils.h"
11 #include "mozilla/gfx/Logging.h"
13 namespace mozilla {
14 namespace gfx {
16 SourceSurfaceCapture::SourceSurfaceCapture(DrawTargetCaptureImpl* aOwner)
17 : mOwner(aOwner),
18 mHasCommandList(false),
19 mShouldResolveToLuminance{false},
20 mLuminanceType{LuminanceType::LUMINANCE},
21 mOpacity{1.0f},
22 mLock("SourceSurfaceCapture.mLock") {
23 mSize = mOwner->GetSize();
24 mFormat = mOwner->GetFormat();
25 mRefDT = mOwner->mRefDT;
26 mStride = mOwner->mStride;
27 mSurfaceAllocationSize = mOwner->mSurfaceAllocationSize;
30 SourceSurfaceCapture::SourceSurfaceCapture(
31 DrawTargetCaptureImpl* aOwner,
32 LuminanceType aLuminanceType /* = LuminanceType::LINEARRGB */,
33 Float aOpacity /* = 1.0f */)
34 : mOwner{aOwner},
35 mHasCommandList{false},
36 mShouldResolveToLuminance{true},
37 mLuminanceType{aLuminanceType},
38 mOpacity{aOpacity},
39 mLock{"SourceSurfaceCapture.mLock"} {
40 mSize = mOwner->GetSize();
41 mFormat = mOwner->GetFormat();
42 mRefDT = mOwner->mRefDT;
43 mStride = mOwner->mStride;
44 mSurfaceAllocationSize = mOwner->mSurfaceAllocationSize;
46 // In this case our DrawTarget will not track us, so copy its drawing
47 // commands.
48 DrawTargetWillChange();
51 SourceSurfaceCapture::SourceSurfaceCapture(DrawTargetCaptureImpl* aOwner,
52 SourceSurface* aSurfToOptimize)
53 : mOwner{aOwner},
54 mHasCommandList{false},
55 mShouldResolveToLuminance{false},
56 mLuminanceType{LuminanceType::LUMINANCE},
57 mOpacity{1.0f},
58 mLock{"SourceSurfaceCapture.mLock"},
59 mSurfToOptimize(aSurfToOptimize) {
60 mSize = aSurfToOptimize->GetSize();
61 mFormat = aSurfToOptimize->GetFormat();
62 mRefDT = mOwner->mRefDT;
65 SourceSurfaceCapture::~SourceSurfaceCapture() = default;
67 void SourceSurfaceCapture::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
68 SizeOfInfo& aInfo) const {
69 MutexAutoLock lock(mLock);
70 aInfo.AddType(SurfaceType::CAPTURE);
71 if (mSurfToOptimize) {
72 mSurfToOptimize->SizeOfExcludingThis(aMallocSizeOf, aInfo);
73 return;
75 if (mResolved) {
76 mResolved->SizeOfExcludingThis(aMallocSizeOf, aInfo);
77 return;
79 if (mHasCommandList) {
80 aInfo.mHeapBytes += mCommands.BufferCapacity();
81 return;
85 bool SourceSurfaceCapture::IsValid() const {
86 // We must either be able to source a command list, or we must have a cached
87 // and rasterized surface.
88 MutexAutoLock lock(mLock);
90 if (mSurfToOptimize) {
91 // We were given a surface, but we haven't tried to optimize it yet
92 // with the reference draw target.
93 return mSurfToOptimize->IsValid();
95 if (mResolved) {
96 // We were given a surface, and we already optimized it with the
97 // reference draw target.
98 return mResolved->IsValid();
101 // We have no underlying surface, so it must be a set of drawing commands.
102 return mOwner || mHasCommandList;
105 RefPtr<SourceSurface> SourceSurfaceCapture::Resolve(BackendType aBackendType) {
106 MutexAutoLock lock(mLock);
108 if (mSurfToOptimize) {
109 mResolved = mRefDT->OptimizeSourceSurface(mSurfToOptimize);
110 mSurfToOptimize = nullptr;
113 if (mResolved || (!mOwner && !mHasCommandList)) {
114 // We are already resolved, or there is no way we can rasterize
115 // anything, we don't have a source DrawTarget and we don't have
116 // a command list. Return whatever our cached surface is.
117 return mResolved;
120 BackendType backendType = aBackendType;
121 if (backendType == BackendType::NONE) {
122 backendType = mRefDT->GetBackendType();
125 // Note: SurfaceType is not 1:1 with BackendType, so we can't easily decide
126 // that they match. Instead we just cache the first thing to be requested.
127 // We ensured no mResolved existed before.
128 mResolved = ResolveImpl(backendType);
130 return mResolved;
133 RefPtr<SourceSurface> SourceSurfaceCapture::ResolveImpl(
134 BackendType aBackendType) {
135 RefPtr<DrawTarget> dt;
136 uint8_t* data = nullptr;
137 if (!mSurfaceAllocationSize) {
138 if (aBackendType == mRefDT->GetBackendType()) {
139 dt = mRefDT->CreateSimilarDrawTarget(mSize, mFormat);
140 } else {
141 dt = Factory::CreateDrawTarget(aBackendType, mSize, mFormat);
143 } else {
144 data = static_cast<uint8_t*>(calloc(1, mSurfaceAllocationSize));
145 if (!data) {
146 return nullptr;
148 BackendType type = Factory::DoesBackendSupportDataDrawtarget(aBackendType)
149 ? aBackendType
150 : BackendType::SKIA;
151 dt = Factory::CreateDrawTargetForData(type, data, mSize, mStride, mFormat);
152 if (!dt || !dt->IsValid()) {
153 free(data);
154 return nullptr;
158 if (!dt || !dt->IsValid()) {
159 // Make sure we haven't allocated and aren't leaking something, the code
160 // right anove here should have guaranteed that.
161 MOZ_ASSERT(!data);
162 return nullptr;
165 // If we're still attached to a DrawTarget, use its command list rather than
166 // our own (which will be empty).
167 CaptureCommandList& commands =
168 mHasCommandList ? mCommands : mOwner->mCommands;
169 for (CaptureCommandList::iterator iter(commands); !iter.Done(); iter.Next()) {
170 DrawingCommand* cmd = iter.Get();
171 cmd->ExecuteOnDT(dt, nullptr);
174 RefPtr<SourceSurface> surf;
175 if (!mShouldResolveToLuminance) {
176 surf = dt->Snapshot();
177 } else {
178 surf = dt->IntoLuminanceSource(mLuminanceType, mOpacity);
181 if (data) {
182 surf->AddUserData(reinterpret_cast<UserDataKey*>(dt.get()), data, free);
185 return surf;
188 already_AddRefed<DataSourceSurface> SourceSurfaceCapture::GetDataSurface() {
189 RefPtr<SourceSurface> surface = Resolve();
190 if (!surface) {
191 return nullptr;
193 return surface->GetDataSurface();
196 void SourceSurfaceCapture::DrawTargetWillDestroy() {
197 MutexAutoLock lock(mLock);
199 // The source DrawTarget is going away, so we can just steal its commands.
200 mCommands = std::move(mOwner->mCommands);
201 mHasCommandList = true;
202 mOwner = nullptr;
205 void SourceSurfaceCapture::DrawTargetWillChange() {
206 MutexAutoLock lock(mLock);
208 for (CaptureCommandList::iterator iter(mOwner->mCommands); !iter.Done();
209 iter.Next()) {
210 DrawingCommand* cmd = iter.Get();
211 cmd->CloneInto(&mCommands);
214 mHasCommandList = true;
215 mOwner = nullptr;
218 } // namespace gfx
219 } // namespace mozilla