1 /* 2 * Copyright 2017 The Chromium OS Authors. All rights reserved. 3 * Use of this source code is governed by a BSD-style license that can be 4 * found in the LICENSE file. 5 */ 6 7 #include "cros_gralloc_driver.h" 8 #include "../util.h" 9 10 #include <cstdlib> 11 #include <fcntl.h> 12 #include <xf86drm.h> 13 14 cros_gralloc_driver::cros_gralloc_driver() : drv_(nullptr) 15 { 16 } 17 18 cros_gralloc_driver::~cros_gralloc_driver() 19 { 20 buffers_.clear(); 21 handles_.clear(); 22 23 if (drv_) { 24 drv_destroy(drv_); 25 drv_ = nullptr; 26 } 27 } 28 29 int32_t cros_gralloc_driver::init() 30 { 31 /* 32 * Create a driver from rendernode while filtering out 33 * the specified undesired driver. 34 * 35 * TODO(gsingh): Enable render nodes on udl/evdi. 36 */ 37 38 int fd; 39 drmVersionPtr version; 40 char const *str = "%s/renderD%d"; 41 const char *undesired[2] = { "vgem", nullptr }; 42 uint32_t num_nodes = 63; 43 uint32_t min_node = 128; 44 uint32_t max_node = (min_node + num_nodes); 45 46 for (uint32_t i = 0; i < ARRAY_SIZE(undesired); i++) { 47 for (uint32_t j = min_node; j < max_node; j++) { 48 char *node; 49 if (asprintf(&node, str, DRM_DIR_NAME, j) < 0) 50 continue; 51 52 fd = open(node, O_RDWR, 0); 53 free(node); 54 55 if (fd < 0) 56 continue; 57 58 version = drmGetVersion(fd); 59 if (!version) 60 continue; 61 62 if (undesired[i] && !strcmp(version->name, undesired[i])) { 63 drmFreeVersion(version); 64 continue; 65 } 66 67 drmFreeVersion(version); 68 drv_ = drv_create(fd); 69 if (drv_) 70 return 0; 71 } 72 } 73 74 return -ENODEV; 75 } 76 77 bool cros_gralloc_driver::is_supported(const struct cros_gralloc_buffer_descriptor *descriptor) 78 { 79 struct combination *combo; 80 uint32_t resolved_format; 81 resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags); 82 combo = drv_get_combination(drv_, resolved_format, descriptor->use_flags); 83 return (combo != nullptr); 84 } 85 86 int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descriptor *descriptor, 87 buffer_handle_t *out_handle) 88 { 89 uint32_t id; 90 uint64_t mod; 91 size_t num_planes; 92 uint32_t resolved_format; 93 uint32_t bytes_per_pixel; 94 uint64_t use_flags; 95 96 struct bo *bo; 97 struct cros_gralloc_handle *hnd; 98 99 resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags); 100 use_flags = descriptor->use_flags; 101 /* 102 * TODO(b/79682290): ARC++ assumes NV12 is always linear and doesn't 103 * send modifiers across Wayland protocol, so we or in the 104 * BO_USE_LINEAR flag here. We need to fix ARC++ to allocate and work 105 * with tiled buffers. 106 */ 107 if (resolved_format == DRM_FORMAT_NV12) 108 use_flags |= BO_USE_LINEAR; 109 110 bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format, use_flags); 111 if (!bo) { 112 drv_log("Failed to create bo.\n"); 113 return -ENOMEM; 114 } 115 116 /* 117 * If there is a desire for more than one kernel buffer, this can be 118 * removed once the ArcCodec and Wayland service have the ability to 119 * send more than one fd. GL/Vulkan drivers may also have to modified. 120 */ 121 if (drv_num_buffers_per_bo(bo) != 1) { 122 drv_bo_destroy(bo); 123 drv_log("Can only support one buffer per bo.\n"); 124 return -EINVAL; 125 } 126 127 hnd = new cros_gralloc_handle(); 128 num_planes = drv_bo_get_num_planes(bo); 129 130 hnd->base.version = sizeof(hnd->base); 131 hnd->base.numFds = num_planes; 132 hnd->base.numInts = handle_data_size - num_planes; 133 134 for (size_t plane = 0; plane < num_planes; plane++) { 135 hnd->fds[plane] = drv_bo_get_plane_fd(bo, plane); 136 hnd->strides[plane] = drv_bo_get_plane_stride(bo, plane); 137 hnd->offsets[plane] = drv_bo_get_plane_offset(bo, plane); 138 139 mod = drv_bo_get_plane_format_modifier(bo, plane); 140 hnd->format_modifiers[2 * plane] = static_cast<uint32_t>(mod >> 32); 141 hnd->format_modifiers[2 * plane + 1] = static_cast<uint32_t>(mod); 142 } 143 144 hnd->width = drv_bo_get_width(bo); 145 hnd->height = drv_bo_get_height(bo); 146 hnd->format = drv_bo_get_format(bo); 147 hnd->use_flags[0] = static_cast<uint32_t>(descriptor->use_flags >> 32); 148 hnd->use_flags[1] = static_cast<uint32_t>(descriptor->use_flags); 149 bytes_per_pixel = drv_bytes_per_pixel_from_format(hnd->format, 0); 150 hnd->pixel_stride = DIV_ROUND_UP(hnd->strides[0], bytes_per_pixel); 151 hnd->magic = cros_gralloc_magic; 152 hnd->droid_format = descriptor->droid_format; 153 hnd->usage = descriptor->producer_usage; 154 155 id = drv_bo_get_plane_handle(bo, 0).u32; 156 auto buffer = new cros_gralloc_buffer(id, bo, hnd); 157 158 std::lock_guard<std::mutex> lock(mutex_); 159 buffers_.emplace(id, buffer); 160 handles_.emplace(hnd, std::make_pair(buffer, 1)); 161 *out_handle = &hnd->base; 162 return 0; 163 } 164 165 int32_t cros_gralloc_driver::retain(buffer_handle_t handle) 166 { 167 uint32_t id; 168 std::lock_guard<std::mutex> lock(mutex_); 169 170 auto hnd = cros_gralloc_convert_handle(handle); 171 if (!hnd) { 172 drv_log("Invalid handle.\n"); 173 return -EINVAL; 174 } 175 176 auto buffer = get_buffer(hnd); 177 if (buffer) { 178 handles_[hnd].second++; 179 buffer->increase_refcount(); 180 return 0; 181 } 182 183 if (drmPrimeFDToHandle(drv_get_fd(drv_), hnd->fds[0], &id)) { 184 drv_log("drmPrimeFDToHandle failed.\n"); 185 return -errno; 186 } 187 188 if (buffers_.count(id)) { 189 buffer = buffers_[id]; 190 buffer->increase_refcount(); 191 } else { 192 struct bo *bo; 193 struct drv_import_fd_data data; 194 data.format = hnd->format; 195 data.width = hnd->width; 196 data.height = hnd->height; 197 data.use_flags = static_cast<uint64_t>(hnd->use_flags[0]) << 32; 198 data.use_flags |= hnd->use_flags[1]; 199 200 memcpy(data.fds, hnd->fds, sizeof(data.fds)); 201 memcpy(data.strides, hnd->strides, sizeof(data.strides)); 202 memcpy(data.offsets, hnd->offsets, sizeof(data.offsets)); 203 for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++) { 204 data.format_modifiers[plane] = 205 static_cast<uint64_t>(hnd->format_modifiers[2 * plane]) << 32; 206 data.format_modifiers[plane] |= hnd->format_modifiers[2 * plane + 1]; 207 } 208 209 bo = drv_bo_import(drv_, &data); 210 if (!bo) 211 return -EFAULT; 212 213 id = drv_bo_get_plane_handle(bo, 0).u32; 214 215 buffer = new cros_gralloc_buffer(id, bo, nullptr); 216 buffers_.emplace(id, buffer); 217 } 218 219 handles_.emplace(hnd, std::make_pair(buffer, 1)); 220 return 0; 221 } 222 223 int32_t cros_gralloc_driver::release(buffer_handle_t handle) 224 { 225 std::lock_guard<std::mutex> lock(mutex_); 226 227 auto hnd = cros_gralloc_convert_handle(handle); 228 if (!hnd) { 229 drv_log("Invalid handle.\n"); 230 return -EINVAL; 231 } 232 233 auto buffer = get_buffer(hnd); 234 if (!buffer) { 235 drv_log("Invalid Reference.\n"); 236 return -EINVAL; 237 } 238 239 if (!--handles_[hnd].second) 240 handles_.erase(hnd); 241 242 if (buffer->decrease_refcount() == 0) { 243 buffers_.erase(buffer->get_id()); 244 delete buffer; 245 } 246 247 return 0; 248 } 249 250 int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence, 251 const struct rectangle *rect, uint32_t map_flags, 252 uint8_t *addr[DRV_MAX_PLANES]) 253 { 254 int32_t ret = cros_gralloc_sync_wait(acquire_fence); 255 if (ret) 256 return ret; 257 258 std::lock_guard<std::mutex> lock(mutex_); 259 auto hnd = cros_gralloc_convert_handle(handle); 260 if (!hnd) { 261 drv_log("Invalid handle.\n"); 262 return -EINVAL; 263 } 264 265 auto buffer = get_buffer(hnd); 266 if (!buffer) { 267 drv_log("Invalid Reference.\n"); 268 return -EINVAL; 269 } 270 271 return buffer->lock(rect, map_flags, addr); 272 } 273 274 int32_t cros_gralloc_driver::unlock(buffer_handle_t handle, int32_t *release_fence) 275 { 276 std::lock_guard<std::mutex> lock(mutex_); 277 278 auto hnd = cros_gralloc_convert_handle(handle); 279 if (!hnd) { 280 drv_log("Invalid handle.\n"); 281 return -EINVAL; 282 } 283 284 auto buffer = get_buffer(hnd); 285 if (!buffer) { 286 drv_log("Invalid Reference.\n"); 287 return -EINVAL; 288 } 289 290 /* 291 * From the ANativeWindow::dequeueBuffer documentation: 292 * 293 * "A value of -1 indicates that the caller may access the buffer immediately without 294 * waiting on a fence." 295 */ 296 *release_fence = -1; 297 return buffer->unlock(); 298 } 299 300 int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t *out_store) 301 { 302 std::lock_guard<std::mutex> lock(mutex_); 303 304 auto hnd = cros_gralloc_convert_handle(handle); 305 if (!hnd) { 306 drv_log("Invalid handle.\n"); 307 return -EINVAL; 308 } 309 310 auto buffer = get_buffer(hnd); 311 if (!buffer) { 312 drv_log("Invalid Reference.\n"); 313 return -EINVAL; 314 } 315 316 *out_store = static_cast<uint64_t>(buffer->get_id()); 317 return 0; 318 } 319 320 cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd) 321 { 322 /* Assumes driver mutex is held. */ 323 if (handles_.count(hnd)) 324 return handles_[hnd].first; 325 326 return nullptr; 327 } 328