summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-15 02:18:36 +0000
committersadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-15 02:18:36 +0000
commitc797cd43680b525ea771dc226ca353078c5c56f1 (patch)
treea172b53773aec97a6c3dd9c4fcf93acc27d0cca2
parent8df9747bff840d1a63b9fe1309b18e5fb21e8340 (diff)
downloadchromium_src-c797cd43680b525ea771dc226ca353078c5c56f1.zip
chromium_src-c797cd43680b525ea771dc226ca353078c5c56f1.tar.gz
chromium_src-c797cd43680b525ea771dc226ca353078c5c56f1.tar.bz2
Start working on compositor tree painting.
As a first step, maintain a skia canvas in each transformed view. Each transformed view will acquire a texture-id for the canvas it owns. Whenever the canvas is updated, it will trigger a refresh in the compositor tree. BUG=none TEST=none Review URL: http://codereview.chromium.org/6594125 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@78149 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ui/gfx/canvas.h5
-rw-r--r--ui/gfx/canvas_direct2d.cc5
-rw-r--r--ui/gfx/canvas_direct2d.h1
-rw-r--r--ui/gfx/canvas_skia.h1
-rw-r--r--ui/gfx/canvas_skia_linux.cc5
-rw-r--r--ui/gfx/canvas_skia_mac.mm5
-rw-r--r--ui/gfx/canvas_skia_win.cc5
-rw-r--r--ui/gfx/compositor.cc14
-rw-r--r--ui/gfx/compositor.h53
-rw-r--r--ui/gfx/compositor_gl.cc80
-rw-r--r--ui/gfx/gfx.gyp15
-rw-r--r--ui/gfx/native_widget_types.h12
-rw-r--r--views/view.cc109
-rw-r--r--views/view.h23
-rw-r--r--views/widget/native_widget.h4
-rw-r--r--views/widget/native_widget_delegate.h5
-rw-r--r--views/widget/root_view.h1
-rw-r--r--views/widget/widget.cc31
-rw-r--r--views/widget/widget.h15
-rw-r--r--views/widget/widget_gtk.cc7
-rw-r--r--views/widget/widget_gtk.h6
-rw-r--r--views/widget/widget_win.cc7
-rw-r--r--views/widget/widget_win.h3
23 files changed, 381 insertions, 31 deletions
diff --git a/ui/gfx/canvas.h b/ui/gfx/canvas.h
index 0149486..e4ce7ad 100644
--- a/ui/gfx/canvas.h
+++ b/ui/gfx/canvas.h
@@ -15,6 +15,8 @@
namespace ui {
class Transform;
+
+typedef unsigned int TextureID;
}
namespace gfx {
@@ -215,6 +217,9 @@ class Canvas {
// Apply transformation on the canvas.
virtual void Transform(const ui::Transform& transform) = 0;
+ // Create a texture ID that can be used for accelerated drawing.
+ virtual ui::TextureID GetTextureID() = 0;
+
// TODO(beng): remove this once we don't need to use any skia-specific methods
// through this interface.
// A quick and dirty way to obtain the underlying SkCanvas.
diff --git a/ui/gfx/canvas_direct2d.cc b/ui/gfx/canvas_direct2d.cc
index 63e9bb9..38ed18aa 100644
--- a/ui/gfx/canvas_direct2d.cc
+++ b/ui/gfx/canvas_direct2d.cc
@@ -345,6 +345,11 @@ void CanvasDirect2D::Transform(const ui::Transform& transform) {
NOTIMPLEMENTED();
}
+ui::TextureID CanvasDirect2D::GetTextureID() {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
CanvasSkia* CanvasDirect2D::AsCanvasSkia() {
return NULL;
}
diff --git a/ui/gfx/canvas_direct2d.h b/ui/gfx/canvas_direct2d.h
index 45452f5..88ab8bf 100644
--- a/ui/gfx/canvas_direct2d.h
+++ b/ui/gfx/canvas_direct2d.h
@@ -78,6 +78,7 @@ class CanvasDirect2D : public Canvas {
virtual gfx::NativeDrawingContext BeginPlatformPaint();
virtual void EndPlatformPaint();
virtual void Transform(const ui::Transform& transform);
+ virtual ui::TextureID GetTextureID();
virtual CanvasSkia* AsCanvasSkia();
virtual const CanvasSkia* AsCanvasSkia() const;
diff --git a/ui/gfx/canvas_skia.h b/ui/gfx/canvas_skia.h
index 854ce84..9516e8a3 100644
--- a/ui/gfx/canvas_skia.h
+++ b/ui/gfx/canvas_skia.h
@@ -140,6 +140,7 @@ class CanvasSkia : public skia::PlatformCanvas,
virtual gfx::NativeDrawingContext BeginPlatformPaint();
virtual void EndPlatformPaint();
virtual void Transform(const ui::Transform& transform);
+ virtual ui::TextureID GetTextureID();
virtual CanvasSkia* AsCanvasSkia();
virtual const CanvasSkia* AsCanvasSkia() const;
diff --git a/ui/gfx/canvas_skia_linux.cc b/ui/gfx/canvas_skia_linux.cc
index d418626..fa9d1a4 100644
--- a/ui/gfx/canvas_skia_linux.cc
+++ b/ui/gfx/canvas_skia_linux.cc
@@ -384,4 +384,9 @@ void CanvasSkia::DrawGdkPixbuf(GdkPixbuf* pixbuf, int x, int y) {
cairo_paint(cr);
}
+ui::TextureID CanvasSkia::GetTextureID() {
+ // TODO(wjmaclean)
+ return 0;
+}
+
} // namespace gfx
diff --git a/ui/gfx/canvas_skia_mac.mm b/ui/gfx/canvas_skia_mac.mm
index c6fb031..aacf100 100644
--- a/ui/gfx/canvas_skia_mac.mm
+++ b/ui/gfx/canvas_skia_mac.mm
@@ -86,4 +86,9 @@ void CanvasSkia::DrawStringInt(const string16& text,
endPlatformPaint();
}
+ui::TextureID CanvasSkia::GetTextureID() {
+ // TODO(wjmaclean)
+ return 0;
+}
+
} // namespace gfx
diff --git a/ui/gfx/canvas_skia_win.cc b/ui/gfx/canvas_skia_win.cc
index 1e108b3..b343234 100644
--- a/ui/gfx/canvas_skia_win.cc
+++ b/ui/gfx/canvas_skia_win.cc
@@ -298,4 +298,9 @@ void CanvasSkia::DrawStringWithHalo(const string16& text,
DrawBitmapInt(text_bitmap, x - 1, y - 1);
}
+ui::TextureID CanvasSkia::GetTextureID() {
+ // TODO(wjmaclean)
+ return 0;
+}
+
} // namespace gfx
diff --git a/ui/gfx/compositor.cc b/ui/gfx/compositor.cc
new file mode 100644
index 0000000..f9c6487
--- /dev/null
+++ b/ui/gfx/compositor.cc
@@ -0,0 +1,14 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/compositor.h"
+
+namespace ui {
+
+// static
+Compositor* Compositor::Create(gfx::AcceleratedWidget widget) {
+ return NULL;
+}
+
+} // namespace ui
diff --git a/ui/gfx/compositor.h b/ui/gfx/compositor.h
new file mode 100644
index 0000000..2c33942
--- /dev/null
+++ b/ui/gfx/compositor.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_COMPOSITOR_H_
+#define UI_GFX_COMPOSITOR_H_
+#pragma once
+
+#include "base/ref_counted.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace ui {
+class Transform;
+
+typedef unsigned int TextureID;
+
+// 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. The initial implementation uses GL for this purpose.
+// Future CLs will adapt this to ongoing Skia development.
+class Compositor : public base::RefCounted<Compositor> {
+ public:
+ // Create a compositor from the provided handle.
+ static Compositor* Create(gfx::AcceleratedWidget widget);
+
+ // Notifies the compositor that compositing is about to start.
+ virtual void NotifyStart() = 0;
+
+ // Notifies the compositor that compositing is complete.
+ virtual void NotifyEnd() = 0;
+
+ // Draws the given texture with the given transform.
+ virtual void DrawTextureWithTransform(TextureID txt,
+ const ui::Transform& transform) = 0;
+
+ // Save the current transformation that can be restored with RestoreTransform.
+ virtual void SaveTransform() = 0;
+
+ // Restore a previously saved transformation using SaveTransform.
+ virtual void RestoreTransform() = 0;
+
+ protected:
+ virtual ~Compositor() {}
+
+ private:
+ friend class base::RefCounted<Compositor>;
+};
+
+} // namespace ui
+
+#endif // UI_GFX_COMPOSITOR_H_
diff --git a/ui/gfx/compositor_gl.cc b/ui/gfx/compositor_gl.cc
new file mode 100644
index 0000000..39a57a1
--- /dev/null
+++ b/ui/gfx/compositor_gl.cc
@@ -0,0 +1,80 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/compositor.h"
+
+#include <GL/gl.h>
+
+#include "app/gfx/gl/gl_context.h"
+#include "app/gfx/gl/gl_implementation.h"
+#include "base/scoped_ptr.h"
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "ui/gfx/transform.h"
+
+namespace ui {
+
+class CompositorGL : public Compositor {
+ public:
+ CompositorGL(gfx::AcceleratedWidget widget);
+
+ private:
+ // Overridden from Compositor.
+ void NotifyStart() OVERRIDE;
+ void NotifyEnd() OVERRIDE;
+ void DrawTextureWithTransform(TextureID txt,
+ const ui::Transform& transform) OVERRIDE;
+ void SaveTransform() OVERRIDE;
+ void RestoreTransform() 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) {
+}
+
+void CompositorGL::NotifyStart() {
+ started_ = true;
+ gl_context_->MakeCurrent();
+}
+
+void CompositorGL::NotifyEnd() {
+ DCHECK(started_);
+ gl_context_->SwapBuffers();
+ started_ = false;
+}
+
+void CompositorGL::DrawTextureWithTransform(TextureID txt,
+ const ui::Transform& transform) {
+ DCHECK(started_);
+
+ // TODO(wjmaclean):
+ NOTIMPLEMENTED();
+}
+
+void CompositorGL::SaveTransform() {
+ glPushMatrix();
+}
+
+void CompositorGL::RestoreTransform() {
+ glPopMatrix();
+}
+
+// static
+Compositor* Compositor::Create(gfx::AcceleratedWidget widget) {
+ if (gfx::GetGLImplementation() != gfx::kGLImplementationNone)
+ return new CompositorGL(widget);
+ return NULL;
+}
+
+} // namespace ui
diff --git a/ui/gfx/gfx.gyp b/ui/gfx/gfx.gyp
index c6906ac..b8e0cad 100644
--- a/ui/gfx/gfx.gyp
+++ b/ui/gfx/gfx.gyp
@@ -106,6 +106,9 @@
'codec/png_codec.h',
'color_utils.cc',
'color_utils.h',
+ 'compositor.cc',
+ 'compositor_gl.cc',
+ 'compositor.h',
'favicon_size.h',
'font.h',
'font.cc',
@@ -175,6 +178,14 @@
'../../build/linux/system.gyp:fontconfig',
'../../build/linux/system.gyp:gtk',
],
+ 'link_settings': {
+ 'libraries': [
+ '-lGL',
+ ],
+ },
+ 'sources!': [
+ 'compositor.cc',
+ ],
'sources': [
'gtk_native_view_id_manager.cc',
'gtk_native_view_id_manager.h',
@@ -186,6 +197,10 @@
'native_theme_linux.h',
'native_widget_types_gtk.cc',
],
+ }, {
+ 'sources!': [
+ 'compositor_gl.cc',
+ ]
}],
],
},
diff --git a/ui/gfx/native_widget_types.h b/ui/gfx/native_widget_types.h
index bc60777..ba530d9 100644
--- a/ui/gfx/native_widget_types.h
+++ b/ui/gfx/native_widget_types.h
@@ -171,6 +171,18 @@ NativeViewId IdFromNativeView(NativeView view);
const PluginWindowHandle kNullPluginWindow = 0;
#endif
+// AcceleratedWidget provides a surface to compositors to paint pixels.
+#if defined(OS_WIN)
+typedef HWND AcceleratedWidget;
+const AcceleratedWidget kNullAcceleratedWidget = NULL;
+#elif defined(USE_X11)
+typedef unsigned long AcceleratedWidget;
+const AcceleratedWidget kNullAcceleratedWidget = 0;
+#else
+typedef void* AcceleratedWidget;
+const AcceleratedWidget kNullAcceleratedWidget = NULL;
+#endif
+
} // namespace gfx
#endif // UI_GFX_NATIVE_WIDGET_TYPES_H_
diff --git a/views/view.cc b/views/view.cc
index 0547efb7..f048892 100644
--- a/views/view.cc
+++ b/views/view.cc
@@ -14,6 +14,7 @@
#include "ui/base/accessibility/accessibility_types.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/compositor.h"
#include "ui/gfx/path.h"
#include "ui/gfx/transform.h"
#include "views/background.h"
@@ -33,6 +34,12 @@
#include "ui/base/gtk/scoped_handle_gtk.h"
#endif
+namespace {
+// Whether to use accelerated compositing when necessary (e.g. when a view has a
+// transformation).
+bool use_acceleration_when_possible = true;
+}
+
namespace views {
// static
@@ -75,6 +82,7 @@ View::View()
clip_y_(0.0),
needs_layout_(true),
flip_canvas_on_paint_for_rtl_ui_(false),
+ texture_id_(0), // TODO(sadrul): 0 can be a valid texture id.
accelerator_registration_delayed_(false),
accelerator_focus_manager_(NULL),
registered_accelerator_count_(0),
@@ -423,6 +431,7 @@ void View::ConcatTranslate(float x, float y) {
void View::ResetTransform() {
transform_.reset(NULL);
clip_x_ = clip_y_ = 0.0;
+ canvas_.reset();
}
@@ -636,46 +645,63 @@ void View::Paint(gfx::Canvas* canvas) {
if (!IsVisible())
return;
- // We're going to modify the canvas, save its state first.
- canvas->Save();
+ 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));
- // Paint this View and its children, setting the clip rect to the bounds
- // of this View and translating the origin to the local bounds' top left
- // point.
- //
- // Note that the X (or left) position we pass to ClipRectInt takes into
- // 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_))) {
+ canvas = canvas_.get();
+ } else {
+ // We're going to modify the canvas, save its state first.
+ canvas->Save();
+
+ // Paint this View and its children, setting the clip rect to the bounds
+ // of this View and translating the origin to the local bounds' top left
+ // point.
+ //
+ // Note that the X (or left) position we pass to ClipRectInt takes into
+ // 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_))) {
+ canvas->Restore();
+ return;
+ }
// Non-empty clip, translate the graphics such that 0,0 corresponds to
// where this view is located (related to its parent).
canvas->TranslateInt(GetMirroredX(), y());
if (transform_.get() && transform_->HasChange())
canvas->Transform(*transform_.get());
+ }
- // If the View we are about to paint requested the canvas to be flipped, we
- // should change the transform appropriately.
- canvas->Save();
- if (FlipCanvasOnPaintForRTLUI()) {
- canvas->TranslateInt(width(), 0);
- canvas->ScaleInt(-1, 1);
- }
+ // If the View we are about to paint requested the canvas to be flipped, we
+ // should change the transform appropriately.
+ canvas->Save();
+ if (FlipCanvasOnPaintForRTLUI()) {
+ canvas->TranslateInt(width(), 0);
+ canvas->ScaleInt(-1, 1);
+ }
- OnPaint(canvas);
+ OnPaint(canvas);
- // We must undo the canvas mirroring once the View is done painting so that
- // we don't pass the canvas with the mirrored transform to Views that
- // didn't request the canvas to be flipped.
- canvas->Restore();
+ // We must undo the canvas mirroring once the View is done painting so that
+ // we don't pass the canvas with the mirrored transform to Views that
+ // didn't request the canvas to be flipped.
+ canvas->Restore();
- PaintChildren(canvas);
- }
+ PaintChildren(canvas);
- // Restore the canvas's original transform.
- canvas->Restore();
+ if (canvas == canvas_.get()) {
+ texture_id_ = canvas->GetTextureID();
+
+ // TODO(sadrul): Make sure the Widget's compositor tree updates itself?
+ } else {
+ // Restore the canvas's original transform.
+ canvas->Restore();
+ }
}
void View::PaintNow() {
@@ -693,6 +719,13 @@ ThemeProvider* View::GetThemeProvider() const {
return widget ? widget->GetThemeProvider() : NULL;
}
+// Accelerated Painting --------------------------------------------------------
+
+// static
+void View::set_use_acceleration_when_possible(bool use) {
+ use_acceleration_when_possible = use;
+}
+
// Input -----------------------------------------------------------------------
View* View::GetEventHandlerForPoint(const gfx::Point& point) {
@@ -1069,6 +1102,23 @@ void View::OnPaintFocusBorder(gfx::Canvas* canvas) {
canvas->DrawFocusRect(0, 0, width(), height());
}
+// Accelerated Painting --------------------------------------------------------
+
+void View::PaintComposite(ui::Compositor* compositor) {
+ compositor->SaveTransform();
+
+ // TODO(sad): Push a transform matrix for the offset and bounds of the view?
+ if (texture_id_)
+ compositor->DrawTextureWithTransform(texture_id_, GetTransform());
+
+ for (int i = 0, count = child_count(); i < count; ++i) {
+ View* child = GetChildViewAt(i);
+ child->PaintComposite(compositor);
+ }
+
+ compositor->RestoreTransform();
+}
+
// Input -----------------------------------------------------------------------
bool View::HasHitTestMask() const {
@@ -1274,6 +1324,9 @@ void View::VisibilityChangedImpl(View* starting_from, bool is_visible) {
}
void View::BoundsChanged(const gfx::Rect& previous_bounds) {
+ if (canvas_.get())
+ canvas_.reset(gfx::Canvas::CreateCanvas(width(), height(), false));
+
if (parent_) {
parent_->SchedulePaintInRect(previous_bounds);
parent_->SchedulePaintInRect(bounds_);
diff --git a/views/view.h b/views/view.h
index 8117ab2..e09f0bee 100644
--- a/views/view.h
+++ b/views/view.h
@@ -34,8 +34,11 @@ class Path;
namespace ui {
struct AccessibleViewState;
+class Compositor;
class ThemeProvider;
class Transform;
+
+typedef unsigned int TextureID;
}
using ui::ThemeProvider;
@@ -562,6 +565,11 @@ class View : public AcceleratorTarget {
flip_canvas_on_paint_for_rtl_ui_ = enable;
}
+ // Accelerated painting ------------------------------------------------------
+
+ // Enable/Disable accelerated compositing.
+ static void set_use_acceleration_when_possible(bool use);
+
// Input ---------------------------------------------------------------------
// The points (and mouse locations) in the following functions are in the
// view's coordinates, except for a RootView.
@@ -1016,6 +1024,11 @@ class View : public AcceleratorTarget {
// relevant contents.
virtual void OnPaintFocusBorder(gfx::Canvas* canvas);
+ // Accelerated painting ------------------------------------------------------
+
+ // Performs accelerated painting using the compositor.
+ virtual void PaintComposite(ui::Compositor* compositor);
+
// Input ---------------------------------------------------------------------
// Called by HitTest to see if this View has a custom hit test mask. If the
@@ -1333,6 +1346,16 @@ class View : public AcceleratorTarget {
// right-to-left locales for this View.
bool flip_canvas_on_paint_for_rtl_ui_;
+ // Accelerated painting ------------------------------------------------------
+
+ // Each transformed view will maintain its own canvas.
+ scoped_ptr<gfx::Canvas> canvas_;
+
+ // Texture ID used for accelerated painting.
+ // TODO(sadrul): This will eventually be replaced by an abstract texture
+ // object.
+ ui::TextureID texture_id_;
+
// Accelerators --------------------------------------------------------------
// true if when we were added to hierarchy we were without focus manager
diff --git a/views/widget/native_widget.h b/views/widget/native_widget.h
index 26dbd9b..a833664 100644
--- a/views/widget/native_widget.h
+++ b/views/widget/native_widget.h
@@ -72,6 +72,10 @@ class NativeWidget {
protected:
friend class Widget;
+ // Returns a handle for the underlying native widget that can be used for
+ // accelerated drawing.
+ virtual gfx::AcceleratedWidget GetAcceleratedWidget() = 0;
+
// Widget pass-thrus, private to Views. --------------------------------------
// See method documentation in Widget.
virtual gfx::Rect GetWindowScreenBounds() const = 0;
diff --git a/views/widget/native_widget_delegate.h b/views/widget/native_widget_delegate.h
index e14e32b..b21cd10 100644
--- a/views/widget/native_widget_delegate.h
+++ b/views/widget/native_widget_delegate.h
@@ -7,6 +7,7 @@
#pragma once
namespace gfx {
+class Canvas;
class Size;
}
@@ -35,6 +36,10 @@ class NativeWidgetDelegate {
// Returns true if the delegate has a FocusManager.
virtual bool HasFocusManager() const = 0;
+
+ // Paints the rootview in the canvas. This will also refresh the compositor
+ // tree if necessary when accelerated painting is enabled.
+ virtual void OnPaint(gfx::Canvas* canvas) = 0;
};
} // namespace internal
diff --git a/views/widget/root_view.h b/views/widget/root_view.h
index 3eac199..6658fe0 100644
--- a/views/widget/root_view.h
+++ b/views/widget/root_view.h
@@ -124,6 +124,7 @@ class RootView : public View,
private:
friend class View;
+ friend class Widget;
#if defined(TOUCH_UI)
// Required so the GestureManager can call the Process* entry points
diff --git a/views/widget/widget.cc b/views/widget/widget.cc
index 4a58b32..88c7bf3 100644
--- a/views/widget/widget.cc
+++ b/views/widget/widget.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "base/message_loop.h"
+#include "ui/gfx/compositor.h"
#include "views/focus/view_storage.h"
#include "views/widget/default_theme_provider.h"
#include "views/widget/root_view.h"
@@ -264,6 +265,11 @@ bool Widget::HasFocusManager() const {
return !!focus_manager_.get();
}
+void Widget::OnPaint(gfx::Canvas* canvas) {
+ GetRootView()->Paint(canvas);
+ RefreshCompositeTree();
+}
+
////////////////////////////////////////////////////////////////////////////////
// Widget, FocusTraversable implementation:
@@ -311,4 +317,29 @@ void Widget::ReplaceFocusManager(FocusManager* focus_manager) {
focus_manager_.reset(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;
+
+ // 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;
+}
+
} // namespace views
diff --git a/views/widget/widget.h b/views/widget/widget.h
index 684cade..21f4f48 100644
--- a/views/widget/widget.h
+++ b/views/widget/widget.h
@@ -8,6 +8,7 @@
#include <vector>
+#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
#include "ui/base/accessibility/accessibility_types.h"
#include "ui/gfx/native_widget_types.h"
@@ -15,6 +16,7 @@
#include "views/widget/native_widget_delegate.h"
namespace gfx {
+class Canvas;
class Path;
class Point;
class Rect;
@@ -22,6 +24,7 @@ class Rect;
namespace ui {
class Accelerator;
+class Compositor;
class OSExchangeData;
class ThemeProvider;
}
@@ -272,6 +275,7 @@ class Widget : public internal::NativeWidgetDelegate,
virtual void OnNativeWidgetCreated() OVERRIDE;
virtual void OnSizeChanged(const gfx::Size& new_size) OVERRIDE;
virtual bool HasFocusManager() const OVERRIDE;
+ virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
// Overridden from FocusTraversable:
virtual FocusSearch* GetFocusSearch() OVERRIDE;
@@ -299,6 +303,14 @@ class Widget : public internal::NativeWidgetDelegate,
void ReplaceFocusManager(FocusManager* focus_manager);
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();
+
NativeWidget* native_widget_;
// Non-owned pointer to the Widget's delegate. May be NULL if no delegate is
@@ -323,6 +335,9 @@ class Widget : public internal::NativeWidgetDelegate,
// started from.
View* dragged_view_;
+ // The compositor for accelerated drawing.
+ scoped_refptr<ui::Compositor> compositor_;
+
DISALLOW_COPY_AND_ASSIGN(Widget);
};
diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc
index 3ebd950..0a89fee 100644
--- a/views/widget/widget_gtk.cc
+++ b/views/widget/widget_gtk.cc
@@ -955,7 +955,7 @@ gboolean WidgetGtk::OnPaint(GtkWidget* widget, GdkEventExpose* event) {
gfx::CanvasSkiaPaint canvas(event);
if (!canvas.is_empty()) {
canvas.set_composite_alpha(is_transparent());
- GetRootView()->Paint(&canvas);
+ delegate_->OnPaint(&canvas);
}
return false; // False indicates other widgets should get the event as well.
}
@@ -1270,6 +1270,11 @@ RootView* WidgetGtk::CreateRootView() {
return new RootView(this);
}
+gfx::AcceleratedWidget WidgetGtk::GetAcceleratedWidget() {
+ DCHECK(window_contents_ && window_contents_->window);
+ return GDK_WINDOW_XID(window_contents_->window);
+}
+
gboolean WidgetGtk::OnWindowPaint(GtkWidget* widget, GdkEventExpose* event) {
// Clear the background to be totally transparent. We don't need to
// paint the root view here as that is done by OnPaint.
diff --git a/views/widget/widget_gtk.h b/views/widget/widget_gtk.h
index 142f2cd..370e9cf 100644
--- a/views/widget/widget_gtk.h
+++ b/views/widget/widget_gtk.h
@@ -287,7 +287,11 @@ class WidgetGtk : public Widget,
class DropObserver;
friend class DropObserver;
- virtual RootView* CreateRootView();
+ // Overridden from Widget
+ virtual RootView* CreateRootView() OVERRIDE;
+
+ // Overridden from NativeWidget
+ virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE;
CHROMEGTK_CALLBACK_1(WidgetGtk, gboolean, OnWindowPaint, GdkEventExpose*);
diff --git a/views/widget/widget_win.cc b/views/widget/widget_win.cc
index 657ece9..823f7d4 100644
--- a/views/widget/widget_win.cc
+++ b/views/widget/widget_win.cc
@@ -820,7 +820,7 @@ LRESULT WidgetWin::OnNotify(int w_param, NMHDR* l_param) {
void WidgetWin::OnPaint(HDC dc) {
scoped_ptr<gfx::CanvasPaint> canvas(
gfx::CanvasPaint::CreateCanvasPaint(hwnd()));
- GetRootView()->Paint(canvas->AsCanvas());
+ delegate_->OnPaint(canvas->AsCanvas());
}
LRESULT WidgetWin::OnPowerBroadcast(DWORD power_event, DWORD data) {
@@ -1123,6 +1123,11 @@ void WidgetWin::ClientAreaSizeChanged() {
}
}
+gfx::AcceleratedWidget WidgetWin::GetAcceleratedWidget() {
+ NOTIMPLEMENTED();
+ return gfx::kNullAcceleratedWidget;
+}
+
////////////////////////////////////////////////////////////////////////////////
// Widget, public:
diff --git a/views/widget/widget_win.h b/views/widget/widget_win.h
index ba78268..9779bd8 100644
--- a/views/widget/widget_win.h
+++ b/views/widget/widget_win.h
@@ -456,6 +456,9 @@ class WidgetWin : public ui::WindowImpl,
// or subsequently.
void ClientAreaSizeChanged();
+ // Overridden from NativeWidget.
+ virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE;
+
// A delegate implementation that handles events received here.
internal::NativeWidgetDelegate* delegate_;