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.h" 43 #include "xf86drm.h" 44 45 #include "buffers.h" 46 47 #ifdef HAVE_CAIRO 48 #include <math.h> 49 #include <cairo.h> 50 #endif 51 52 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 53 54 struct bo 55 { 56 int fd; 57 void *ptr; 58 size_t size; 59 size_t offset; 60 size_t pitch; 61 unsigned handle; 62 }; 63 64 /* ----------------------------------------------------------------------------- 65 * Formats 66 */ 67 68 struct color_component { 69 unsigned int length; 70 unsigned int offset; 71 }; 72 73 struct rgb_info { 74 struct color_component red; 75 struct color_component green; 76 struct color_component blue; 77 struct color_component alpha; 78 }; 79 80 enum yuv_order { 81 YUV_YCbCr = 1, 82 YUV_YCrCb = 2, 83 YUV_YC = 4, 84 YUV_CY = 8, 85 }; 86 87 struct yuv_info { 88 enum yuv_order order; 89 unsigned int xsub; 90 unsigned int ysub; 91 unsigned int chroma_stride; 92 }; 93 94 struct format_info { 95 unsigned int format; 96 const char *name; 97 const struct rgb_info rgb; 98 const struct yuv_info yuv; 99 }; 100 101 #define MAKE_RGB_INFO(rl, ro, bl, bo, gl, go, al, ao) \ 102 .rgb = { { (rl), (ro) }, { (bl), (bo) }, { (gl), (go) }, { (al), (ao) } } 103 104 #define MAKE_YUV_INFO(order, xsub, ysub, chroma_stride) \ 105 .yuv = { (order), (xsub), (ysub), (chroma_stride) } 106 107 static const struct format_info format_info[] = { 108 /* YUV packed */ 109 { DRM_FORMAT_UYVY, "UYVY", MAKE_YUV_INFO(YUV_YCbCr | YUV_CY, 2, 2, 2) }, 110 { DRM_FORMAT_VYUY, "VYUY", MAKE_YUV_INFO(YUV_YCrCb | YUV_CY, 2, 2, 2) }, 111 { DRM_FORMAT_YUYV, "YUYV", MAKE_YUV_INFO(YUV_YCbCr | YUV_YC, 2, 2, 2) }, 112 { DRM_FORMAT_YVYU, "YVYU", MAKE_YUV_INFO(YUV_YCrCb | YUV_YC, 2, 2, 2) }, 113 /* YUV semi-planar */ 114 { DRM_FORMAT_NV12, "NV12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 2) }, 115 { DRM_FORMAT_NV21, "NV21", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 2) }, 116 { DRM_FORMAT_NV16, "NV16", MAKE_YUV_INFO(YUV_YCbCr, 2, 1, 2) }, 117 { DRM_FORMAT_NV61, "NV61", MAKE_YUV_INFO(YUV_YCrCb, 2, 1, 2) }, 118 /* YUV planar */ 119 { DRM_FORMAT_YUV420, "YU12", MAKE_YUV_INFO(YUV_YCbCr, 2, 2, 1) }, 120 { DRM_FORMAT_YVU420, "YV12", MAKE_YUV_INFO(YUV_YCrCb, 2, 2, 1) }, 121 /* RGB16 */ 122 { DRM_FORMAT_ARGB4444, "AR12", MAKE_RGB_INFO(4, 8, 4, 4, 4, 0, 4, 12) }, 123 { DRM_FORMAT_XRGB4444, "XR12", MAKE_RGB_INFO(4, 8, 4, 4, 4, 0, 0, 0) }, 124 { DRM_FORMAT_ABGR4444, "AB12", MAKE_RGB_INFO(4, 0, 4, 4, 4, 8, 4, 12) }, 125 { DRM_FORMAT_XBGR4444, "XB12", MAKE_RGB_INFO(4, 0, 4, 4, 4, 8, 0, 0) }, 126 { DRM_FORMAT_RGBA4444, "RA12", MAKE_RGB_INFO(4, 12, 4, 8, 4, 4, 4, 0) }, 127 { DRM_FORMAT_RGBX4444, "RX12", MAKE_RGB_INFO(4, 12, 4, 8, 4, 4, 0, 0) }, 128 { DRM_FORMAT_BGRA4444, "BA12", MAKE_RGB_INFO(4, 4, 4, 8, 4, 12, 4, 0) }, 129 { DRM_FORMAT_BGRX4444, "BX12", MAKE_RGB_INFO(4, 4, 4, 8, 4, 12, 0, 0) }, 130 { DRM_FORMAT_ARGB1555, "AR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 1, 15) }, 131 { DRM_FORMAT_XRGB1555, "XR15", MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 0, 0) }, 132 { DRM_FORMAT_ABGR1555, "AB15", MAKE_RGB_INFO(5, 0, 5, 5, 5, 10, 1, 15) }, 133 { DRM_FORMAT_XBGR1555, "XB15", MAKE_RGB_INFO(5, 0, 5, 5, 5, 10, 0, 0) }, 134 { DRM_FORMAT_RGBA5551, "RA15", MAKE_RGB_INFO(5, 11, 5, 6, 5, 1, 1, 0) }, 135 { DRM_FORMAT_RGBX5551, "RX15", MAKE_RGB_INFO(5, 11, 5, 6, 5, 1, 0, 0) }, 136 { DRM_FORMAT_BGRA5551, "BA15", MAKE_RGB_INFO(5, 1, 5, 6, 5, 11, 1, 0) }, 137 { DRM_FORMAT_BGRX5551, "BX15", MAKE_RGB_INFO(5, 1, 5, 6, 5, 11, 0, 0) }, 138 { DRM_FORMAT_RGB565, "RG16", MAKE_RGB_INFO(5, 11, 6, 5, 5, 0, 0, 0) }, 139 { DRM_FORMAT_BGR565, "BG16", MAKE_RGB_INFO(5, 0, 6, 5, 5, 11, 0, 0) }, 140 /* RGB24 */ 141 { DRM_FORMAT_BGR888, "BG24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) }, 142 { DRM_FORMAT_RGB888, "RG24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) }, 143 /* RGB32 */ 144 { DRM_FORMAT_ARGB8888, "AR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 8, 24) }, 145 { DRM_FORMAT_XRGB8888, "XR24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) }, 146 { DRM_FORMAT_ABGR8888, "AB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 8, 24) }, 147 { DRM_FORMAT_XBGR8888, "XB24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) }, 148 { DRM_FORMAT_RGBA8888, "RA24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 8, 0) }, 149 { DRM_FORMAT_RGBX8888, "RX24", MAKE_RGB_INFO(8, 24, 8, 16, 8, 8, 0, 0) }, 150 { DRM_FORMAT_BGRA8888, "BA24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 8, 0) }, 151 { DRM_FORMAT_BGRX8888, "BX24", MAKE_RGB_INFO(8, 8, 8, 16, 8, 24, 0, 0) }, 152 { DRM_FORMAT_ARGB2101010, "AR30", MAKE_RGB_INFO(10, 20, 10, 10, 10, 0, 2, 30) }, 153 { DRM_FORMAT_XRGB2101010, "XR30", MAKE_RGB_INFO(10, 20, 10, 10, 10, 0, 0, 0) }, 154 { DRM_FORMAT_ABGR2101010, "AB30", MAKE_RGB_INFO(10, 0, 10, 10, 10, 20, 2, 30) }, 155 { DRM_FORMAT_XBGR2101010, "XB30", MAKE_RGB_INFO(10, 0, 10, 10, 10, 20, 0, 0) }, 156 { DRM_FORMAT_RGBA1010102, "RA30", MAKE_RGB_INFO(10, 22, 10, 12, 10, 2, 2, 0) }, 157 { DRM_FORMAT_RGBX1010102, "RX30", MAKE_RGB_INFO(10, 22, 10, 12, 10, 2, 0, 0) }, 158 { DRM_FORMAT_BGRA1010102, "BA30", MAKE_RGB_INFO(10, 2, 10, 12, 10, 22, 2, 0) }, 159 { DRM_FORMAT_BGRX1010102, "BX30", MAKE_RGB_INFO(10, 2, 10, 12, 10, 22, 0, 0) }, 160 }; 161 162 unsigned int format_fourcc(const char *name) 163 { 164 unsigned int i; 165 for (i = 0; i < ARRAY_SIZE(format_info); i++) { 166 if (!strcmp(format_info[i].name, name)) 167 return format_info[i].format; 168 } 169 return 0; 170 } 171 172 /* ----------------------------------------------------------------------------- 173 * Test patterns 174 */ 175 176 struct color_rgb24 { 177 unsigned int value:24; 178 } __attribute__((__packed__)); 179 180 struct color_yuv { 181 unsigned char y; 182 unsigned char u; 183 unsigned char v; 184 }; 185 186 #define MAKE_YUV_601_Y(r, g, b) \ 187 ((( 66 * (r) + 129 * (g) + 25 * (b) + 128) >> 8) + 16) 188 #define MAKE_YUV_601_U(r, g, b) \ 189 (((-38 * (r) - 74 * (g) + 112 * (b) + 128) >> 8) + 128) 190 #define MAKE_YUV_601_V(r, g, b) \ 191 (((112 * (r) - 94 * (g) - 18 * (b) + 128) >> 8) + 128) 192 193 #define MAKE_YUV_601(r, g, b) \ 194 { .y = MAKE_YUV_601_Y(r, g, b), \ 195 .u = MAKE_YUV_601_U(r, g, b), \ 196 .v = MAKE_YUV_601_V(r, g, b) } 197 198 #define MAKE_RGBA(rgb, r, g, b, a) \ 199 ((((r) >> (8 - (rgb)->red.length)) << (rgb)->red.offset) | \ 200 (((g) >> (8 - (rgb)->green.length)) << (rgb)->green.offset) | \ 201 (((b) >> (8 - (rgb)->blue.length)) << (rgb)->blue.offset) | \ 202 (((a) >> (8 - (rgb)->alpha.length)) << (rgb)->alpha.offset)) 203 204 #define MAKE_RGB24(rgb, r, g, b) \ 205 { .value = MAKE_RGBA(rgb, r, g, b, 0) } 206 207 static void 208 fill_smpte_yuv_planar(const struct yuv_info *yuv, 209 unsigned char *y_mem, unsigned char *u_mem, 210 unsigned char *v_mem, unsigned int width, 211 unsigned int height, unsigned int stride) 212 { 213 const struct color_yuv colors_top[] = { 214 MAKE_YUV_601(191, 192, 192), /* grey */ 215 MAKE_YUV_601(192, 192, 0), /* yellow */ 216 MAKE_YUV_601(0, 192, 192), /* cyan */ 217 MAKE_YUV_601(0, 192, 0), /* green */ 218 MAKE_YUV_601(192, 0, 192), /* magenta */ 219 MAKE_YUV_601(192, 0, 0), /* red */ 220 MAKE_YUV_601(0, 0, 192), /* blue */ 221 }; 222 const struct color_yuv colors_middle[] = { 223 MAKE_YUV_601(0, 0, 192), /* blue */ 224 MAKE_YUV_601(19, 19, 19), /* black */ 225 MAKE_YUV_601(192, 0, 192), /* magenta */ 226 MAKE_YUV_601(19, 19, 19), /* black */ 227 MAKE_YUV_601(0, 192, 192), /* cyan */ 228 MAKE_YUV_601(19, 19, 19), /* black */ 229 MAKE_YUV_601(192, 192, 192), /* grey */ 230 }; 231 const struct color_yuv colors_bottom[] = { 232 MAKE_YUV_601(0, 33, 76), /* in-phase */ 233 MAKE_YUV_601(255, 255, 255), /* super white */ 234 MAKE_YUV_601(50, 0, 106), /* quadrature */ 235 MAKE_YUV_601(19, 19, 19), /* black */ 236 MAKE_YUV_601(9, 9, 9), /* 3.5% */ 237 MAKE_YUV_601(19, 19, 19), /* 7.5% */ 238 MAKE_YUV_601(29, 29, 29), /* 11.5% */ 239 MAKE_YUV_601(19, 19, 19), /* black */ 240 }; 241 unsigned int cs = yuv->chroma_stride; 242 unsigned int xsub = yuv->xsub; 243 unsigned int ysub = yuv->ysub; 244 unsigned int x; 245 unsigned int y; 246 247 /* Luma */ 248 for (y = 0; y < height * 6 / 9; ++y) { 249 for (x = 0; x < width; ++x) 250 y_mem[x] = colors_top[x * 7 / width].y; 251 y_mem += stride; 252 } 253 254 for (; y < height * 7 / 9; ++y) { 255 for (x = 0; x < width; ++x) 256 y_mem[x] = colors_middle[x * 7 / width].y; 257 y_mem += stride; 258 } 259 260 for (; y < height; ++y) { 261 for (x = 0; x < width * 5 / 7; ++x) 262 y_mem[x] = colors_bottom[x * 4 / (width * 5 / 7)].y; 263 for (; x < width * 6 / 7; ++x) 264 y_mem[x] = colors_bottom[(x - width * 5 / 7) * 3 265 / (width / 7) + 4].y; 266 for (; x < width; ++x) 267 y_mem[x] = colors_bottom[7].y; 268 y_mem += stride; 269 } 270 271 /* Chroma */ 272 for (y = 0; y < height / ysub * 6 / 9; ++y) { 273 for (x = 0; x < width; x += xsub) { 274 u_mem[x*cs/xsub] = colors_top[x * 7 / width].u; 275 v_mem[x*cs/xsub] = colors_top[x * 7 / width].v; 276 } 277 u_mem += stride * cs / xsub; 278 v_mem += stride * cs / xsub; 279 } 280 281 for (; y < height / ysub * 7 / 9; ++y) { 282 for (x = 0; x < width; x += xsub) { 283 u_mem[x*cs/xsub] = colors_middle[x * 7 / width].u; 284 v_mem[x*cs/xsub] = colors_middle[x * 7 / width].v; 285 } 286 u_mem += stride * cs / xsub; 287 v_mem += stride * cs / xsub; 288 } 289 290 for (; y < height / ysub; ++y) { 291 for (x = 0; x < width * 5 / 7; x += xsub) { 292 u_mem[x*cs/xsub] = 293 colors_bottom[x * 4 / (width * 5 / 7)].u; 294 v_mem[x*cs/xsub] = 295 colors_bottom[x * 4 / (width * 5 / 7)].v; 296 } 297 for (; x < width * 6 / 7; x += xsub) { 298 u_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) * 299 3 / (width / 7) + 4].u; 300 v_mem[x*cs/xsub] = colors_bottom[(x - width * 5 / 7) * 301 3 / (width / 7) + 4].v; 302 } 303 for (; x < width; x += xsub) { 304 u_mem[x*cs/xsub] = colors_bottom[7].u; 305 v_mem[x*cs/xsub] = colors_bottom[7].v; 306 } 307 u_mem += stride * cs / xsub; 308 v_mem += stride * cs / xsub; 309 } 310 } 311 312 static void 313 fill_smpte_yuv_packed(const struct yuv_info *yuv, unsigned char *mem, 314 unsigned int width, unsigned int height, 315 unsigned int stride) 316 { 317 const struct color_yuv colors_top[] = { 318 MAKE_YUV_601(191, 192, 192), /* grey */ 319 MAKE_YUV_601(192, 192, 0), /* yellow */ 320 MAKE_YUV_601(0, 192, 192), /* cyan */ 321 MAKE_YUV_601(0, 192, 0), /* green */ 322 MAKE_YUV_601(192, 0, 192), /* magenta */ 323 MAKE_YUV_601(192, 0, 0), /* red */ 324 MAKE_YUV_601(0, 0, 192), /* blue */ 325 }; 326 const struct color_yuv colors_middle[] = { 327 MAKE_YUV_601(0, 0, 192), /* blue */ 328 MAKE_YUV_601(19, 19, 19), /* black */ 329 MAKE_YUV_601(192, 0, 192), /* magenta */ 330 MAKE_YUV_601(19, 19, 19), /* black */ 331 MAKE_YUV_601(0, 192, 192), /* cyan */ 332 MAKE_YUV_601(19, 19, 19), /* black */ 333 MAKE_YUV_601(192, 192, 192), /* grey */ 334 }; 335 const struct color_yuv colors_bottom[] = { 336 MAKE_YUV_601(0, 33, 76), /* in-phase */ 337 MAKE_YUV_601(255, 255, 255), /* super white */ 338 MAKE_YUV_601(50, 0, 106), /* quadrature */ 339 MAKE_YUV_601(19, 19, 19), /* black */ 340 MAKE_YUV_601(9, 9, 9), /* 3.5% */ 341 MAKE_YUV_601(19, 19, 19), /* 7.5% */ 342 MAKE_YUV_601(29, 29, 29), /* 11.5% */ 343 MAKE_YUV_601(19, 19, 19), /* black */ 344 }; 345 unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1; 346 unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1; 347 unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0; 348 unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0; 349 unsigned int x; 350 unsigned int y; 351 352 /* Luma */ 353 for (y = 0; y < height * 6 / 9; ++y) { 354 for (x = 0; x < width; ++x) 355 y_mem[2*x] = colors_top[x * 7 / width].y; 356 y_mem += stride; 357 } 358 359 for (; y < height * 7 / 9; ++y) { 360 for (x = 0; x < width; ++x) 361 y_mem[2*x] = colors_middle[x * 7 / width].y; 362 y_mem += stride; 363 } 364 365 for (; y < height; ++y) { 366 for (x = 0; x < width * 5 / 7; ++x) 367 y_mem[2*x] = colors_bottom[x * 4 / (width * 5 / 7)].y; 368 for (; x < width * 6 / 7; ++x) 369 y_mem[2*x] = colors_bottom[(x - width * 5 / 7) * 3 370 / (width / 7) + 4].y; 371 for (; x < width; ++x) 372 y_mem[2*x] = colors_bottom[7].y; 373 y_mem += stride; 374 } 375 376 /* Chroma */ 377 for (y = 0; y < height * 6 / 9; ++y) { 378 for (x = 0; x < width; x += 2) { 379 c_mem[2*x+u] = colors_top[x * 7 / width].u; 380 c_mem[2*x+v] = colors_top[x * 7 / width].v; 381 } 382 c_mem += stride; 383 } 384 385 for (; y < height * 7 / 9; ++y) { 386 for (x = 0; x < width; x += 2) { 387 c_mem[2*x+u] = colors_middle[x * 7 / width].u; 388 c_mem[2*x+v] = colors_middle[x * 7 / width].v; 389 } 390 c_mem += stride; 391 } 392 393 for (; y < height; ++y) { 394 for (x = 0; x < width * 5 / 7; x += 2) { 395 c_mem[2*x+u] = colors_bottom[x * 4 / (width * 5 / 7)].u; 396 c_mem[2*x+v] = colors_bottom[x * 4 / (width * 5 / 7)].v; 397 } 398 for (; x < width * 6 / 7; x += 2) { 399 c_mem[2*x+u] = colors_bottom[(x - width * 5 / 7) * 400 3 / (width / 7) + 4].u; 401 c_mem[2*x+v] = colors_bottom[(x - width * 5 / 7) * 402 3 / (width / 7) + 4].v; 403 } 404 for (; x < width; x += 2) { 405 c_mem[2*x+u] = colors_bottom[7].u; 406 c_mem[2*x+v] = colors_bottom[7].v; 407 } 408 c_mem += stride; 409 } 410 } 411 412 static void 413 fill_smpte_rgb16(const struct rgb_info *rgb, unsigned char *mem, 414 unsigned int width, unsigned int height, unsigned int stride) 415 { 416 const uint16_t colors_top[] = { 417 MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */ 418 MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */ 419 MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ 420 MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */ 421 MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ 422 MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */ 423 MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */ 424 }; 425 const uint16_t colors_middle[] = { 426 MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */ 427 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ 428 MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ 429 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ 430 MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ 431 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ 432 MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */ 433 }; 434 const uint16_t colors_bottom[] = { 435 MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */ 436 MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */ 437 MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */ 438 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ 439 MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */ 440 MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */ 441 MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */ 442 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ 443 }; 444 unsigned int x; 445 unsigned int y; 446 447 for (y = 0; y < height * 6 / 9; ++y) { 448 for (x = 0; x < width; ++x) 449 ((uint16_t *)mem)[x] = colors_top[x * 7 / width]; 450 mem += stride; 451 } 452 453 for (; y < height * 7 / 9; ++y) { 454 for (x = 0; x < width; ++x) 455 ((uint16_t *)mem)[x] = colors_middle[x * 7 / width]; 456 mem += stride; 457 } 458 459 for (; y < height; ++y) { 460 for (x = 0; x < width * 5 / 7; ++x) 461 ((uint16_t *)mem)[x] = 462 colors_bottom[x * 4 / (width * 5 / 7)]; 463 for (; x < width * 6 / 7; ++x) 464 ((uint16_t *)mem)[x] = 465 colors_bottom[(x - width * 5 / 7) * 3 466 / (width / 7) + 4]; 467 for (; x < width; ++x) 468 ((uint16_t *)mem)[x] = colors_bottom[7]; 469 mem += stride; 470 } 471 } 472 473 static void 474 fill_smpte_rgb24(const struct rgb_info *rgb, void *mem, 475 unsigned int width, unsigned int height, unsigned int stride) 476 { 477 const struct color_rgb24 colors_top[] = { 478 MAKE_RGB24(rgb, 192, 192, 192), /* grey */ 479 MAKE_RGB24(rgb, 192, 192, 0), /* yellow */ 480 MAKE_RGB24(rgb, 0, 192, 192), /* cyan */ 481 MAKE_RGB24(rgb, 0, 192, 0), /* green */ 482 MAKE_RGB24(rgb, 192, 0, 192), /* magenta */ 483 MAKE_RGB24(rgb, 192, 0, 0), /* red */ 484 MAKE_RGB24(rgb, 0, 0, 192), /* blue */ 485 }; 486 const struct color_rgb24 colors_middle[] = { 487 MAKE_RGB24(rgb, 0, 0, 192), /* blue */ 488 MAKE_RGB24(rgb, 19, 19, 19), /* black */ 489 MAKE_RGB24(rgb, 192, 0, 192), /* magenta */ 490 MAKE_RGB24(rgb, 19, 19, 19), /* black */ 491 MAKE_RGB24(rgb, 0, 192, 192), /* cyan */ 492 MAKE_RGB24(rgb, 19, 19, 19), /* black */ 493 MAKE_RGB24(rgb, 192, 192, 192), /* grey */ 494 }; 495 const struct color_rgb24 colors_bottom[] = { 496 MAKE_RGB24(rgb, 0, 33, 76), /* in-phase */ 497 MAKE_RGB24(rgb, 255, 255, 255), /* super white */ 498 MAKE_RGB24(rgb, 50, 0, 106), /* quadrature */ 499 MAKE_RGB24(rgb, 19, 19, 19), /* black */ 500 MAKE_RGB24(rgb, 9, 9, 9), /* 3.5% */ 501 MAKE_RGB24(rgb, 19, 19, 19), /* 7.5% */ 502 MAKE_RGB24(rgb, 29, 29, 29), /* 11.5% */ 503 MAKE_RGB24(rgb, 19, 19, 19), /* black */ 504 }; 505 unsigned int x; 506 unsigned int y; 507 508 for (y = 0; y < height * 6 / 9; ++y) { 509 for (x = 0; x < width; ++x) 510 ((struct color_rgb24 *)mem)[x] = 511 colors_top[x * 7 / width]; 512 mem += stride; 513 } 514 515 for (; y < height * 7 / 9; ++y) { 516 for (x = 0; x < width; ++x) 517 ((struct color_rgb24 *)mem)[x] = 518 colors_middle[x * 7 / width]; 519 mem += stride; 520 } 521 522 for (; y < height; ++y) { 523 for (x = 0; x < width * 5 / 7; ++x) 524 ((struct color_rgb24 *)mem)[x] = 525 colors_bottom[x * 4 / (width * 5 / 7)]; 526 for (; x < width * 6 / 7; ++x) 527 ((struct color_rgb24 *)mem)[x] = 528 colors_bottom[(x - width * 5 / 7) * 3 529 / (width / 7) + 4]; 530 for (; x < width; ++x) 531 ((struct color_rgb24 *)mem)[x] = colors_bottom[7]; 532 mem += stride; 533 } 534 } 535 536 static void 537 fill_smpte_rgb32(const struct rgb_info *rgb, unsigned char *mem, 538 unsigned int width, unsigned int height, unsigned int stride) 539 { 540 const uint32_t colors_top[] = { 541 MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */ 542 MAKE_RGBA(rgb, 192, 192, 0, 255), /* yellow */ 543 MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ 544 MAKE_RGBA(rgb, 0, 192, 0, 255), /* green */ 545 MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ 546 MAKE_RGBA(rgb, 192, 0, 0, 255), /* red */ 547 MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */ 548 }; 549 const uint32_t colors_middle[] = { 550 MAKE_RGBA(rgb, 0, 0, 192, 255), /* blue */ 551 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ 552 MAKE_RGBA(rgb, 192, 0, 192, 255), /* magenta */ 553 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ 554 MAKE_RGBA(rgb, 0, 192, 192, 255), /* cyan */ 555 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ 556 MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */ 557 }; 558 const uint32_t colors_bottom[] = { 559 MAKE_RGBA(rgb, 0, 33, 76, 255), /* in-phase */ 560 MAKE_RGBA(rgb, 255, 255, 255, 255), /* super white */ 561 MAKE_RGBA(rgb, 50, 0, 106, 255), /* quadrature */ 562 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ 563 MAKE_RGBA(rgb, 9, 9, 9, 255), /* 3.5% */ 564 MAKE_RGBA(rgb, 19, 19, 19, 255), /* 7.5% */ 565 MAKE_RGBA(rgb, 29, 29, 29, 255), /* 11.5% */ 566 MAKE_RGBA(rgb, 19, 19, 19, 255), /* black */ 567 }; 568 unsigned int x; 569 unsigned int y; 570 571 for (y = 0; y < height * 6 / 9; ++y) { 572 for (x = 0; x < width; ++x) 573 ((uint32_t *)mem)[x] = colors_top[x * 7 / width]; 574 mem += stride; 575 } 576 577 for (; y < height * 7 / 9; ++y) { 578 for (x = 0; x < width; ++x) 579 ((uint32_t *)mem)[x] = colors_middle[x * 7 / width]; 580 mem += stride; 581 } 582 583 for (; y < height; ++y) { 584 for (x = 0; x < width * 5 / 7; ++x) 585 ((uint32_t *)mem)[x] = 586 colors_bottom[x * 4 / (width * 5 / 7)]; 587 for (; x < width * 6 / 7; ++x) 588 ((uint32_t *)mem)[x] = 589 colors_bottom[(x - width * 5 / 7) * 3 590 / (width / 7) + 4]; 591 for (; x < width; ++x) 592 ((uint32_t *)mem)[x] = colors_bottom[7]; 593 mem += stride; 594 } 595 } 596 597 static void 598 fill_smpte(const struct format_info *info, void *planes[3], unsigned int width, 599 unsigned int height, unsigned int stride) 600 { 601 unsigned char *u, *v; 602 603 switch (info->format) { 604 case DRM_FORMAT_UYVY: 605 case DRM_FORMAT_VYUY: 606 case DRM_FORMAT_YUYV: 607 case DRM_FORMAT_YVYU: 608 return fill_smpte_yuv_packed(&info->yuv, planes[0], width, 609 height, stride); 610 611 case DRM_FORMAT_NV12: 612 case DRM_FORMAT_NV21: 613 case DRM_FORMAT_NV16: 614 case DRM_FORMAT_NV61: 615 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1; 616 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1; 617 return fill_smpte_yuv_planar(&info->yuv, planes[0], u, v, 618 width, height, stride); 619 620 case DRM_FORMAT_YUV420: 621 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[1], 622 planes[2], width, height, stride); 623 624 case DRM_FORMAT_YVU420: 625 return fill_smpte_yuv_planar(&info->yuv, planes[0], planes[2], 626 planes[1], width, height, stride); 627 628 case DRM_FORMAT_ARGB4444: 629 case DRM_FORMAT_XRGB4444: 630 case DRM_FORMAT_ABGR4444: 631 case DRM_FORMAT_XBGR4444: 632 case DRM_FORMAT_RGBA4444: 633 case DRM_FORMAT_RGBX4444: 634 case DRM_FORMAT_BGRA4444: 635 case DRM_FORMAT_BGRX4444: 636 case DRM_FORMAT_RGB565: 637 case DRM_FORMAT_BGR565: 638 case DRM_FORMAT_ARGB1555: 639 case DRM_FORMAT_XRGB1555: 640 case DRM_FORMAT_ABGR1555: 641 case DRM_FORMAT_XBGR1555: 642 case DRM_FORMAT_RGBA5551: 643 case DRM_FORMAT_RGBX5551: 644 case DRM_FORMAT_BGRA5551: 645 case DRM_FORMAT_BGRX5551: 646 return fill_smpte_rgb16(&info->rgb, planes[0], 647 width, height, stride); 648 649 case DRM_FORMAT_BGR888: 650 case DRM_FORMAT_RGB888: 651 return fill_smpte_rgb24(&info->rgb, planes[0], 652 width, height, stride); 653 case DRM_FORMAT_ARGB8888: 654 case DRM_FORMAT_XRGB8888: 655 case DRM_FORMAT_ABGR8888: 656 case DRM_FORMAT_XBGR8888: 657 case DRM_FORMAT_RGBA8888: 658 case DRM_FORMAT_RGBX8888: 659 case DRM_FORMAT_BGRA8888: 660 case DRM_FORMAT_BGRX8888: 661 case DRM_FORMAT_ARGB2101010: 662 case DRM_FORMAT_XRGB2101010: 663 case DRM_FORMAT_ABGR2101010: 664 case DRM_FORMAT_XBGR2101010: 665 case DRM_FORMAT_RGBA1010102: 666 case DRM_FORMAT_RGBX1010102: 667 case DRM_FORMAT_BGRA1010102: 668 case DRM_FORMAT_BGRX1010102: 669 return fill_smpte_rgb32(&info->rgb, planes[0], 670 width, height, stride); 671 } 672 } 673 674 /* swap these for big endian.. */ 675 #define RED 2 676 #define GREEN 1 677 #define BLUE 0 678 679 static void 680 make_pwetty(void *data, int width, int height, int stride, uint32_t format) 681 { 682 #ifdef HAVE_CAIRO 683 cairo_surface_t *surface; 684 cairo_t *cr; 685 int x, y; 686 cairo_format_t cairo_format; 687 688 /* we can ignore the order of R,G,B channels */ 689 switch (format) { 690 case DRM_FORMAT_XRGB8888: 691 case DRM_FORMAT_ARGB8888: 692 case DRM_FORMAT_XBGR8888: 693 case DRM_FORMAT_ABGR8888: 694 cairo_format = CAIRO_FORMAT_ARGB32; 695 break; 696 case DRM_FORMAT_RGB565: 697 case DRM_FORMAT_BGR565: 698 cairo_format = CAIRO_FORMAT_RGB16_565; 699 break; 700 default: 701 return; 702 } 703 704 surface = cairo_image_surface_create_for_data(data, 705 cairo_format, 706 width, height, 707 stride); 708 cr = cairo_create(surface); 709 cairo_surface_destroy(surface); 710 711 cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE); 712 for (x = 0; x < width; x += 250) 713 for (y = 0; y < height; y += 250) { 714 char buf[64]; 715 716 cairo_move_to(cr, x, y - 20); 717 cairo_line_to(cr, x, y + 20); 718 cairo_move_to(cr, x - 20, y); 719 cairo_line_to(cr, x + 20, y); 720 cairo_new_sub_path(cr); 721 cairo_arc(cr, x, y, 10, 0, M_PI * 2); 722 cairo_set_line_width(cr, 4); 723 cairo_set_source_rgb(cr, 0, 0, 0); 724 cairo_stroke_preserve(cr); 725 cairo_set_source_rgb(cr, 1, 1, 1); 726 cairo_set_line_width(cr, 2); 727 cairo_stroke(cr); 728 729 snprintf(buf, sizeof buf, "%d, %d", x, y); 730 cairo_move_to(cr, x + 20, y + 20); 731 cairo_text_path(cr, buf); 732 cairo_set_source_rgb(cr, 0, 0, 0); 733 cairo_stroke_preserve(cr); 734 cairo_set_source_rgb(cr, 1, 1, 1); 735 cairo_fill(cr); 736 } 737 738 cairo_destroy(cr); 739 #endif 740 } 741 742 static void 743 fill_tiles_yuv_planar(const struct format_info *info, 744 unsigned char *y_mem, unsigned char *u_mem, 745 unsigned char *v_mem, unsigned int width, 746 unsigned int height, unsigned int stride) 747 { 748 const struct yuv_info *yuv = &info->yuv; 749 unsigned int cs = yuv->chroma_stride; 750 unsigned int xsub = yuv->xsub; 751 unsigned int ysub = yuv->ysub; 752 unsigned int x; 753 unsigned int y; 754 755 for (y = 0; y < height; ++y) { 756 for (x = 0; x < width; ++x) { 757 div_t d = div(x+y, width); 758 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 759 + 0x000a1120 * (d.rem >> 6); 760 struct color_yuv color = 761 MAKE_YUV_601((rgb32 >> 16) & 0xff, 762 (rgb32 >> 8) & 0xff, rgb32 & 0xff); 763 764 y_mem[x] = color.y; 765 u_mem[x/xsub*cs] = color.u; 766 v_mem[x/xsub*cs] = color.v; 767 } 768 769 y_mem += stride; 770 if ((y + 1) % ysub == 0) { 771 u_mem += stride * cs / xsub; 772 v_mem += stride * cs / xsub; 773 } 774 } 775 } 776 777 static void 778 fill_tiles_yuv_packed(const struct format_info *info, unsigned char *mem, 779 unsigned int width, unsigned int height, 780 unsigned int stride) 781 { 782 const struct yuv_info *yuv = &info->yuv; 783 unsigned char *y_mem = (yuv->order & YUV_YC) ? mem : mem + 1; 784 unsigned char *c_mem = (yuv->order & YUV_CY) ? mem : mem + 1; 785 unsigned int u = (yuv->order & YUV_YCrCb) ? 2 : 0; 786 unsigned int v = (yuv->order & YUV_YCbCr) ? 2 : 0; 787 unsigned int x; 788 unsigned int y; 789 790 for (y = 0; y < height; ++y) { 791 for (x = 0; x < width; x += 2) { 792 div_t d = div(x+y, width); 793 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 794 + 0x000a1120 * (d.rem >> 6); 795 struct color_yuv color = 796 MAKE_YUV_601((rgb32 >> 16) & 0xff, 797 (rgb32 >> 8) & 0xff, rgb32 & 0xff); 798 799 y_mem[2*x] = color.y; 800 c_mem[2*x+u] = color.u; 801 y_mem[2*x+2] = color.y; 802 c_mem[2*x+v] = color.v; 803 } 804 805 y_mem += stride; 806 c_mem += stride; 807 } 808 } 809 810 static void 811 fill_tiles_rgb16(const struct format_info *info, unsigned char *mem, 812 unsigned int width, unsigned int height, unsigned int stride) 813 { 814 const struct rgb_info *rgb = &info->rgb; 815 unsigned char *mem_base = mem; 816 unsigned int x, y; 817 818 for (y = 0; y < height; ++y) { 819 for (x = 0; x < width; ++x) { 820 div_t d = div(x+y, width); 821 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 822 + 0x000a1120 * (d.rem >> 6); 823 uint16_t color = 824 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff, 825 (rgb32 >> 8) & 0xff, rgb32 & 0xff, 826 255); 827 828 ((uint16_t *)mem)[x] = color; 829 } 830 mem += stride; 831 } 832 833 make_pwetty(mem_base, width, height, stride, info->format); 834 } 835 836 static void 837 fill_tiles_rgb24(const struct format_info *info, unsigned char *mem, 838 unsigned int width, unsigned int height, unsigned int stride) 839 { 840 const struct rgb_info *rgb = &info->rgb; 841 unsigned int x, y; 842 843 for (y = 0; y < height; ++y) { 844 for (x = 0; x < width; ++x) { 845 div_t d = div(x+y, width); 846 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 847 + 0x000a1120 * (d.rem >> 6); 848 struct color_rgb24 color = 849 MAKE_RGB24(rgb, (rgb32 >> 16) & 0xff, 850 (rgb32 >> 8) & 0xff, rgb32 & 0xff); 851 852 ((struct color_rgb24 *)mem)[x] = color; 853 } 854 mem += stride; 855 } 856 } 857 858 static void 859 fill_tiles_rgb32(const struct format_info *info, unsigned char *mem, 860 unsigned int width, unsigned int height, unsigned int stride) 861 { 862 const struct rgb_info *rgb = &info->rgb; 863 unsigned char *mem_base = mem; 864 unsigned int x, y; 865 866 for (y = 0; y < height; ++y) { 867 for (x = 0; x < width; ++x) { 868 div_t d = div(x+y, width); 869 uint32_t rgb32 = 0x00130502 * (d.quot >> 6) 870 + 0x000a1120 * (d.rem >> 6); 871 uint32_t alpha = ((y < height/2) && (x < width/2)) ? 127 : 255; 872 uint32_t color = 873 MAKE_RGBA(rgb, (rgb32 >> 16) & 0xff, 874 (rgb32 >> 8) & 0xff, rgb32 & 0xff, 875 alpha); 876 877 ((uint32_t *)mem)[x] = color; 878 } 879 mem += stride; 880 } 881 882 make_pwetty(mem_base, width, height, stride, info->format); 883 } 884 885 static void 886 fill_tiles(const struct format_info *info, void *planes[3], unsigned int width, 887 unsigned int height, unsigned int stride) 888 { 889 unsigned char *u, *v; 890 891 switch (info->format) { 892 case DRM_FORMAT_UYVY: 893 case DRM_FORMAT_VYUY: 894 case DRM_FORMAT_YUYV: 895 case DRM_FORMAT_YVYU: 896 return fill_tiles_yuv_packed(info, planes[0], 897 width, height, stride); 898 899 case DRM_FORMAT_NV12: 900 case DRM_FORMAT_NV21: 901 case DRM_FORMAT_NV16: 902 case DRM_FORMAT_NV61: 903 u = info->yuv.order & YUV_YCbCr ? planes[1] : planes[1] + 1; 904 v = info->yuv.order & YUV_YCrCb ? planes[1] : planes[1] + 1; 905 return fill_tiles_yuv_planar(info, planes[0], u, v, 906 width, height, stride); 907 908 case DRM_FORMAT_YUV420: 909 return fill_tiles_yuv_planar(info, planes[0], planes[1], 910 planes[2], width, height, stride); 911 912 case DRM_FORMAT_YVU420: 913 return fill_tiles_yuv_planar(info, planes[0], planes[2], 914 planes[1], width, height, stride); 915 916 case DRM_FORMAT_ARGB4444: 917 case DRM_FORMAT_XRGB4444: 918 case DRM_FORMAT_ABGR4444: 919 case DRM_FORMAT_XBGR4444: 920 case DRM_FORMAT_RGBA4444: 921 case DRM_FORMAT_RGBX4444: 922 case DRM_FORMAT_BGRA4444: 923 case DRM_FORMAT_BGRX4444: 924 case DRM_FORMAT_RGB565: 925 case DRM_FORMAT_BGR565: 926 case DRM_FORMAT_ARGB1555: 927 case DRM_FORMAT_XRGB1555: 928 case DRM_FORMAT_ABGR1555: 929 case DRM_FORMAT_XBGR1555: 930 case DRM_FORMAT_RGBA5551: 931 case DRM_FORMAT_RGBX5551: 932 case DRM_FORMAT_BGRA5551: 933 case DRM_FORMAT_BGRX5551: 934 return fill_tiles_rgb16(info, planes[0], 935 width, height, stride); 936 937 case DRM_FORMAT_BGR888: 938 case DRM_FORMAT_RGB888: 939 return fill_tiles_rgb24(info, planes[0], 940 width, height, stride); 941 case DRM_FORMAT_ARGB8888: 942 case DRM_FORMAT_XRGB8888: 943 case DRM_FORMAT_ABGR8888: 944 case DRM_FORMAT_XBGR8888: 945 case DRM_FORMAT_RGBA8888: 946 case DRM_FORMAT_RGBX8888: 947 case DRM_FORMAT_BGRA8888: 948 case DRM_FORMAT_BGRX8888: 949 case DRM_FORMAT_ARGB2101010: 950 case DRM_FORMAT_XRGB2101010: 951 case DRM_FORMAT_ABGR2101010: 952 case DRM_FORMAT_XBGR2101010: 953 case DRM_FORMAT_RGBA1010102: 954 case DRM_FORMAT_RGBX1010102: 955 case DRM_FORMAT_BGRA1010102: 956 case DRM_FORMAT_BGRX1010102: 957 return fill_tiles_rgb32(info, planes[0], 958 width, height, stride); 959 } 960 } 961 962 static void 963 fill_plain(const struct format_info *info, void *planes[3], unsigned int width, 964 unsigned int height, unsigned int stride) 965 { 966 memset(planes[0], 0x77, stride * height); 967 } 968 969 /* 970 * fill_pattern - Fill a buffer with a test pattern 971 * @format: Pixel format 972 * @pattern: Test pattern 973 * @buffer: Buffer memory 974 * @width: Width in pixels 975 * @height: Height in pixels 976 * @stride: Line stride (pitch) in bytes 977 * 978 * Fill the buffer with the test pattern specified by the pattern parameter. 979 * Supported formats vary depending on the selected pattern. 980 */ 981 static void 982 fill_pattern(unsigned int format, enum fill_pattern pattern, void *planes[3], 983 unsigned int width, unsigned int height, unsigned int stride) 984 { 985 const struct format_info *info = NULL; 986 unsigned int i; 987 988 for (i = 0; i < ARRAY_SIZE(format_info); ++i) { 989 if (format_info[i].format == format) { 990 info = &format_info[i]; 991 break; 992 } 993 } 994 995 if (info == NULL) 996 return; 997 998 switch (pattern) { 999 case PATTERN_TILES: 1000 return fill_tiles(info, planes, width, height, stride); 1001 1002 case PATTERN_SMPTE: 1003 return fill_smpte(info, planes, width, height, stride); 1004 1005 case PATTERN_PLAIN: 1006 return fill_plain(info, planes, width, height, stride); 1007 1008 default: 1009 printf("Error: unsupported test pattern %u.\n", pattern); 1010 break; 1011 } 1012 } 1013 1014 /* ----------------------------------------------------------------------------- 1015 * Buffers management 1016 */ 1017 1018 static struct bo * 1019 bo_create_dumb(int fd, unsigned int width, unsigned int height, unsigned int bpp) 1020 { 1021 struct drm_mode_create_dumb arg; 1022 struct bo *bo; 1023 int ret; 1024 1025 bo = malloc(sizeof(*bo)); 1026 if (bo == NULL) { 1027 fprintf(stderr, "failed to allocate buffer object\n"); 1028 return NULL; 1029 } 1030 1031 memset(&arg, 0, sizeof(arg)); 1032 arg.bpp = bpp; 1033 arg.width = width; 1034 arg.height = height; 1035 1036 ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg); 1037 if (ret) { 1038 fprintf(stderr, "failed to create dumb buffer: %s\n", 1039 strerror(errno)); 1040 free(bo); 1041 return NULL; 1042 } 1043 1044 bo->fd = fd; 1045 bo->handle = arg.handle; 1046 bo->size = arg.size; 1047 bo->pitch = arg.pitch; 1048 1049 return bo; 1050 } 1051 1052 static int bo_map(struct bo *bo, void **out) 1053 { 1054 struct drm_mode_map_dumb arg; 1055 void *map; 1056 int ret; 1057 1058 memset(&arg, 0, sizeof(arg)); 1059 arg.handle = bo->handle; 1060 1061 ret = drmIoctl(bo->fd, DRM_IOCTL_MODE_MAP_DUMB, &arg); 1062 if (ret) 1063 return ret; 1064 1065 map = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, 1066 bo->fd, arg.offset); 1067 if (map == MAP_FAILED) 1068 return -EINVAL; 1069 1070 bo->ptr = map; 1071 *out = map; 1072 1073 return 0; 1074 } 1075 1076 static void bo_unmap(struct bo *bo) 1077 { 1078 if (!bo->ptr) 1079 return; 1080 1081 drm_munmap(bo->ptr, bo->size); 1082 bo->ptr = NULL; 1083 } 1084 1085 struct bo * 1086 bo_create(int fd, unsigned int format, 1087 unsigned int width, unsigned int height, 1088 unsigned int handles[4], unsigned int pitches[4], 1089 unsigned int offsets[4], enum fill_pattern pattern) 1090 { 1091 unsigned int virtual_height; 1092 struct bo *bo; 1093 unsigned int bpp; 1094 void *planes[3] = { 0, }; 1095 void *virtual; 1096 int ret; 1097 1098 switch (format) { 1099 case DRM_FORMAT_NV12: 1100 case DRM_FORMAT_NV21: 1101 case DRM_FORMAT_NV16: 1102 case DRM_FORMAT_NV61: 1103 case DRM_FORMAT_YUV420: 1104 case DRM_FORMAT_YVU420: 1105 bpp = 8; 1106 break; 1107 1108 case DRM_FORMAT_ARGB4444: 1109 case DRM_FORMAT_XRGB4444: 1110 case DRM_FORMAT_ABGR4444: 1111 case DRM_FORMAT_XBGR4444: 1112 case DRM_FORMAT_RGBA4444: 1113 case DRM_FORMAT_RGBX4444: 1114 case DRM_FORMAT_BGRA4444: 1115 case DRM_FORMAT_BGRX4444: 1116 case DRM_FORMAT_ARGB1555: 1117 case DRM_FORMAT_XRGB1555: 1118 case DRM_FORMAT_ABGR1555: 1119 case DRM_FORMAT_XBGR1555: 1120 case DRM_FORMAT_RGBA5551: 1121 case DRM_FORMAT_RGBX5551: 1122 case DRM_FORMAT_BGRA5551: 1123 case DRM_FORMAT_BGRX5551: 1124 case DRM_FORMAT_RGB565: 1125 case DRM_FORMAT_BGR565: 1126 case DRM_FORMAT_UYVY: 1127 case DRM_FORMAT_VYUY: 1128 case DRM_FORMAT_YUYV: 1129 case DRM_FORMAT_YVYU: 1130 bpp = 16; 1131 break; 1132 1133 case DRM_FORMAT_BGR888: 1134 case DRM_FORMAT_RGB888: 1135 bpp = 24; 1136 break; 1137 1138 case DRM_FORMAT_ARGB8888: 1139 case DRM_FORMAT_XRGB8888: 1140 case DRM_FORMAT_ABGR8888: 1141 case DRM_FORMAT_XBGR8888: 1142 case DRM_FORMAT_RGBA8888: 1143 case DRM_FORMAT_RGBX8888: 1144 case DRM_FORMAT_BGRA8888: 1145 case DRM_FORMAT_BGRX8888: 1146 case DRM_FORMAT_ARGB2101010: 1147 case DRM_FORMAT_XRGB2101010: 1148 case DRM_FORMAT_ABGR2101010: 1149 case DRM_FORMAT_XBGR2101010: 1150 case DRM_FORMAT_RGBA1010102: 1151 case DRM_FORMAT_RGBX1010102: 1152 case DRM_FORMAT_BGRA1010102: 1153 case DRM_FORMAT_BGRX1010102: 1154 bpp = 32; 1155 break; 1156 1157 default: 1158 fprintf(stderr, "unsupported format 0x%08x\n", format); 1159 return NULL; 1160 } 1161 1162 switch (format) { 1163 case DRM_FORMAT_NV12: 1164 case DRM_FORMAT_NV21: 1165 virtual_height = height * 3 / 2; 1166 break; 1167 1168 case DRM_FORMAT_NV16: 1169 case DRM_FORMAT_NV61: 1170 virtual_height = height * 2; 1171 break; 1172 1173 default: 1174 virtual_height = height; 1175 break; 1176 } 1177 1178 bo = bo_create_dumb(fd, width, virtual_height, bpp); 1179 if (!bo) 1180 return NULL; 1181 1182 ret = bo_map(bo, &virtual); 1183 if (ret) { 1184 fprintf(stderr, "failed to map buffer: %s\n", 1185 strerror(-errno)); 1186 bo_destroy(bo); 1187 return NULL; 1188 } 1189 1190 /* just testing a limited # of formats to test single 1191 * and multi-planar path.. would be nice to add more.. 1192 */ 1193 switch (format) { 1194 case DRM_FORMAT_UYVY: 1195 case DRM_FORMAT_VYUY: 1196 case DRM_FORMAT_YUYV: 1197 case DRM_FORMAT_YVYU: 1198 offsets[0] = 0; 1199 handles[0] = bo->handle; 1200 pitches[0] = bo->pitch; 1201 1202 planes[0] = virtual; 1203 break; 1204 1205 case DRM_FORMAT_NV12: 1206 case DRM_FORMAT_NV21: 1207 case DRM_FORMAT_NV16: 1208 case DRM_FORMAT_NV61: 1209 offsets[0] = 0; 1210 handles[0] = bo->handle; 1211 pitches[0] = bo->pitch; 1212 pitches[1] = pitches[0]; 1213 offsets[1] = pitches[0] * height; 1214 handles[1] = bo->handle; 1215 1216 planes[0] = virtual; 1217 planes[1] = virtual + offsets[1]; 1218 break; 1219 1220 case DRM_FORMAT_YUV420: 1221 case DRM_FORMAT_YVU420: 1222 offsets[0] = 0; 1223 handles[0] = bo->handle; 1224 pitches[0] = bo->pitch; 1225 pitches[1] = pitches[0] / 2; 1226 offsets[1] = pitches[0] * height; 1227 handles[1] = bo->handle; 1228 pitches[2] = pitches[1]; 1229 offsets[2] = offsets[1] + pitches[1] * height / 2; 1230 handles[2] = bo->handle; 1231 1232 planes[0] = virtual; 1233 planes[1] = virtual + offsets[1]; 1234 planes[2] = virtual + offsets[2]; 1235 break; 1236 1237 case DRM_FORMAT_ARGB4444: 1238 case DRM_FORMAT_XRGB4444: 1239 case DRM_FORMAT_ABGR4444: 1240 case DRM_FORMAT_XBGR4444: 1241 case DRM_FORMAT_RGBA4444: 1242 case DRM_FORMAT_RGBX4444: 1243 case DRM_FORMAT_BGRA4444: 1244 case DRM_FORMAT_BGRX4444: 1245 case DRM_FORMAT_ARGB1555: 1246 case DRM_FORMAT_XRGB1555: 1247 case DRM_FORMAT_ABGR1555: 1248 case DRM_FORMAT_XBGR1555: 1249 case DRM_FORMAT_RGBA5551: 1250 case DRM_FORMAT_RGBX5551: 1251 case DRM_FORMAT_BGRA5551: 1252 case DRM_FORMAT_BGRX5551: 1253 case DRM_FORMAT_RGB565: 1254 case DRM_FORMAT_BGR565: 1255 case DRM_FORMAT_BGR888: 1256 case DRM_FORMAT_RGB888: 1257 case DRM_FORMAT_ARGB8888: 1258 case DRM_FORMAT_XRGB8888: 1259 case DRM_FORMAT_ABGR8888: 1260 case DRM_FORMAT_XBGR8888: 1261 case DRM_FORMAT_RGBA8888: 1262 case DRM_FORMAT_RGBX8888: 1263 case DRM_FORMAT_BGRA8888: 1264 case DRM_FORMAT_BGRX8888: 1265 case DRM_FORMAT_ARGB2101010: 1266 case DRM_FORMAT_XRGB2101010: 1267 case DRM_FORMAT_ABGR2101010: 1268 case DRM_FORMAT_XBGR2101010: 1269 case DRM_FORMAT_RGBA1010102: 1270 case DRM_FORMAT_RGBX1010102: 1271 case DRM_FORMAT_BGRA1010102: 1272 case DRM_FORMAT_BGRX1010102: 1273 offsets[0] = 0; 1274 handles[0] = bo->handle; 1275 pitches[0] = bo->pitch; 1276 1277 planes[0] = virtual; 1278 break; 1279 } 1280 1281 fill_pattern(format, pattern, planes, width, height, pitches[0]); 1282 bo_unmap(bo); 1283 1284 return bo; 1285 } 1286 1287 void bo_destroy(struct bo *bo) 1288 { 1289 struct drm_mode_destroy_dumb arg; 1290 int ret; 1291 1292 memset(&arg, 0, sizeof(arg)); 1293 arg.handle = bo->handle; 1294 1295 ret = drmIoctl(bo->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg); 1296 if (ret) 1297 fprintf(stderr, "failed to destroy dumb buffer: %s\n", 1298 strerror(errno)); 1299 1300 free(bo); 1301 } 1302