Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(157)

Side by Side Diff: ui/gfx/compositor/layer.cc

Issue 10365007: ui: Move compositor/ directory out of gfx/, up to ui/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix DEPS Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/gfx/compositor/layer.h ('k') | ui/gfx/compositor/layer_animation_delegate.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 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.
4
5 #include "ui/gfx/compositor/layer.h"
6
7 #include <algorithm>
8
9 #include "base/command_line.h"
10 #include "base/debug/trace_event.h"
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "third_party/WebKit/Source/Platform/chromium/public/WebContentLayer.h"
14 #include "third_party/WebKit/Source/Platform/chromium/public/WebExternalTextureL ayer.h"
15 #include "third_party/WebKit/Source/Platform/chromium/public/WebFilterOperation. h"
16 #include "third_party/WebKit/Source/Platform/chromium/public/WebFilterOperations .h"
17 #include "third_party/WebKit/Source/Platform/chromium/public/WebFloatPoint.h"
18 #include "third_party/WebKit/Source/Platform/chromium/public/WebFloatRect.h"
19 #include "third_party/WebKit/Source/Platform/chromium/public/WebSize.h"
20 #include "third_party/WebKit/Source/Platform/chromium/public/WebSolidColorLayer. h"
21 #include "ui/base/animation/animation.h"
22 #include "ui/gfx/canvas.h"
23 #include "ui/gfx/compositor/compositor_switches.h"
24 #include "ui/gfx/compositor/layer_animator.h"
25 #include "ui/gfx/interpolated_transform.h"
26 #include "ui/gfx/point3.h"
27
28 namespace {
29
30 const float EPSILON = 1e-3f;
31
32 bool IsApproximateMultipleOf(float value, float base) {
33 float remainder = fmod(fabs(value), base);
34 return remainder < EPSILON || base - remainder < EPSILON;
35 }
36
37 const ui::Layer* GetRoot(const ui::Layer* layer) {
38 return layer->parent() ? GetRoot(layer->parent()) : layer;
39 }
40
41 } // namespace
42
43 namespace ui {
44
45 Layer::Layer()
46 : type_(LAYER_TEXTURED),
47 compositor_(NULL),
48 parent_(NULL),
49 visible_(true),
50 fills_bounds_opaquely_(true),
51 layer_updated_externally_(false),
52 opacity_(1.0f),
53 delegate_(NULL) {
54 CreateWebLayer();
55 }
56
57 Layer::Layer(LayerType type)
58 : type_(type),
59 compositor_(NULL),
60 parent_(NULL),
61 visible_(true),
62 fills_bounds_opaquely_(true),
63 layer_updated_externally_(false),
64 opacity_(1.0f),
65 delegate_(NULL) {
66 CreateWebLayer();
67 }
68
69 Layer::~Layer() {
70 // Destroying the animator may cause observers to use the layer (and
71 // indirectly the WebLayer). Destroy the animator first so that the WebLayer
72 // is still around.
73 animator_.reset();
74 if (compositor_)
75 compositor_->SetRootLayer(NULL);
76 if (parent_)
77 parent_->Remove(this);
78 for (size_t i = 0; i < children_.size(); ++i)
79 children_[i]->parent_ = NULL;
80 web_layer_.removeFromParent();
81 }
82
83 Compositor* Layer::GetCompositor() {
84 return GetRoot(this)->compositor_;
85 }
86
87 void Layer::SetCompositor(Compositor* compositor) {
88 // This function must only be called to set the compositor on the root layer,
89 // or to reset it.
90 DCHECK(!compositor || !compositor_);
91 DCHECK(!compositor || compositor->root_layer() == this);
92 DCHECK(!parent_);
93 compositor_ = compositor;
94 }
95
96 void Layer::Add(Layer* child) {
97 DCHECK(!child->compositor_);
98 if (child->parent_)
99 child->parent_->Remove(child);
100 child->parent_ = this;
101 children_.push_back(child);
102 web_layer_.addChild(child->web_layer_);
103 }
104
105 void Layer::Remove(Layer* child) {
106 std::vector<Layer*>::iterator i =
107 std::find(children_.begin(), children_.end(), child);
108 DCHECK(i != children_.end());
109 children_.erase(i);
110 child->parent_ = NULL;
111 child->web_layer_.removeFromParent();
112 }
113
114 void Layer::StackAtTop(Layer* child) {
115 if (children_.size() <= 1 || child == children_.back())
116 return; // Already in front.
117 StackAbove(child, children_.back());
118 }
119
120 void Layer::StackAbove(Layer* child, Layer* other) {
121 StackRelativeTo(child, other, true);
122 }
123
124 void Layer::StackAtBottom(Layer* child) {
125 if (children_.size() <= 1 || child == children_.front())
126 return; // Already on bottom.
127 StackBelow(child, children_.front());
128 }
129
130 void Layer::StackBelow(Layer* child, Layer* other) {
131 StackRelativeTo(child, other, false);
132 }
133
134 bool Layer::Contains(const Layer* other) const {
135 for (const Layer* parent = other; parent; parent = parent->parent()) {
136 if (parent == this)
137 return true;
138 }
139 return false;
140 }
141
142 void Layer::SetAnimator(LayerAnimator* animator) {
143 if (animator)
144 animator->SetDelegate(this);
145 animator_.reset(animator);
146 }
147
148 LayerAnimator* Layer::GetAnimator() {
149 if (!animator_.get())
150 SetAnimator(LayerAnimator::CreateDefaultAnimator());
151 return animator_.get();
152 }
153
154 void Layer::SetTransform(const ui::Transform& transform) {
155 GetAnimator()->SetTransform(transform);
156 }
157
158 Transform Layer::GetTargetTransform() const {
159 if (animator_.get() && animator_->IsAnimatingProperty(
160 LayerAnimationElement::TRANSFORM))
161 return animator_->GetTargetTransform();
162 return transform_;
163 }
164
165 void Layer::SetBounds(const gfx::Rect& bounds) {
166 GetAnimator()->SetBounds(bounds);
167 }
168
169 gfx::Rect Layer::GetTargetBounds() const {
170 if (animator_.get() && animator_->IsAnimatingProperty(
171 LayerAnimationElement::BOUNDS))
172 return animator_->GetTargetBounds();
173 return bounds_;
174 }
175
176 void Layer::SetMasksToBounds(bool masks_to_bounds) {
177 web_layer_.setMasksToBounds(masks_to_bounds);
178 }
179
180 bool Layer::GetMasksToBounds() const {
181 return web_layer_.masksToBounds();
182 }
183
184 void Layer::SetOpacity(float opacity) {
185 GetAnimator()->SetOpacity(opacity);
186 }
187
188 void Layer::SetBackgroundBlur(int blur_radius)
189 {
190 WebKit::WebFilterOperations filters;
191 if (blur_radius)
192 filters.append(WebKit::WebBlurFilterOperation(blur_radius));
193 web_layer_.setBackgroundFilters(filters);
194
195 background_blur_radius_ = blur_radius;
196 }
197
198 float Layer::GetTargetOpacity() const {
199 if (animator_.get() && animator_->IsAnimatingProperty(
200 LayerAnimationElement::OPACITY))
201 return animator_->GetTargetOpacity();
202 return opacity_;
203 }
204
205 void Layer::SetVisible(bool visible) {
206 GetAnimator()->SetVisibility(visible);
207 }
208
209 bool Layer::GetTargetVisibility() const {
210 if (animator_.get() && animator_->IsAnimatingProperty(
211 LayerAnimationElement::VISIBILITY))
212 return animator_->GetTargetVisibility();
213 return visible_;
214 }
215
216 bool Layer::IsDrawn() const {
217 const Layer* layer = this;
218 while (layer && layer->visible_)
219 layer = layer->parent_;
220 return layer == NULL;
221 }
222
223 bool Layer::ShouldDraw() const {
224 return type_ != LAYER_NOT_DRAWN && GetCombinedOpacity() > 0.0f;
225 }
226
227 // static
228 void Layer::ConvertPointToLayer(const Layer* source,
229 const Layer* target,
230 gfx::Point* point) {
231 if (source == target)
232 return;
233
234 const Layer* root_layer = GetRoot(source);
235 CHECK_EQ(root_layer, GetRoot(target));
236
237 if (source != root_layer)
238 source->ConvertPointForAncestor(root_layer, point);
239 if (target != root_layer)
240 target->ConvertPointFromAncestor(root_layer, point);
241 }
242
243 void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) {
244 if (fills_bounds_opaquely_ == fills_bounds_opaquely)
245 return;
246
247 fills_bounds_opaquely_ = fills_bounds_opaquely;
248
249 web_layer_.setOpaque(fills_bounds_opaquely);
250 RecomputeDebugBorderColor();
251 }
252
253 void Layer::SetExternalTexture(Texture* texture) {
254 DCHECK_EQ(type_, LAYER_TEXTURED);
255 layer_updated_externally_ = !!texture;
256 texture_ = texture;
257 if (web_layer_is_accelerated_ != layer_updated_externally_) {
258 // Switch to a different type of layer.
259 web_layer_.removeAllChildren();
260 WebKit::WebLayer new_layer;
261 if (layer_updated_externally_) {
262 WebKit::WebExternalTextureLayer texture_layer =
263 WebKit::WebExternalTextureLayer::create();
264 texture_layer.setFlipped(texture_->flipped());
265 new_layer = texture_layer;
266 } else {
267 new_layer = WebKit::WebContentLayer::create(this);
268 }
269 if (parent_) {
270 DCHECK(!parent_->web_layer_.isNull());
271 parent_->web_layer_.replaceChild(web_layer_, new_layer);
272 }
273 web_layer_ = new_layer;
274 web_layer_is_accelerated_ = layer_updated_externally_;
275 for (size_t i = 0; i < children_.size(); ++i) {
276 DCHECK(!children_[i]->web_layer_.isNull());
277 web_layer_.addChild(children_[i]->web_layer_);
278 }
279 web_layer_.setAnchorPoint(WebKit::WebFloatPoint(0.f, 0.f));
280 web_layer_.setOpaque(fills_bounds_opaquely_);
281 web_layer_.setOpacity(visible_ ? opacity_ : 0.f);
282 web_layer_.setDebugBorderWidth(show_debug_borders_ ? 2 : 0);
283 RecomputeTransform();
284 RecomputeDebugBorderColor();
285 }
286 RecomputeDrawsContentAndUVRect();
287 }
288
289 void Layer::SetColor(SkColor color) {
290 DCHECK_EQ(type_, LAYER_SOLID_COLOR);
291 // WebColor is equivalent to SkColor, per WebColor.h.
292 web_layer_.to<WebKit::WebSolidColorLayer>().setBackgroundColor(
293 static_cast<WebKit::WebColor>(color));
294 SetFillsBoundsOpaquely(SkColorGetA(color) == 0xFF);
295 }
296
297 bool Layer::SchedulePaint(const gfx::Rect& invalid_rect) {
298 if (type_ == LAYER_SOLID_COLOR || !delegate_)
299 return false;
300 damaged_region_.op(invalid_rect.x(),
301 invalid_rect.y(),
302 invalid_rect.right(),
303 invalid_rect.bottom(),
304 SkRegion::kUnion_Op);
305 ScheduleDraw();
306 return true;
307 }
308
309 void Layer::ScheduleDraw() {
310 Compositor* compositor = GetCompositor();
311 if (compositor)
312 compositor->ScheduleDraw();
313 }
314
315 void Layer::SendDamagedRects() {
316 if (delegate_ && !damaged_region_.isEmpty()) {
317 for (SkRegion::Iterator iter(damaged_region_);
318 !iter.done(); iter.next()) {
319 const SkIRect& damaged = iter.rect();
320 WebKit::WebFloatRect web_rect(
321 damaged.x(),
322 damaged.y(),
323 damaged.width(),
324 damaged.height());
325 if (!web_layer_is_accelerated_)
326 web_layer_.to<WebKit::WebContentLayer>().invalidateRect(web_rect);
327 else
328 web_layer_.to<WebKit::WebExternalTextureLayer>().invalidateRect(
329 web_rect);
330 }
331 damaged_region_.setEmpty();
332 }
333 for (size_t i = 0; i < children_.size(); ++i)
334 children_[i]->SendDamagedRects();
335 }
336
337 void Layer::SuppressPaint() {
338 if (!delegate_)
339 return;
340 delegate_ = NULL;
341 for (size_t i = 0; i < children_.size(); ++i)
342 children_[i]->SuppressPaint();
343 }
344
345 void Layer::paintContents(WebKit::WebCanvas* web_canvas,
346 const WebKit::WebRect& clip) {
347 TRACE_EVENT0("ui", "Layer::paintContents");
348 gfx::Canvas canvas(web_canvas);
349 if (delegate_)
350 delegate_->OnPaintLayer(&canvas);
351 }
352
353 float Layer::GetCombinedOpacity() const {
354 float opacity = opacity_;
355 Layer* current = this->parent_;
356 while (current) {
357 opacity *= current->opacity_;
358 current = current->parent_;
359 }
360 return opacity;
361 }
362
363 void Layer::StackRelativeTo(Layer* child, Layer* other, bool above) {
364 DCHECK_NE(child, other);
365 DCHECK_EQ(this, child->parent());
366 DCHECK_EQ(this, other->parent());
367
368 const size_t child_i =
369 std::find(children_.begin(), children_.end(), child) - children_.begin();
370 const size_t other_i =
371 std::find(children_.begin(), children_.end(), other) - children_.begin();
372 if ((above && child_i == other_i + 1) || (!above && child_i + 1 == other_i))
373 return;
374
375 const size_t dest_i =
376 above ?
377 (child_i < other_i ? other_i : other_i + 1) :
378 (child_i < other_i ? other_i - 1 : other_i);
379 children_.erase(children_.begin() + child_i);
380 children_.insert(children_.begin() + dest_i, child);
381
382 child->web_layer_.removeFromParent();
383 web_layer_.insertChild(child->web_layer_, dest_i);
384 }
385
386 bool Layer::ConvertPointForAncestor(const Layer* ancestor,
387 gfx::Point* point) const {
388 ui::Transform transform;
389 bool result = GetTransformRelativeTo(ancestor, &transform);
390 gfx::Point3f p(*point);
391 transform.TransformPoint(p);
392 *point = p.AsPoint();
393 return result;
394 }
395
396 bool Layer::ConvertPointFromAncestor(const Layer* ancestor,
397 gfx::Point* point) const {
398 ui::Transform transform;
399 bool result = GetTransformRelativeTo(ancestor, &transform);
400 gfx::Point3f p(*point);
401 transform.TransformPointReverse(p);
402 *point = p.AsPoint();
403 return result;
404 }
405
406 bool Layer::GetTransformRelativeTo(const Layer* ancestor,
407 ui::Transform* transform) const {
408 const Layer* p = this;
409 for (; p && p != ancestor; p = p->parent()) {
410 if (p->transform().HasChange())
411 transform->ConcatTransform(p->transform());
412 transform->ConcatTranslate(static_cast<float>(p->bounds().x()),
413 static_cast<float>(p->bounds().y()));
414 }
415 return p == ancestor;
416 }
417
418 void Layer::SetBoundsImmediately(const gfx::Rect& bounds) {
419 if (bounds == bounds_)
420 return;
421
422 bool was_move = bounds_.size() == bounds.size();
423 bounds_ = bounds;
424 if (IsDrawn()) {
425 if (was_move)
426 ScheduleDraw();
427 else
428 SchedulePaint(gfx::Rect(bounds.size()));
429 }
430
431 RecomputeTransform();
432 RecomputeDrawsContentAndUVRect();
433 }
434
435 void Layer::SetTransformImmediately(const ui::Transform& transform) {
436 transform_ = transform;
437
438 RecomputeTransform();
439 }
440
441 void Layer::SetOpacityImmediately(float opacity) {
442 bool schedule_draw = (opacity != opacity_ && IsDrawn());
443 opacity_ = opacity;
444
445 if (visible_)
446 web_layer_.setOpacity(opacity);
447 RecomputeDebugBorderColor();
448 if (schedule_draw)
449 ScheduleDraw();
450 }
451
452 void Layer::SetVisibilityImmediately(bool visible) {
453 if (visible_ == visible)
454 return;
455
456 visible_ = visible;
457 // TODO(piman): Expose a visibility flag on WebLayer.
458 web_layer_.setOpacity(visible_ ? opacity_ : 0.f);
459 }
460
461 void Layer::SetBoundsFromAnimation(const gfx::Rect& bounds) {
462 SetBoundsImmediately(bounds);
463 }
464
465 void Layer::SetTransformFromAnimation(const Transform& transform) {
466 SetTransformImmediately(transform);
467 }
468
469 void Layer::SetOpacityFromAnimation(float opacity) {
470 SetOpacityImmediately(opacity);
471 }
472
473 void Layer::SetVisibilityFromAnimation(bool visibility) {
474 SetVisibilityImmediately(visibility);
475 }
476
477 void Layer::ScheduleDrawForAnimation() {
478 ScheduleDraw();
479 }
480
481 const gfx::Rect& Layer::GetBoundsForAnimation() const {
482 return bounds();
483 }
484
485 const Transform& Layer::GetTransformForAnimation() const {
486 return transform();
487 }
488
489 float Layer::GetOpacityForAnimation() const {
490 return opacity();
491 }
492
493 bool Layer::GetVisibilityForAnimation() const {
494 return visible();
495 }
496
497 void Layer::CreateWebLayer() {
498 if (type_ == LAYER_SOLID_COLOR)
499 web_layer_ = WebKit::WebSolidColorLayer::create();
500 else
501 web_layer_ = WebKit::WebContentLayer::create(this);
502 web_layer_.setAnchorPoint(WebKit::WebFloatPoint(0.f, 0.f));
503 web_layer_.setOpaque(true);
504 web_layer_is_accelerated_ = false;
505 show_debug_borders_ = CommandLine::ForCurrentProcess()->HasSwitch(
506 switches::kUIShowLayerBorders);
507 web_layer_.setDebugBorderWidth(show_debug_borders_ ? 2 : 0);
508 RecomputeDrawsContentAndUVRect();
509 RecomputeDebugBorderColor();
510 }
511
512 void Layer::RecomputeTransform() {
513 ui::Transform transform = transform_;
514 transform.ConcatTranslate(bounds_.x(), bounds_.y());
515 web_layer_.setTransform(transform.matrix());
516 }
517
518 void Layer::RecomputeDrawsContentAndUVRect() {
519 DCHECK(!web_layer_.isNull());
520 bool should_draw = type_ != LAYER_NOT_DRAWN;
521 if (!web_layer_is_accelerated_) {
522 if (type_ != LAYER_SOLID_COLOR)
523 web_layer_.to<WebKit::WebContentLayer>().setDrawsContent(should_draw);
524 web_layer_.setBounds(bounds_.size());
525 } else {
526 DCHECK(texture_);
527 unsigned int texture_id = texture_->texture_id();
528 WebKit::WebExternalTextureLayer texture_layer =
529 web_layer_.to<WebKit::WebExternalTextureLayer>();
530 texture_layer.setTextureId(should_draw ? texture_id : 0);
531 gfx::Size texture_size = texture_->size();
532 gfx::Size size(std::min(bounds_.width(), texture_size.width()),
533 std::min(bounds_.height(), texture_size.height()));
534 WebKit::WebFloatRect rect(
535 0,
536 0,
537 static_cast<float>(size.width())/texture_size.width(),
538 static_cast<float>(size.height())/texture_size.height());
539 texture_layer.setUVRect(rect);
540 web_layer_.setBounds(size);
541 }
542 }
543
544 void Layer::RecomputeDebugBorderColor() {
545 if (!show_debug_borders_)
546 return;
547 unsigned int color = 0xFF000000;
548 color |= web_layer_is_accelerated_ ? 0x0000FF00 : 0x00FF0000;
549 bool opaque = fills_bounds_opaquely_ && (GetCombinedOpacity() == 1.f);
550 if (!opaque)
551 color |= 0xFF;
552 web_layer_.setDebugBorderColor(color);
553 }
554
555 } // namespace ui
OLDNEW
« no previous file with comments | « ui/gfx/compositor/layer.h ('k') | ui/gfx/compositor/layer_animation_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698