Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / ui / ozone / platform / dri / dri_surface_factory.cc
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.
4
5 #include "ui/ozone/platform/dri/dri_surface_factory.h"
6
7 #include <errno.h>
8
9 #include "base/debug/trace_event.h"
10 #include "third_party/skia/include/core/SkBitmap.h"
11 #include "third_party/skia/include/core/SkDevice.h"
12 #include "third_party/skia/include/core/SkSurface.h"
13 #include "ui/gfx/native_widget_types.h"
14 #include "ui/ozone/platform/dri/dri_buffer.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_window_delegate_impl.h"
18 #include "ui/ozone/platform/dri/dri_window_delegate_manager.h"
19 #include "ui/ozone/platform/dri/dri_wrapper.h"
20 #include "ui/ozone/platform/dri/hardware_display_controller.h"
21 #include "ui/ozone/platform/dri/screen_manager.h"
22 #include "ui/ozone/public/surface_ozone_canvas.h"
23
24 namespace ui {
25
26 namespace {
27
28 // TODO(dnicoara) Read the cursor plane size from the hardware.
29 const gfx::Size kCursorSize(64, 64);
30
31 void UpdateCursorImage(DriBuffer* cursor, const SkBitmap& image) {
32   SkRect damage;
33   image.getBounds(&damage);
34
35   // Clear to transparent in case |image| is smaller than the canvas.
36   SkCanvas* canvas = cursor->GetCanvas();
37   canvas->clear(SK_ColorTRANSPARENT);
38
39   SkRect clip;
40   clip.set(
41       0, 0, canvas->getDeviceSize().width(), canvas->getDeviceSize().height());
42   canvas->clipRect(clip, SkRegion::kReplace_Op);
43   canvas->drawBitmapRectToRect(image, &damage, damage);
44 }
45
46 }  // namespace
47
48 // static
49 const gfx::AcceleratedWidget DriSurfaceFactory::kDefaultWidgetHandle = 1;
50
51 DriSurfaceFactory::DriSurfaceFactory(DriWrapper* drm,
52                                      ScreenManager* screen_manager,
53                                      DriWindowDelegateManager* window_manager)
54     : drm_(drm),
55       screen_manager_(screen_manager),
56       window_manager_(window_manager),
57       state_(UNINITIALIZED),
58       cursor_frontbuffer_(0),
59       cursor_widget_(0),
60       cursor_frame_(0),
61       cursor_frame_delay_ms_(0) {
62 }
63
64 DriSurfaceFactory::~DriSurfaceFactory() {
65   if (state_ == INITIALIZED)
66     ShutdownHardware();
67 }
68
69 DriSurfaceFactory::HardwareState DriSurfaceFactory::InitializeHardware() {
70   if (state_ != UNINITIALIZED)
71     return state_;
72
73   if (drm_->get_fd() < 0) {
74     LOG(ERROR) << "Failed to create DRI connection";
75     state_ = FAILED;
76     return state_;
77   }
78
79   SkImageInfo info = SkImageInfo::MakeN32Premul(kCursorSize.width(),
80                                                 kCursorSize.height());
81   for (size_t i = 0; i < arraysize(cursor_buffers_); ++i) {
82     cursor_buffers_[i] = new DriBuffer(drm_);
83     if (!cursor_buffers_[i]->Initialize(info)) {
84       LOG(ERROR) << "Failed to initialize cursor buffer";
85       state_ = FAILED;
86       return state_;
87     }
88   }
89
90   state_ = INITIALIZED;
91   return state_;
92 }
93
94 void DriSurfaceFactory::ShutdownHardware() {
95   DCHECK(state_ == INITIALIZED);
96   state_ = UNINITIALIZED;
97 }
98
99 scoped_ptr<ui::SurfaceOzoneCanvas> DriSurfaceFactory::CreateCanvasForWidget(
100     gfx::AcceleratedWidget widget) {
101   DCHECK(state_ == INITIALIZED);
102
103   return scoped_ptr<ui::SurfaceOzoneCanvas>(
104       new DriSurface(window_manager_->GetWindowDelegate(widget), drm_));
105 }
106
107 bool DriSurfaceFactory::LoadEGLGLES2Bindings(
108       AddGLLibraryCallback add_gl_library,
109       SetGLGetProcAddressProcCallback set_gl_get_proc_address) {
110   return false;
111 }
112
113 void DriSurfaceFactory::SetHardwareCursor(gfx::AcceleratedWidget widget,
114                                           const std::vector<SkBitmap>& bitmaps,
115                                           const gfx::Point& location,
116                                           int frame_delay_ms) {
117   cursor_widget_ = widget;
118   cursor_bitmaps_ = bitmaps;
119   cursor_location_ = location;
120   cursor_frame_ = 0;
121   cursor_frame_delay_ms_ = frame_delay_ms;
122   cursor_timer_.Stop();
123
124   if (cursor_frame_delay_ms_)
125     cursor_timer_.Start(
126         FROM_HERE,
127         base::TimeDelta::FromMilliseconds(cursor_frame_delay_ms_),
128         this,
129         &DriSurfaceFactory::OnCursorAnimationTimeout);
130
131   if (state_ != INITIALIZED)
132     return;
133
134   ResetCursor();
135 }
136
137 void DriSurfaceFactory::MoveHardwareCursor(gfx::AcceleratedWidget widget,
138                                            const gfx::Point& location) {
139   cursor_location_ = location;
140
141   if (state_ != INITIALIZED)
142     return;
143
144   HardwareDisplayController* controller =
145       window_manager_->GetWindowDelegate(widget)->GetController();
146   if (controller)
147     controller->MoveCursor(location);
148 }
149
150 ////////////////////////////////////////////////////////////////////////////////
151 // DriSurfaceFactory private
152
153 void DriSurfaceFactory::ResetCursor() {
154   if (!cursor_widget_)
155     return;
156
157   HardwareDisplayController* controller =
158       window_manager_->GetWindowDelegate(cursor_widget_)->GetController();
159   if (cursor_bitmaps_.size()) {
160     // Draw new cursor into backbuffer.
161     UpdateCursorImage(cursor_buffers_[cursor_frontbuffer_ ^ 1].get(),
162                       cursor_bitmaps_[cursor_frame_]);
163
164     // Reset location & buffer.
165     if (controller) {
166       controller->MoveCursor(cursor_location_);
167       controller->SetCursor(cursor_buffers_[cursor_frontbuffer_ ^ 1]);
168       cursor_frontbuffer_ ^= 1;
169     }
170   } else {
171     // No cursor set.
172     if (controller)
173       controller->UnsetCursor();
174   }
175 }
176
177 void DriSurfaceFactory::OnCursorAnimationTimeout() {
178   cursor_frame_++;
179   cursor_frame_ %= cursor_bitmaps_.size();
180
181   ResetCursor();
182 }
183
184 }  // namespace ui