1 /* 2 * Copyright 2014 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 <assert.h> 8 #include <fcntl.h> 9 #include <stdint.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <sys/mman.h> 14 #include <xf86drm.h> 15 16 #include "drv.h" 17 #include "gbm_helpers.h" 18 #include "gbm_priv.h" 19 #include "util.h" 20 21 PUBLIC int gbm_device_get_fd(struct gbm_device *gbm) 22 { 23 24 return drv_get_fd(gbm->drv); 25 } 26 27 PUBLIC const char *gbm_device_get_backend_name(struct gbm_device *gbm) 28 { 29 return drv_get_name(gbm->drv); 30 } 31 32 PUBLIC int gbm_device_is_format_supported(struct gbm_device *gbm, uint32_t format, uint32_t usage) 33 { 34 uint64_t use_flags; 35 36 if (usage & GBM_BO_USE_CURSOR && usage & GBM_BO_USE_RENDERING) 37 return 0; 38 39 use_flags = gbm_convert_usage(usage); 40 41 return (drv_get_combination(gbm->drv, format, use_flags) != NULL); 42 } 43 44 PUBLIC struct gbm_device *gbm_create_device(int fd) 45 { 46 struct gbm_device *gbm; 47 48 gbm = (struct gbm_device *)malloc(sizeof(*gbm)); 49 50 if (!gbm) 51 return NULL; 52 53 gbm->drv = drv_create(fd); 54 if (!gbm->drv) { 55 free(gbm); 56 return NULL; 57 } 58 59 return gbm; 60 } 61 62 PUBLIC void gbm_device_destroy(struct gbm_device *gbm) 63 { 64 drv_destroy(gbm->drv); 65 free(gbm); 66 } 67 68 PUBLIC struct gbm_surface *gbm_surface_create(struct gbm_device *gbm, uint32_t width, 69 uint32_t height, uint32_t format, uint32_t usage) 70 { 71 struct gbm_surface *surface = (struct gbm_surface *)malloc(sizeof(*surface)); 72 73 if (!surface) 74 return NULL; 75 76 return surface; 77 } 78 79 PUBLIC void gbm_surface_destroy(struct gbm_surface *surface) 80 { 81 free(surface); 82 } 83 84 PUBLIC struct gbm_bo *gbm_surface_lock_front_buffer(struct gbm_surface *surface) 85 { 86 return NULL; 87 } 88 89 PUBLIC void gbm_surface_release_buffer(struct gbm_surface *surface, struct gbm_bo *bo) 90 { 91 } 92 93 static struct gbm_bo *gbm_bo_new(struct gbm_device *gbm, uint32_t format) 94 { 95 struct gbm_bo *bo; 96 97 bo = (struct gbm_bo *)calloc(1, sizeof(*bo)); 98 if (!bo) 99 return NULL; 100 101 bo->gbm = gbm; 102 bo->gbm_format = format; 103 104 return bo; 105 } 106 107 PUBLIC struct gbm_bo *gbm_bo_create(struct gbm_device *gbm, uint32_t width, uint32_t height, 108 uint32_t format, uint32_t usage) 109 { 110 struct gbm_bo *bo; 111 112 if (!gbm_device_is_format_supported(gbm, format, usage)) 113 return NULL; 114 115 bo = gbm_bo_new(gbm, format); 116 117 if (!bo) 118 return NULL; 119 120 bo->bo = drv_bo_create(gbm->drv, width, height, format, gbm_convert_usage(usage)); 121 122 if (!bo->bo) { 123 free(bo); 124 return NULL; 125 } 126 127 return bo; 128 } 129 130 PUBLIC struct gbm_bo *gbm_bo_create_with_modifiers(struct gbm_device *gbm, uint32_t width, 131 uint32_t height, uint32_t format, 132 const uint64_t *modifiers, uint32_t count) 133 { 134 struct gbm_bo *bo; 135 136 bo = gbm_bo_new(gbm, format); 137 138 if (!bo) 139 return NULL; 140 141 bo->bo = drv_bo_create_with_modifiers(gbm->drv, width, height, format, modifiers, count); 142 143 if (!bo->bo) { 144 free(bo); 145 return NULL; 146 } 147 148 return bo; 149 } 150 151 PUBLIC void gbm_bo_destroy(struct gbm_bo *bo) 152 { 153 if (bo->destroy_user_data) { 154 bo->destroy_user_data(bo, bo->user_data); 155 bo->destroy_user_data = NULL; 156 bo->user_data = NULL; 157 } 158 159 drv_bo_destroy(bo->bo); 160 free(bo); 161 } 162 163 PUBLIC struct gbm_bo *gbm_bo_import(struct gbm_device *gbm, uint32_t type, void *buffer, 164 uint32_t usage) 165 { 166 struct gbm_bo *bo; 167 struct drv_import_fd_data drv_data; 168 struct gbm_import_fd_data *fd_data = buffer; 169 struct gbm_import_fd_planar_data *fd_planar_data = buffer; 170 uint32_t gbm_format; 171 size_t num_planes, i; 172 173 memset(&drv_data, 0, sizeof(drv_data)); 174 drv_data.use_flags = gbm_convert_usage(usage); 175 switch (type) { 176 case GBM_BO_IMPORT_FD: 177 gbm_format = fd_data->format; 178 drv_data.width = fd_data->width; 179 drv_data.height = fd_data->height; 180 drv_data.format = fd_data->format; 181 drv_data.fds[0] = fd_data->fd; 182 drv_data.strides[0] = fd_data->stride; 183 break; 184 case GBM_BO_IMPORT_FD_PLANAR: 185 gbm_format = fd_planar_data->format; 186 drv_data.width = fd_planar_data->width; 187 drv_data.height = fd_planar_data->height; 188 drv_data.format = fd_planar_data->format; 189 num_planes = drv_num_planes_from_format(drv_data.format); 190 191 assert(num_planes); 192 193 for (i = 0; i < num_planes; i++) { 194 drv_data.fds[i] = fd_planar_data->fds[i]; 195 drv_data.offsets[i] = fd_planar_data->offsets[i]; 196 drv_data.strides[i] = fd_planar_data->strides[i]; 197 drv_data.format_modifiers[i] = fd_planar_data->format_modifiers[i]; 198 } 199 200 for (i = num_planes; i < GBM_MAX_PLANES; i++) 201 drv_data.fds[i] = -1; 202 203 break; 204 default: 205 return NULL; 206 } 207 208 if (!gbm_device_is_format_supported(gbm, gbm_format, usage)) 209 return NULL; 210 211 bo = gbm_bo_new(gbm, gbm_format); 212 213 if (!bo) 214 return NULL; 215 216 bo->bo = drv_bo_import(gbm->drv, &drv_data); 217 218 if (!bo->bo) { 219 free(bo); 220 return NULL; 221 } 222 223 return bo; 224 } 225 226 PUBLIC void *gbm_bo_map(struct gbm_bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height, 227 uint32_t transfer_flags, uint32_t *stride, void **map_data, size_t plane) 228 { 229 void *addr; 230 off_t offset; 231 uint32_t map_flags; 232 struct rectangle rect = { .x = x, .y = y, .width = width, .height = height }; 233 if (!bo || width == 0 || height == 0 || !stride || !map_data) 234 return NULL; 235 236 map_flags = (transfer_flags & GBM_BO_TRANSFER_READ) ? BO_MAP_READ : BO_MAP_NONE; 237 map_flags |= (transfer_flags & GBM_BO_TRANSFER_WRITE) ? BO_MAP_WRITE : BO_MAP_NONE; 238 239 addr = drv_bo_map(bo->bo, &rect, map_flags, (struct mapping **)map_data, plane); 240 if (addr == MAP_FAILED) 241 return MAP_FAILED; 242 243 *stride = ((struct mapping *)*map_data)->vma->map_strides[plane]; 244 245 offset = *stride * rect.y; 246 offset += drv_stride_from_format(bo->gbm_format, rect.x, plane); 247 return (void *)((uint8_t *)addr + offset); 248 } 249 250 PUBLIC void gbm_bo_unmap(struct gbm_bo *bo, void *map_data) 251 { 252 assert(bo); 253 drv_bo_flush_or_unmap(bo->bo, map_data); 254 } 255 256 PUBLIC uint32_t gbm_bo_get_width(struct gbm_bo *bo) 257 { 258 return drv_bo_get_width(bo->bo); 259 } 260 261 PUBLIC uint32_t gbm_bo_get_height(struct gbm_bo *bo) 262 { 263 return drv_bo_get_height(bo->bo); 264 } 265 266 PUBLIC uint32_t gbm_bo_get_stride(struct gbm_bo *bo) 267 { 268 return gbm_bo_get_plane_stride(bo, 0); 269 } 270 271 PUBLIC uint32_t gbm_bo_get_stride_or_tiling(struct gbm_bo *bo) 272 { 273 return drv_bo_get_stride_or_tiling(bo->bo); 274 } 275 276 PUBLIC uint32_t gbm_bo_get_format(struct gbm_bo *bo) 277 { 278 return bo->gbm_format; 279 } 280 281 PUBLIC uint64_t gbm_bo_get_format_modifier(struct gbm_bo *bo) 282 { 283 return gbm_bo_get_plane_format_modifier(bo, 0); 284 } 285 286 PUBLIC struct gbm_device *gbm_bo_get_device(struct gbm_bo *bo) 287 { 288 return bo->gbm; 289 } 290 291 PUBLIC union gbm_bo_handle gbm_bo_get_handle(struct gbm_bo *bo) 292 { 293 return gbm_bo_get_plane_handle(bo, 0); 294 } 295 296 PUBLIC int gbm_bo_get_fd(struct gbm_bo *bo) 297 { 298 return gbm_bo_get_plane_fd(bo, 0); 299 } 300 301 PUBLIC size_t gbm_bo_get_num_planes(struct gbm_bo *bo) 302 { 303 return drv_bo_get_num_planes(bo->bo); 304 } 305 306 PUBLIC union gbm_bo_handle gbm_bo_get_plane_handle(struct gbm_bo *bo, size_t plane) 307 { 308 return (union gbm_bo_handle)drv_bo_get_plane_handle(bo->bo, plane).u64; 309 } 310 311 PUBLIC int gbm_bo_get_plane_fd(struct gbm_bo *bo, size_t plane) 312 { 313 return drv_bo_get_plane_fd(bo->bo, plane); 314 } 315 316 PUBLIC uint32_t gbm_bo_get_plane_offset(struct gbm_bo *bo, size_t plane) 317 { 318 return drv_bo_get_plane_offset(bo->bo, plane); 319 } 320 321 PUBLIC uint32_t gbm_bo_get_plane_size(struct gbm_bo *bo, size_t plane) 322 { 323 return drv_bo_get_plane_size(bo->bo, plane); 324 } 325 326 PUBLIC uint32_t gbm_bo_get_plane_stride(struct gbm_bo *bo, size_t plane) 327 { 328 return drv_bo_get_plane_stride(bo->bo, plane); 329 } 330 331 PUBLIC uint64_t gbm_bo_get_plane_format_modifier(struct gbm_bo *bo, size_t plane) 332 { 333 return drv_bo_get_plane_format_modifier(bo->bo, plane); 334 } 335 336 PUBLIC void gbm_bo_set_user_data(struct gbm_bo *bo, void *data, 337 void (*destroy_user_data)(struct gbm_bo *, void *)) 338 { 339 bo->user_data = data; 340 bo->destroy_user_data = destroy_user_data; 341 } 342 343 PUBLIC void *gbm_bo_get_user_data(struct gbm_bo *bo) 344 { 345 return bo->user_data; 346 } 347