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 #ifdef HAVE_CONFIG_H 28 #include "config.h" 29 #endif 30 31 #include <assert.h> 32 #include <errno.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <stdint.h> 36 #include <string.h> 37 #include <sys/ioctl.h> 38 39 #include "drm.h" 40 #include "drm_fourcc.h" 41 42 #include "libdrm_macros.h" 43 #include "xf86drm.h" 44 45 #include "buffers.h" 46 47 struct bo 48 { 49 int fd; 50 void *ptr; 51 size_t size; 52 size_t offset; 53 size_t pitch; 54 unsigned handle; 55 }; 56 57 /* ----------------------------------------------------------------------------- 58 * Buffers management 59 */ 60 61 static struct bo * 62 bo_create_dumb(int fd, unsigned int width, unsigned int height, unsigned int bpp) 63 { 64 struct drm_mode_create_dumb arg; 65 struct bo *bo; 66 int ret; 67 68 bo = calloc(1, sizeof(*bo)); 69 if (bo == NULL) { 70 fprintf(stderr, "failed to allocate buffer object\n"); 71 return NULL; 72 } 73 74 memset(&arg, 0, sizeof(arg)); 75 arg.bpp = bpp; 76 arg.width = width; 77 arg.height = height; 78 79 ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg); 80 if (ret) { 81 fprintf(stderr, "failed to create dumb buffer: %s\n", 82 strerror(errno)); 83 free(bo); 84 return NULL; 85 } 86 87 bo->fd = fd; 88 bo->handle = arg.handle; 89 bo->size = arg.size; 90 bo->pitch = arg.pitch; 91 92 return bo; 93 } 94 95 static int bo_map(struct bo *bo, void **out) 96 { 97 struct drm_mode_map_dumb arg; 98 void *map; 99 int ret; 100 101 memset(&arg, 0, sizeof(arg)); 102 arg.handle = bo->handle; 103 104 ret = drmIoctl(bo->fd, DRM_IOCTL_MODE_MAP_DUMB, &arg); 105 if (ret) 106 return ret; 107 108 map = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, 109 bo->fd, arg.offset); 110 if (map == MAP_FAILED) 111 return -EINVAL; 112 113 bo->ptr = map; 114 *out = map; 115 116 return 0; 117 } 118 119 static void bo_unmap(struct bo *bo) 120 { 121 if (!bo->ptr) 122 return; 123 124 drm_munmap(bo->ptr, bo->size); 125 bo->ptr = NULL; 126 } 127 128 struct bo * 129 bo_create(int fd, unsigned int format, 130 unsigned int width, unsigned int height, 131 unsigned int handles[4], unsigned int pitches[4], 132 unsigned int offsets[4], enum util_fill_pattern pattern) 133 { 134 unsigned int virtual_height; 135 struct bo *bo; 136 unsigned int bpp; 137 void *planes[3] = { 0, }; 138 void *virtual; 139 int ret; 140 141 switch (format) { 142 case DRM_FORMAT_NV12: 143 case DRM_FORMAT_NV21: 144 case DRM_FORMAT_NV16: 145 case DRM_FORMAT_NV61: 146 case DRM_FORMAT_YUV420: 147 case DRM_FORMAT_YVU420: 148 bpp = 8; 149 break; 150 151 case DRM_FORMAT_ARGB4444: 152 case DRM_FORMAT_XRGB4444: 153 case DRM_FORMAT_ABGR4444: 154 case DRM_FORMAT_XBGR4444: 155 case DRM_FORMAT_RGBA4444: 156 case DRM_FORMAT_RGBX4444: 157 case DRM_FORMAT_BGRA4444: 158 case DRM_FORMAT_BGRX4444: 159 case DRM_FORMAT_ARGB1555: 160 case DRM_FORMAT_XRGB1555: 161 case DRM_FORMAT_ABGR1555: 162 case DRM_FORMAT_XBGR1555: 163 case DRM_FORMAT_RGBA5551: 164 case DRM_FORMAT_RGBX5551: 165 case DRM_FORMAT_BGRA5551: 166 case DRM_FORMAT_BGRX5551: 167 case DRM_FORMAT_RGB565: 168 case DRM_FORMAT_BGR565: 169 case DRM_FORMAT_UYVY: 170 case DRM_FORMAT_VYUY: 171 case DRM_FORMAT_YUYV: 172 case DRM_FORMAT_YVYU: 173 bpp = 16; 174 break; 175 176 case DRM_FORMAT_BGR888: 177 case DRM_FORMAT_RGB888: 178 bpp = 24; 179 break; 180 181 case DRM_FORMAT_ARGB8888: 182 case DRM_FORMAT_XRGB8888: 183 case DRM_FORMAT_ABGR8888: 184 case DRM_FORMAT_XBGR8888: 185 case DRM_FORMAT_RGBA8888: 186 case DRM_FORMAT_RGBX8888: 187 case DRM_FORMAT_BGRA8888: 188 case DRM_FORMAT_BGRX8888: 189 case DRM_FORMAT_ARGB2101010: 190 case DRM_FORMAT_XRGB2101010: 191 case DRM_FORMAT_ABGR2101010: 192 case DRM_FORMAT_XBGR2101010: 193 case DRM_FORMAT_RGBA1010102: 194 case DRM_FORMAT_RGBX1010102: 195 case DRM_FORMAT_BGRA1010102: 196 case DRM_FORMAT_BGRX1010102: 197 bpp = 32; 198 break; 199 200 default: 201 fprintf(stderr, "unsupported format 0x%08x\n", format); 202 return NULL; 203 } 204 205 switch (format) { 206 case DRM_FORMAT_NV12: 207 case DRM_FORMAT_NV21: 208 case DRM_FORMAT_YUV420: 209 case DRM_FORMAT_YVU420: 210 virtual_height = height * 3 / 2; 211 break; 212 213 case DRM_FORMAT_NV16: 214 case DRM_FORMAT_NV61: 215 virtual_height = height * 2; 216 break; 217 218 default: 219 virtual_height = height; 220 break; 221 } 222 223 bo = bo_create_dumb(fd, width, virtual_height, bpp); 224 if (!bo) 225 return NULL; 226 227 ret = bo_map(bo, &virtual); 228 if (ret) { 229 fprintf(stderr, "failed to map buffer: %s\n", 230 strerror(-errno)); 231 bo_destroy(bo); 232 return NULL; 233 } 234 235 /* just testing a limited # of formats to test single 236 * and multi-planar path.. would be nice to add more.. 237 */ 238 switch (format) { 239 case DRM_FORMAT_UYVY: 240 case DRM_FORMAT_VYUY: 241 case DRM_FORMAT_YUYV: 242 case DRM_FORMAT_YVYU: 243 offsets[0] = 0; 244 handles[0] = bo->handle; 245 pitches[0] = bo->pitch; 246 247 planes[0] = virtual; 248 break; 249 250 case DRM_FORMAT_NV12: 251 case DRM_FORMAT_NV21: 252 case DRM_FORMAT_NV16: 253 case DRM_FORMAT_NV61: 254 offsets[0] = 0; 255 handles[0] = bo->handle; 256 pitches[0] = bo->pitch; 257 pitches[1] = pitches[0]; 258 offsets[1] = pitches[0] * height; 259 handles[1] = bo->handle; 260 261 planes[0] = virtual; 262 planes[1] = virtual + offsets[1]; 263 break; 264 265 case DRM_FORMAT_YUV420: 266 case DRM_FORMAT_YVU420: 267 offsets[0] = 0; 268 handles[0] = bo->handle; 269 pitches[0] = bo->pitch; 270 pitches[1] = pitches[0] / 2; 271 offsets[1] = pitches[0] * height; 272 handles[1] = bo->handle; 273 pitches[2] = pitches[1]; 274 offsets[2] = offsets[1] + pitches[1] * height / 2; 275 handles[2] = bo->handle; 276 277 planes[0] = virtual; 278 planes[1] = virtual + offsets[1]; 279 planes[2] = virtual + offsets[2]; 280 break; 281 282 case DRM_FORMAT_ARGB4444: 283 case DRM_FORMAT_XRGB4444: 284 case DRM_FORMAT_ABGR4444: 285 case DRM_FORMAT_XBGR4444: 286 case DRM_FORMAT_RGBA4444: 287 case DRM_FORMAT_RGBX4444: 288 case DRM_FORMAT_BGRA4444: 289 case DRM_FORMAT_BGRX4444: 290 case DRM_FORMAT_ARGB1555: 291 case DRM_FORMAT_XRGB1555: 292 case DRM_FORMAT_ABGR1555: 293 case DRM_FORMAT_XBGR1555: 294 case DRM_FORMAT_RGBA5551: 295 case DRM_FORMAT_RGBX5551: 296 case DRM_FORMAT_BGRA5551: 297 case DRM_FORMAT_BGRX5551: 298 case DRM_FORMAT_RGB565: 299 case DRM_FORMAT_BGR565: 300 case DRM_FORMAT_BGR888: 301 case DRM_FORMAT_RGB888: 302 case DRM_FORMAT_ARGB8888: 303 case DRM_FORMAT_XRGB8888: 304 case DRM_FORMAT_ABGR8888: 305 case DRM_FORMAT_XBGR8888: 306 case DRM_FORMAT_RGBA8888: 307 case DRM_FORMAT_RGBX8888: 308 case DRM_FORMAT_BGRA8888: 309 case DRM_FORMAT_BGRX8888: 310 case DRM_FORMAT_ARGB2101010: 311 case DRM_FORMAT_XRGB2101010: 312 case DRM_FORMAT_ABGR2101010: 313 case DRM_FORMAT_XBGR2101010: 314 case DRM_FORMAT_RGBA1010102: 315 case DRM_FORMAT_RGBX1010102: 316 case DRM_FORMAT_BGRA1010102: 317 case DRM_FORMAT_BGRX1010102: 318 offsets[0] = 0; 319 handles[0] = bo->handle; 320 pitches[0] = bo->pitch; 321 322 planes[0] = virtual; 323 break; 324 } 325 326 util_fill_pattern(format, pattern, planes, width, height, pitches[0]); 327 bo_unmap(bo); 328 329 return bo; 330 } 331 332 void bo_destroy(struct bo *bo) 333 { 334 struct drm_mode_destroy_dumb arg; 335 int ret; 336 337 memset(&arg, 0, sizeof(arg)); 338 arg.handle = bo->handle; 339 340 ret = drmIoctl(bo->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg); 341 if (ret) 342 fprintf(stderr, "failed to destroy dumb buffer: %s\n", 343 strerror(errno)); 344 345 free(bo); 346 } 347