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