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