Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "WebRenderImageLayer.h"
7 :
8 : #include "gfxPrefs.h"
9 : #include "LayersLogging.h"
10 : #include "mozilla/gfx/gfxVars.h"
11 : #include "mozilla/layers/CompositorBridgeChild.h"
12 : #include "mozilla/layers/ImageClient.h"
13 : #include "mozilla/layers/ScrollingLayersHelper.h"
14 : #include "mozilla/layers/StackingContextHelper.h"
15 : #include "mozilla/layers/TextureClientRecycleAllocator.h"
16 : #include "mozilla/layers/TextureWrapperImage.h"
17 : #include "mozilla/layers/WebRenderBridgeChild.h"
18 : #include "mozilla/webrender/WebRenderTypes.h"
19 :
20 : namespace mozilla {
21 : namespace layers {
22 :
23 : using namespace gfx;
24 :
25 0 : WebRenderImageLayer::WebRenderImageLayer(WebRenderLayerManager* aLayerManager)
26 : : ImageLayer(aLayerManager, static_cast<WebRenderLayer*>(this))
27 0 : , mImageClientContainerType(CompositableType::UNKNOWN)
28 : {
29 0 : MOZ_COUNT_CTOR(WebRenderImageLayer);
30 0 : }
31 :
32 0 : WebRenderImageLayer::~WebRenderImageLayer()
33 : {
34 0 : MOZ_COUNT_DTOR(WebRenderImageLayer);
35 :
36 0 : if (mKey.isSome()) {
37 0 : WrManager()->AddImageKeyForDiscard(mKey.value());
38 : }
39 :
40 0 : if (mExternalImageId.isSome()) {
41 0 : WrBridge()->DeallocExternalImageId(mExternalImageId.ref());
42 : }
43 0 : if (mPipelineId.isSome()) {
44 0 : WrBridge()->RemovePipelineIdForAsyncCompositable(mPipelineId.ref());
45 : }
46 0 : }
47 :
48 : CompositableType
49 0 : WebRenderImageLayer::GetImageClientType()
50 : {
51 0 : if (mImageClientContainerType != CompositableType::UNKNOWN) {
52 0 : return mImageClientContainerType;
53 : }
54 :
55 0 : if (mContainer->IsAsync()) {
56 0 : mImageClientContainerType = CompositableType::IMAGE_BRIDGE;
57 0 : return mImageClientContainerType;
58 : }
59 :
60 0 : AutoLockImage autoLock(mContainer);
61 :
62 0 : mImageClientContainerType = autoLock.HasImage()
63 0 : ? CompositableType::IMAGE : CompositableType::UNKNOWN;
64 0 : return mImageClientContainerType;
65 : }
66 :
67 : already_AddRefed<gfx::SourceSurface>
68 0 : WebRenderImageLayer::GetAsSourceSurface()
69 : {
70 0 : if (!mContainer) {
71 0 : return nullptr;
72 : }
73 0 : AutoLockImage autoLock(mContainer);
74 0 : Image *image = autoLock.GetImage();
75 0 : if (!image) {
76 0 : return nullptr;
77 : }
78 0 : RefPtr<gfx::SourceSurface> surface = image->GetAsSourceSurface();
79 0 : if (!surface || !surface->IsValid()) {
80 0 : return nullptr;
81 : }
82 0 : return surface.forget();
83 : }
84 :
85 : void
86 0 : WebRenderImageLayer::ClearCachedResources()
87 : {
88 0 : if (mImageClient) {
89 0 : mImageClient->ClearCachedResources();
90 : }
91 0 : }
92 :
93 : bool
94 0 : WebRenderImageLayer::SupportsAsyncUpdate()
95 : {
96 0 : if (GetImageClientType() == CompositableType::IMAGE_BRIDGE &&
97 0 : mPipelineId.isSome()) {
98 0 : return true;
99 : }
100 0 : return false;
101 : }
102 :
103 : void
104 0 : WebRenderImageLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
105 : const StackingContextHelper& aSc)
106 : {
107 0 : if (!mContainer) {
108 0 : return;
109 : }
110 :
111 0 : CompositableType type = GetImageClientType();
112 0 : if (type == CompositableType::UNKNOWN) {
113 0 : return;
114 : }
115 :
116 0 : MOZ_ASSERT(GetImageClientType() != CompositableType::UNKNOWN);
117 :
118 0 : if (GetImageClientType() == CompositableType::IMAGE && !mImageClient) {
119 0 : mImageClient = ImageClient::CreateImageClient(CompositableType::IMAGE,
120 0 : WrBridge(),
121 0 : TextureFlags::DEFAULT);
122 0 : if (!mImageClient) {
123 0 : return;
124 : }
125 0 : mImageClient->Connect();
126 : }
127 :
128 0 : if (GetImageClientType() == CompositableType::IMAGE_BRIDGE && mPipelineId.isNothing()) {
129 0 : MOZ_ASSERT(!mImageClient);
130 : // Alloc async image pipeline id.
131 0 : mPipelineId = Some(WrBridge()->GetCompositorBridgeChild()->GetNextPipelineId());
132 0 : WrBridge()->AddPipelineIdForAsyncCompositable(mPipelineId.ref(),
133 0 : mContainer->GetAsyncContainerHandle());
134 0 : } else if (GetImageClientType() == CompositableType::IMAGE && mExternalImageId.isNothing()) {
135 0 : MOZ_ASSERT(mImageClient);
136 0 : mExternalImageId = Some(WrBridge()->AllocExternalImageIdForCompositable(mImageClient));
137 0 : MOZ_ASSERT(mExternalImageId.isSome());
138 : }
139 :
140 0 : if (GetImageClientType() == CompositableType::IMAGE_BRIDGE) {
141 0 : MOZ_ASSERT(!mImageClient);
142 0 : MOZ_ASSERT(mExternalImageId.isNothing());
143 :
144 : // Push IFrame for async image pipeline.
145 : // XXX Remove this once partial display list update is supported.
146 :
147 0 : ScrollingLayersHelper scroller(this, aBuilder, aSc);
148 :
149 0 : ParentLayerRect bounds = GetLocalTransformTyped().TransformBounds(Bounds());
150 :
151 : // We don't push a stacking context for this async image pipeline here.
152 : // Instead, we do it inside the iframe that hosts the image. As a result,
153 : // a bunch of the calculations normally done as part of that stacking
154 : // context need to be done manually and pushed over to the parent side,
155 : // where it will be done when we build the display list for the iframe.
156 : // That happens in WebRenderCompositableHolder.
157 :
158 : LayerRect rect = ViewAs<LayerPixel>(bounds,
159 0 : PixelCastJustification::MovingDownToChildren);
160 0 : DumpLayerInfo("Image Layer async", rect);
161 :
162 0 : WrRect r = aSc.ToRelativeWrRect(rect);
163 0 : aBuilder.PushIFrame(r, mPipelineId.ref());
164 :
165 0 : gfx::Matrix4x4 scTransform = GetTransform();
166 : // Translate is applied as part of PushIFrame()
167 0 : scTransform.PostTranslate(-rect.x, -rect.y, 0);
168 : // Adjust transform as to apply origin
169 0 : LayerPoint scOrigin = Bounds().TopLeft();
170 0 : scTransform.PreTranslate(-scOrigin.x, -scOrigin.y, 0);
171 :
172 0 : MaybeIntSize scaleToSize;
173 0 : if (mScaleMode != ScaleMode::SCALE_NONE) {
174 0 : NS_ASSERTION(mScaleMode == ScaleMode::STRETCH,
175 : "No other scalemodes than stretch and none supported yet.");
176 0 : scaleToSize = Some(mScaleToSize);
177 : }
178 0 : LayerRect scBounds = BoundsForStackingContext();
179 0 : wr::ImageRendering filter = wr::ToImageRendering(mSamplingFilter);
180 0 : wr::MixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode());
181 :
182 0 : WrBridge()->AddWebRenderParentCommand(OpUpdateAsyncImagePipeline(mPipelineId.value(),
183 : scBounds,
184 : scTransform,
185 : scaleToSize,
186 : filter,
187 0 : mixBlendMode));
188 0 : return;
189 : }
190 :
191 0 : MOZ_ASSERT(GetImageClientType() == CompositableType::IMAGE);
192 0 : MOZ_ASSERT(mImageClient->AsImageClientSingle());
193 :
194 0 : AutoLockImage autoLock(mContainer);
195 0 : Image* image = autoLock.GetImage();
196 0 : if (!image) {
197 0 : return;
198 : }
199 0 : gfx::IntSize size = image->GetSize();
200 0 : mKey = UpdateImageKey(mImageClient->AsImageClientSingle(),
201 : mContainer,
202 : mKey,
203 0 : mExternalImageId.ref());
204 0 : if (mKey.isNothing()) {
205 0 : return;
206 : }
207 :
208 0 : ScrollingLayersHelper scroller(this, aBuilder, aSc);
209 0 : StackingContextHelper sc(aSc, aBuilder, this);
210 :
211 0 : LayerRect rect(0, 0, size.width, size.height);
212 0 : if (mScaleMode != ScaleMode::SCALE_NONE) {
213 0 : NS_ASSERTION(mScaleMode == ScaleMode::STRETCH,
214 : "No other scalemodes than stretch and none supported yet.");
215 0 : rect = LayerRect(0, 0, mScaleToSize.width, mScaleToSize.height);
216 : }
217 :
218 0 : wr::ImageRendering filter = wr::ToImageRendering(mSamplingFilter);
219 :
220 0 : DumpLayerInfo("Image Layer", rect);
221 0 : if (gfxPrefs::LayersDump()) {
222 0 : printf_stderr("ImageLayer %p texture-filter=%s \n",
223 0 : GetLayer(),
224 0 : Stringify(filter).c_str());
225 : }
226 0 : WrRect r = sc.ToRelativeWrRect(rect);
227 0 : aBuilder.PushImage(r, r, filter, mKey.value());
228 : }
229 :
230 : Maybe<WrImageMask>
231 0 : WebRenderImageLayer::RenderMaskLayer(const StackingContextHelper& aSc,
232 : const gfx::Matrix4x4& aTransform)
233 : {
234 0 : if (!mContainer) {
235 0 : return Nothing();
236 : }
237 :
238 0 : CompositableType type = GetImageClientType();
239 0 : if (type == CompositableType::UNKNOWN) {
240 0 : return Nothing();
241 : }
242 :
243 0 : MOZ_ASSERT(GetImageClientType() == CompositableType::IMAGE);
244 0 : if (GetImageClientType() != CompositableType::IMAGE) {
245 0 : return Nothing();
246 : }
247 :
248 0 : if (!mImageClient) {
249 0 : mImageClient = ImageClient::CreateImageClient(CompositableType::IMAGE,
250 0 : WrBridge(),
251 0 : TextureFlags::DEFAULT);
252 0 : if (!mImageClient) {
253 0 : return Nothing();
254 : }
255 0 : mImageClient->Connect();
256 : }
257 :
258 0 : if (mExternalImageId.isNothing()) {
259 0 : mExternalImageId = Some(WrBridge()->AllocExternalImageIdForCompositable(mImageClient));
260 : }
261 :
262 0 : AutoLockImage autoLock(mContainer);
263 0 : Image* image = autoLock.GetImage();
264 0 : if (!image) {
265 0 : return Nothing();
266 : }
267 :
268 0 : MOZ_ASSERT(mImageClient->AsImageClientSingle());
269 0 : mKey = UpdateImageKey(mImageClient->AsImageClientSingle(),
270 : mContainer,
271 : mKey,
272 0 : mExternalImageId.ref());
273 0 : if (mKey.isNothing()) {
274 0 : return Nothing();
275 : }
276 :
277 0 : gfx::IntSize size = image->GetSize();
278 : WrImageMask imageMask;
279 0 : imageMask.image = mKey.value();
280 0 : Rect maskRect = aTransform.TransformBounds(Rect(0, 0, size.width, size.height));
281 0 : imageMask.rect = aSc.ToRelativeWrRect(ViewAs<LayerPixel>(maskRect));
282 0 : imageMask.repeat = false;
283 0 : return Some(imageMask);
284 : }
285 :
286 : } // namespace layers
287 9 : } // namespace mozilla
|