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 "third_party/WebKit/Source/Platform/chromium/public/WebRect.h"
14 #include "ui/gfx/rect_conversions.h"
18 scoped_ptr
<LayerImpl
> ScrollbarLayer::createLayerImpl(LayerTreeImpl
* treeImpl
)
20 return ScrollbarLayerImpl::create(treeImpl
, id()).PassAs
<LayerImpl
>();
23 scoped_refptr
<ScrollbarLayer
> ScrollbarLayer::create(
24 scoped_ptr
<WebKit::WebScrollbar
> scrollbar
,
25 scoped_ptr
<ScrollbarThemePainter
> painter
,
26 scoped_ptr
<WebKit::WebScrollbarThemeGeometry
> geometry
,
29 return make_scoped_refptr(new ScrollbarLayer(scrollbar
.Pass(), painter
.Pass(), geometry
.Pass(), scrollLayerId
));
32 ScrollbarLayer::ScrollbarLayer(
33 scoped_ptr
<WebKit::WebScrollbar
> scrollbar
,
34 scoped_ptr
<ScrollbarThemePainter
> painter
,
35 scoped_ptr
<WebKit::WebScrollbarThemeGeometry
> geometry
,
37 : m_scrollbar(scrollbar
.Pass())
38 , m_painter(painter
.Pass())
39 , m_geometry(geometry
.Pass())
40 , m_scrollLayerId(scrollLayerId
)
41 , m_textureFormat(GL_INVALID_ENUM
)
43 if (!m_scrollbar
->isOverlay())
44 setShouldScrollOnMainThread(true);
47 ScrollbarLayer::~ScrollbarLayer()
51 void ScrollbarLayer::setScrollLayerId(int id
)
53 if (id
== m_scrollLayerId
)
57 setNeedsFullTreeSync();
60 int ScrollbarLayer::maxTextureSize() {
61 DCHECK(layerTreeHost());
62 return layerTreeHost()->rendererCapabilities().maxTextureSize
;
65 float ScrollbarLayer::clampScaleToMaxTextureSize(float scale
) {
66 // If the scaled contentBounds() is bigger than the max texture size of the
67 // device, we need to clamp it by rescaling, since contentBounds() is used
68 // below to set the texture size.
69 gfx::Size scaledBounds
= computeContentBoundsForScale(scale
, scale
);
70 if (scaledBounds
.width() > maxTextureSize() || scaledBounds
.height() > maxTextureSize()) {
71 if (scaledBounds
.width() > scaledBounds
.height())
72 return (maxTextureSize() - 1) / static_cast<float>(bounds().width());
74 return (maxTextureSize() - 1) / static_cast<float>(bounds().height());
79 void ScrollbarLayer::calculateContentsScale(
80 float idealContentsScale
,
81 float* contentsScaleX
,
82 float* contentsScaleY
,
83 gfx::Size
* contentBounds
)
85 ContentsScalingLayer::calculateContentsScale(
86 clampScaleToMaxTextureSize(idealContentsScale
),
90 DCHECK_LE(contentBounds
->width(), maxTextureSize());
91 DCHECK_LE(contentBounds
->height(), maxTextureSize());
94 void ScrollbarLayer::pushPropertiesTo(LayerImpl
* layer
)
96 ContentsScalingLayer::pushPropertiesTo(layer
);
98 ScrollbarLayerImpl
* scrollbarLayer
= static_cast<ScrollbarLayerImpl
*>(layer
);
100 if (!scrollbarLayer
->scrollbarGeometry())
101 scrollbarLayer
->setScrollbarGeometry(ScrollbarGeometryFixedThumb::create(make_scoped_ptr(m_geometry
->clone())));
103 scrollbarLayer
->setScrollbarData(m_scrollbar
.get());
105 if (m_backTrack
&& m_backTrack
->texture()->haveBackingTexture())
106 scrollbarLayer
->setBackTrackResourceId(m_backTrack
->texture()->resourceId());
108 scrollbarLayer
->setBackTrackResourceId(0);
110 if (m_foreTrack
&& m_foreTrack
->texture()->haveBackingTexture())
111 scrollbarLayer
->setForeTrackResourceId(m_foreTrack
->texture()->resourceId());
113 scrollbarLayer
->setForeTrackResourceId(0);
115 if (m_thumb
&& m_thumb
->texture()->haveBackingTexture())
116 scrollbarLayer
->setThumbResourceId(m_thumb
->texture()->resourceId());
118 scrollbarLayer
->setThumbResourceId(0);
121 ScrollbarLayer
* ScrollbarLayer::toScrollbarLayer()
126 class ScrollbarBackgroundPainter
: public LayerPainter
{
128 static scoped_ptr
<ScrollbarBackgroundPainter
> create(WebKit::WebScrollbar
* scrollbar
, ScrollbarThemePainter
*painter
, WebKit::WebScrollbarThemeGeometry
* geometry
, WebKit::WebScrollbar::ScrollbarPart trackPart
)
130 return make_scoped_ptr(new ScrollbarBackgroundPainter(scrollbar
, painter
, geometry
, trackPart
));
133 virtual void paint(SkCanvas
* canvas
, gfx::Rect contentRect
, gfx::RectF
&) OVERRIDE
135 // The following is a simplification of ScrollbarThemeComposite::paint.
136 m_painter
->PaintScrollbarBackground(canvas
, contentRect
);
138 if (m_geometry
->hasButtons(m_scrollbar
)) {
139 gfx::Rect backButtonStartPaintRect
= m_geometry
->backButtonStartRect(m_scrollbar
);
140 m_painter
->PaintBackButtonStart(canvas
, backButtonStartPaintRect
);
142 gfx::Rect backButtonEndPaintRect
= m_geometry
->backButtonEndRect(m_scrollbar
);
143 m_painter
->PaintBackButtonEnd(canvas
, backButtonEndPaintRect
);
145 gfx::Rect forwardButtonStartPaintRect
= m_geometry
->forwardButtonStartRect(m_scrollbar
);
146 m_painter
->PaintForwardButtonStart(canvas
, forwardButtonStartPaintRect
);
148 gfx::Rect forwardButtonEndPaintRect
= m_geometry
->forwardButtonEndRect(m_scrollbar
);
149 m_painter
->PaintForwardButtonEnd(canvas
, forwardButtonEndPaintRect
);
152 gfx::Rect trackPaintRect
= m_geometry
->trackRect(m_scrollbar
);
153 m_painter
->PaintTrackBackground(canvas
, trackPaintRect
);
155 bool thumbPresent
= m_geometry
->hasThumb(m_scrollbar
);
157 if (m_trackPart
== WebKit::WebScrollbar::ForwardTrackPart
)
158 m_painter
->PaintForwardTrackPart(canvas
, trackPaintRect
);
160 m_painter
->PaintBackTrackPart(canvas
, trackPaintRect
);
163 m_painter
->PaintTickmarks(canvas
, trackPaintRect
);
166 ScrollbarBackgroundPainter(WebKit::WebScrollbar
* scrollbar
, ScrollbarThemePainter
*painter
, WebKit::WebScrollbarThemeGeometry
* geometry
, WebKit::WebScrollbar::ScrollbarPart trackPart
)
167 : m_scrollbar(scrollbar
)
169 , m_geometry(geometry
)
170 , m_trackPart(trackPart
)
174 WebKit::WebScrollbar
* m_scrollbar
;
175 ScrollbarThemePainter
* m_painter
;
176 WebKit::WebScrollbarThemeGeometry
* m_geometry
;
177 WebKit::WebScrollbar::ScrollbarPart m_trackPart
;
179 DISALLOW_COPY_AND_ASSIGN(ScrollbarBackgroundPainter
);
182 class ScrollbarThumbPainter
: public LayerPainter
{
184 static scoped_ptr
<ScrollbarThumbPainter
> create(WebKit::WebScrollbar
* scrollbar
, ScrollbarThemePainter
* painter
, WebKit::WebScrollbarThemeGeometry
* geometry
)
186 return make_scoped_ptr(new ScrollbarThumbPainter(scrollbar
, painter
, geometry
));
189 virtual void paint(SkCanvas
* canvas
, gfx::Rect contentRect
, gfx::RectF
& opaque
) OVERRIDE
191 // Consider the thumb to be at the origin when painting.
192 gfx::Rect thumbRect
= m_geometry
->thumbRect(m_scrollbar
);
193 m_painter
->PaintThumb(canvas
, gfx::Rect(thumbRect
.size()));
197 ScrollbarThumbPainter(WebKit::WebScrollbar
* scrollbar
, ScrollbarThemePainter
* painter
, WebKit::WebScrollbarThemeGeometry
* geometry
)
198 : m_scrollbar(scrollbar
)
200 , m_geometry(geometry
)
204 WebKit::WebScrollbar
* m_scrollbar
;
205 ScrollbarThemePainter
* m_painter
;
206 WebKit::WebScrollbarThemeGeometry
* m_geometry
;
208 DISALLOW_COPY_AND_ASSIGN(ScrollbarThumbPainter
);
211 void ScrollbarLayer::setLayerTreeHost(LayerTreeHost
* host
)
213 if (!host
|| host
!= layerTreeHost()) {
214 m_backTrackUpdater
= NULL
;
216 m_thumbUpdater
= NULL
;
220 ContentsScalingLayer::setLayerTreeHost(host
);
223 void ScrollbarLayer::createUpdaterIfNeeded()
225 m_textureFormat
= layerTreeHost()->rendererCapabilities().bestTextureFormat
;
227 if (!m_backTrackUpdater
)
228 m_backTrackUpdater
= CachingBitmapContentLayerUpdater::Create(ScrollbarBackgroundPainter::create(m_scrollbar
.get(), m_painter
.get(), m_geometry
.get(), WebKit::WebScrollbar::BackTrackPart
).PassAs
<LayerPainter
>());
230 m_backTrack
= m_backTrackUpdater
->createResource(layerTreeHost()->contentsTextureManager());
232 // Only create two-part track if we think the two parts could be different in appearance.
233 if (m_scrollbar
->isCustomScrollbar()) {
234 if (!m_foreTrackUpdater
)
235 m_foreTrackUpdater
= CachingBitmapContentLayerUpdater::Create(ScrollbarBackgroundPainter::create(m_scrollbar
.get(), m_painter
.get(), m_geometry
.get(), WebKit::WebScrollbar::ForwardTrackPart
).PassAs
<LayerPainter
>());
237 m_foreTrack
= m_foreTrackUpdater
->createResource(layerTreeHost()->contentsTextureManager());
241 m_thumbUpdater
= CachingBitmapContentLayerUpdater::Create(ScrollbarThumbPainter::create(m_scrollbar
.get(), m_painter
.get(), m_geometry
.get()).PassAs
<LayerPainter
>());
243 m_thumb
= m_thumbUpdater
->createResource(layerTreeHost()->contentsTextureManager());
246 void ScrollbarLayer::updatePart(CachingBitmapContentLayerUpdater
* painter
, LayerUpdater::Resource
* resource
, const gfx::Rect
& rect
, ResourceUpdateQueue
& queue
, RenderingStats
& stats
)
248 // Skip painting and uploading if there are no invalidations and
249 // we already have valid texture data.
250 if (resource
->texture()->haveBackingTexture() &&
251 resource
->texture()->size() == rect
.size() &&
255 // We should always have enough memory for UI.
256 DCHECK(resource
->texture()->canAcquireBackingTexture());
257 if (!resource
->texture()->canAcquireBackingTexture())
260 // Paint and upload the entire part.
261 gfx::Rect paintedOpaqueRect
;
262 painter
->prepareToUpdate(rect
, rect
.size(), contentsScaleX(), contentsScaleY(), paintedOpaqueRect
, stats
);
263 if (!painter
->pixelsDidChange() && resource
->texture()->haveBackingTexture()) {
264 TRACE_EVENT_INSTANT0("cc","ScrollbarLayer::updatePart no texture upload needed");
268 bool partialUpdatesAllowed
= layerTreeHost()->settings().maxPartialTextureUpdates
> 0;
269 if (!partialUpdatesAllowed
)
270 resource
->texture()->returnBackingTexture();
272 gfx::Vector2d
destOffset(0, 0);
273 resource
->update(queue
, rect
, destOffset
, partialUpdatesAllowed
, stats
);
276 gfx::Rect
ScrollbarLayer::scrollbarLayerRectToContentRect(const gfx::Rect
& layerRect
) const
278 // Don't intersect with the bounds as in layerRectToContentRect() because
279 // layerRect here might be in coordinates of the containing layer.
280 gfx::RectF contentRect
= gfx::ScaleRect(layerRect
, contentsScaleX(), contentsScaleY());
281 return gfx::ToEnclosingRect(contentRect
);
284 void ScrollbarLayer::setTexturePriorities(const PriorityCalculator
&)
286 if (contentBounds().IsEmpty())
288 DCHECK_LE(contentBounds().width(), maxTextureSize());
289 DCHECK_LE(contentBounds().height(), maxTextureSize());
291 createUpdaterIfNeeded();
293 bool drawsToRoot
= !renderTarget()->parent();
295 m_backTrack
->texture()->setDimensions(contentBounds(), m_textureFormat
);
296 m_backTrack
->texture()->setRequestPriority(PriorityCalculator::uiPriority(drawsToRoot
));
299 m_foreTrack
->texture()->setDimensions(contentBounds(), m_textureFormat
);
300 m_foreTrack
->texture()->setRequestPriority(PriorityCalculator::uiPriority(drawsToRoot
));
303 gfx::Size thumbSize
= scrollbarLayerRectToContentRect(m_geometry
->thumbRect(m_scrollbar
.get())).size();
304 m_thumb
->texture()->setDimensions(thumbSize
, m_textureFormat
);
305 m_thumb
->texture()->setRequestPriority(PriorityCalculator::uiPriority(drawsToRoot
));
309 void ScrollbarLayer::update(ResourceUpdateQueue
& queue
, const OcclusionTracker
* occlusion
, RenderingStats
& stats
)
311 ContentsScalingLayer::update(queue
, occlusion
, stats
);
313 m_dirtyRect
.Union(m_updateRect
);
314 if (contentBounds().IsEmpty())
316 if (visibleContentRect().IsEmpty())
321 createUpdaterIfNeeded();
323 gfx::Rect contentRect
= scrollbarLayerRectToContentRect(gfx::Rect(m_scrollbar
->location(), bounds()));
324 updatePart(m_backTrackUpdater
.get(), m_backTrack
.get(), contentRect
, queue
, stats
);
325 if (m_foreTrack
&& m_foreTrackUpdater
)
326 updatePart(m_foreTrackUpdater
.get(), m_foreTrack
.get(), contentRect
, queue
, stats
);
328 // Consider the thumb to be at the origin when painting.
329 gfx::Rect thumbRect
= m_geometry
->thumbRect(m_scrollbar
.get());
330 gfx::Rect originThumbRect
= scrollbarLayerRectToContentRect(gfx::Rect(thumbRect
.size()));
331 if (!originThumbRect
.IsEmpty())
332 updatePart(m_thumbUpdater
.get(), m_thumb
.get(), originThumbRect
, queue
, stats
);
334 m_dirtyRect
= gfx::RectF();