Use "= default" to denote default constructor or destructor
[WebKit-https.git] / Source / WebCore / platform / graphics / texmap / coordinated / CoordinatedImageBacking.cpp
1 /*
2  * Copyright (C) 2012 Company 100, Inc. All rights reserved.
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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #if USE(COORDINATED_GRAPHICS)
29 #include "CoordinatedImageBacking.h"
30
31 #include "CoordinatedGraphicsState.h"
32 #include "GraphicsContext.h"
33
34 namespace WebCore {
35
36 class ImageBackingSurfaceClient : public CoordinatedSurface::Client {
37 public:
38     ImageBackingSurfaceClient(Image& image, const IntRect& rect)
39         : m_image(image)
40         , m_rect(rect)
41     {
42     }
43
44     void paintToSurfaceContext(GraphicsContext& context) override
45     {
46         context.drawImage(m_image, m_rect, m_rect);
47     }
48
49 private:
50     Image& m_image;
51     IntRect m_rect;
52 };
53
54 CoordinatedImageBackingID CoordinatedImageBacking::getCoordinatedImageBackingID(Image* image)
55 {
56     // CoordinatedImageBacking keeps a RefPtr<Image> member, so the same Image pointer can not refer two different instances until CoordinatedImageBacking releases the member.
57     return reinterpret_cast<CoordinatedImageBackingID>(image);
58 }
59
60 Ref<CoordinatedImageBacking> CoordinatedImageBacking::create(Client& client, Ref<Image>&& image)
61 {
62     return adoptRef(*new CoordinatedImageBacking(client, WTFMove(image)));
63 }
64
65 CoordinatedImageBacking::CoordinatedImageBacking(Client& client, Ref<Image>&& image)
66     : m_client(&client)
67     , m_image(WTFMove(image))
68     , m_id(getCoordinatedImageBackingID(m_image.get()))
69     , m_clearContentsTimer(*this, &CoordinatedImageBacking::clearContentsTimerFired)
70     , m_isDirty(false)
71     , m_isVisible(false)
72 {
73     // FIXME: We would need to decode a small image directly into a GraphicsSurface.
74     // http://webkit.org/b/101426
75
76     m_client->createImageBacking(id());
77 }
78
79 CoordinatedImageBacking::~CoordinatedImageBacking() = default;
80
81 void CoordinatedImageBacking::addHost(Host* host)
82 {
83     ASSERT(!m_hosts.contains(host));
84     m_hosts.append(host);
85 }
86
87 void CoordinatedImageBacking::removeHost(Host* host)
88 {
89     size_t position = m_hosts.find(host);
90     ASSERT(position != notFound);
91     m_hosts.remove(position);
92
93     if (m_hosts.isEmpty())
94         m_client->removeImageBacking(id());
95 }
96
97 void CoordinatedImageBacking::markDirty()
98 {
99     m_isDirty = true;
100 }
101
102 void CoordinatedImageBacking::update()
103 {
104     releaseSurfaceIfNeeded();
105
106     bool changedToVisible;
107     updateVisibilityIfNeeded(changedToVisible);
108     if (!m_isVisible)
109         return;
110
111     if (!changedToVisible) {
112         if (!m_isDirty)
113             return;
114
115         if (m_nativeImagePtr == m_image->nativeImageForCurrentFrame()) {
116             m_isDirty = false;
117             return;
118         }
119     }
120
121     m_surface = CoordinatedSurface::create(IntSize(m_image->size()), !m_image->currentFrameKnownToBeOpaque() ? CoordinatedSurface::SupportsAlpha : CoordinatedSurface::NoFlags);
122     if (!m_surface) {
123         m_isDirty = false;
124         return;
125     }
126
127     IntRect rect(IntPoint::zero(), IntSize(m_image->size()));
128
129     ImageBackingSurfaceClient surfaceClient(*m_image, rect);
130     m_surface->paintToSurface(rect, surfaceClient);
131
132     m_nativeImagePtr = m_image->nativeImageForCurrentFrame();
133
134     m_client->updateImageBacking(id(), m_surface.copyRef());
135     m_isDirty = false;
136 }
137
138 void CoordinatedImageBacking::releaseSurfaceIfNeeded()
139 {
140     // We must keep m_surface until UI Process reads m_surface.
141     // If m_surface exists, it was created in the previous update.
142     m_surface = nullptr;
143 }
144
145 static const Seconds clearContentsTimerInterval { 3_s };
146
147 void CoordinatedImageBacking::updateVisibilityIfNeeded(bool& changedToVisible)
148 {
149     bool previousIsVisible = m_isVisible;
150
151     m_isVisible = false;
152     for (auto& host : m_hosts) {
153         if (host->imageBackingVisible()) {
154             m_isVisible = true;
155             break;
156         }
157     }
158
159     bool changedToInvisible = previousIsVisible && !m_isVisible;
160     if (changedToInvisible) {
161         ASSERT(!m_clearContentsTimer.isActive());
162         m_clearContentsTimer.startOneShot(clearContentsTimerInterval);
163     }
164
165     changedToVisible = !previousIsVisible && m_isVisible;
166
167     if (m_isVisible && m_clearContentsTimer.isActive()) {
168         m_clearContentsTimer.stop();
169         // We don't want to update the texture if we didn't remove the texture.
170         changedToVisible = false;
171     }
172 }
173
174 void CoordinatedImageBacking::clearContentsTimerFired()
175 {
176     m_client->clearImageBackingContents(id());
177 }
178
179 } // namespace WebCore
180 #endif