| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 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/gfx/ozone/impl/dri_skbitmap.h" | |
| 6 | |
| 7 #include <errno.h> | |
| 8 #include <sys/mman.h> | |
| 9 #include <sys/types.h> | |
| 10 #include <xf86drm.h> | |
| 11 | |
| 12 #include "base/compiler_specific.h" | |
| 13 #include "base/logging.h" | |
| 14 #include "third_party/skia/include/core/SkPixelRef.h" | |
| 15 | |
| 16 namespace gfx { | |
| 17 | |
| 18 namespace { | |
| 19 | |
| 20 void DestroyDumbBuffer(int fd, uint32_t handle) { | |
| 21 struct drm_mode_destroy_dumb destroy_request; | |
| 22 destroy_request.handle = handle; | |
| 23 drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_request); | |
| 24 } | |
| 25 | |
| 26 // Special DRM implementation of a SkPixelRef. The DRM allocator will create a | |
| 27 // SkPixelRef for the backing pixels. It will then associate the SkPixelRef with | |
| 28 // the SkBitmap. SkBitmap will access the allocated memory by locking the pixels | |
| 29 // in the SkPixelRef. | |
| 30 // At the end of its life the SkPixelRef is responsible for deallocating the | |
| 31 // pixel memory. | |
| 32 class DriSkPixelRef : public SkPixelRef { | |
| 33 public: | |
| 34 DriSkPixelRef(void* pixels, | |
| 35 SkColorTable* color_table_, | |
| 36 size_t size, | |
| 37 int fd, | |
| 38 uint32_t handle); | |
| 39 virtual ~DriSkPixelRef(); | |
| 40 | |
| 41 virtual void* onLockPixels(SkColorTable** ct) OVERRIDE; | |
| 42 virtual void onUnlockPixels() OVERRIDE; | |
| 43 | |
| 44 SK_DECLARE_UNFLATTENABLE_OBJECT() | |
| 45 private: | |
| 46 // Raw pointer to the pixel memory. | |
| 47 void* pixels_; | |
| 48 | |
| 49 // Optional color table associated with the pixel memory. | |
| 50 SkColorTable* color_table_; | |
| 51 | |
| 52 // Size of the allocated memory. | |
| 53 size_t size_; | |
| 54 | |
| 55 // File descriptor to the graphics card used to allocate/deallocate the | |
| 56 // memory. | |
| 57 int fd_; | |
| 58 | |
| 59 // Handle for the allocated memory. | |
| 60 uint32_t handle_; | |
| 61 | |
| 62 DISALLOW_COPY_AND_ASSIGN(DriSkPixelRef); | |
| 63 }; | |
| 64 | |
| 65 //////////////////////////////////////////////////////////////////////////////// | |
| 66 // DriSkPixelRef implementation | |
| 67 | |
| 68 DriSkPixelRef::DriSkPixelRef( | |
| 69 void* pixels, | |
| 70 SkColorTable* color_table, | |
| 71 size_t size, | |
| 72 int fd, | |
| 73 uint32_t handle) | |
| 74 : pixels_(pixels), | |
| 75 color_table_(color_table), | |
| 76 size_(size), | |
| 77 fd_(fd), | |
| 78 handle_(handle) { | |
| 79 } | |
| 80 | |
| 81 DriSkPixelRef::~DriSkPixelRef() { | |
| 82 munmap(pixels_, size_); | |
| 83 DestroyDumbBuffer(fd_, handle_); | |
| 84 } | |
| 85 | |
| 86 void* DriSkPixelRef::onLockPixels(SkColorTable** ct) { | |
| 87 *ct = color_table_; | |
| 88 return pixels_; | |
| 89 } | |
| 90 | |
| 91 void DriSkPixelRef::onUnlockPixels() { | |
| 92 } | |
| 93 | |
| 94 } // namespace | |
| 95 | |
| 96 // Allocates pixel memory for a SkBitmap using DRM dumb buffers. | |
| 97 class DriAllocator : public SkBitmap::Allocator { | |
| 98 public: | |
| 99 DriAllocator(); | |
| 100 | |
| 101 virtual bool allocPixelRef(SkBitmap* bitmap, | |
| 102 SkColorTable* color_table) OVERRIDE; | |
| 103 | |
| 104 private: | |
| 105 bool AllocatePixels(DriSkBitmap* bitmap, SkColorTable* color_table); | |
| 106 | |
| 107 DISALLOW_COPY_AND_ASSIGN(DriAllocator); | |
| 108 }; | |
| 109 | |
| 110 //////////////////////////////////////////////////////////////////////////////// | |
| 111 // DriAllocator implementation | |
| 112 | |
| 113 DriAllocator::DriAllocator() { | |
| 114 } | |
| 115 | |
| 116 bool DriAllocator::allocPixelRef(SkBitmap* bitmap, | |
| 117 SkColorTable* color_table) { | |
| 118 return AllocatePixels(static_cast<DriSkBitmap*>(bitmap), color_table); | |
| 119 } | |
| 120 | |
| 121 bool DriAllocator::AllocatePixels(DriSkBitmap* bitmap, | |
| 122 SkColorTable* color_table) { | |
| 123 struct drm_mode_create_dumb request; | |
| 124 request.width = bitmap->width(); | |
| 125 request.height = bitmap->height(); | |
| 126 request.bpp = bitmap->bytesPerPixel() << 3; | |
| 127 request.flags = 0; | |
| 128 | |
| 129 if (drmIoctl(bitmap->get_fd(), DRM_IOCTL_MODE_CREATE_DUMB, &request) < 0) { | |
| 130 DLOG(ERROR) << "Cannot create dumb buffer (" << errno << ") " | |
| 131 << strerror(errno); | |
| 132 return false; | |
| 133 } | |
| 134 | |
| 135 CHECK(request.size == bitmap->getSize()); | |
| 136 | |
| 137 bitmap->set_handle(request.handle); | |
| 138 | |
| 139 struct drm_mode_map_dumb map_request; | |
| 140 map_request.handle = bitmap->get_handle(); | |
| 141 if (drmIoctl(bitmap->get_fd(), DRM_IOCTL_MODE_MAP_DUMB, &map_request)) { | |
| 142 DLOG(ERROR) << "Cannot prepare dumb buffer for mapping (" << errno << ") " | |
| 143 << strerror(errno); | |
| 144 DestroyDumbBuffer(bitmap->get_fd(), bitmap->get_handle()); | |
| 145 return false; | |
| 146 } | |
| 147 | |
| 148 void* pixels = mmap(0, | |
| 149 bitmap->getSize(), | |
| 150 PROT_READ | PROT_WRITE, | |
| 151 MAP_SHARED, | |
| 152 bitmap->get_fd(), | |
| 153 map_request.offset); | |
| 154 if (pixels == MAP_FAILED) { | |
| 155 DLOG(ERROR) << "Cannot mmap dumb buffer (" << errno << ") " | |
| 156 << strerror(errno); | |
| 157 DestroyDumbBuffer(bitmap->get_fd(), bitmap->get_handle()); | |
| 158 return false; | |
| 159 } | |
| 160 | |
| 161 bitmap->setPixelRef(new DriSkPixelRef( | |
| 162 pixels, | |
| 163 color_table, | |
| 164 bitmap->getSize(), | |
| 165 bitmap->get_fd(), | |
| 166 bitmap->get_handle()))->unref(); | |
| 167 bitmap->lockPixels(); | |
| 168 | |
| 169 return true; | |
| 170 } | |
| 171 | |
| 172 //////////////////////////////////////////////////////////////////////////////// | |
| 173 // DriSkBitmap implementation | |
| 174 | |
| 175 DriSkBitmap::DriSkBitmap(int fd) | |
| 176 : fd_(fd), | |
| 177 handle_(0), | |
| 178 framebuffer_(0) { | |
| 179 } | |
| 180 | |
| 181 DriSkBitmap::~DriSkBitmap() { | |
| 182 } | |
| 183 | |
| 184 bool DriSkBitmap::Initialize() { | |
| 185 DriAllocator drm_allocator; | |
| 186 return allocPixels(&drm_allocator, NULL); | |
| 187 } | |
| 188 | |
| 189 uint8_t DriSkBitmap::GetColorDepth() const { | |
| 190 switch (config()) { | |
| 191 case SkBitmap::kNo_Config: | |
| 192 case SkBitmap::kA1_Config: | |
| 193 case SkBitmap::kA8_Config: | |
| 194 return 0; | |
| 195 case SkBitmap::kIndex8_Config: | |
| 196 return 8; | |
| 197 case SkBitmap::kRGB_565_Config: | |
| 198 return 16; | |
| 199 case SkBitmap::kARGB_4444_Config: | |
| 200 return 12; | |
| 201 case SkBitmap::kARGB_8888_Config: | |
| 202 return 24; | |
| 203 default: | |
| 204 NOTREACHED(); | |
| 205 return 0; | |
| 206 } | |
| 207 } | |
| 208 | |
| 209 } // namespace gfx | |
| OLD | NEW |