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 41#include "buffers.h" 42 43struct 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 57static struct bo * 58bo_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 91static 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 115static 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 124struct bo * 125bo_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_C8: 139 case DRM_FORMAT_NV12: 140 case DRM_FORMAT_NV21: 141 case DRM_FORMAT_NV16: 142 case DRM_FORMAT_NV61: 143 case DRM_FORMAT_YUV420: 144 case DRM_FORMAT_YVU420: 145 bpp = 8; 146 break; 147 148 case DRM_FORMAT_ARGB4444: 149 case DRM_FORMAT_XRGB4444: 150 case DRM_FORMAT_ABGR4444: 151 case DRM_FORMAT_XBGR4444: 152 case DRM_FORMAT_RGBA4444: 153 case DRM_FORMAT_RGBX4444: 154 case DRM_FORMAT_BGRA4444: 155 case DRM_FORMAT_BGRX4444: 156 case DRM_FORMAT_ARGB1555: 157 case DRM_FORMAT_XRGB1555: 158 case DRM_FORMAT_ABGR1555: 159 case DRM_FORMAT_XBGR1555: 160 case DRM_FORMAT_RGBA5551: 161 case DRM_FORMAT_RGBX5551: 162 case DRM_FORMAT_BGRA5551: 163 case DRM_FORMAT_BGRX5551: 164 case DRM_FORMAT_RGB565: 165 case DRM_FORMAT_BGR565: 166 case DRM_FORMAT_UYVY: 167 case DRM_FORMAT_VYUY: 168 case DRM_FORMAT_YUYV: 169 case DRM_FORMAT_YVYU: 170 bpp = 16; 171 break; 172 173 case DRM_FORMAT_BGR888: 174 case DRM_FORMAT_RGB888: 175 bpp = 24; 176 break; 177 178 case DRM_FORMAT_ARGB8888: 179 case DRM_FORMAT_XRGB8888: 180 case DRM_FORMAT_ABGR8888: 181 case DRM_FORMAT_XBGR8888: 182 case DRM_FORMAT_RGBA8888: 183 case DRM_FORMAT_RGBX8888: 184 case DRM_FORMAT_BGRA8888: 185 case DRM_FORMAT_BGRX8888: 186 case DRM_FORMAT_ARGB2101010: 187 case DRM_FORMAT_XRGB2101010: 188 case DRM_FORMAT_ABGR2101010: 189 case DRM_FORMAT_XBGR2101010: 190 case DRM_FORMAT_RGBA1010102: 191 case DRM_FORMAT_RGBX1010102: 192 case DRM_FORMAT_BGRA1010102: 193 case DRM_FORMAT_BGRX1010102: 194 bpp = 32; 195 break; 196 197 case DRM_FORMAT_XRGB16161616F: 198 case DRM_FORMAT_XBGR16161616F: 199 case DRM_FORMAT_ARGB16161616F: 200 case DRM_FORMAT_ABGR16161616F: 201 bpp = 64; 202 break; 203 204 default: 205 fprintf(stderr, "unsupported format 0x%08x\n", format); 206 return NULL; 207 } 208 209 switch (format) { 210 case DRM_FORMAT_NV12: 211 case DRM_FORMAT_NV21: 212 case DRM_FORMAT_YUV420: 213 case DRM_FORMAT_YVU420: 214 virtual_height = height * 3 / 2; 215 break; 216 217 case DRM_FORMAT_NV16: 218 case DRM_FORMAT_NV61: 219 virtual_height = height * 2; 220 break; 221 222 default: 223 virtual_height = height; 224 break; 225 } 226 227 bo = bo_create_dumb(fd, width, virtual_height, bpp); 228 if (!bo) 229 return NULL; 230 231 ret = bo_map(bo, &virtual); 232 if (ret) { 233 fprintf(stderr, "failed to map buffer: %s\n", 234 strerror(-errno)); 235 bo_destroy(bo); 236 return NULL; 237 } 238 239 /* just testing a limited # of formats to test single 240 * and multi-planar path.. would be nice to add more.. 241 */ 242 switch (format) { 243 case DRM_FORMAT_UYVY: 244 case DRM_FORMAT_VYUY: 245 case DRM_FORMAT_YUYV: 246 case DRM_FORMAT_YVYU: 247 offsets[0] = 0; 248 handles[0] = bo->handle; 249 pitches[0] = bo->pitch; 250 251 planes[0] = virtual; 252 break; 253 254 case DRM_FORMAT_NV12: 255 case DRM_FORMAT_NV21: 256 case DRM_FORMAT_NV16: 257 case DRM_FORMAT_NV61: 258 offsets[0] = 0; 259 handles[0] = bo->handle; 260 pitches[0] = bo->pitch; 261 pitches[1] = pitches[0]; 262 offsets[1] = pitches[0] * height; 263 handles[1] = bo->handle; 264 265 planes[0] = virtual; 266 planes[1] = virtual + offsets[1]; 267 break; 268 269 case DRM_FORMAT_YUV420: 270 case DRM_FORMAT_YVU420: 271 offsets[0] = 0; 272 handles[0] = bo->handle; 273 pitches[0] = bo->pitch; 274 pitches[1] = pitches[0] / 2; 275 offsets[1] = pitches[0] * height; 276 handles[1] = bo->handle; 277 pitches[2] = pitches[1]; 278 offsets[2] = offsets[1] + pitches[1] * height / 2; 279 handles[2] = bo->handle; 280 281 planes[0] = virtual; 282 planes[1] = virtual + offsets[1]; 283 planes[2] = virtual + offsets[2]; 284 break; 285 286 case DRM_FORMAT_C8: 287 case DRM_FORMAT_ARGB4444: 288 case DRM_FORMAT_XRGB4444: 289 case DRM_FORMAT_ABGR4444: 290 case DRM_FORMAT_XBGR4444: 291 case DRM_FORMAT_RGBA4444: 292 case DRM_FORMAT_RGBX4444: 293 case DRM_FORMAT_BGRA4444: 294 case DRM_FORMAT_BGRX4444: 295 case DRM_FORMAT_ARGB1555: 296 case DRM_FORMAT_XRGB1555: 297 case DRM_FORMAT_ABGR1555: 298 case DRM_FORMAT_XBGR1555: 299 case DRM_FORMAT_RGBA5551: 300 case DRM_FORMAT_RGBX5551: 301 case DRM_FORMAT_BGRA5551: 302 case DRM_FORMAT_BGRX5551: 303 case DRM_FORMAT_RGB565: 304 case DRM_FORMAT_BGR565: 305 case DRM_FORMAT_BGR888: 306 case DRM_FORMAT_RGB888: 307 case DRM_FORMAT_ARGB8888: 308 case DRM_FORMAT_XRGB8888: 309 case DRM_FORMAT_ABGR8888: 310 case DRM_FORMAT_XBGR8888: 311 case DRM_FORMAT_RGBA8888: 312 case DRM_FORMAT_RGBX8888: 313 case DRM_FORMAT_BGRA8888: 314 case DRM_FORMAT_BGRX8888: 315 case DRM_FORMAT_ARGB2101010: 316 case DRM_FORMAT_XRGB2101010: 317 case DRM_FORMAT_ABGR2101010: 318 case DRM_FORMAT_XBGR2101010: 319 case DRM_FORMAT_RGBA1010102: 320 case DRM_FORMAT_RGBX1010102: 321 case DRM_FORMAT_BGRA1010102: 322 case DRM_FORMAT_BGRX1010102: 323 case DRM_FORMAT_XRGB16161616F: 324 case DRM_FORMAT_XBGR16161616F: 325 case DRM_FORMAT_ARGB16161616F: 326 case DRM_FORMAT_ABGR16161616F: 327 offsets[0] = 0; 328 handles[0] = bo->handle; 329 pitches[0] = bo->pitch; 330 331 planes[0] = virtual; 332 break; 333 } 334 335 util_fill_pattern(format, pattern, planes, width, height, pitches[0]); 336 bo_unmap(bo); 337 338 return bo; 339} 340 341void bo_destroy(struct bo *bo) 342{ 343 struct drm_mode_destroy_dumb arg; 344 int ret; 345 346 memset(&arg, 0, sizeof(arg)); 347 arg.handle = bo->handle; 348 349 ret = drmIoctl(bo->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg); 350 if (ret) 351 fprintf(stderr, "failed to destroy dumb buffer: %s\n", 352 strerror(errno)); 353 354 free(bo); 355} 356