buffers.c revision bbff01ce
1/* 2 * DRM based mode setting test program 3 * Copyright 2008 Tungsten Graphics 4 * Jakob Bornecrantz <jakob@tungstengraphics.com> 5 * Copyright 2008 Intel Corporation 6 * Jesse Barnes <jesse.barnes@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#include "xf86drmMode.h" 41 42#include "buffers.h" 43 44struct bo 45{ 46 int fd; 47 void *ptr; 48 uint64_t size; 49 uint32_t pitch; 50 uint32_t handle; 51}; 52 53/* ----------------------------------------------------------------------------- 54 * Buffers management 55 */ 56 57static struct bo * 58bo_create_dumb(int fd, unsigned int width, unsigned int height, unsigned int bpp) 59{ 60 struct bo *bo; 61 int ret; 62 63 bo = calloc(1, sizeof(*bo)); 64 if (bo == NULL) { 65 fprintf(stderr, "failed to allocate buffer object\n"); 66 return NULL; 67 } 68 69 ret = drmModeCreateDumbBuffer(fd, width, height, bpp, 0, &bo->handle, 70 &bo->pitch, &bo->size); 71 if (ret) { 72 fprintf(stderr, "failed to create dumb buffer: %s\n", 73 strerror(errno)); 74 free(bo); 75 return NULL; 76 } 77 78 bo->fd = fd; 79 80 return bo; 81} 82 83static int bo_map(struct bo *bo, void **out) 84{ 85 void *map; 86 int ret; 87 uint64_t offset; 88 89 ret = drmModeMapDumbBuffer(bo->fd, bo->handle, &offset); 90 if (ret) 91 return ret; 92 93 map = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, 94 bo->fd, offset); 95 if (map == MAP_FAILED) 96 return -EINVAL; 97 98 bo->ptr = map; 99 *out = map; 100 101 return 0; 102} 103 104static void bo_unmap(struct bo *bo) 105{ 106 if (!bo->ptr) 107 return; 108 109 drm_munmap(bo->ptr, bo->size); 110 bo->ptr = NULL; 111} 112 113struct bo * 114bo_create(int fd, unsigned int format, 115 unsigned int width, unsigned int height, 116 unsigned int handles[4], unsigned int pitches[4], 117 unsigned int offsets[4], enum util_fill_pattern pattern) 118{ 119 unsigned int virtual_height; 120 struct bo *bo; 121 unsigned int bpp; 122 void *planes[3] = { 0, }; 123 void *virtual; 124 int ret; 125 126 switch (format) { 127 case DRM_FORMAT_C1: 128 bpp = 1; 129 break; 130 131 case DRM_FORMAT_C2: 132 bpp = 2; 133 break; 134 135 case DRM_FORMAT_C4: 136 bpp = 4; 137 break; 138 139 case DRM_FORMAT_C8: 140 case DRM_FORMAT_NV12: 141 case DRM_FORMAT_NV21: 142 case DRM_FORMAT_NV16: 143 case DRM_FORMAT_NV61: 144 case DRM_FORMAT_NV24: 145 case DRM_FORMAT_NV42: 146 case DRM_FORMAT_YUV420: 147 case DRM_FORMAT_YVU420: 148 bpp = 8; 149 break; 150 151 case DRM_FORMAT_NV15: 152 case DRM_FORMAT_NV20: 153 case DRM_FORMAT_NV30: 154 bpp = 10; 155 break; 156 157 case DRM_FORMAT_ARGB4444: 158 case DRM_FORMAT_XRGB4444: 159 case DRM_FORMAT_ABGR4444: 160 case DRM_FORMAT_XBGR4444: 161 case DRM_FORMAT_RGBA4444: 162 case DRM_FORMAT_RGBX4444: 163 case DRM_FORMAT_BGRA4444: 164 case DRM_FORMAT_BGRX4444: 165 case DRM_FORMAT_ARGB1555: 166 case DRM_FORMAT_XRGB1555: 167 case DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN: 168 case DRM_FORMAT_ABGR1555: 169 case DRM_FORMAT_XBGR1555: 170 case DRM_FORMAT_RGBA5551: 171 case DRM_FORMAT_RGBX5551: 172 case DRM_FORMAT_BGRA5551: 173 case DRM_FORMAT_BGRX5551: 174 case DRM_FORMAT_RGB565: 175 case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN: 176 case DRM_FORMAT_BGR565: 177 case DRM_FORMAT_UYVY: 178 case DRM_FORMAT_VYUY: 179 case DRM_FORMAT_YUYV: 180 case DRM_FORMAT_YVYU: 181 bpp = 16; 182 break; 183 184 case DRM_FORMAT_BGR888: 185 case DRM_FORMAT_RGB888: 186 bpp = 24; 187 break; 188 189 case DRM_FORMAT_ARGB8888: 190 case DRM_FORMAT_XRGB8888: 191 case DRM_FORMAT_ABGR8888: 192 case DRM_FORMAT_XBGR8888: 193 case DRM_FORMAT_RGBA8888: 194 case DRM_FORMAT_RGBX8888: 195 case DRM_FORMAT_BGRA8888: 196 case DRM_FORMAT_BGRX8888: 197 case DRM_FORMAT_ARGB2101010: 198 case DRM_FORMAT_XRGB2101010: 199 case DRM_FORMAT_ABGR2101010: 200 case DRM_FORMAT_XBGR2101010: 201 case DRM_FORMAT_RGBA1010102: 202 case DRM_FORMAT_RGBX1010102: 203 case DRM_FORMAT_BGRA1010102: 204 case DRM_FORMAT_BGRX1010102: 205 bpp = 32; 206 break; 207 208 case DRM_FORMAT_XRGB16161616F: 209 case DRM_FORMAT_XBGR16161616F: 210 case DRM_FORMAT_ARGB16161616F: 211 case DRM_FORMAT_ABGR16161616F: 212 bpp = 64; 213 break; 214 215 default: 216 fprintf(stderr, "unsupported format 0x%08x\n", format); 217 return NULL; 218 } 219 220 switch (format) { 221 case DRM_FORMAT_NV12: 222 case DRM_FORMAT_NV21: 223 case DRM_FORMAT_NV15: 224 case DRM_FORMAT_YUV420: 225 case DRM_FORMAT_YVU420: 226 virtual_height = height * 3 / 2; 227 break; 228 229 case DRM_FORMAT_NV16: 230 case DRM_FORMAT_NV61: 231 case DRM_FORMAT_NV20: 232 virtual_height = height * 2; 233 break; 234 235 case DRM_FORMAT_NV24: 236 case DRM_FORMAT_NV42: 237 case DRM_FORMAT_NV30: 238 virtual_height = height * 3; 239 break; 240 241 default: 242 virtual_height = height; 243 break; 244 } 245 246 bo = bo_create_dumb(fd, width, virtual_height, bpp); 247 if (!bo) 248 return NULL; 249 250 ret = bo_map(bo, &virtual); 251 if (ret) { 252 fprintf(stderr, "failed to map buffer: %s\n", 253 strerror(-errno)); 254 bo_destroy(bo); 255 return NULL; 256 } 257 258 /* just testing a limited # of formats to test single 259 * and multi-planar path.. would be nice to add more.. 260 */ 261 switch (format) { 262 case DRM_FORMAT_UYVY: 263 case DRM_FORMAT_VYUY: 264 case DRM_FORMAT_YUYV: 265 case DRM_FORMAT_YVYU: 266 offsets[0] = 0; 267 handles[0] = bo->handle; 268 pitches[0] = bo->pitch; 269 270 planes[0] = virtual; 271 break; 272 273 case DRM_FORMAT_NV12: 274 case DRM_FORMAT_NV21: 275 case DRM_FORMAT_NV16: 276 case DRM_FORMAT_NV61: 277 case DRM_FORMAT_NV15: 278 case DRM_FORMAT_NV20: 279 offsets[0] = 0; 280 handles[0] = bo->handle; 281 pitches[0] = bo->pitch; 282 pitches[1] = pitches[0]; 283 offsets[1] = pitches[0] * height; 284 handles[1] = bo->handle; 285 286 planes[0] = virtual; 287 planes[1] = virtual + offsets[1]; 288 break; 289 290 case DRM_FORMAT_NV24: 291 case DRM_FORMAT_NV42: 292 case DRM_FORMAT_NV30: 293 offsets[0] = 0; 294 handles[0] = bo->handle; 295 pitches[0] = bo->pitch; 296 pitches[1] = pitches[0] * 2; 297 offsets[1] = pitches[0] * height; 298 handles[1] = bo->handle; 299 300 planes[0] = virtual; 301 planes[1] = virtual + offsets[1]; 302 break; 303 304 case DRM_FORMAT_YUV420: 305 case DRM_FORMAT_YVU420: 306 offsets[0] = 0; 307 handles[0] = bo->handle; 308 pitches[0] = bo->pitch; 309 pitches[1] = pitches[0] / 2; 310 offsets[1] = pitches[0] * height; 311 handles[1] = bo->handle; 312 pitches[2] = pitches[1]; 313 offsets[2] = offsets[1] + pitches[1] * height / 2; 314 handles[2] = bo->handle; 315 316 planes[0] = virtual; 317 planes[1] = virtual + offsets[1]; 318 planes[2] = virtual + offsets[2]; 319 break; 320 321 case DRM_FORMAT_C1: 322 case DRM_FORMAT_C2: 323 case DRM_FORMAT_C4: 324 case DRM_FORMAT_C8: 325 case DRM_FORMAT_ARGB4444: 326 case DRM_FORMAT_XRGB4444: 327 case DRM_FORMAT_ABGR4444: 328 case DRM_FORMAT_XBGR4444: 329 case DRM_FORMAT_RGBA4444: 330 case DRM_FORMAT_RGBX4444: 331 case DRM_FORMAT_BGRA4444: 332 case DRM_FORMAT_BGRX4444: 333 case DRM_FORMAT_ARGB1555: 334 case DRM_FORMAT_XRGB1555: 335 case DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN: 336 case DRM_FORMAT_ABGR1555: 337 case DRM_FORMAT_XBGR1555: 338 case DRM_FORMAT_RGBA5551: 339 case DRM_FORMAT_RGBX5551: 340 case DRM_FORMAT_BGRA5551: 341 case DRM_FORMAT_BGRX5551: 342 case DRM_FORMAT_RGB565: 343 case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN: 344 case DRM_FORMAT_BGR565: 345 case DRM_FORMAT_BGR888: 346 case DRM_FORMAT_RGB888: 347 case DRM_FORMAT_ARGB8888: 348 case DRM_FORMAT_XRGB8888: 349 case DRM_FORMAT_ABGR8888: 350 case DRM_FORMAT_XBGR8888: 351 case DRM_FORMAT_RGBA8888: 352 case DRM_FORMAT_RGBX8888: 353 case DRM_FORMAT_BGRA8888: 354 case DRM_FORMAT_BGRX8888: 355 case DRM_FORMAT_ARGB2101010: 356 case DRM_FORMAT_XRGB2101010: 357 case DRM_FORMAT_ABGR2101010: 358 case DRM_FORMAT_XBGR2101010: 359 case DRM_FORMAT_RGBA1010102: 360 case DRM_FORMAT_RGBX1010102: 361 case DRM_FORMAT_BGRA1010102: 362 case DRM_FORMAT_BGRX1010102: 363 case DRM_FORMAT_XRGB16161616F: 364 case DRM_FORMAT_XBGR16161616F: 365 case DRM_FORMAT_ARGB16161616F: 366 case DRM_FORMAT_ABGR16161616F: 367 offsets[0] = 0; 368 handles[0] = bo->handle; 369 pitches[0] = bo->pitch; 370 371 planes[0] = virtual; 372 break; 373 } 374 375 util_fill_pattern(format, pattern, planes, width, height, pitches[0]); 376 bo_unmap(bo); 377 378 return bo; 379} 380 381void bo_destroy(struct bo *bo) 382{ 383 int ret; 384 385 ret = drmModeDestroyDumbBuffer(bo->fd, bo->handle); 386 if (ret) 387 fprintf(stderr, "failed to destroy dumb buffer: %s\n", 388 strerror(errno)); 389 390 free(bo); 391} 392 393void bo_dump(struct bo *bo, const char *filename) 394{ 395 FILE *fp; 396 397 if (!bo || !filename) 398 return; 399 400 fp = fopen(filename, "wb"); 401 if (fp) { 402 void *addr; 403 404 bo_map(bo, &addr); 405 printf("Dumping buffer %p to file %s.\n", bo->ptr, filename); 406 fwrite(bo->ptr, 1, bo->size, fp); 407 bo_unmap(bo); 408 fclose(fp); 409 } 410} 411