1/*
2 * Copyright (C) 2021 Sony Interactive Entertainment Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "GraphicsLayerWC.h"
28
29#include <WebCore/WCPlatformLayerGCGL.h>
30
31namespace WebKit {
32using namespace WebCore;
33
34GraphicsLayerWC::GraphicsLayerWC(Type layerType, GraphicsLayerClient& client, Observer& observer)
35 : GraphicsLayer(layerType, client)
36 , m_observer(&observer)
37{
38 m_observer->graphicsLayerAdded(*this);
39}
40
41GraphicsLayerWC::~GraphicsLayerWC()
42{
43 willBeDestroyed();
44 if (m_observer)
45 m_observer->graphicsLayerRemoved(*this);
46}
47
48GraphicsLayer::PlatformLayerID GraphicsLayerWC::generateLayerID()
49{
50 // 0 and max can't be used for hash keys
51 static GraphicsLayer::PlatformLayerID id = 1;
52 return id++;
53}
54
55GraphicsLayer::PlatformLayerID GraphicsLayerWC::primaryLayerID() const
56{
57 return m_layerID;
58}
59
60void GraphicsLayerWC::setNeedsDisplay()
61{
62 if (!drawsContent())
63 return;
64 noteLayerPropertyChanged(WCLayerChange::BackingStore);
65 addRepaintRect({ { }, m_size });
66}
67
68void GraphicsLayerWC::setNeedsDisplayInRect(const WebCore::FloatRect& rect, ShouldClipToLayer)
69{
70 if (!drawsContent())
71 return;
72 noteLayerPropertyChanged(WCLayerChange::BackingStore);
73 addRepaintRect(rect);
74}
75
76void GraphicsLayerWC::setContentsNeedsDisplay()
77{
78 // For example, if WebGL canvas changed, it needs flush to display.
79 noteLayerPropertyChanged({ });
80}
81
82bool GraphicsLayerWC::setChildren(Vector<Ref<GraphicsLayer>>&& children)
83{
84 bool childrenChanged = GraphicsLayer::setChildren(WTFMove(children));
85 if (childrenChanged)
86 noteLayerPropertyChanged(WCLayerChange::Children);
87 return childrenChanged;
88}
89
90void GraphicsLayerWC::addChild(Ref<GraphicsLayer>&& childLayer)
91{
92 GraphicsLayer::addChild(WTFMove(childLayer));
93 noteLayerPropertyChanged(WCLayerChange::Children);
94}
95
96void GraphicsLayerWC::addChildAtIndex(Ref<GraphicsLayer>&& childLayer, int index)
97{
98 GraphicsLayer::addChildAtIndex(WTFMove(childLayer), index);
99 noteLayerPropertyChanged(WCLayerChange::Children);
100}
101
102void GraphicsLayerWC::addChildBelow(Ref<GraphicsLayer>&& childLayer, GraphicsLayer* sibling)
103{
104 GraphicsLayer::addChildBelow(WTFMove(childLayer), sibling);
105 noteLayerPropertyChanged(WCLayerChange::Children);
106}
107
108void GraphicsLayerWC::addChildAbove(Ref<GraphicsLayer>&& childLayer, GraphicsLayer* sibling)
109{
110 GraphicsLayer::addChildAbove(WTFMove(childLayer), sibling);
111 noteLayerPropertyChanged(WCLayerChange::Children);
112}
113
114bool GraphicsLayerWC::replaceChild(GraphicsLayer* oldChild, Ref<GraphicsLayer>&& newChild)
115{
116 if (GraphicsLayer::replaceChild(oldChild, WTFMove(newChild))) {
117 noteLayerPropertyChanged(WCLayerChange::Children);
118 return true;
119 }
120 return false;
121}
122
123void GraphicsLayerWC::removeFromParent()
124{
125 if (m_parent)
126 static_cast<GraphicsLayerWC*>(m_parent)->noteLayerPropertyChanged(WCLayerChange::Children);
127 GraphicsLayer::removeFromParent();
128}
129
130void GraphicsLayerWC::setMaskLayer(RefPtr<GraphicsLayer>&& layer)
131{
132 if (layer == m_maskLayer)
133 return;
134 GraphicsLayer::setMaskLayer(WTFMove(layer));
135 noteLayerPropertyChanged(WCLayerChange::MaskLayer);
136}
137
138void GraphicsLayerWC::setReplicatedLayer(GraphicsLayer* layer)
139{
140 if (layer == m_replicatedLayer)
141 return;
142 GraphicsLayer::setReplicatedLayer(layer);
143 noteLayerPropertyChanged(WCLayerChange::ReplicaLayer);
144}
145
146void GraphicsLayerWC::setReplicatedByLayer(RefPtr<GraphicsLayer>&& layer)
147{
148 if (layer == m_replicaLayer)
149 return;
150 GraphicsLayer::setReplicatedByLayer(WTFMove(layer));
151 noteLayerPropertyChanged(WCLayerChange::ReplicaLayer);
152}
153
154void GraphicsLayerWC::setPosition(const FloatPoint& point)
155{
156 if (point == m_position)
157 return;
158 GraphicsLayer::setPosition(point);
159 noteLayerPropertyChanged(WCLayerChange::Geometry);
160}
161
162void GraphicsLayerWC::setAnchorPoint(const FloatPoint3D& point)
163{
164 if (point == m_anchorPoint)
165 return;
166 GraphicsLayer::setAnchorPoint(point);
167 noteLayerPropertyChanged(WCLayerChange::Geometry);
168}
169
170void GraphicsLayerWC::setSize(const FloatSize& size)
171{
172 if (size == m_size)
173 return;
174 GraphicsLayer::setSize(size);
175 noteLayerPropertyChanged(WCLayerChange::Geometry);
176}
177
178void GraphicsLayerWC::setBoundsOrigin(const FloatPoint& origin)
179{
180 if (origin == m_boundsOrigin)
181 return;
182 GraphicsLayer::setBoundsOrigin(origin);
183 noteLayerPropertyChanged(WCLayerChange::Geometry);
184}
185
186void GraphicsLayerWC::setTransform(const TransformationMatrix& t)
187{
188 if (t == transform())
189 return;
190 GraphicsLayer::setTransform(t);
191 noteLayerPropertyChanged(WCLayerChange::Transform);
192}
193
194void GraphicsLayerWC::setChildrenTransform(const TransformationMatrix& t)
195{
196 if (t == childrenTransform())
197 return;
198 GraphicsLayer::setChildrenTransform(t);
199 noteLayerPropertyChanged(WCLayerChange::ChildrenTransform);
200}
201
202void GraphicsLayerWC::setPreserves3D(bool value)
203{
204 if (value == preserves3D())
205 return;
206 GraphicsLayer::setPreserves3D(value);
207 noteLayerPropertyChanged(WCLayerChange::Preserves3D);
208}
209
210void GraphicsLayerWC::setMasksToBounds(bool value)
211{
212 if (value == masksToBounds())
213 return;
214 GraphicsLayer::setMasksToBounds(value);
215 noteLayerPropertyChanged(WCLayerChange::MasksToBounds);
216}
217
218void GraphicsLayerWC::setOpacity(float value)
219{
220 if (value == opacity())
221 return;
222 GraphicsLayer::setOpacity(value);
223 noteLayerPropertyChanged(WCLayerChange::Opacity);
224}
225
226void GraphicsLayerWC::setContentsRect(const FloatRect& value)
227{
228 if (value == contentsRect())
229 return;
230 GraphicsLayer::setContentsRect(value);
231 noteLayerPropertyChanged(WCLayerChange::ContentsRect);
232}
233
234void GraphicsLayerWC::setContentsClippingRect(const FloatRoundedRect& value)
235{
236 if (value == contentsClippingRect())
237 return;
238 GraphicsLayer::setContentsClippingRect(value);
239 noteLayerPropertyChanged(WCLayerChange::ContentsClippingRect);
240}
241
242void GraphicsLayerWC::setDrawsContent(bool value)
243{
244 if (value == drawsContent())
245 return;
246 GraphicsLayer::setDrawsContent(value);
247 noteLayerPropertyChanged(WCLayerChange::BackingStore);
248}
249
250void GraphicsLayerWC::setContentsVisible(bool value)
251{
252 if (value == contentsAreVisible())
253 return;
254 GraphicsLayer::setContentsVisible(value);
255 noteLayerPropertyChanged(WCLayerChange::ContentsVisible);
256}
257
258void GraphicsLayerWC::setBackfaceVisibility(bool value)
259{
260 if (value == backfaceVisibility())
261 return;
262 GraphicsLayer::setBackfaceVisibility(value);
263 noteLayerPropertyChanged(WCLayerChange::BackfaceVisibility);
264}
265
266void GraphicsLayerWC::setContentsToSolidColor(const Color& color)
267{
268 if (color == m_solidColor)
269 return;
270 m_solidColor = color;
271 noteLayerPropertyChanged(WCLayerChange::SolidColor);
272}
273
274void GraphicsLayerWC::setContentsToPlatformLayer(PlatformLayer* platformLayer, ContentsLayerPurpose)
275{
276 if (m_platformLayer == platformLayer)
277 return;
278 m_platformLayer = platformLayer;
279 noteLayerPropertyChanged(WCLayerChange::PlatformLayer);
280}
281
282bool GraphicsLayerWC::usesContentsLayer() const
283{
284 return m_platformLayer;
285}
286
287void GraphicsLayerWC::setShowDebugBorder(bool show)
288{
289 if (isShowingDebugBorder() == show)
290 return;
291 GraphicsLayer::setShowDebugBorder(show);
292 updateDebugIndicators();
293 noteLayerPropertyChanged(WCLayerChange::DebugVisuals);
294}
295
296void GraphicsLayerWC::setDebugBorder(const Color& color, float width)
297{
298 m_debugBorderColor = color;
299 m_debugBorderWidth = width;
300 noteLayerPropertyChanged(WCLayerChange::DebugVisuals);
301}
302
303void GraphicsLayerWC::setShowRepaintCounter(bool show)
304{
305 if (isShowingRepaintCounter() == show)
306 return;
307 GraphicsLayer::setShowRepaintCounter(show);
308 noteLayerPropertyChanged(WCLayerChange::RepaintCount);
309}
310
311static bool filtersCanBeComposited(const FilterOperations& filters)
312{
313 if (!filters.size())
314 return false;
315 for (const auto& filterOperation : filters.operations()) {
316 if (filterOperation->type() == FilterOperation::REFERENCE)
317 return false;
318 }
319 return true;
320}
321
322bool GraphicsLayerWC::setFilters(const FilterOperations& filters)
323{
324 bool canCompositeFilters = filtersCanBeComposited(filters);
325 if (GraphicsLayer::filters() == filters)
326 return canCompositeFilters;
327
328 if (canCompositeFilters) {
329 if (!GraphicsLayer::setFilters(filters))
330 return false;
331 } else if (GraphicsLayer::filters().size())
332 clearFilters();
333
334 noteLayerPropertyChanged(WCLayerChange::Filters);
335 return canCompositeFilters;
336}
337
338bool GraphicsLayerWC::setBackdropFilters(const FilterOperations& filters)
339{
340 bool canCompositeFilters = filtersCanBeComposited(filters);
341 if (m_backdropFilters == filters)
342 return canCompositeFilters;
343 if (canCompositeFilters)
344 GraphicsLayer::setBackdropFilters(filters);
345 else
346 clearBackdropFilters();
347 noteLayerPropertyChanged(WCLayerChange::BackdropFilters);
348 return canCompositeFilters;
349}
350
351void GraphicsLayerWC::setBackdropFiltersRect(const FloatRoundedRect& backdropFiltersRect)
352{
353 if (m_backdropFiltersRect == backdropFiltersRect)
354 return;
355 GraphicsLayer::setBackdropFiltersRect(backdropFiltersRect);
356 noteLayerPropertyChanged(WCLayerChange::BackdropFilters);
357}
358
359void GraphicsLayerWC::noteLayerPropertyChanged(OptionSet<WCLayerChange> flags)
360{
361 if (beingDestroyed())
362 return;
363 bool needsFlush = !m_uncommittedChanges;
364 m_uncommittedChanges.add(flags);
365 if (needsFlush)
366 client().notifyFlushRequired(this);
367}
368
369void GraphicsLayerWC::flushCompositingState(const FloatRect& rect)
370{
371 if (auto* mask = maskLayer())
372 mask->flushCompositingStateForThisLayerOnly();
373 if (auto* replica = replicaLayer())
374 replica->flushCompositingStateForThisLayerOnly();
375 flushCompositingStateForThisLayerOnly();
376 for (auto& child : children())
377 child->flushCompositingState(rect);
378}
379
380void GraphicsLayerWC::flushCompositingStateForThisLayerOnly()
381{
382 if (!m_uncommittedChanges)
383 return;
384 WCLayerUpateInfo update;
385 update.id = primaryLayerID();
386 update.changes = std::exchange(m_uncommittedChanges, { });
387 if (update.changes & WCLayerChange::Children) {
388 update.children = WTF::map(children(), [](auto& layer) {
389 return layer->primaryLayerID();
390 });
391 }
392 if (update.changes & WCLayerChange::MaskLayer) {
393 if (maskLayer())
394 update.maskLayer = maskLayer()->primaryLayerID();
395 else
396 update.maskLayer = std::nullopt;
397 }
398 if (update.changes & WCLayerChange::ReplicaLayer) {
399 if (replicaLayer())
400 update.replicaLayer = replicaLayer()->primaryLayerID();
401 else
402 update.replicaLayer = std::nullopt;
403 }
404 if (update.changes & WCLayerChange::Geometry) {
405 update.position = position();
406 update.anchorPoint = anchorPoint();
407 update.size = size();
408 update.boundsOrigin = boundsOrigin();
409 }
410 if (update.changes & WCLayerChange::Preserves3D)
411 update.preserves3D = preserves3D();
412 if (update.changes & WCLayerChange::ContentsRect)
413 update.contentsRect = contentsRect();
414 if (update.changes & WCLayerChange::ContentsClippingRect)
415 update.contentsClippingRect = contentsClippingRect();
416 if (update.changes & WCLayerChange::ContentsVisible)
417 update.contentsVisible = contentsAreVisible();
418 if (update.changes & WCLayerChange::BackfaceVisibility)
419 update.backfaceVisibility = backfaceVisibility();
420 if (update.changes & WCLayerChange::MasksToBounds)
421 update.masksToBounds = masksToBounds();
422 if (update.changes & WCLayerChange::BackingStore) {
423 if (drawsContent() && contentsAreVisible() && !size().isEmpty()) {
424 auto image = m_observer->createImageBuffer(size());
425 FloatRect clipRect = { { }, size() };
426 paintGraphicsLayerContents(image->context(), clipRect);
427 image->flushDrawingContextAsync();
428 update.backingStore.setImageBuffer(WTFMove(image));
429
430 incrementRepaintCount();
431 update.changes.add(WCLayerChange::RepaintCount);
432 }
433 }
434 if (update.changes & WCLayerChange::SolidColor)
435 update.solidColor = m_solidColor;
436 if (update.changes & WCLayerChange::DebugVisuals) {
437 update.showDebugBorder = isShowingDebugBorder();
438 update.debugBorderColor = m_debugBorderColor;
439 update.debugBorderWidth = m_debugBorderWidth;
440 }
441 if (update.changes & WCLayerChange::RepaintCount) {
442 update.showRepaintCounter = isShowingRepaintCounter();
443 update.repaintCount = repaintCount();
444 }
445 if (update.changes & WCLayerChange::Opacity)
446 update.opacity = opacity();
447 if (update.changes & WCLayerChange::Transform)
448 update.transform = transform();
449 if (update.changes & WCLayerChange::ChildrenTransform)
450 update.childrenTransform = childrenTransform();
451 if (update.changes & WCLayerChange::Filters)
452 update.filters = filters();
453 if (update.changes & WCLayerChange::BackdropFilters) {
454 update.backdropFilters = backdropFilters();
455 update.backdropFiltersRect = backdropFiltersRect();
456 }
457 if (update.changes & WCLayerChange::PlatformLayer) {
458 if (m_platformLayer)
459 update.graphicsContextGLIdentifier = static_cast<WCPlatformLayerGCGL*>(m_platformLayer)->graphicsContextGLIdentifier();
460 else
461 update.graphicsContextGLIdentifier = 0;
462 }
463 m_observer->commitLayerUpateInfo(WTFMove(update));
464}
465
466} // namespace WebKit