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 24namespace ui { 25 26namespace { 27 28// TODO(dnicoara) Read the cursor plane size from the hardware. 29const gfx::Size kCursorSize(64, 64); 30 31void 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 49const gfx::AcceleratedWidget DriSurfaceFactory::kDefaultWidgetHandle = 1; 50 51DriSurfaceFactory::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 64DriSurfaceFactory::~DriSurfaceFactory() { 65 if (state_ == INITIALIZED) 66 ShutdownHardware(); 67} 68 69DriSurfaceFactory::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 94void DriSurfaceFactory::ShutdownHardware() { 95 DCHECK(state_ == INITIALIZED); 96 state_ = UNINITIALIZED; 97} 98 99scoped_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 107bool DriSurfaceFactory::LoadEGLGLES2Bindings( 108 AddGLLibraryCallback add_gl_library, 109 SetGLGetProcAddressProcCallback set_gl_get_proc_address) { 110 return false; 111} 112 113void 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 137void 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 153void 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 177void DriSurfaceFactory::OnCursorAnimationTimeout() { 178 cursor_frame_++; 179 cursor_frame_ %= cursor_bitmaps_.size(); 180 181 ResetCursor(); 182} 183 184} // namespace ui 185