ozone: gbm: Update hardware cursor in GPU process
[chromium-blink-merge.git] / ui / ozone / platform / dri / dri_surface_factory.cc
blobdb5be89d429d1dc9817acd4906a28bdf5dbe3f46
1 // Copyright 2014 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 "ui/ozone/platform/dri/dri_surface_factory.h"
7 #include <errno.h>
9 #include "base/debug/trace_event.h"
10 #include "base/message_loop/message_loop.h"
11 #include "third_party/skia/include/core/SkBitmap.h"
12 #include "third_party/skia/include/core/SkDevice.h"
13 #include "third_party/skia/include/core/SkSurface.h"
14 #include "ui/gfx/native_widget_types.h"
15 #include "ui/ozone/platform/dri/dri_surface.h"
16 #include "ui/ozone/platform/dri/dri_util.h"
17 #include "ui/ozone/platform/dri/dri_vsync_provider.h"
18 #include "ui/ozone/platform/dri/dri_wrapper.h"
19 #include "ui/ozone/platform/dri/hardware_display_controller.h"
20 #include "ui/ozone/platform/dri/screen_manager.h"
21 #include "ui/ozone/public/surface_ozone_canvas.h"
23 namespace ui {
25 namespace {
27 // TODO(dnicoara) Read the cursor plane size from the hardware.
28 const gfx::Size kCursorSize(64, 64);
30 void UpdateCursorImage(DriSurface* cursor, const SkBitmap& image) {
31 SkRect damage;
32 image.getBounds(&damage);
34 // Clear to transparent in case |image| is smaller than the canvas.
35 SkCanvas* canvas = cursor->GetDrawableForWidget();
36 canvas->clear(SK_ColorTRANSPARENT);
38 SkRect clip;
39 clip.set(
40 0, 0, canvas->getDeviceSize().width(), canvas->getDeviceSize().height());
41 canvas->clipRect(clip, SkRegion::kReplace_Op);
42 canvas->drawBitmapRectToRect(image, &damage, damage);
45 class DriSurfaceAdapter : public ui::SurfaceOzoneCanvas {
46 public:
47 DriSurfaceAdapter(const base::WeakPtr<HardwareDisplayController>& controller);
48 virtual ~DriSurfaceAdapter();
50 // SurfaceOzoneCanvas:
51 virtual skia::RefPtr<SkCanvas> GetCanvas() OVERRIDE;
52 virtual void ResizeCanvas(const gfx::Size& viewport_size) OVERRIDE;
53 virtual void PresentCanvas(const gfx::Rect& damage) OVERRIDE;
54 virtual scoped_ptr<gfx::VSyncProvider> CreateVSyncProvider() OVERRIDE;
56 private:
57 void UpdateNativeSurface(const gfx::Rect& damage);
59 skia::RefPtr<SkSurface> surface_;
60 gfx::Rect last_damage_;
61 base::WeakPtr<HardwareDisplayController> controller_;
63 DISALLOW_COPY_AND_ASSIGN(DriSurfaceAdapter);
66 DriSurfaceAdapter::DriSurfaceAdapter(
67 const base::WeakPtr<HardwareDisplayController>& controller)
68 : controller_(controller) {
71 DriSurfaceAdapter::~DriSurfaceAdapter() {
74 skia::RefPtr<SkCanvas> DriSurfaceAdapter::GetCanvas() {
75 return skia::SharePtr(surface_->getCanvas());
78 void DriSurfaceAdapter::ResizeCanvas(const gfx::Size& viewport_size) {
79 SkImageInfo info = SkImageInfo::MakeN32(
80 viewport_size.width(), viewport_size.height(), kOpaque_SkAlphaType);
81 surface_ = skia::AdoptRef(SkSurface::NewRaster(info));
84 void DriSurfaceAdapter::PresentCanvas(const gfx::Rect& damage) {
85 CHECK(base::MessageLoopForUI::IsCurrent());
86 if (!controller_)
87 return;
89 UpdateNativeSurface(damage);
90 controller_->SchedulePageFlip();
91 controller_->WaitForPageFlipEvent();
94 scoped_ptr<gfx::VSyncProvider> DriSurfaceAdapter::CreateVSyncProvider() {
95 return scoped_ptr<gfx::VSyncProvider>(new DriVSyncProvider(controller_));
98 void DriSurfaceAdapter::UpdateNativeSurface(const gfx::Rect& damage) {
99 SkCanvas* canvas = static_cast<DriSurface*>(controller_->surface())
100 ->GetDrawableForWidget();
102 // The DriSurface is double buffered, so the current back buffer is
103 // missing the previous update. Expand damage region.
104 SkRect real_damage = RectToSkRect(UnionRects(damage, last_damage_));
106 // Copy damage region.
107 skia::RefPtr<SkImage> image = skia::AdoptRef(surface_->newImageSnapshot());
108 image->draw(canvas, &real_damage, real_damage, NULL);
110 last_damage_ = damage;
113 } // namespace
115 // static
116 const gfx::AcceleratedWidget DriSurfaceFactory::kDefaultWidgetHandle = 1;
118 DriSurfaceFactory::DriSurfaceFactory(DriWrapper* drm,
119 ScreenManager* screen_manager)
120 : drm_(drm),
121 screen_manager_(screen_manager),
122 state_(UNINITIALIZED),
123 allocated_widgets_(0) {
126 DriSurfaceFactory::~DriSurfaceFactory() {
127 if (state_ == INITIALIZED)
128 ShutdownHardware();
131 ui::SurfaceFactoryOzone::HardwareState DriSurfaceFactory::InitializeHardware() {
132 if (state_ != UNINITIALIZED)
133 return state_;
135 if (drm_->get_fd() < 0) {
136 LOG(ERROR) << "Failed to create DRI connection";
137 state_ = FAILED;
138 return state_;
141 cursor_surface_.reset(CreateSurface(kCursorSize));
142 if (!cursor_surface_->Initialize()) {
143 LOG(ERROR) << "Failed to initialize cursor surface";
144 state_ = FAILED;
145 return state_;
148 state_ = INITIALIZED;
149 return state_;
152 void DriSurfaceFactory::ShutdownHardware() {
153 CHECK(state_ == INITIALIZED);
154 state_ = UNINITIALIZED;
157 gfx::AcceleratedWidget DriSurfaceFactory::GetAcceleratedWidget() {
158 CHECK(state_ != FAILED);
160 // We're not using 0 since other code assumes that a 0 AcceleratedWidget is an
161 // invalid widget.
162 return ++allocated_widgets_;
165 scoped_ptr<ui::SurfaceOzoneCanvas> DriSurfaceFactory::CreateCanvasForWidget(
166 gfx::AcceleratedWidget w) {
167 CHECK(state_ == INITIALIZED);
168 // Initial cursor set.
169 ResetCursor(w);
171 return scoped_ptr<ui::SurfaceOzoneCanvas>(
172 new DriSurfaceAdapter(screen_manager_->GetDisplayController(w)));
175 bool DriSurfaceFactory::LoadEGLGLES2Bindings(
176 AddGLLibraryCallback add_gl_library,
177 SetGLGetProcAddressProcCallback set_gl_get_proc_address) {
178 return false;
181 gfx::Size DriSurfaceFactory::GetWidgetSize(gfx::AcceleratedWidget w) {
182 base::WeakPtr<HardwareDisplayController> controller =
183 screen_manager_->GetDisplayController(w);
184 if (controller)
185 return gfx::Size(controller->get_mode().hdisplay,
186 controller->get_mode().vdisplay);
188 return gfx::Size(0, 0);
191 void DriSurfaceFactory::SetHardwareCursor(gfx::AcceleratedWidget window,
192 const SkBitmap& image,
193 const gfx::Point& location) {
194 cursor_bitmap_ = image;
195 cursor_location_ = location;
197 if (state_ != INITIALIZED)
198 return;
200 ResetCursor(window);
203 void DriSurfaceFactory::MoveHardwareCursor(gfx::AcceleratedWidget window,
204 const gfx::Point& location) {
205 cursor_location_ = location;
207 if (state_ != INITIALIZED)
208 return;
210 base::WeakPtr<HardwareDisplayController> controller =
211 screen_manager_->GetDisplayController(window);
212 if (controller)
213 controller->MoveCursor(location);
216 ////////////////////////////////////////////////////////////////////////////////
217 // DriSurfaceFactory private
219 DriSurface* DriSurfaceFactory::CreateSurface(const gfx::Size& size) {
220 return new DriSurface(drm_, size);
223 void DriSurfaceFactory::ResetCursor(gfx::AcceleratedWidget w) {
224 base::WeakPtr<HardwareDisplayController> controller =
225 screen_manager_->GetDisplayController(w);
227 if (!cursor_bitmap_.empty()) {
228 // Draw new cursor into backbuffer.
229 UpdateCursorImage(cursor_surface_.get(), cursor_bitmap_);
231 // Reset location & buffer.
232 if (controller) {
233 controller->MoveCursor(cursor_location_);
234 controller->SetCursor(cursor_surface_.get());
236 } else {
237 // No cursor set.
238 if (controller)
239 controller->UnsetCursor();
243 } // namespace ui