ozone: gbm: Update hardware cursor in GPU process
[chromium-blink-merge.git] / ui / ozone / platform / dri / dri_buffer.cc
blob50bd17dd88e33b450754dc4c99aa21a9e9af477c
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/dri/dri_buffer.h"
7 #include <errno.h>
8 #include <sys/mman.h>
9 #include <sys/types.h>
10 #include <xf86drm.h>
12 #include "base/logging.h"
13 #include "third_party/skia/include/core/SkCanvas.h"
14 #include "ui/ozone/platform/dri/dri_util.h"
15 #include "ui/ozone/platform/dri/dri_wrapper.h"
17 namespace ui {
19 namespace {
21 // Modesetting cannot happen from a buffer with transparencies. Return the size
22 // of a pixel without alpha.
23 uint8_t GetColorDepth(SkColorType type) {
24 switch (type) {
25 case kUnknown_SkColorType:
26 case kAlpha_8_SkColorType:
27 return 0;
28 case kIndex_8_SkColorType:
29 return 8;
30 case kRGB_565_SkColorType:
31 return 16;
32 case kARGB_4444_SkColorType:
33 return 12;
34 case kPMColor_SkColorType:
35 return 24;
36 default:
37 NOTREACHED();
38 return 0;
42 void DestroyDumbBuffer(int fd, uint32_t handle) {
43 struct drm_mode_destroy_dumb destroy_request;
44 destroy_request.handle = handle;
45 drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_request);
48 bool CreateDumbBuffer(int fd,
49 const SkImageInfo& info,
50 uint32_t* handle,
51 uint32_t* stride) {
52 struct drm_mode_create_dumb request;
53 request.width = info.width();
54 request.height = info.height();
55 request.bpp = info.bytesPerPixel() << 3;
56 request.flags = 0;
58 if (drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &request) < 0) {
59 DLOG(ERROR) << "Cannot create dumb buffer (" << errno << ") "
60 << strerror(errno);
61 return false;
64 // The driver may choose to align the last row as well. We don't care about
65 // the last alignment bits since they aren't used for display purposes, so
66 // just check that the expected size is <= to what the driver allocated.
67 DCHECK_LE(info.getSafeSize(request.pitch), request.size);
69 *handle = request.handle;
70 *stride = request.pitch;
71 return true;
74 } // namespace
76 DriBuffer::DriBuffer(DriWrapper* dri)
77 : dri_(dri), handle_(0), framebuffer_(0) {}
79 DriBuffer::~DriBuffer() {
80 if (!surface_)
81 return;
83 if (framebuffer_)
84 dri_->RemoveFramebuffer(framebuffer_);
86 SkImageInfo info;
87 void* pixels = const_cast<void*>(surface_->peekPixels(&info, NULL));
88 if (!pixels)
89 return;
91 munmap(pixels, info.getSafeSize(stride_));
92 DestroyDumbBuffer(dri_->get_fd(), handle_);
95 bool DriBuffer::Initialize(const SkImageInfo& info) {
96 void* pixels = NULL;
97 if (!CreateDumbBuffer(dri_->get_fd(), info, &handle_, &stride_)) {
98 DLOG(ERROR) << "Cannot allocate drm dumb buffer";
99 return false;
102 if (!MapDumbBuffer(dri_->get_fd(),
103 handle_,
104 info.getSafeSize(stride_),
105 &pixels)) {
106 DLOG(ERROR) << "Cannot map drm dumb buffer";
107 DestroyDumbBuffer(dri_->get_fd(), handle_);
108 return false;
111 if (!dri_->AddFramebuffer(info.width(),
112 info.height(),
113 GetColorDepth(info.colorType()),
114 info.bytesPerPixel() << 3,
115 stride_,
116 handle_,
117 &framebuffer_)) {
118 DLOG(ERROR) << "Failed to register framebuffer: " << strerror(errno);
119 return false;
122 surface_ = skia::AdoptRef(SkSurface::NewRasterDirect(info, pixels, stride_));
123 if (!surface_) {
124 DLOG(ERROR) << "Cannot install Skia pixels for drm buffer";
125 return false;
128 return true;
131 } // namespace ui