Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / ui / ozone / platform / drm / gpu / drm_window.cc
blob3e92f4039ce4af7f6db4c1ad04da1ce9eda39574
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/drm/gpu/drm_window.h"
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/common/gpu/ozone_gpu_message_params.h"
12 #include "ui/ozone/platform/drm/gpu/drm_buffer.h"
13 #include "ui/ozone/platform/drm/gpu/drm_device.h"
14 #include "ui/ozone/platform/drm/gpu/drm_device_manager.h"
15 #include "ui/ozone/platform/drm/gpu/scanout_buffer.h"
16 #include "ui/ozone/platform/drm/gpu/screen_manager.h"
18 namespace ui {
20 namespace {
22 #ifndef DRM_CAP_CURSOR_WIDTH
23 #define DRM_CAP_CURSOR_WIDTH 0x8
24 #endif
26 #ifndef DRM_CAP_CURSOR_HEIGHT
27 #define DRM_CAP_CURSOR_HEIGHT 0x9
28 #endif
30 void EmptyFlipCallback(gfx::SwapResult) {
33 void UpdateCursorImage(DrmBuffer* cursor, const SkBitmap& image) {
34 SkRect damage;
35 image.getBounds(&damage);
37 // Clear to transparent in case |image| is smaller than the canvas.
38 SkCanvas* canvas = cursor->GetCanvas();
39 canvas->clear(SK_ColorTRANSPARENT);
41 SkRect clip;
42 clip.set(0, 0, canvas->getDeviceSize().width(),
43 canvas->getDeviceSize().height());
44 canvas->clipRect(clip, SkRegion::kReplace_Op);
45 canvas->drawBitmapRect(image, damage);
48 } // namespace
50 DrmWindow::DrmWindow(gfx::AcceleratedWidget widget,
51 DrmDeviceManager* device_manager,
52 ScreenManager* screen_manager)
53 : widget_(widget),
54 device_manager_(device_manager),
55 screen_manager_(screen_manager) {
58 DrmWindow::~DrmWindow() {
61 void DrmWindow::Initialize() {
62 TRACE_EVENT1("drm", "DrmWindow::Initialize", "widget", widget_);
64 device_manager_->UpdateDrmDevice(widget_, nullptr);
67 void DrmWindow::Shutdown() {
68 TRACE_EVENT1("drm", "DrmWindow::Shutdown", "widget", widget_);
69 device_manager_->RemoveDrmDevice(widget_);
72 gfx::AcceleratedWidget DrmWindow::GetAcceleratedWidget() {
73 return widget_;
76 HardwareDisplayController* DrmWindow::GetController() {
77 return controller_;
80 void DrmWindow::OnBoundsChanged(const gfx::Rect& bounds) {
81 TRACE_EVENT2("drm", "DrmWindow::OnBoundsChanged", "widget", widget_, "bounds",
82 bounds.ToString());
83 bounds_ = bounds;
84 if (bounds_.size() != bounds.size())
85 last_submitted_planes_.clear();
87 screen_manager_->UpdateControllerToWindowMapping();
90 void DrmWindow::SetCursor(const std::vector<SkBitmap>& bitmaps,
91 const gfx::Point& location,
92 int frame_delay_ms) {
93 cursor_bitmaps_ = bitmaps;
94 cursor_location_ = location;
95 cursor_frame_ = 0;
96 cursor_frame_delay_ms_ = frame_delay_ms;
97 cursor_timer_.Stop();
99 if (cursor_frame_delay_ms_)
100 cursor_timer_.Start(
101 FROM_HERE, base::TimeDelta::FromMilliseconds(cursor_frame_delay_ms_),
102 this, &DrmWindow::OnCursorAnimationTimeout);
104 ResetCursor(false);
107 void DrmWindow::SetCursorWithoutAnimations(const std::vector<SkBitmap>& bitmaps,
108 const gfx::Point& location) {
109 cursor_bitmaps_ = bitmaps;
110 cursor_location_ = location;
111 cursor_frame_ = 0;
112 cursor_frame_delay_ms_ = 0;
113 ResetCursor(false);
116 void DrmWindow::MoveCursor(const gfx::Point& location) {
117 cursor_location_ = location;
119 if (controller_)
120 controller_->MoveCursor(location);
123 void DrmWindow::QueueOverlayPlane(const OverlayPlane& plane) {
124 pending_planes_.push_back(plane);
127 bool DrmWindow::SchedulePageFlip(bool is_sync,
128 const SwapCompletionCallback& callback) {
129 last_submitted_planes_.clear();
130 last_submitted_planes_.swap(pending_planes_);
131 last_swap_sync_ = is_sync;
133 if (controller_) {
134 return controller_->SchedulePageFlip(last_submitted_planes_, is_sync, false,
135 callback);
138 callback.Run(gfx::SwapResult::SWAP_ACK);
139 return true;
142 bool DrmWindow::TestPageFlip(const std::vector<OverlayCheck_Params>& overlays,
143 ScanoutBufferGenerator* buffer_generator) {
144 if (!controller_)
145 return true;
146 for (const auto& overlay : overlays) {
147 // It is possible that the cc rect we get actually falls off the edge of
148 // the screen. Usually this is prevented via things like status bars
149 // blocking overlaying or cc clipping it, but in case it wasn't properly
150 // clipped (since GL will render this situation fine) just ignore it here.
151 // This should be an extremely rare occurrance.
152 if (overlay.plane_z_order != 0 && !bounds().Contains(overlay.display_rect))
153 return false;
156 scoped_refptr<DrmDevice> drm = controller_->GetAllocationDrmDevice();
157 OverlayPlaneList planes;
158 for (const auto& overlay : overlays) {
159 gfx::Size size =
160 (overlay.plane_z_order == 0) ? bounds().size() : overlay.buffer_size;
161 scoped_refptr<ScanoutBuffer> buffer = buffer_generator->Create(drm, size);
162 if (!buffer)
163 return false;
164 planes.push_back(OverlayPlane(buffer, overlay.plane_z_order,
165 overlay.transform, overlay.display_rect,
166 gfx::RectF(gfx::Size(1, 1))));
168 return controller_->SchedulePageFlip(planes, true, true,
169 base::Bind(&EmptyFlipCallback));
172 const OverlayPlane* DrmWindow::GetLastModesetBuffer() {
173 return OverlayPlane::GetPrimaryPlane(last_submitted_planes_);
176 void DrmWindow::ResetCursor(bool bitmap_only) {
177 if (!controller_)
178 return;
180 if (cursor_bitmaps_.size()) {
181 // Draw new cursor into backbuffer.
182 UpdateCursorImage(cursor_buffers_[cursor_frontbuffer_ ^ 1].get(),
183 cursor_bitmaps_[cursor_frame_]);
185 // Reset location & buffer.
186 if (!bitmap_only)
187 controller_->MoveCursor(cursor_location_);
188 controller_->SetCursor(cursor_buffers_[cursor_frontbuffer_ ^ 1]);
189 cursor_frontbuffer_ ^= 1;
190 } else {
191 // No cursor set.
192 controller_->UnsetCursor();
196 void DrmWindow::OnCursorAnimationTimeout() {
197 cursor_frame_++;
198 cursor_frame_ %= cursor_bitmaps_.size();
200 ResetCursor(true);
203 void DrmWindow::SetController(HardwareDisplayController* controller) {
204 if (controller_ == controller)
205 return;
207 controller_ = controller;
208 device_manager_->UpdateDrmDevice(
209 widget_, controller ? controller->GetAllocationDrmDevice() : nullptr);
211 UpdateCursorBuffers();
212 // We changed displays, so we want to update the cursor as well.
213 ResetCursor(false /* bitmap_only */);
216 void DrmWindow::UpdateCursorBuffers() {
217 if (!controller_) {
218 for (size_t i = 0; i < arraysize(cursor_buffers_); ++i) {
219 cursor_buffers_[i] = nullptr;
221 } else {
222 scoped_refptr<DrmDevice> drm = controller_->GetAllocationDrmDevice();
224 uint64_t cursor_width = 64;
225 uint64_t cursor_height = 64;
226 drm->GetCapability(DRM_CAP_CURSOR_WIDTH, &cursor_width);
227 drm->GetCapability(DRM_CAP_CURSOR_HEIGHT, &cursor_height);
229 SkImageInfo info = SkImageInfo::MakeN32Premul(cursor_width, cursor_height);
230 for (size_t i = 0; i < arraysize(cursor_buffers_); ++i) {
231 cursor_buffers_[i] = new DrmBuffer(drm);
232 // Don't register a framebuffer for cursors since they are special (they
233 // aren't modesetting buffers and drivers may fail to register them due to
234 // their small sizes).
235 if (!cursor_buffers_[i]->Initialize(
236 info, false /* should_register_framebuffer */)) {
237 LOG(FATAL) << "Failed to initialize cursor buffer";
238 return;
244 } // namespace ui