1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/scrollbar_layer.h"
7 #include "base/basictypes.h"
8 #include "base/debug/trace_event.h"
9 #include "cc/layer_painter.h"
10 #include "cc/layer_tree_host.h"
11 #include "cc/resource_update_queue.h"
12 #include "cc/scrollbar_layer_impl.h"
13 #include "ui/gfx/rect_conversions.h"
14 #include <public/WebRect.h>
16 using WebKit::WebRect
;
20 scoped_ptr
<LayerImpl
> ScrollbarLayer::createLayerImpl()
22 return ScrollbarLayerImpl::create(id()).PassAs
<LayerImpl
>();
25 scoped_refptr
<ScrollbarLayer
> ScrollbarLayer::create(scoped_ptr
<WebKit::WebScrollbar
> scrollbar
, WebKit::WebScrollbarThemePainter painter
, scoped_ptr
<WebKit::WebScrollbarThemeGeometry
> geometry
, int scrollLayerId
)
27 return make_scoped_refptr(new ScrollbarLayer(scrollbar
.Pass(), painter
, geometry
.Pass(), scrollLayerId
));
30 ScrollbarLayer::ScrollbarLayer(scoped_ptr
<WebKit::WebScrollbar
> scrollbar
, WebKit::WebScrollbarThemePainter painter
, scoped_ptr
<WebKit::WebScrollbarThemeGeometry
> geometry
, int scrollLayerId
)
31 : m_scrollbar(scrollbar
.Pass())
33 , m_geometry(geometry
.Pass())
34 , m_scrollLayerId(scrollLayerId
)
35 , m_textureFormat(GL_INVALID_ENUM
)
39 ScrollbarLayer::~ScrollbarLayer()
43 void ScrollbarLayer::setScrollLayerId(int id
)
45 if (id
== m_scrollLayerId
)
49 setNeedsFullTreeSync();
52 int ScrollbarLayer::maxTextureSize() {
53 DCHECK(layerTreeHost());
54 return layerTreeHost()->rendererCapabilities().maxTextureSize
;
57 float ScrollbarLayer::clampScaleToMaxTextureSize(float scale
) {
58 // If the scaled contentBounds() is bigger than the max texture size of the
59 // device, we need to clamp it by rescaling, since contentBounds() is used
60 // below to set the texture size.
61 gfx::Size scaledBounds
= computeContentBoundsForScale(scale
, scale
);
62 if (scaledBounds
.width() > maxTextureSize() || scaledBounds
.height() > maxTextureSize()) {
63 if (scaledBounds
.width() > scaledBounds
.height())
64 return (maxTextureSize() - 1) / static_cast<float>(bounds().width());
66 return (maxTextureSize() - 1) / static_cast<float>(bounds().height());
71 void ScrollbarLayer::setContentsScale(float contentsScale
) {
72 contentsScale
= clampScaleToMaxTextureSize(contentsScale
);
73 ContentsScalingLayer::setContentsScale(contentsScale
);
74 DCHECK_LE(contentBounds().width(), maxTextureSize());
75 DCHECK_LE(contentBounds().height(), maxTextureSize());
78 void ScrollbarLayer::pushPropertiesTo(LayerImpl
* layer
)
80 ContentsScalingLayer::pushPropertiesTo(layer
);
82 ScrollbarLayerImpl
* scrollbarLayer
= static_cast<ScrollbarLayerImpl
*>(layer
);
84 if (!scrollbarLayer
->scrollbarGeometry())
85 scrollbarLayer
->setScrollbarGeometry(ScrollbarGeometryFixedThumb::create(make_scoped_ptr(m_geometry
->clone())));
87 scrollbarLayer
->setScrollbarData(m_scrollbar
.get());
89 if (m_backTrack
&& m_backTrack
->texture()->haveBackingTexture())
90 scrollbarLayer
->setBackTrackResourceId(m_backTrack
->texture()->resourceId());
92 scrollbarLayer
->setBackTrackResourceId(0);
94 if (m_foreTrack
&& m_foreTrack
->texture()->haveBackingTexture())
95 scrollbarLayer
->setForeTrackResourceId(m_foreTrack
->texture()->resourceId());
97 scrollbarLayer
->setForeTrackResourceId(0);
99 if (m_thumb
&& m_thumb
->texture()->haveBackingTexture())
100 scrollbarLayer
->setThumbResourceId(m_thumb
->texture()->resourceId());
102 scrollbarLayer
->setThumbResourceId(0);
105 ScrollbarLayer
* ScrollbarLayer::toScrollbarLayer()
110 class ScrollbarBackgroundPainter
: public LayerPainter
{
112 static scoped_ptr
<ScrollbarBackgroundPainter
> create(WebKit::WebScrollbar
* scrollbar
, WebKit::WebScrollbarThemePainter painter
, WebKit::WebScrollbarThemeGeometry
* geometry
, WebKit::WebScrollbar::ScrollbarPart trackPart
)
114 return make_scoped_ptr(new ScrollbarBackgroundPainter(scrollbar
, painter
, geometry
, trackPart
));
117 virtual void paint(SkCanvas
* skCanvas
, const gfx::Rect
& contentRect
, gfx::RectF
&) OVERRIDE
119 WebKit::WebCanvas
* canvas
= skCanvas
;
120 // The following is a simplification of ScrollbarThemeComposite::paint.
121 m_painter
.paintScrollbarBackground(canvas
, contentRect
);
123 if (m_geometry
->hasButtons(m_scrollbar
)) {
124 WebRect backButtonStartPaintRect
= m_geometry
->backButtonStartRect(m_scrollbar
);
125 m_painter
.paintBackButtonStart(canvas
, backButtonStartPaintRect
);
127 WebRect backButtonEndPaintRect
= m_geometry
->backButtonEndRect(m_scrollbar
);
128 m_painter
.paintBackButtonEnd(canvas
, backButtonEndPaintRect
);
130 WebRect forwardButtonStartPaintRect
= m_geometry
->forwardButtonStartRect(m_scrollbar
);
131 m_painter
.paintForwardButtonStart(canvas
, forwardButtonStartPaintRect
);
133 WebRect forwardButtonEndPaintRect
= m_geometry
->forwardButtonEndRect(m_scrollbar
);
134 m_painter
.paintForwardButtonEnd(canvas
, forwardButtonEndPaintRect
);
137 WebRect trackPaintRect
= m_geometry
->trackRect(m_scrollbar
);
138 m_painter
.paintTrackBackground(canvas
, trackPaintRect
);
140 bool thumbPresent
= m_geometry
->hasThumb(m_scrollbar
);
142 if (m_trackPart
== WebKit::WebScrollbar::ForwardTrackPart
)
143 m_painter
.paintForwardTrackPart(canvas
, trackPaintRect
);
145 m_painter
.paintBackTrackPart(canvas
, trackPaintRect
);
148 m_painter
.paintTickmarks(canvas
, trackPaintRect
);
151 ScrollbarBackgroundPainter(WebKit::WebScrollbar
* scrollbar
, WebKit::WebScrollbarThemePainter painter
, WebKit::WebScrollbarThemeGeometry
* geometry
, WebKit::WebScrollbar::ScrollbarPart trackPart
)
152 : m_scrollbar(scrollbar
)
154 , m_geometry(geometry
)
155 , m_trackPart(trackPart
)
159 WebKit::WebScrollbar
* m_scrollbar
;
160 WebKit::WebScrollbarThemePainter m_painter
;
161 WebKit::WebScrollbarThemeGeometry
* m_geometry
;
162 WebKit::WebScrollbar::ScrollbarPart m_trackPart
;
164 DISALLOW_COPY_AND_ASSIGN(ScrollbarBackgroundPainter
);
167 class ScrollbarThumbPainter
: public LayerPainter
{
169 static scoped_ptr
<ScrollbarThumbPainter
> create(WebKit::WebScrollbar
* scrollbar
, WebKit::WebScrollbarThemePainter painter
, WebKit::WebScrollbarThemeGeometry
* geometry
)
171 return make_scoped_ptr(new ScrollbarThumbPainter(scrollbar
, painter
, geometry
));
174 virtual void paint(SkCanvas
* skCanvas
, const gfx::Rect
& contentRect
, gfx::RectF
& opaque
) OVERRIDE
176 WebKit::WebCanvas
* canvas
= skCanvas
;
178 // Consider the thumb to be at the origin when painting.
179 WebRect thumbRect
= m_geometry
->thumbRect(m_scrollbar
);
182 m_painter
.paintThumb(canvas
, thumbRect
);
186 ScrollbarThumbPainter(WebKit::WebScrollbar
* scrollbar
, WebKit::WebScrollbarThemePainter painter
, WebKit::WebScrollbarThemeGeometry
* geometry
)
187 : m_scrollbar(scrollbar
)
189 , m_geometry(geometry
)
193 WebKit::WebScrollbar
* m_scrollbar
;
194 WebKit::WebScrollbarThemePainter m_painter
;
195 WebKit::WebScrollbarThemeGeometry
* m_geometry
;
197 DISALLOW_COPY_AND_ASSIGN(ScrollbarThumbPainter
);
200 void ScrollbarLayer::setLayerTreeHost(LayerTreeHost
* host
)
202 if (!host
|| host
!= layerTreeHost()) {
203 m_backTrackUpdater
= NULL
;
205 m_thumbUpdater
= NULL
;
209 ContentsScalingLayer::setLayerTreeHost(host
);
212 void ScrollbarLayer::createUpdaterIfNeeded()
214 m_textureFormat
= layerTreeHost()->rendererCapabilities().bestTextureFormat
;
216 if (!m_backTrackUpdater
)
217 m_backTrackUpdater
= CachingBitmapContentLayerUpdater::Create(ScrollbarBackgroundPainter::create(m_scrollbar
.get(), m_painter
, m_geometry
.get(), WebKit::WebScrollbar::BackTrackPart
).PassAs
<LayerPainter
>());
219 m_backTrack
= m_backTrackUpdater
->createResource(layerTreeHost()->contentsTextureManager());
221 // Only create two-part track if we think the two parts could be different in appearance.
222 if (m_scrollbar
->isCustomScrollbar()) {
223 if (!m_foreTrackUpdater
)
224 m_foreTrackUpdater
= CachingBitmapContentLayerUpdater::Create(ScrollbarBackgroundPainter::create(m_scrollbar
.get(), m_painter
, m_geometry
.get(), WebKit::WebScrollbar::ForwardTrackPart
).PassAs
<LayerPainter
>());
226 m_foreTrack
= m_foreTrackUpdater
->createResource(layerTreeHost()->contentsTextureManager());
230 m_thumbUpdater
= CachingBitmapContentLayerUpdater::Create(ScrollbarThumbPainter::create(m_scrollbar
.get(), m_painter
, m_geometry
.get()).PassAs
<LayerPainter
>());
232 m_thumb
= m_thumbUpdater
->createResource(layerTreeHost()->contentsTextureManager());
235 void ScrollbarLayer::updatePart(CachingBitmapContentLayerUpdater
* painter
, LayerUpdater::Resource
* texture
, const gfx::Rect
& rect
, ResourceUpdateQueue
& queue
, RenderingStats
& stats
)
237 // Skip painting and uploading if there are no invalidations and
238 // we already have valid texture data.
239 if (texture
->texture()->haveBackingTexture()
240 && texture
->texture()->size() == rect
.size()
241 && m_updateRect
.IsEmpty())
244 // We should always have enough memory for UI.
245 DCHECK(texture
->texture()->canAcquireBackingTexture());
246 if (!texture
->texture()->canAcquireBackingTexture())
249 // Paint and upload the entire part.
250 gfx::Rect paintedOpaqueRect
;
251 painter
->prepareToUpdate(rect
, rect
.size(), contentsScaleX(), contentsScaleY(), paintedOpaqueRect
, stats
);
252 if (!painter
->pixelsDidChange() && texture
->texture()->haveBackingTexture()) {
253 TRACE_EVENT_INSTANT0("cc","ScrollbarLayer::updatePart no texture upload needed");
257 gfx::Vector2d
destOffset(0, 0);
258 texture
->update(queue
, rect
, destOffset
, false, stats
);
261 gfx::Rect
ScrollbarLayer::scrollbarLayerRectToContentRect(const gfx::Rect
& layerRect
) const
263 // Don't intersect with the bounds as in layerRectToContentRect() because
264 // layerRect here might be in coordinates of the containing layer.
265 gfx::RectF contentRect
= gfx::ScaleRect(layerRect
, contentsScaleX(), contentsScaleY());
266 return gfx::ToEnclosingRect(contentRect
);
269 void ScrollbarLayer::setTexturePriorities(const PriorityCalculator
&)
271 if (contentBounds().IsEmpty())
273 DCHECK_LE(contentBounds().width(), maxTextureSize());
274 DCHECK_LE(contentBounds().height(), maxTextureSize());
276 createUpdaterIfNeeded();
278 bool drawsToRoot
= !renderTarget()->parent();
280 m_backTrack
->texture()->setDimensions(contentBounds(), m_textureFormat
);
281 m_backTrack
->texture()->setRequestPriority(PriorityCalculator::uiPriority(drawsToRoot
));
284 m_foreTrack
->texture()->setDimensions(contentBounds(), m_textureFormat
);
285 m_foreTrack
->texture()->setRequestPriority(PriorityCalculator::uiPriority(drawsToRoot
));
288 gfx::Size thumbSize
= scrollbarLayerRectToContentRect(m_geometry
->thumbRect(m_scrollbar
.get())).size();
289 m_thumb
->texture()->setDimensions(thumbSize
, m_textureFormat
);
290 m_thumb
->texture()->setRequestPriority(PriorityCalculator::uiPriority(drawsToRoot
));
294 void ScrollbarLayer::update(ResourceUpdateQueue
& queue
, const OcclusionTracker
*, RenderingStats
& stats
)
296 if (contentBounds().IsEmpty())
299 createUpdaterIfNeeded();
301 gfx::Rect contentRect
= scrollbarLayerRectToContentRect(gfx::Rect(m_scrollbar
->location(), bounds()));
302 updatePart(m_backTrackUpdater
.get(), m_backTrack
.get(), contentRect
, queue
, stats
);
303 if (m_foreTrack
&& m_foreTrackUpdater
)
304 updatePart(m_foreTrackUpdater
.get(), m_foreTrack
.get(), contentRect
, queue
, stats
);
306 // Consider the thumb to be at the origin when painting.
307 WebKit::WebRect thumbRect
= m_geometry
->thumbRect(m_scrollbar
.get());
308 gfx::Rect originThumbRect
= scrollbarLayerRectToContentRect(gfx::Rect(0, 0, thumbRect
.width
, thumbRect
.height
));
309 if (!originThumbRect
.IsEmpty())
310 updatePart(m_thumbUpdater
.get(), m_thumb
.get(), originThumbRect
, queue
, stats
);