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