Home | History | Annotate | Download | only in modetest
      1 /*
      2  * DRM based mode setting test program
      3  * Copyright 2008 Tungsten Graphics
      4  *   Jakob Bornecrantz <jakob (at) tungstengraphics.com>
      5  * Copyright 2008 Intel Corporation
      6  *   Jesse Barnes <jesse.barnes (at) intel.com>
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining a
      9  * copy of this software and associated documentation files (the "Software"),
     10  * to deal in the Software without restriction, including without limitation
     11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     12  * and/or sell copies of the Software, and to permit persons to whom the
     13  * Software is furnished to do so, subject to the following conditions:
     14  *
     15  * The above copyright notice and this permission notice shall be included in
     16  * all copies or substantial portions of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     24  * IN THE SOFTWARE.
     25  */
     26 
     27 #include <assert.h>
     28 #include <errno.h>
     29 #include <stdio.h>
     30 #include <stdlib.h>
     31 #include <stdint.h>
     32 #include <string.h>
     33 #include <sys/ioctl.h>
     34 
     35 #include "drm.h"
     36 #include "drm_fourcc.h"
     37 
     38 #include "libdrm_macros.h"
     39 #include "xf86drm.h"
     40 
     41 #include "buffers.h"
     42 
     43 struct bo
     44 {
     45 	int fd;
     46 	void *ptr;
     47 	size_t size;
     48 	size_t offset;
     49 	size_t pitch;
     50 	unsigned handle;
     51 };
     52 
     53 /* -----------------------------------------------------------------------------
     54  * Buffers management
     55  */
     56 
     57 static struct bo *
     58 bo_create_dumb(int fd, unsigned int width, unsigned int height, unsigned int bpp)
     59 {
     60 	struct drm_mode_create_dumb arg;
     61 	struct bo *bo;
     62 	int ret;
     63 
     64 	bo = calloc(1, sizeof(*bo));
     65 	if (bo == NULL) {
     66 		fprintf(stderr, "failed to allocate buffer object\n");
     67 		return NULL;
     68 	}
     69 
     70 	memset(&arg, 0, sizeof(arg));
     71 	arg.bpp = bpp;
     72 	arg.width = width;
     73 	arg.height = height;
     74 
     75 	ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg);
     76 	if (ret) {
     77 		fprintf(stderr, "failed to create dumb buffer: %s\n",
     78 			strerror(errno));
     79 		free(bo);
     80 		return NULL;
     81 	}
     82 
     83 	bo->fd = fd;
     84 	bo->handle = arg.handle;
     85 	bo->size = arg.size;
     86 	bo->pitch = arg.pitch;
     87 
     88 	return bo;
     89 }
     90 
     91 static int bo_map(struct bo *bo, void **out)
     92 {
     93 	struct drm_mode_map_dumb arg;
     94 	void *map;
     95 	int ret;
     96 
     97 	memset(&arg, 0, sizeof(arg));
     98 	arg.handle = bo->handle;
     99 
    100 	ret = drmIoctl(bo->fd, DRM_IOCTL_MODE_MAP_DUMB, &arg);
    101 	if (ret)
    102 		return ret;
    103 
    104 	map = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
    105 		       bo->fd, arg.offset);
    106 	if (map == MAP_FAILED)
    107 		return -EINVAL;
    108 
    109 	bo->ptr = map;
    110 	*out = map;
    111 
    112 	return 0;
    113 }
    114 
    115 static void bo_unmap(struct bo *bo)
    116 {
    117 	if (!bo->ptr)
    118 		return;
    119 
    120 	drm_munmap(bo->ptr, bo->size);
    121 	bo->ptr = NULL;
    122 }
    123 
    124 struct bo *
    125 bo_create(int fd, unsigned int format,
    126 	  unsigned int width, unsigned int height,
    127 	  unsigned int handles[4], unsigned int pitches[4],
    128 	  unsigned int offsets[4], enum util_fill_pattern pattern)
    129 {
    130 	unsigned int virtual_height;
    131 	struct bo *bo;
    132 	unsigned int bpp;
    133 	void *planes[3] = { 0, };
    134 	void *virtual;
    135 	int ret;
    136 
    137 	switch (format) {
    138 	case DRM_FORMAT_NV12:
    139 	case DRM_FORMAT_NV21:
    140 	case DRM_FORMAT_NV16:
    141 	case DRM_FORMAT_NV61:
    142 	case DRM_FORMAT_YUV420:
    143 	case DRM_FORMAT_YVU420:
    144 		bpp = 8;
    145 		break;
    146 
    147 	case DRM_FORMAT_ARGB4444:
    148 	case DRM_FORMAT_XRGB4444:
    149 	case DRM_FORMAT_ABGR4444:
    150 	case DRM_FORMAT_XBGR4444:
    151 	case DRM_FORMAT_RGBA4444:
    152 	case DRM_FORMAT_RGBX4444:
    153 	case DRM_FORMAT_BGRA4444:
    154 	case DRM_FORMAT_BGRX4444:
    155 	case DRM_FORMAT_ARGB1555:
    156 	case DRM_FORMAT_XRGB1555:
    157 	case DRM_FORMAT_ABGR1555:
    158 	case DRM_FORMAT_XBGR1555:
    159 	case DRM_FORMAT_RGBA5551:
    160 	case DRM_FORMAT_RGBX5551:
    161 	case DRM_FORMAT_BGRA5551:
    162 	case DRM_FORMAT_BGRX5551:
    163 	case DRM_FORMAT_RGB565:
    164 	case DRM_FORMAT_BGR565:
    165 	case DRM_FORMAT_UYVY:
    166 	case DRM_FORMAT_VYUY:
    167 	case DRM_FORMAT_YUYV:
    168 	case DRM_FORMAT_YVYU:
    169 		bpp = 16;
    170 		break;
    171 
    172 	case DRM_FORMAT_BGR888:
    173 	case DRM_FORMAT_RGB888:
    174 		bpp = 24;
    175 		break;
    176 
    177 	case DRM_FORMAT_ARGB8888:
    178 	case DRM_FORMAT_XRGB8888:
    179 	case DRM_FORMAT_ABGR8888:
    180 	case DRM_FORMAT_XBGR8888:
    181 	case DRM_FORMAT_RGBA8888:
    182 	case DRM_FORMAT_RGBX8888:
    183 	case DRM_FORMAT_BGRA8888:
    184 	case DRM_FORMAT_BGRX8888:
    185 	case DRM_FORMAT_ARGB2101010:
    186 	case DRM_FORMAT_XRGB2101010:
    187 	case DRM_FORMAT_ABGR2101010:
    188 	case DRM_FORMAT_XBGR2101010:
    189 	case DRM_FORMAT_RGBA1010102:
    190 	case DRM_FORMAT_RGBX1010102:
    191 	case DRM_FORMAT_BGRA1010102:
    192 	case DRM_FORMAT_BGRX1010102:
    193 		bpp = 32;
    194 		break;
    195 
    196 	default:
    197 		fprintf(stderr, "unsupported format 0x%08x\n",  format);
    198 		return NULL;
    199 	}
    200 
    201 	switch (format) {
    202 	case DRM_FORMAT_NV12:
    203 	case DRM_FORMAT_NV21:
    204 	case DRM_FORMAT_YUV420:
    205 	case DRM_FORMAT_YVU420:
    206 		virtual_height = height * 3 / 2;
    207 		break;
    208 
    209 	case DRM_FORMAT_NV16:
    210 	case DRM_FORMAT_NV61:
    211 		virtual_height = height * 2;
    212 		break;
    213 
    214 	default:
    215 		virtual_height = height;
    216 		break;
    217 	}
    218 
    219 	bo = bo_create_dumb(fd, width, virtual_height, bpp);
    220 	if (!bo)
    221 		return NULL;
    222 
    223 	ret = bo_map(bo, &virtual);
    224 	if (ret) {
    225 		fprintf(stderr, "failed to map buffer: %s\n",
    226 			strerror(-errno));
    227 		bo_destroy(bo);
    228 		return NULL;
    229 	}
    230 
    231 	/* just testing a limited # of formats to test single
    232 	 * and multi-planar path.. would be nice to add more..
    233 	 */
    234 	switch (format) {
    235 	case DRM_FORMAT_UYVY:
    236 	case DRM_FORMAT_VYUY:
    237 	case DRM_FORMAT_YUYV:
    238 	case DRM_FORMAT_YVYU:
    239 		offsets[0] = 0;
    240 		handles[0] = bo->handle;
    241 		pitches[0] = bo->pitch;
    242 
    243 		planes[0] = virtual;
    244 		break;
    245 
    246 	case DRM_FORMAT_NV12:
    247 	case DRM_FORMAT_NV21:
    248 	case DRM_FORMAT_NV16:
    249 	case DRM_FORMAT_NV61:
    250 		offsets[0] = 0;
    251 		handles[0] = bo->handle;
    252 		pitches[0] = bo->pitch;
    253 		pitches[1] = pitches[0];
    254 		offsets[1] = pitches[0] * height;
    255 		handles[1] = bo->handle;
    256 
    257 		planes[0] = virtual;
    258 		planes[1] = virtual + offsets[1];
    259 		break;
    260 
    261 	case DRM_FORMAT_YUV420:
    262 	case DRM_FORMAT_YVU420:
    263 		offsets[0] = 0;
    264 		handles[0] = bo->handle;
    265 		pitches[0] = bo->pitch;
    266 		pitches[1] = pitches[0] / 2;
    267 		offsets[1] = pitches[0] * height;
    268 		handles[1] = bo->handle;
    269 		pitches[2] = pitches[1];
    270 		offsets[2] = offsets[1] + pitches[1] * height / 2;
    271 		handles[2] = bo->handle;
    272 
    273 		planes[0] = virtual;
    274 		planes[1] = virtual + offsets[1];
    275 		planes[2] = virtual + offsets[2];
    276 		break;
    277 
    278 	case DRM_FORMAT_ARGB4444:
    279 	case DRM_FORMAT_XRGB4444:
    280 	case DRM_FORMAT_ABGR4444:
    281 	case DRM_FORMAT_XBGR4444:
    282 	case DRM_FORMAT_RGBA4444:
    283 	case DRM_FORMAT_RGBX4444:
    284 	case DRM_FORMAT_BGRA4444:
    285 	case DRM_FORMAT_BGRX4444:
    286 	case DRM_FORMAT_ARGB1555:
    287 	case DRM_FORMAT_XRGB1555:
    288 	case DRM_FORMAT_ABGR1555:
    289 	case DRM_FORMAT_XBGR1555:
    290 	case DRM_FORMAT_RGBA5551:
    291 	case DRM_FORMAT_RGBX5551:
    292 	case DRM_FORMAT_BGRA5551:
    293 	case DRM_FORMAT_BGRX5551:
    294 	case DRM_FORMAT_RGB565:
    295 	case DRM_FORMAT_BGR565:
    296 	case DRM_FORMAT_BGR888:
    297 	case DRM_FORMAT_RGB888:
    298 	case DRM_FORMAT_ARGB8888:
    299 	case DRM_FORMAT_XRGB8888:
    300 	case DRM_FORMAT_ABGR8888:
    301 	case DRM_FORMAT_XBGR8888:
    302 	case DRM_FORMAT_RGBA8888:
    303 	case DRM_FORMAT_RGBX8888:
    304 	case DRM_FORMAT_BGRA8888:
    305 	case DRM_FORMAT_BGRX8888:
    306 	case DRM_FORMAT_ARGB2101010:
    307 	case DRM_FORMAT_XRGB2101010:
    308 	case DRM_FORMAT_ABGR2101010:
    309 	case DRM_FORMAT_XBGR2101010:
    310 	case DRM_FORMAT_RGBA1010102:
    311 	case DRM_FORMAT_RGBX1010102:
    312 	case DRM_FORMAT_BGRA1010102:
    313 	case DRM_FORMAT_BGRX1010102:
    314 		offsets[0] = 0;
    315 		handles[0] = bo->handle;
    316 		pitches[0] = bo->pitch;
    317 
    318 		planes[0] = virtual;
    319 		break;
    320 	}
    321 
    322 	util_fill_pattern(format, pattern, planes, width, height, pitches[0]);
    323 	bo_unmap(bo);
    324 
    325 	return bo;
    326 }
    327 
    328 void bo_destroy(struct bo *bo)
    329 {
    330 	struct drm_mode_destroy_dumb arg;
    331 	int ret;
    332 
    333 	memset(&arg, 0, sizeof(arg));
    334 	arg.handle = bo->handle;
    335 
    336 	ret = drmIoctl(bo->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg);
    337 	if (ret)
    338 		fprintf(stderr, "failed to destroy dumb buffer: %s\n",
    339 			strerror(errno));
    340 
    341 	free(bo);
    342 }
    343