| 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 |