Home | History | Annotate | Download | only in minigbm
      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 <errno.h>
      9 #include <stdbool.h>
     10 #include <stdio.h>
     11 #include <stdlib.h>
     12 #include <string.h>
     13 #include <sys/mman.h>
     14 #include <xf86drm.h>
     15 #include <xf86drmMode.h>
     16 
     17 #include "drv_priv.h"
     18 #include "helpers.h"
     19 #include "util.h"
     20 
     21 struct planar_layout {
     22 	size_t num_planes;
     23 	int horizontal_subsampling[DRV_MAX_PLANES];
     24 	int vertical_subsampling[DRV_MAX_PLANES];
     25 	int bytes_per_pixel[DRV_MAX_PLANES];
     26 };
     27 
     28 // clang-format off
     29 
     30 static const struct planar_layout packed_1bpp_layout = {
     31 	.num_planes = 1,
     32 	.horizontal_subsampling = { 1 },
     33 	.vertical_subsampling = { 1 },
     34 	.bytes_per_pixel = { 1 }
     35 };
     36 
     37 static const struct planar_layout packed_2bpp_layout = {
     38 	.num_planes = 1,
     39 	.horizontal_subsampling = { 1 },
     40 	.vertical_subsampling = { 1 },
     41 	.bytes_per_pixel = { 2 }
     42 };
     43 
     44 static const struct planar_layout packed_3bpp_layout = {
     45 	.num_planes = 1,
     46 	.horizontal_subsampling = { 1 },
     47 	.vertical_subsampling = { 1 },
     48 	.bytes_per_pixel = { 3 }
     49 };
     50 
     51 static const struct planar_layout packed_4bpp_layout = {
     52 	.num_planes = 1,
     53 	.horizontal_subsampling = { 1 },
     54 	.vertical_subsampling = { 1 },
     55 	.bytes_per_pixel = { 4 }
     56 };
     57 
     58 static const struct planar_layout biplanar_yuv_420_layout = {
     59 	.num_planes = 2,
     60 	.horizontal_subsampling = { 1, 2 },
     61 	.vertical_subsampling = { 1, 2 },
     62 	.bytes_per_pixel = { 1, 2 }
     63 };
     64 
     65 static const struct planar_layout triplanar_yuv_420_layout = {
     66 	.num_planes = 3,
     67 	.horizontal_subsampling = { 1, 2, 2 },
     68 	.vertical_subsampling = { 1, 2, 2 },
     69 	.bytes_per_pixel = { 1, 1, 1 }
     70 };
     71 
     72 // clang-format on
     73 
     74 static const struct planar_layout *layout_from_format(uint32_t format)
     75 {
     76 	switch (format) {
     77 	case DRM_FORMAT_BGR233:
     78 	case DRM_FORMAT_C8:
     79 	case DRM_FORMAT_R8:
     80 	case DRM_FORMAT_RGB332:
     81 		return &packed_1bpp_layout;
     82 
     83 	case DRM_FORMAT_YVU420:
     84 	case DRM_FORMAT_YVU420_ANDROID:
     85 		return &triplanar_yuv_420_layout;
     86 
     87 	case DRM_FORMAT_NV12:
     88 	case DRM_FORMAT_NV21:
     89 		return &biplanar_yuv_420_layout;
     90 
     91 	case DRM_FORMAT_ABGR1555:
     92 	case DRM_FORMAT_ABGR4444:
     93 	case DRM_FORMAT_ARGB1555:
     94 	case DRM_FORMAT_ARGB4444:
     95 	case DRM_FORMAT_BGR565:
     96 	case DRM_FORMAT_BGRA4444:
     97 	case DRM_FORMAT_BGRA5551:
     98 	case DRM_FORMAT_BGRX4444:
     99 	case DRM_FORMAT_BGRX5551:
    100 	case DRM_FORMAT_GR88:
    101 	case DRM_FORMAT_RG88:
    102 	case DRM_FORMAT_RGB565:
    103 	case DRM_FORMAT_RGBA4444:
    104 	case DRM_FORMAT_RGBA5551:
    105 	case DRM_FORMAT_RGBX4444:
    106 	case DRM_FORMAT_RGBX5551:
    107 	case DRM_FORMAT_UYVY:
    108 	case DRM_FORMAT_VYUY:
    109 	case DRM_FORMAT_XBGR1555:
    110 	case DRM_FORMAT_XBGR4444:
    111 	case DRM_FORMAT_XRGB1555:
    112 	case DRM_FORMAT_XRGB4444:
    113 	case DRM_FORMAT_YUYV:
    114 	case DRM_FORMAT_YVYU:
    115 		return &packed_2bpp_layout;
    116 
    117 	case DRM_FORMAT_BGR888:
    118 	case DRM_FORMAT_RGB888:
    119 		return &packed_3bpp_layout;
    120 
    121 	case DRM_FORMAT_ABGR2101010:
    122 	case DRM_FORMAT_ABGR8888:
    123 	case DRM_FORMAT_ARGB2101010:
    124 	case DRM_FORMAT_ARGB8888:
    125 	case DRM_FORMAT_AYUV:
    126 	case DRM_FORMAT_BGRA1010102:
    127 	case DRM_FORMAT_BGRA8888:
    128 	case DRM_FORMAT_BGRX1010102:
    129 	case DRM_FORMAT_BGRX8888:
    130 	case DRM_FORMAT_RGBA1010102:
    131 	case DRM_FORMAT_RGBA8888:
    132 	case DRM_FORMAT_RGBX1010102:
    133 	case DRM_FORMAT_RGBX8888:
    134 	case DRM_FORMAT_XBGR2101010:
    135 	case DRM_FORMAT_XBGR8888:
    136 	case DRM_FORMAT_XRGB2101010:
    137 	case DRM_FORMAT_XRGB8888:
    138 		return &packed_4bpp_layout;
    139 
    140 	default:
    141 		drv_log("UNKNOWN FORMAT %d\n", format);
    142 		return NULL;
    143 	}
    144 }
    145 
    146 size_t drv_num_planes_from_format(uint32_t format)
    147 {
    148 	const struct planar_layout *layout = layout_from_format(format);
    149 
    150 	/*
    151 	 * drv_bo_new calls this function early to query number of planes and
    152 	 * considers 0 planes to mean unknown format, so we have to support
    153 	 * that.  All other layout_from_format() queries can assume that the
    154 	 * format is supported and that the return value is non-NULL.
    155 	 */
    156 
    157 	return layout ? layout->num_planes : 0;
    158 }
    159 
    160 uint32_t drv_height_from_format(uint32_t format, uint32_t height, size_t plane)
    161 {
    162 	const struct planar_layout *layout = layout_from_format(format);
    163 
    164 	assert(plane < layout->num_planes);
    165 
    166 	return DIV_ROUND_UP(height, layout->vertical_subsampling[plane]);
    167 }
    168 
    169 uint32_t drv_bytes_per_pixel_from_format(uint32_t format, size_t plane)
    170 {
    171 	const struct planar_layout *layout = layout_from_format(format);
    172 
    173 	assert(plane < layout->num_planes);
    174 
    175 	return layout->bytes_per_pixel[plane];
    176 }
    177 
    178 /*
    179  * This function returns the stride for a given format, width and plane.
    180  */
    181 uint32_t drv_stride_from_format(uint32_t format, uint32_t width, size_t plane)
    182 {
    183 	const struct planar_layout *layout = layout_from_format(format);
    184 	assert(plane < layout->num_planes);
    185 
    186 	uint32_t plane_width = DIV_ROUND_UP(width, layout->horizontal_subsampling[plane]);
    187 	uint32_t stride = plane_width * layout->bytes_per_pixel[plane];
    188 
    189 	/*
    190 	 * The stride of Android YV12 buffers is required to be aligned to 16 bytes
    191 	 * (see <system/graphics.h>).
    192 	 */
    193 	if (format == DRM_FORMAT_YVU420_ANDROID)
    194 		stride = (plane == 0) ? ALIGN(stride, 32) : ALIGN(stride, 16);
    195 
    196 	return stride;
    197 }
    198 
    199 uint32_t drv_size_from_format(uint32_t format, uint32_t stride, uint32_t height, size_t plane)
    200 {
    201 	return stride * drv_height_from_format(format, height, plane);
    202 }
    203 
    204 static uint32_t subsample_stride(uint32_t stride, uint32_t format, size_t plane)
    205 {
    206 	if (plane != 0) {
    207 		switch (format) {
    208 		case DRM_FORMAT_YVU420:
    209 		case DRM_FORMAT_YVU420_ANDROID:
    210 			stride = DIV_ROUND_UP(stride, 2);
    211 			break;
    212 		}
    213 	}
    214 
    215 	return stride;
    216 }
    217 
    218 /*
    219  * This function fills in the buffer object given the driver aligned stride of
    220  * the first plane, height and a format. This function assumes there is just
    221  * one kernel buffer per buffer object.
    222  */
    223 int drv_bo_from_format(struct bo *bo, uint32_t stride, uint32_t aligned_height, uint32_t format)
    224 {
    225 
    226 	size_t p, num_planes;
    227 	uint32_t offset = 0;
    228 
    229 	num_planes = drv_num_planes_from_format(format);
    230 	assert(num_planes);
    231 
    232 	/*
    233 	 * HAL_PIXEL_FORMAT_YV12 requires that (see <system/graphics.h>):
    234 	 *  - the aligned height is same as the buffer's height.
    235 	 *  - the chroma stride is 16 bytes aligned, i.e., the luma's strides
    236 	 *    is 32 bytes aligned.
    237 	 */
    238 	if (format == DRM_FORMAT_YVU420_ANDROID) {
    239 		assert(aligned_height == bo->height);
    240 		assert(stride == ALIGN(stride, 32));
    241 	}
    242 
    243 	for (p = 0; p < num_planes; p++) {
    244 		bo->strides[p] = subsample_stride(stride, format, p);
    245 		bo->sizes[p] = drv_size_from_format(format, bo->strides[p], aligned_height, p);
    246 		bo->offsets[p] = offset;
    247 		offset += bo->sizes[p];
    248 	}
    249 
    250 	bo->total_size = offset;
    251 	return 0;
    252 }
    253 
    254 int drv_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
    255 		       uint64_t use_flags)
    256 {
    257 	int ret;
    258 	size_t plane;
    259 	uint32_t aligned_width, aligned_height;
    260 	struct drm_mode_create_dumb create_dumb;
    261 
    262 	aligned_width = width;
    263 	aligned_height = height;
    264 	if (format == DRM_FORMAT_YVU420_ANDROID) {
    265 		/*
    266 		 * Align width to 32 pixels, so chroma strides are 16 bytes as
    267 		 * Android requires.
    268 		 */
    269 		aligned_width = ALIGN(width, 32);
    270 	}
    271 
    272 	if (format == DRM_FORMAT_YVU420_ANDROID || format == DRM_FORMAT_YVU420) {
    273 		aligned_height = 3 * DIV_ROUND_UP(height, 2);
    274 	}
    275 
    276 	memset(&create_dumb, 0, sizeof(create_dumb));
    277 	create_dumb.height = aligned_height;
    278 	create_dumb.width = aligned_width;
    279 	create_dumb.bpp = layout_from_format(format)->bytes_per_pixel[0] * 8;
    280 	create_dumb.flags = 0;
    281 
    282 	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
    283 	if (ret) {
    284 		drv_log("DRM_IOCTL_MODE_CREATE_DUMB failed (%d, %d)\n", bo->drv->fd, errno);
    285 		return ret;
    286 	}
    287 
    288 	drv_bo_from_format(bo, create_dumb.pitch, height, format);
    289 
    290 	for (plane = 0; plane < bo->num_planes; plane++)
    291 		bo->handles[plane].u32 = create_dumb.handle;
    292 
    293 	bo->total_size = create_dumb.size;
    294 	return 0;
    295 }
    296 
    297 int drv_dumb_bo_destroy(struct bo *bo)
    298 {
    299 	struct drm_mode_destroy_dumb destroy_dumb;
    300 	int ret;
    301 
    302 	memset(&destroy_dumb, 0, sizeof(destroy_dumb));
    303 	destroy_dumb.handle = bo->handles[0].u32;
    304 
    305 	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
    306 	if (ret) {
    307 		drv_log("DRM_IOCTL_MODE_DESTROY_DUMB failed (handle=%x)\n", bo->handles[0].u32);
    308 		return ret;
    309 	}
    310 
    311 	return 0;
    312 }
    313 
    314 int drv_gem_bo_destroy(struct bo *bo)
    315 {
    316 	struct drm_gem_close gem_close;
    317 	int ret, error = 0;
    318 	size_t plane, i;
    319 
    320 	for (plane = 0; plane < bo->num_planes; plane++) {
    321 		for (i = 0; i < plane; i++)
    322 			if (bo->handles[i].u32 == bo->handles[plane].u32)
    323 				break;
    324 		/* Make sure close hasn't already been called on this handle */
    325 		if (i != plane)
    326 			continue;
    327 
    328 		memset(&gem_close, 0, sizeof(gem_close));
    329 		gem_close.handle = bo->handles[plane].u32;
    330 
    331 		ret = drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
    332 		if (ret) {
    333 			drv_log("DRM_IOCTL_GEM_CLOSE failed (handle=%x) error %d\n",
    334 				bo->handles[plane].u32, ret);
    335 			error = ret;
    336 		}
    337 	}
    338 
    339 	return error;
    340 }
    341 
    342 int drv_prime_bo_import(struct bo *bo, struct drv_import_fd_data *data)
    343 {
    344 	int ret;
    345 	size_t plane;
    346 	struct drm_prime_handle prime_handle;
    347 
    348 	for (plane = 0; plane < bo->num_planes; plane++) {
    349 		memset(&prime_handle, 0, sizeof(prime_handle));
    350 		prime_handle.fd = data->fds[plane];
    351 
    352 		ret = drmIoctl(bo->drv->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime_handle);
    353 
    354 		if (ret) {
    355 			drv_log("DRM_IOCTL_PRIME_FD_TO_HANDLE failed (fd=%u)\n", prime_handle.fd);
    356 
    357 			/*
    358 			 * Need to call GEM close on planes that were opened,
    359 			 * if any. Adjust the num_planes variable to be the
    360 			 * plane that failed, so GEM close will be called on
    361 			 * planes before that plane.
    362 			 */
    363 			bo->num_planes = plane;
    364 			drv_gem_bo_destroy(bo);
    365 			return ret;
    366 		}
    367 
    368 		bo->handles[plane].u32 = prime_handle.handle;
    369 	}
    370 
    371 	for (plane = 0; plane < bo->num_planes; plane++) {
    372 		pthread_mutex_lock(&bo->drv->driver_lock);
    373 		drv_increment_reference_count(bo->drv, bo, plane);
    374 		pthread_mutex_unlock(&bo->drv->driver_lock);
    375 	}
    376 
    377 	return 0;
    378 }
    379 
    380 void *drv_dumb_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
    381 {
    382 	int ret;
    383 	size_t i;
    384 	struct drm_mode_map_dumb map_dumb;
    385 
    386 	memset(&map_dumb, 0, sizeof(map_dumb));
    387 	map_dumb.handle = bo->handles[plane].u32;
    388 
    389 	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb);
    390 	if (ret) {
    391 		drv_log("DRM_IOCTL_MODE_MAP_DUMB failed\n");
    392 		return MAP_FAILED;
    393 	}
    394 
    395 	for (i = 0; i < bo->num_planes; i++)
    396 		if (bo->handles[i].u32 == bo->handles[plane].u32)
    397 			vma->length += bo->sizes[i];
    398 
    399 	return mmap(0, vma->length, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
    400 		    map_dumb.offset);
    401 }
    402 
    403 int drv_bo_munmap(struct bo *bo, struct vma *vma)
    404 {
    405 	return munmap(vma->addr, vma->length);
    406 }
    407 
    408 int drv_mapping_destroy(struct bo *bo)
    409 {
    410 	int ret;
    411 	size_t plane;
    412 	struct mapping *mapping;
    413 	uint32_t idx;
    414 
    415 	/*
    416 	 * This function is called right before the buffer is destroyed. It will free any mappings
    417 	 * associated with the buffer.
    418 	 */
    419 
    420 	idx = 0;
    421 	for (plane = 0; plane < bo->num_planes; plane++) {
    422 		while (idx < drv_array_size(bo->drv->mappings)) {
    423 			mapping = (struct mapping *)drv_array_at_idx(bo->drv->mappings, idx);
    424 			if (mapping->vma->handle != bo->handles[plane].u32) {
    425 				idx++;
    426 				continue;
    427 			}
    428 
    429 			if (!--mapping->vma->refcount) {
    430 				ret = bo->drv->backend->bo_unmap(bo, mapping->vma);
    431 				if (ret) {
    432 					drv_log("munmap failed\n");
    433 					return ret;
    434 				}
    435 
    436 				free(mapping->vma);
    437 			}
    438 
    439 			/* This shrinks and shifts the array, so don't increment idx. */
    440 			drv_array_remove(bo->drv->mappings, idx);
    441 		}
    442 	}
    443 
    444 	return 0;
    445 }
    446 
    447 int drv_get_prot(uint32_t map_flags)
    448 {
    449 	return (BO_MAP_WRITE & map_flags) ? PROT_WRITE | PROT_READ : PROT_READ;
    450 }
    451 
    452 uintptr_t drv_get_reference_count(struct driver *drv, struct bo *bo, size_t plane)
    453 {
    454 	void *count;
    455 	uintptr_t num = 0;
    456 
    457 	if (!drmHashLookup(drv->buffer_table, bo->handles[plane].u32, &count))
    458 		num = (uintptr_t)(count);
    459 
    460 	return num;
    461 }
    462 
    463 void drv_increment_reference_count(struct driver *drv, struct bo *bo, size_t plane)
    464 {
    465 	uintptr_t num = drv_get_reference_count(drv, bo, plane);
    466 
    467 	/* If a value isn't in the table, drmHashDelete is a no-op */
    468 	drmHashDelete(drv->buffer_table, bo->handles[plane].u32);
    469 	drmHashInsert(drv->buffer_table, bo->handles[plane].u32, (void *)(num + 1));
    470 }
    471 
    472 void drv_decrement_reference_count(struct driver *drv, struct bo *bo, size_t plane)
    473 {
    474 	uintptr_t num = drv_get_reference_count(drv, bo, plane);
    475 
    476 	drmHashDelete(drv->buffer_table, bo->handles[plane].u32);
    477 
    478 	if (num > 0)
    479 		drmHashInsert(drv->buffer_table, bo->handles[plane].u32, (void *)(num - 1));
    480 }
    481 
    482 uint32_t drv_log_base2(uint32_t value)
    483 {
    484 	int ret = 0;
    485 
    486 	while (value >>= 1)
    487 		++ret;
    488 
    489 	return ret;
    490 }
    491 
    492 void drv_add_combinations(struct driver *drv, const uint32_t *formats, uint32_t num_formats,
    493 			  struct format_metadata *metadata, uint64_t use_flags)
    494 {
    495 	uint32_t i;
    496 
    497 	for (i = 0; i < num_formats; i++) {
    498 		struct combination combo = { .format = formats[i],
    499 					     .metadata = *metadata,
    500 					     .use_flags = use_flags };
    501 
    502 		drv_array_append(drv->combos, &combo);
    503 	}
    504 }
    505 
    506 void drv_modify_combination(struct driver *drv, uint32_t format, struct format_metadata *metadata,
    507 			    uint64_t use_flags)
    508 {
    509 	uint32_t i;
    510 	struct combination *combo;
    511 	/* Attempts to add the specified flags to an existing combination. */
    512 	for (i = 0; i < drv_array_size(drv->combos); i++) {
    513 		combo = (struct combination *)drv_array_at_idx(drv->combos, i);
    514 		if (combo->format == format && combo->metadata.tiling == metadata->tiling &&
    515 		    combo->metadata.modifier == metadata->modifier)
    516 			combo->use_flags |= use_flags;
    517 	}
    518 }
    519 
    520 struct drv_array *drv_query_kms(struct driver *drv)
    521 {
    522 	struct drv_array *kms_items;
    523 	uint64_t plane_type, use_flag;
    524 	uint32_t i, j, k;
    525 
    526 	drmModePlanePtr plane;
    527 	drmModePropertyPtr prop;
    528 	drmModePlaneResPtr resources;
    529 	drmModeObjectPropertiesPtr props;
    530 
    531 	kms_items = drv_array_init(sizeof(struct kms_item));
    532 	if (!kms_items)
    533 		goto out;
    534 
    535 	/*
    536 	 * The ability to return universal planes is only complete on
    537 	 * ChromeOS kernel versions >= v3.18.  The SET_CLIENT_CAP ioctl
    538 	 * therefore might return an error code, so don't check it.  If it
    539 	 * fails, it'll just return the plane list as overlay planes, which is
    540 	 * fine in our case (our drivers already have cursor bits set).
    541 	 * modetest in libdrm does the same thing.
    542 	 */
    543 	drmSetClientCap(drv->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
    544 
    545 	resources = drmModeGetPlaneResources(drv->fd);
    546 	if (!resources)
    547 		goto out;
    548 
    549 	for (i = 0; i < resources->count_planes; i++) {
    550 		plane = drmModeGetPlane(drv->fd, resources->planes[i]);
    551 		if (!plane)
    552 			goto out;
    553 
    554 		props = drmModeObjectGetProperties(drv->fd, plane->plane_id, DRM_MODE_OBJECT_PLANE);
    555 		if (!props)
    556 			goto out;
    557 
    558 		for (j = 0; j < props->count_props; j++) {
    559 			prop = drmModeGetProperty(drv->fd, props->props[j]);
    560 			if (prop) {
    561 				if (strcmp(prop->name, "type") == 0) {
    562 					plane_type = props->prop_values[j];
    563 				}
    564 
    565 				drmModeFreeProperty(prop);
    566 			}
    567 		}
    568 
    569 		switch (plane_type) {
    570 		case DRM_PLANE_TYPE_OVERLAY:
    571 		case DRM_PLANE_TYPE_PRIMARY:
    572 			use_flag = BO_USE_SCANOUT;
    573 			break;
    574 		case DRM_PLANE_TYPE_CURSOR:
    575 			use_flag = BO_USE_CURSOR;
    576 			break;
    577 		default:
    578 			assert(0);
    579 		}
    580 
    581 		for (j = 0; j < plane->count_formats; j++) {
    582 			bool found = false;
    583 			for (k = 0; k < drv_array_size(kms_items); k++) {
    584 				struct kms_item *item = drv_array_at_idx(kms_items, k);
    585 				if (item->format == plane->formats[j] &&
    586 				    item->modifier == DRM_FORMAT_MOD_LINEAR) {
    587 					item->use_flags |= use_flag;
    588 					found = true;
    589 					break;
    590 				}
    591 			}
    592 
    593 			if (!found) {
    594 				struct kms_item item = { .format = plane->formats[j],
    595 							 .modifier = DRM_FORMAT_MOD_LINEAR,
    596 							 .use_flags = use_flag };
    597 
    598 				drv_array_append(kms_items, &item);
    599 			}
    600 		}
    601 
    602 		drmModeFreeObjectProperties(props);
    603 		drmModeFreePlane(plane);
    604 	}
    605 
    606 	drmModeFreePlaneResources(resources);
    607 out:
    608 	if (kms_items && !drv_array_size(kms_items)) {
    609 		drv_array_destroy(kms_items);
    610 		return NULL;
    611 	}
    612 
    613 	return kms_items;
    614 }
    615 
    616 int drv_modify_linear_combinations(struct driver *drv)
    617 {
    618 	uint32_t i, j;
    619 	struct kms_item *item;
    620 	struct combination *combo;
    621 	struct drv_array *kms_items;
    622 
    623 	/*
    624 	 * All current drivers can scanout linear XRGB8888/ARGB8888 as a primary
    625 	 * plane and as a cursor. Some drivers don't support
    626 	 * drmModeGetPlaneResources, so add the combination here. Note that the
    627 	 * kernel disregards the alpha component of ARGB unless it's an overlay
    628 	 * plane.
    629 	 */
    630 	drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &LINEAR_METADATA,
    631 			       BO_USE_CURSOR | BO_USE_SCANOUT);
    632 	drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &LINEAR_METADATA,
    633 			       BO_USE_CURSOR | BO_USE_SCANOUT);
    634 
    635 	kms_items = drv_query_kms(drv);
    636 	if (!kms_items)
    637 		return 0;
    638 
    639 	for (i = 0; i < drv_array_size(kms_items); i++) {
    640 		item = (struct kms_item *)drv_array_at_idx(kms_items, i);
    641 		for (j = 0; j < drv_array_size(drv->combos); j++) {
    642 			combo = drv_array_at_idx(drv->combos, j);
    643 			if (item->format == combo->format)
    644 				combo->use_flags |= BO_USE_SCANOUT;
    645 		}
    646 	}
    647 
    648 	drv_array_destroy(kms_items);
    649 	return 0;
    650 }
    651 
    652 /*
    653  * Pick the best modifier from modifiers, according to the ordering
    654  * given by modifier_order.
    655  */
    656 uint64_t drv_pick_modifier(const uint64_t *modifiers, uint32_t count,
    657 			   const uint64_t *modifier_order, uint32_t order_count)
    658 {
    659 	uint32_t i, j;
    660 
    661 	for (i = 0; i < order_count; i++) {
    662 		for (j = 0; j < count; j++) {
    663 			if (modifiers[j] == modifier_order[i]) {
    664 				return modifiers[j];
    665 			}
    666 		}
    667 	}
    668 
    669 	return DRM_FORMAT_MOD_LINEAR;
    670 }
    671