summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-10 18:26:25 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-10 18:26:25 +0000
commitc36b0bfba80a88ce3776739575a1103235c409d1 (patch)
treed37790e560bff4136f3c723c95c645abec7caf76
parent5b37cb72a5bfbcc1daa57249319a8235d0d4874a (diff)
downloadchromium_src-c36b0bfba80a88ce3776739575a1103235c409d1.zip
chromium_src-c36b0bfba80a88ce3776739575a1103235c409d1.tar.gz
chromium_src-c36b0bfba80a88ce3776739575a1103235c409d1.tar.bz2
Tweaks Compositor API. To make it possible to land this I've ifdef'd
the code in a couple of places. BUG=none TEST=none R=ben@chromium.org,wjmaclean@chromium.org,rjkroege@chromium.org Review URL: http://codereview.chromium.org/6999005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@84823 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/chrome_dll.gypi1
-rw-r--r--ui/gfx/compositor/compositor.gyp22
-rw-r--r--ui/gfx/compositor/compositor.h57
-rw-r--r--ui/gfx/compositor/compositor_gl.cc53
-rw-r--r--views/view.cc131
-rw-r--r--views/view.h44
-rw-r--r--views/views.gyp1
-rw-r--r--views/widget/native_widget_delegate.h5
-rw-r--r--views/widget/root_view.cc12
-rw-r--r--views/widget/root_view.h3
-rw-r--r--views/widget/widget.cc40
-rw-r--r--views/widget/widget.h14
-rw-r--r--views/widget/widget_gtk.cc21
-rw-r--r--views/widget/widget_win.cc18
14 files changed, 381 insertions, 41 deletions
diff --git a/chrome/chrome_dll.gypi b/chrome/chrome_dll.gypi
index 8381331..930acae 100644
--- a/chrome/chrome_dll.gypi
+++ b/chrome/chrome_dll.gypi
@@ -119,6 +119,7 @@
'<(SHARED_INTERMEDIATE_DIR)/chrome/theme_resources.rc',
'<(SHARED_INTERMEDIATE_DIR)/chrome/theme_resources_standard.rc',
'<(SHARED_INTERMEDIATE_DIR)/net/net_resources.rc',
+ '<(SHARED_INTERMEDIATE_DIR)/ui/gfx/gfx_resources.rc',
'<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_chromium_resources.rc',
'<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_resources.rc',
diff --git a/ui/gfx/compositor/compositor.gyp b/ui/gfx/compositor/compositor.gyp
index f739b93..98adcf8 100644
--- a/ui/gfx/compositor/compositor.gyp
+++ b/ui/gfx/compositor/compositor.gyp
@@ -3,6 +3,19 @@
# found in the LICENSE file.
{
+ 'target_defaults': {
+ 'sources/': [
+ ['exclude', '_(gl|win)\\.(cc?)$'],
+ ],
+ 'conditions': [
+ ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {'sources/': [
+ ['include', '_(gl)\\.cc$'],
+ ]}],
+ ['OS=="win"', {'sources/': [
+ ['include', '_(win)\\.cc$'],
+ ]}],
+ ],
+ },
'targets': [
{
'target_name': 'compositor',
@@ -10,25 +23,22 @@
'msvs_guid': '21CEE0E3-6F4E-4F01-B8C9-F7751CC21AA9',
'dependencies': [
'<(DEPTH)/base/base.gyp:base',
+ '<(DEPTH)/skia/skia.gyp:skia',
'<(DEPTH)/ui/gfx/gl/gl.gyp:gl',
'<(DEPTH)/ui/ui.gyp:ui_gfx',
],
'sources': [
'compositor.cc',
- 'compositor_gl.cc',
'compositor.h',
+ 'compositor_gl.cc',
],
'conditions': [
['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
'sources!': [
'compositor.cc',
],
- }, {
- 'sources!': [
- 'compositor_gl.cc',
- ]
}],
],
},
],
-} \ No newline at end of file
+}
diff --git a/ui/gfx/compositor/compositor.h b/ui/gfx/compositor/compositor.h
index 7d19598..9b35eb1 100644
--- a/ui/gfx/compositor/compositor.h
+++ b/ui/gfx/compositor/compositor.h
@@ -9,9 +9,16 @@
#include "base/memory/ref_counted.h"
#include "ui/gfx/native_widget_types.h"
+class SkBitmap;
+namespace gfx {
+class Point;
+class Size;
+}
+
namespace ui {
class Transform;
+#if !defined(COMPOSITOR_2)
typedef unsigned int TextureID;
// Compositor object to take care of GPU painting.
@@ -48,6 +55,56 @@ class Compositor : public base::RefCounted<Compositor> {
friend class base::RefCounted<Compositor>;
};
+#else
+// Textures are created by a Compositor for managing an accelerated view.
+// Any time a View with a texture needs to redraw itself it invokes SetBitmap().
+// When the view is ready to be drawn Draw() is invoked.
+//
+// Texture is really a proxy to the gpu. Texture does not itself keep a copy of
+// the bitmap.
+//
+// Views own the Texture.
+class Texture {
+ public:
+ virtual ~Texture() {}
+
+ // Sets the bitmap of this texture. The bitmaps origin is at |origin|.
+ // |overall_size| gives the total size of texture.
+ virtual void SetBitmap(const SkBitmap& bitmap,
+ const gfx::Point& origin,
+ const gfx::Size& overall_size) = 0;
+
+ // Draws the texture.
+ virtual void Draw(const ui::Transform& transform) = 0;
+};
+
+// Compositor object to take care of GPU painting.
+// A Browser compositor object is responsible for generating the final
+// displayable form of pixels comprising a single widget's contents. It draws an
+// appropriately transformed texture for each transformed view in the widget's
+// view hierarchy.
+class Compositor : public base::RefCounted<Compositor> {
+ public:
+ // Create a compositor from the provided handle.
+ static Compositor* Create(gfx::AcceleratedWidget widget);
+
+ // Creates a new texture. The caller owns the returned object.
+ virtual Texture* CreateTexture() = 0;
+
+ // Notifies the compositor that compositing is about to start.
+ virtual void NotifyStart() = 0;
+
+ // Notifies the compositor that compositing is complete.
+ virtual void NotifyEnd() = 0;
+
+ protected:
+ virtual ~Compositor() {}
+
+ private:
+ friend class base::RefCounted<Compositor>;
+};
+
+#endif // COMPOSITOR_2
} // namespace ui
#endif // UI_GFX_COMPOSITOR_COMPOSITOR_H_
diff --git a/ui/gfx/compositor/compositor_gl.cc b/ui/gfx/compositor/compositor_gl.cc
index f152ffc..4beb65c 100644
--- a/ui/gfx/compositor/compositor_gl.cc
+++ b/ui/gfx/compositor/compositor_gl.cc
@@ -15,6 +15,57 @@
namespace ui {
+#if defined COMPOSITOR_2
+namespace {
+
+class CompositorGL : public Compositor {
+ public:
+ explicit CompositorGL(gfx::AcceleratedWidget widget);
+
+ private:
+ // Overridden from Compositor.
+ virtual Texture* CreateTexture() OVERRIDE;
+ virtual void NotifyStart() OVERRIDE;
+ virtual void NotifyEnd() OVERRIDE;
+
+ // The GL context used for compositing.
+ scoped_ptr<gfx::GLContext> gl_context_;
+
+ // Keep track of whether compositing has started or not.
+ bool started_;
+
+ DISALLOW_COPY_AND_ASSIGN(CompositorGL);
+};
+
+CompositorGL::CompositorGL(gfx::AcceleratedWidget widget)
+ : gl_context_(gfx::GLContext::CreateViewGLContext(widget, false)),
+ started_(false) {
+}
+
+Texture* CompositorGL::CreateTexture() {
+ return NULL;
+}
+
+void CompositorGL::NotifyStart() {
+ started_ = true;
+ gl_context_->MakeCurrent();
+}
+
+void CompositorGL::NotifyEnd() {
+ DCHECK(started_);
+ gl_context_->SwapBuffers();
+ started_ = false;
+}
+
+} // namespace
+
+// static
+Compositor* Compositor::Create(gfx::AcceleratedWidget widget) {
+ if (gfx::GetGLImplementation() != gfx::kGLImplementationNone)
+ return new CompositorGL(widget);
+ return NULL;
+}
+#else
class CompositorGL : public Compositor {
public:
explicit CompositorGL(gfx::AcceleratedWidget widget);
@@ -77,5 +128,5 @@ Compositor* Compositor::Create(gfx::AcceleratedWidget widget) {
return new CompositorGL(widget);
return NULL;
}
-
+#endif
} // namespace ui
diff --git a/views/view.cc b/views/view.cc
index 12fbf45..52234d7 100644
--- a/views/view.cc
+++ b/views/view.cc
@@ -107,7 +107,10 @@ View::View()
clip_y_(0.0),
needs_layout_(true),
flip_canvas_on_paint_for_rtl_ui_(false),
+#if !defined(COMPOSITOR_2)
texture_id_(0), // TODO(sadrul): 0 can be a valid texture id.
+#endif
+ texture_needs_updating_(true),
accelerator_registration_delayed_(false),
accelerator_focus_manager_(NULL),
registered_accelerator_count_(0),
@@ -363,6 +366,8 @@ void View::SetVisible(bool flag) {
// refresh parent
if (IsVisible())
SchedulePaint();
+ else
+ ResetTexture();
is_visible_ = flag;
@@ -456,7 +461,11 @@ void View::ConcatTranslate(float x, float y) {
void View::ResetTransform() {
transform_.reset(NULL);
clip_x_ = clip_y_ = 0.0;
+#if !defined(COMPOSITOR_2)
canvas_.reset();
+#else
+ texture_.reset();
+#endif
}
@@ -671,13 +680,43 @@ void View::Paint(gfx::Canvas* canvas) {
return;
ScopedCanvas scoped_canvas(NULL);
+ scoped_ptr<gfx::Canvas> texture_canvas;
+ gfx::Rect texture_rect;
+
+#if !defined(COMPOSITOR_2)
if (use_acceleration_when_possible &&
transform_.get() && transform_->HasChange()) {
// This view has a transformation. So this maintains its own canvas.
if (!canvas_.get())
canvas_.reset(gfx::Canvas::CreateCanvas(width(), height(), false));
+#else
+ if (ShouldPaintToTexture()) {
+ gfx::Rect dirty_rect;
+ if (!texture_clip_rect_.IsEmpty()) {
+ dirty_rect = texture_clip_rect_;
+ } else {
+ // TODO: clip against dirty rect of canvas (if canvas is non-null).
+ dirty_rect = gfx::Rect(0, 0, width(), height());
+ }
+ if (dirty_rect.IsEmpty())
+ return;
+
+ if (!texture_.get())
+ texture_.reset(GetCompositor()->CreateTexture());
+
+ if (!texture_needs_updating_) {
+ // We don't need to be painted. Iterate over descendants in case one of
+ // them is dirty.
+ PaintToTexture(dirty_rect);
+ return;
+ }
- canvas = canvas_.get();
+ texture_canvas.reset(gfx::Canvas::CreateCanvas(dirty_rect.width(),
+ dirty_rect.height(), false));
+ texture_canvas->TranslateInt(-dirty_rect.x(), -dirty_rect.y());
+ canvas = texture_canvas.get();
+ // TODO: set texture_needs_updating_ to false.
+#endif
} else {
// We're going to modify the canvas, save its state first.
scoped_canvas.SetCanvas(canvas);
@@ -690,8 +729,8 @@ void View::Paint(gfx::Canvas* canvas) {
// consideration whether or not the view uses a right-to-left layout so that
// we paint our view in its mirrored position if need be.
if (!canvas->ClipRectInt(GetMirroredX(), y(),
- width() - static_cast<int>(clip_x_),
- height() - static_cast<int>(clip_y_))) {
+ width() - static_cast<int>(clip_x_),
+ height() - static_cast<int>(clip_y_))) {
return;
}
// Non-empty clip, translate the graphics such that 0,0 corresponds to
@@ -720,11 +759,20 @@ void View::Paint(gfx::Canvas* canvas) {
PaintChildren(canvas);
+#if !defined(COMPOSITOR_2)
if (canvas == canvas_.get()) {
texture_id_ = canvas->GetTextureID();
// TODO(sadrul): Make sure the Widget's compositor tree updates itself?
}
+#else
+ if (texture_canvas.get()) {
+ texture_->SetBitmap(
+ texture_canvas->AsCanvasSkia()->getDevice()->accessBitmap(false),
+ texture_rect.origin(),
+ size());
+ }
+#endif
}
ThemeProvider* View::GetThemeProvider() const {
@@ -1133,6 +1181,7 @@ void View::OnPaintFocusBorder(gfx::Canvas* canvas) {
// Accelerated Painting --------------------------------------------------------
+#if !defined(COMPOSITOR_2)
void View::PaintComposite(ui::Compositor* compositor) {
compositor->SaveTransform();
@@ -1147,6 +1196,56 @@ void View::PaintComposite(ui::Compositor* compositor) {
compositor->RestoreTransform();
}
+#else
+void View::PaintComposite() {
+ if (!IsVisible())
+ return;
+
+ if (texture_.get()) {
+ // TODO: if dirty_region doesn't itersect bounds, return.
+ scoped_ptr<ui::Transform> transform(ui::Transform::Create());
+ GetTransformRelativeToRoot(transform.get());
+ texture_->Draw(*transform);
+ }
+
+ for (int i = 0, count = child_count(); i < count; ++i)
+ GetChildViewAt(i)->PaintComposite();
+}
+
+void View::PaintToTexture(const gfx::Rect& dirty_region) {
+ if (!IsVisible())
+ return;
+
+ if (ShouldPaintToTexture() && texture_needs_updating_) {
+ texture_clip_rect_ = dirty_region;
+ Paint(NULL);
+ texture_clip_rect_.SetRect(0, 0, 0, 0);
+ } else {
+ // Forward to all children as a descendant may be dirty and have a texture.
+ for (int i = child_count() - 1; i >= 0; --i) {
+ View* child_view = GetChildViewAt(i);
+ gfx::Rect child_dirty_rect(child_view->bounds().Intersect(dirty_region));
+ if (!child_dirty_rect.IsEmpty()) {
+ child_dirty_rect.Offset(-child_view->x(), -child_view->y());
+ GetChildViewAt(i)->PaintToTexture(child_dirty_rect);
+ }
+ }
+ }
+}
+#endif
+
+bool View::ShouldPaintToTexture() const {
+ return use_acceleration_when_possible && transform_.get() &&
+ transform_->HasChange() && GetCompositor();
+}
+
+const ui::Compositor* View::GetCompositor() const {
+ return parent_ ? parent_->GetCompositor() : NULL;
+}
+
+ui::Compositor* View::GetCompositor() {
+ return parent_ ? parent_->GetCompositor() : NULL;
+}
// Input -----------------------------------------------------------------------
@@ -1266,6 +1365,7 @@ void View::DoRemoveChildView(View* view,
if (GetWidget())
UnregisterChildrenForVisibleBoundsNotification(view);
+ view->ResetTexture();
view->PropagateRemoveNotifications(this);
view->SetParent(NULL);
@@ -1353,8 +1453,10 @@ void View::VisibilityChangedImpl(View* starting_from, bool is_visible) {
}
void View::BoundsChanged(const gfx::Rect& previous_bounds) {
+#if !defined(COMPOSITOR_2)
if (canvas_.get())
canvas_.reset(gfx::Canvas::CreateCanvas(width(), height(), false));
+#endif
if (IsVisible()) {
if (parent_) {
@@ -1461,6 +1563,19 @@ void View::InitTransform() {
transform_.reset(ui::Transform::Create());
}
+void View::GetTransformRelativeToRoot(ui::Transform* transform) {
+ // TODO: the direction of transformation is likely wrong here.
+ if (parent_) {
+ parent_->GetTransformRelativeToRoot(transform);
+ } else if (transform_.get()) {
+ transform->Copy(*transform_);
+ }
+ transform->ConcatTranslate(static_cast<float>(GetMirroredX()),
+ static_cast<float>(y()));
+ if (transform_.get())
+ transform->ConcatTransform(*transform_);
+}
+
// Coordinate conversion -------------------------------------------------------
// static
@@ -1535,6 +1650,16 @@ bool View::ConvertPointFromAncestor(const View* ancestor,
return v == ancestor;
}
+// Accelerated painting --------------------------------------------------------
+
+void View::ResetTexture() {
+#if defined(COMPOSITOR_2)
+ texture_.reset();
+ for (int i = child_count() - 1; i >= 0; --i)
+ GetChildViewAt(i)->ResetTexture();
+#endif
+}
+
// Input -----------------------------------------------------------------------
bool View::ProcessMousePressed(const MouseEvent& event, DragInfo* drag_info) {
diff --git a/views/view.h b/views/view.h
index a2a6156..98337a5 100644
--- a/views/view.h
+++ b/views/view.h
@@ -25,7 +25,6 @@
using ui::OSExchangeData;
-
namespace gfx {
class Canvas;
class Insets;
@@ -35,6 +34,7 @@ class Path;
namespace ui {
struct AccessibleViewState;
class Compositor;
+class Texture;
class ThemeProvider;
class Transform;
@@ -1040,8 +1040,29 @@ class View : public AcceleratorTarget {
// Accelerated painting ------------------------------------------------------
+#if !defined(COMPOSITOR_2)
// Performs accelerated painting using the compositor.
virtual void PaintComposite(ui::Compositor* compositor);
+#else
+ // If our texture is out of date invokes Paint() with a canvas that is then
+ // copied to the texture. If the texture is not out of date recursively
+ // descends in case any children needed their textures updated.
+ //
+ // This is invoked internally by Widget and painting code.
+ void PaintToTexture(const gfx::Rect& dirty_rect);
+
+ // Instructs the compositor to show our texture and all children textures.
+ //
+ // This is invoked internally by Widget and painting code.
+ void PaintComposite();
+#endif
+
+ // Returns true if this view should paint using a texture.
+ virtual bool ShouldPaintToTexture() const;
+
+ // Returns the Compositor.
+ virtual const ui::Compositor* GetCompositor() const;
+ virtual ui::Compositor* GetCompositor();
// Input ---------------------------------------------------------------------
@@ -1216,6 +1237,10 @@ class View : public AcceleratorTarget {
// Initialize the transform matrix when necessary.
void InitTransform();
+ // Returns in |transform| the transform to get from root view coordinates to
+ // this views coordinates.
+ void GetTransformRelativeToRoot(ui::Transform* transform);
+
// Coordinate conversion -----------------------------------------------------
// This is the actual implementation for ConvertPointToView()
@@ -1238,6 +1263,11 @@ class View : public AcceleratorTarget {
// coordinate system.
bool ConvertPointFromAncestor(const View* ancestor, gfx::Point* point) const;
+ // Accelerated painting ------------------------------------------------------
+
+ // Releases the texture of this and recurses through all children.
+ void ResetTexture();
+
// Input ---------------------------------------------------------------------
// RootView invokes these. These in turn invoke the appropriate OnMouseXXX
@@ -1372,6 +1402,7 @@ class View : public AcceleratorTarget {
// Accelerated painting ------------------------------------------------------
+#if !defined(COMPOSITOR_2)
// Each transformed view will maintain its own canvas.
scoped_ptr<gfx::Canvas> canvas_;
@@ -1379,6 +1410,17 @@ class View : public AcceleratorTarget {
// TODO(sadrul): This will eventually be replaced by an abstract texture
// object.
ui::TextureID texture_id_;
+#else
+ scoped_ptr<ui::Texture> texture_;
+
+ // If not empty and Paint() is invoked, the canvas is created with the
+ // specified size.
+ // TODO(sky): this should be passed in.
+ gfx::Rect texture_clip_rect_;
+#endif
+
+ // Is the texture out of date?
+ bool texture_needs_updating_;
// Accelerators --------------------------------------------------------------
diff --git a/views/views.gyp b/views/views.gyp
index 6489d87..3c4bf77 100644
--- a/views/views.gyp
+++ b/views/views.gyp
@@ -603,6 +603,7 @@
'test/test_views_delegate.cc',
'test/test_views_delegate.h',
'<(SHARED_INTERMEDIATE_DIR)/app/app_resources/app_resources.rc',
+ '<(SHARED_INTERMEDIATE_DIR)/ui/gfx/gfx_resources.rc',
],
'conditions': [
['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
diff --git a/views/widget/native_widget_delegate.h b/views/widget/native_widget_delegate.h
index 0ac5e09..036bb48 100644
--- a/views/widget/native_widget_delegate.h
+++ b/views/widget/native_widget_delegate.h
@@ -37,6 +37,11 @@ class NativeWidgetDelegate {
// Returns true if the delegate has a FocusManager.
virtual bool HasFocusManager() const = 0;
+ // Paints the widget using acceleration. If the widget is not using
+ // accelerated painting this returns false and does nothing.
+ virtual bool OnNativeWidgetPaintAccelerated(
+ const gfx::Rect& dirty_region) = 0;
+
// Paints the rootview in the canvas. This will also refresh the compositor
// tree if necessary when accelerated painting is enabled.
virtual void OnNativeWidgetPaint(gfx::Canvas* canvas) = 0;
diff --git a/views/widget/root_view.cc b/views/widget/root_view.cc
index bea5b58..6942d3d 100644
--- a/views/widget/root_view.cc
+++ b/views/widget/root_view.cc
@@ -451,6 +451,18 @@ void RootView::OnPaint(gfx::Canvas* canvas) {
canvas->AsCanvasSkia()->drawColor(SK_ColorBLACK, SkXfermode::kClear_Mode);
}
+bool RootView::ShouldPaintToTexture() const {
+ return widget_->compositor() != NULL;
+}
+
+const ui::Compositor* RootView::GetCompositor() const {
+ return widget_->compositor();
+}
+
+ui::Compositor* RootView::GetCompositor() {
+ return widget_->compositor();
+}
+
////////////////////////////////////////////////////////////////////////////////
// RootView, private:
diff --git a/views/widget/root_view.h b/views/widget/root_view.h
index 12212e0..fc8b632 100644
--- a/views/widget/root_view.h
+++ b/views/widget/root_view.h
@@ -128,6 +128,9 @@ class RootView : public View,
virtual void ViewHierarchyChanged(bool is_add, View* parent,
View* child) OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
+ virtual bool ShouldPaintToTexture() const OVERRIDE;
+ virtual const ui::Compositor* GetCompositor() const OVERRIDE;
+ virtual ui::Compositor* GetCompositor() OVERRIDE;
private:
friend class View;
diff --git a/views/widget/widget.cc b/views/widget/widget.cc
index 71cd85f..a7c03d9 100644
--- a/views/widget/widget.cc
+++ b/views/widget/widget.cc
@@ -314,6 +314,7 @@ void Widget::OnNativeWidgetCreated() {
// manager.
focus_manager_.reset(new FocusManager(this));
}
+ EnsureCompositor();
}
void Widget::OnSizeChanged(const gfx::Size& new_size) {
@@ -324,9 +325,30 @@ bool Widget::HasFocusManager() const {
return !!focus_manager_.get();
}
+bool Widget::OnNativeWidgetPaintAccelerated(const gfx::Rect& dirty_region) {
+#if !defined(COMPOSITOR_2)
+ return false;
+#else
+ if (!compositor_.get())
+ return false;
+
+ compositor_->NotifyStart();
+ GetRootView()->PaintToTexture(dirty_region);
+ GetRootView()->PaintComposite();
+ compositor_->NotifyEnd();
+ return true;
+#endif
+}
+
void Widget::OnNativeWidgetPaint(gfx::Canvas* canvas) {
GetRootView()->Paint(canvas);
- RefreshCompositeTree();
+#if !defined(COMPOSITOR_2)
+ if (compositor_.get()) {
+ compositor_->NotifyStart();
+ root_view_->PaintComposite(compositor_.get());
+ compositor_->NotifyEnd();
+ }
+#endif
}
bool Widget::OnKeyEvent(const KeyEvent& event) {
@@ -435,26 +457,14 @@ void Widget::ReplaceFocusManager(FocusManager* focus_manager) {
////////////////////////////////////////////////////////////////////////////////
// Widget, private:
-void Widget::RefreshCompositeTree() {
- if (!EnsureCompositor())
- return;
-
- compositor_->NotifyStart();
- root_view_->PaintComposite(compositor_.get());
- compositor_->NotifyEnd();
-}
-
-bool Widget::EnsureCompositor() {
- if (compositor_.get())
- return true;
+void Widget::EnsureCompositor() {
+ DCHECK(!compositor_.get());
// TODO(sad): If there is a parent Widget, then use the same compositor
// instead of creating a new one here.
gfx::AcceleratedWidget widget = native_widget_->GetAcceleratedWidget();
if (widget != gfx::kNullAcceleratedWidget)
compositor_ = ui::Compositor::Create(widget);
-
- return compositor_.get() != NULL;
}
bool Widget::ShouldReleaseCaptureOnMouseReleased() const {
diff --git a/views/widget/widget.h b/views/widget/widget.h
index ae77851..110ee20 100644
--- a/views/widget/widget.h
+++ b/views/widget/widget.h
@@ -271,6 +271,9 @@ class Widget : public internal::NativeWidgetDelegate,
void SetFocusTraversableParent(FocusTraversable* parent);
void SetFocusTraversableParentView(View* parent_view);
+ const ui::Compositor* compositor() const { return compositor_.get(); }
+ ui::Compositor* compositor() { return compositor_.get(); }
+
// Notifies assistive technology that an accessibility event has
// occurred on |view|, such as when the view is focused or when its
// value changes. Pass true for |send_native_event| except for rare
@@ -290,6 +293,8 @@ class Widget : public internal::NativeWidgetDelegate,
virtual void OnNativeWidgetCreated() OVERRIDE;
virtual void OnSizeChanged(const gfx::Size& new_size) OVERRIDE;
virtual bool HasFocusManager() const OVERRIDE;
+ virtual bool OnNativeWidgetPaintAccelerated(
+ const gfx::Rect& dirty_region) OVERRIDE;
virtual void OnNativeWidgetPaint(gfx::Canvas* canvas) OVERRIDE;
virtual bool OnKeyEvent(const KeyEvent& event) OVERRIDE;
virtual bool OnMouseEvent(const MouseEvent& event) OVERRIDE;
@@ -332,13 +337,8 @@ class Widget : public internal::NativeWidgetDelegate,
gfx::Point last_mouse_event_position_;
private:
- // Refresh the compositor tree. This is called by a View whenever its texture
- // is updated.
- void RefreshCompositeTree();
-
- // Try to create a compositor if one hasn't been created yet. Returns false if
- // a compositor couldn't be created.
- bool EnsureCompositor();
+ // Try to create a compositor if one hasn't been created yet.
+ void EnsureCompositor();
// Returns whether capture should be released on mouse release.
virtual bool ShouldReleaseCaptureOnMouseReleased() const;
diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc
index 6f63876..b506dac 100644
--- a/views/widget/widget_gtk.cc
+++ b/views/widget/widget_gtk.cc
@@ -21,6 +21,7 @@
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/dragdrop/os_exchange_data_provider_gtk.h"
#include "ui/base/gtk/gtk_windowing.h"
+#include "ui/base/gtk/scoped_handle_gtk.h"
#include "ui/base/x/x11_util.h"
#include "ui/gfx/canvas_skia_paint.h"
#include "ui/gfx/path.h"
@@ -1061,10 +1062,17 @@ gboolean WidgetGtk::OnPaint(GtkWidget* widget, GdkEventExpose* event) {
XSync(ui::GetXDisplay(), false /* don't discard events */);
}
- gfx::CanvasSkiaPaint canvas(event);
- if (!canvas.is_empty()) {
- canvas.set_composite_alpha(is_transparent());
- delegate_->OnNativeWidgetPaint(&canvas);
+ ui::ScopedRegion region(gdk_region_copy(event->region));
+ if (!gdk_region_empty(region.Get())) {
+ GdkRectangle clip_bounds;
+ gdk_region_get_clipbox(region.Get(), &clip_bounds);
+ if (!delegate_->OnNativeWidgetPaintAccelerated(gfx::Rect(clip_bounds))) {
+ gfx::CanvasSkiaPaint canvas(event);
+ if (!canvas.is_empty()) {
+ canvas.set_composite_alpha(is_transparent());
+ delegate_->OnNativeWidgetPaint(&canvas);
+ }
+ }
}
if (!painted_) {
@@ -1559,6 +1567,11 @@ void WidgetGtk::CreateGtkWidget(const InitParams& params) {
if (ignore_events_)
ConfigureWidgetForIgnoreEvents();
+ // Realize the window_contents_ so that we can always get a handle for
+ // acceleration. Without this we need to check every time paint is
+ // invoked.
+ gtk_widget_realize(window_contents_);
+
SetAlwaysOnTop(always_on_top_);
// UpdateFreezeUpdatesProperty will realize the widget and handlers like
// size-allocate will function properly.
diff --git a/views/widget/widget_win.cc b/views/widget/widget_win.cc
index 4fb0802..a5d2044 100644
--- a/views/widget/widget_win.cc
+++ b/views/widget/widget_win.cc
@@ -845,9 +845,19 @@ LRESULT WidgetWin::OnNotify(int w_param, NMHDR* l_param) {
}
void WidgetWin::OnPaint(HDC dc) {
- scoped_ptr<gfx::CanvasPaint> canvas(
- gfx::CanvasPaint::CreateCanvasPaint(hwnd()));
- delegate_->OnNativeWidgetPaint(canvas->AsCanvas());
+ RECT dirty_rect;
+ // Try to paint accelerated first.
+ if (GetUpdateRect(hwnd(), &dirty_rect, FALSE) &&
+ !IsRectEmpty(&dirty_rect)) {
+ if (delegate_->OnNativeWidgetPaintAccelerated(
+ gfx::Rect(dirty_rect))) {
+ ValidateRect(hwnd(), NULL);
+ } else {
+ scoped_ptr<gfx::CanvasPaint> canvas(
+ gfx::CanvasPaint::CreateCanvasPaint(hwnd()));
+ delegate_->OnNativeWidgetPaint(canvas->AsCanvas());
+ }
+ }
}
LRESULT WidgetWin::OnPowerBroadcast(DWORD power_event, DWORD data) {
@@ -1111,7 +1121,7 @@ void WidgetWin::ClientAreaSizeChanged() {
}
gfx::AcceleratedWidget WidgetWin::GetAcceleratedWidget() {
- // TODO(beng):
+ // TODO(sky):
return gfx::kNullAcceleratedWidget;
}