OLD | NEW |
| (Empty) |
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_window_delegate_impl.h" | |
6 | |
7 #include "base/trace_event/trace_event.h" | |
8 #include "third_party/skia/include/core/SkBitmap.h" | |
9 #include "third_party/skia/include/core/SkDevice.h" | |
10 #include "third_party/skia/include/core/SkSurface.h" | |
11 #include "ui/ozone/platform/dri/dri_buffer.h" | |
12 #include "ui/ozone/platform/dri/drm_device.h" | |
13 #include "ui/ozone/platform/dri/drm_device_manager.h" | |
14 #include "ui/ozone/platform/dri/screen_manager.h" | |
15 | |
16 namespace ui { | |
17 | |
18 namespace { | |
19 | |
20 #ifndef DRM_CAP_CURSOR_WIDTH | |
21 #define DRM_CAP_CURSOR_WIDTH 0x8 | |
22 #endif | |
23 | |
24 #ifndef DRM_CAP_CURSOR_HEIGHT | |
25 #define DRM_CAP_CURSOR_HEIGHT 0x9 | |
26 #endif | |
27 | |
28 void UpdateCursorImage(DriBuffer* cursor, const SkBitmap& image) { | |
29 SkRect damage; | |
30 image.getBounds(&damage); | |
31 | |
32 // Clear to transparent in case |image| is smaller than the canvas. | |
33 SkCanvas* canvas = cursor->GetCanvas(); | |
34 canvas->clear(SK_ColorTRANSPARENT); | |
35 | |
36 SkRect clip; | |
37 clip.set(0, 0, canvas->getDeviceSize().width(), | |
38 canvas->getDeviceSize().height()); | |
39 canvas->clipRect(clip, SkRegion::kReplace_Op); | |
40 canvas->drawBitmapRectToRect(image, &damage, damage); | |
41 } | |
42 | |
43 } // namespace | |
44 | |
45 DriWindowDelegateImpl::DriWindowDelegateImpl( | |
46 gfx::AcceleratedWidget widget, | |
47 DrmDeviceManager* device_manager, | |
48 ScreenManager* screen_manager) | |
49 : widget_(widget), | |
50 device_manager_(device_manager), | |
51 screen_manager_(screen_manager), | |
52 controller_(NULL), | |
53 cursor_frontbuffer_(0), | |
54 cursor_frame_(0), | |
55 cursor_frame_delay_ms_(0) { | |
56 } | |
57 | |
58 DriWindowDelegateImpl::~DriWindowDelegateImpl() { | |
59 } | |
60 | |
61 void DriWindowDelegateImpl::Initialize() { | |
62 TRACE_EVENT1("dri", "DriWindowDelegateImpl::Initialize", "widget", widget_); | |
63 | |
64 device_manager_->UpdateDrmDevice(widget_, nullptr); | |
65 screen_manager_->AddObserver(this); | |
66 } | |
67 | |
68 void DriWindowDelegateImpl::Shutdown() { | |
69 TRACE_EVENT1("dri", "DriWindowDelegateImpl::Shutdown", "widget", widget_); | |
70 screen_manager_->RemoveObserver(this); | |
71 device_manager_->RemoveDrmDevice(widget_); | |
72 } | |
73 | |
74 gfx::AcceleratedWidget DriWindowDelegateImpl::GetAcceleratedWidget() { | |
75 return widget_; | |
76 } | |
77 | |
78 HardwareDisplayController* DriWindowDelegateImpl::GetController() { | |
79 return controller_; | |
80 } | |
81 | |
82 void DriWindowDelegateImpl::OnBoundsChanged(const gfx::Rect& bounds) { | |
83 TRACE_EVENT2("dri", "DriWindowDelegateImpl::OnBoundsChanged", "widget", | |
84 widget_, "bounds", bounds.ToString()); | |
85 bounds_ = bounds; | |
86 controller_ = screen_manager_->GetDisplayController(bounds); | |
87 UpdateWidgetToDrmDeviceMapping(); | |
88 UpdateCursorBuffers(); | |
89 } | |
90 | |
91 void DriWindowDelegateImpl::SetCursor(const std::vector<SkBitmap>& bitmaps, | |
92 const gfx::Point& location, | |
93 int frame_delay_ms) { | |
94 cursor_bitmaps_ = bitmaps; | |
95 cursor_location_ = location; | |
96 cursor_frame_ = 0; | |
97 cursor_frame_delay_ms_ = frame_delay_ms; | |
98 cursor_timer_.Stop(); | |
99 | |
100 if (cursor_frame_delay_ms_) | |
101 cursor_timer_.Start( | |
102 FROM_HERE, base::TimeDelta::FromMilliseconds(cursor_frame_delay_ms_), | |
103 this, &DriWindowDelegateImpl::OnCursorAnimationTimeout); | |
104 | |
105 ResetCursor(false); | |
106 } | |
107 | |
108 void DriWindowDelegateImpl::SetCursorWithoutAnimations( | |
109 const std::vector<SkBitmap>& bitmaps, | |
110 const gfx::Point& location) { | |
111 cursor_bitmaps_ = bitmaps; | |
112 cursor_location_ = location; | |
113 cursor_frame_ = 0; | |
114 cursor_frame_delay_ms_ = 0; | |
115 ResetCursor(false); | |
116 } | |
117 | |
118 void DriWindowDelegateImpl::MoveCursor(const gfx::Point& location) { | |
119 cursor_location_ = location; | |
120 | |
121 if (controller_) | |
122 controller_->MoveCursor(location); | |
123 } | |
124 | |
125 void DriWindowDelegateImpl::OnDisplayChanged( | |
126 HardwareDisplayController* controller) { | |
127 DCHECK(controller); | |
128 | |
129 // If we have a new controller we need to re-allocate the buffers. | |
130 bool should_allocate_cursor_buffers = controller_ != controller; | |
131 | |
132 gfx::Rect controller_bounds = | |
133 gfx::Rect(controller->origin(), controller->GetModeSize()); | |
134 if (controller_) { | |
135 if (controller_ != controller) | |
136 return; | |
137 | |
138 if (controller->IsDisabled() || bounds_ != controller_bounds) | |
139 controller_ = nullptr; | |
140 } else { | |
141 if (bounds_ == controller_bounds && !controller->IsDisabled()) | |
142 controller_ = controller; | |
143 } | |
144 | |
145 UpdateWidgetToDrmDeviceMapping(); | |
146 if (should_allocate_cursor_buffers) | |
147 UpdateCursorBuffers(); | |
148 } | |
149 | |
150 void DriWindowDelegateImpl::OnDisplayRemoved( | |
151 HardwareDisplayController* controller) { | |
152 if (controller_ == controller) | |
153 controller_ = nullptr; | |
154 } | |
155 | |
156 void DriWindowDelegateImpl::ResetCursor(bool bitmap_only) { | |
157 if (!controller_) | |
158 return; | |
159 | |
160 if (cursor_bitmaps_.size()) { | |
161 // Draw new cursor into backbuffer. | |
162 UpdateCursorImage(cursor_buffers_[cursor_frontbuffer_ ^ 1].get(), | |
163 cursor_bitmaps_[cursor_frame_]); | |
164 | |
165 // Reset location & buffer. | |
166 if (!bitmap_only) | |
167 controller_->MoveCursor(cursor_location_); | |
168 controller_->SetCursor(cursor_buffers_[cursor_frontbuffer_ ^ 1]); | |
169 cursor_frontbuffer_ ^= 1; | |
170 } else { | |
171 // No cursor set. | |
172 controller_->UnsetCursor(); | |
173 } | |
174 } | |
175 | |
176 void DriWindowDelegateImpl::OnCursorAnimationTimeout() { | |
177 cursor_frame_++; | |
178 cursor_frame_ %= cursor_bitmaps_.size(); | |
179 | |
180 ResetCursor(true); | |
181 } | |
182 | |
183 void DriWindowDelegateImpl::UpdateWidgetToDrmDeviceMapping() { | |
184 scoped_refptr<DrmDevice> drm = nullptr; | |
185 if (controller_) | |
186 drm = controller_->GetAllocationDrmDevice(); | |
187 | |
188 device_manager_->UpdateDrmDevice(widget_, drm); | |
189 } | |
190 | |
191 void DriWindowDelegateImpl::UpdateCursorBuffers() { | |
192 if (!controller_) { | |
193 for (size_t i = 0; i < arraysize(cursor_buffers_); ++i) { | |
194 cursor_buffers_[i] = nullptr; | |
195 } | |
196 } else { | |
197 scoped_refptr<DrmDevice> drm = controller_->GetAllocationDrmDevice(); | |
198 | |
199 uint64_t cursor_width = 64; | |
200 uint64_t cursor_height = 64; | |
201 drm->GetCapability(DRM_CAP_CURSOR_WIDTH, &cursor_width); | |
202 drm->GetCapability(DRM_CAP_CURSOR_HEIGHT, &cursor_height); | |
203 | |
204 SkImageInfo info = SkImageInfo::MakeN32Premul(cursor_width, cursor_height); | |
205 for (size_t i = 0; i < arraysize(cursor_buffers_); ++i) { | |
206 cursor_buffers_[i] = new DriBuffer(drm); | |
207 // Don't register a framebuffer for cursors since they are special (they | |
208 // aren't modesetting buffers and drivers may fail to register them due to | |
209 // their small sizes). | |
210 if (!cursor_buffers_[i]->Initialize( | |
211 info, false /* should_register_framebuffer */)) { | |
212 LOG(FATAL) << "Failed to initialize cursor buffer"; | |
213 return; | |
214 } | |
215 } | |
216 } | |
217 } | |
218 | |
219 } // namespace ui | |
OLD | NEW |