1/************************************************************************** 2 * 3 * Copyright 2009 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 29/** 30 * @file 31 * Unit tests for blend LLVM IR generation 32 * 33 * @author Jose Fonseca <jfonseca@vmware.com> 34 * 35 * Blend computation code derived from code written by 36 * @author Brian Paul <brian@vmware.com> 37 */ 38 39#include "util/u_memory.h" 40 41#include "gallivm/lp_bld_init.h" 42#include "gallivm/lp_bld_type.h" 43#include "gallivm/lp_bld_debug.h" 44#include "lp_bld_blend.h" 45#include "lp_test.h" 46 47 48typedef void (*blend_test_ptr_t)(const void *src, const void *src1, 49 const void *dst, const void *con, void *res); 50 51 52void 53write_tsv_header(FILE *fp) 54{ 55 fprintf(fp, 56 "result\t" 57 "cycles_per_channel\t" 58 "type\t" 59 "sep_func\t" 60 "sep_src_factor\t" 61 "sep_dst_factor\t" 62 "rgb_func\t" 63 "rgb_src_factor\t" 64 "rgb_dst_factor\t" 65 "alpha_func\t" 66 "alpha_src_factor\t" 67 "alpha_dst_factor\n"); 68 69 fflush(fp); 70} 71 72 73static void 74write_tsv_row(FILE *fp, 75 const struct pipe_blend_state *blend, 76 struct lp_type type, 77 double cycles, 78 boolean success) 79{ 80 fprintf(fp, "%s\t", success ? "pass" : "fail"); 81 82 fprintf(fp, "%.1f\t", cycles / type.length); 83 84 fprintf(fp, "%s%u%sx%u\t", 85 type.floating ? "f" : (type.fixed ? "h" : (type.sign ? "s" : "u")), 86 type.width, 87 type.norm ? "n" : "", 88 type.length); 89 90 fprintf(fp, 91 "%s\t%s\t%s\t", 92 blend->rt[0].rgb_func != blend->rt[0].alpha_func ? "true" : "false", 93 blend->rt[0].rgb_src_factor != blend->rt[0].alpha_src_factor ? "true" : "false", 94 blend->rt[0].rgb_dst_factor != blend->rt[0].alpha_dst_factor ? "true" : "false"); 95 96 fprintf(fp, 97 "%s\t%s\t%s\t%s\t%s\t%s\n", 98 util_str_blend_func(blend->rt[0].rgb_func, TRUE), 99 util_str_blend_factor(blend->rt[0].rgb_src_factor, TRUE), 100 util_str_blend_factor(blend->rt[0].rgb_dst_factor, TRUE), 101 util_str_blend_func(blend->rt[0].alpha_func, TRUE), 102 util_str_blend_factor(blend->rt[0].alpha_src_factor, TRUE), 103 util_str_blend_factor(blend->rt[0].alpha_dst_factor, TRUE)); 104 105 fflush(fp); 106} 107 108 109static void 110dump_blend_type(FILE *fp, 111 const struct pipe_blend_state *blend, 112 struct lp_type type) 113{ 114 fprintf(fp, " type=%s%u%sx%u", 115 type.floating ? "f" : (type.fixed ? "h" : (type.sign ? "s" : "u")), 116 type.width, 117 type.norm ? "n" : "", 118 type.length); 119 120 fprintf(fp, 121 " %s=%s %s=%s %s=%s %s=%s %s=%s %s=%s", 122 "rgb_func", util_str_blend_func(blend->rt[0].rgb_func, TRUE), 123 "rgb_src_factor", util_str_blend_factor(blend->rt[0].rgb_src_factor, TRUE), 124 "rgb_dst_factor", util_str_blend_factor(blend->rt[0].rgb_dst_factor, TRUE), 125 "alpha_func", util_str_blend_func(blend->rt[0].alpha_func, TRUE), 126 "alpha_src_factor", util_str_blend_factor(blend->rt[0].alpha_src_factor, TRUE), 127 "alpha_dst_factor", util_str_blend_factor(blend->rt[0].alpha_dst_factor, TRUE)); 128 129 fprintf(fp, " ...\n"); 130 fflush(fp); 131} 132 133 134static LLVMValueRef 135add_blend_test(struct gallivm_state *gallivm, 136 const struct pipe_blend_state *blend, 137 struct lp_type type) 138{ 139 LLVMModuleRef module = gallivm->module; 140 LLVMContextRef context = gallivm->context; 141 LLVMTypeRef vec_type; 142 LLVMTypeRef args[5]; 143 LLVMValueRef func; 144 LLVMValueRef src_ptr; 145 LLVMValueRef src1_ptr; 146 LLVMValueRef dst_ptr; 147 LLVMValueRef const_ptr; 148 LLVMValueRef res_ptr; 149 LLVMBasicBlockRef block; 150 LLVMBuilderRef builder; 151 const enum pipe_format format = PIPE_FORMAT_R8G8B8A8_UNORM; 152 const unsigned rt = 0; 153 const unsigned char swizzle[4] = { 0, 1, 2, 3 }; 154 LLVMValueRef src; 155 LLVMValueRef src1; 156 LLVMValueRef dst; 157 LLVMValueRef con; 158 LLVMValueRef res; 159 160 vec_type = lp_build_vec_type(gallivm, type); 161 162 args[4] = args[3] = args[2] = args[1] = args[0] = LLVMPointerType(vec_type, 0); 163 func = LLVMAddFunction(module, "test", LLVMFunctionType(LLVMVoidTypeInContext(context), args, 5, 0)); 164 LLVMSetFunctionCallConv(func, LLVMCCallConv); 165 src_ptr = LLVMGetParam(func, 0); 166 src1_ptr = LLVMGetParam(func, 1); 167 dst_ptr = LLVMGetParam(func, 2); 168 const_ptr = LLVMGetParam(func, 3); 169 res_ptr = LLVMGetParam(func, 4); 170 171 block = LLVMAppendBasicBlockInContext(context, func, "entry"); 172 builder = gallivm->builder; 173 LLVMPositionBuilderAtEnd(builder, block); 174 175 src = LLVMBuildLoad(builder, src_ptr, "src"); 176 src1 = LLVMBuildLoad(builder, src1_ptr, "src1"); 177 dst = LLVMBuildLoad(builder, dst_ptr, "dst"); 178 con = LLVMBuildLoad(builder, const_ptr, "const"); 179 180 res = lp_build_blend_aos(gallivm, blend, format, type, rt, src, NULL, 181 src1, NULL, dst, NULL, con, NULL, swizzle, 4); 182 183 lp_build_name(res, "res"); 184 185 LLVMBuildStore(builder, res, res_ptr); 186 187 LLVMBuildRetVoid(builder); 188 189 gallivm_verify_function(gallivm, func); 190 191 return func; 192} 193 194 195static void 196compute_blend_ref_term(unsigned rgb_factor, 197 unsigned alpha_factor, 198 const double *factor, 199 const double *src, 200 const double *src1, 201 const double *dst, 202 const double *con, 203 double *term) 204{ 205 double temp; 206 207 switch (rgb_factor) { 208 case PIPE_BLENDFACTOR_ONE: 209 term[0] = factor[0]; /* R */ 210 term[1] = factor[1]; /* G */ 211 term[2] = factor[2]; /* B */ 212 break; 213 case PIPE_BLENDFACTOR_SRC_COLOR: 214 term[0] = factor[0] * src[0]; /* R */ 215 term[1] = factor[1] * src[1]; /* G */ 216 term[2] = factor[2] * src[2]; /* B */ 217 break; 218 case PIPE_BLENDFACTOR_SRC_ALPHA: 219 term[0] = factor[0] * src[3]; /* R */ 220 term[1] = factor[1] * src[3]; /* G */ 221 term[2] = factor[2] * src[3]; /* B */ 222 break; 223 case PIPE_BLENDFACTOR_DST_COLOR: 224 term[0] = factor[0] * dst[0]; /* R */ 225 term[1] = factor[1] * dst[1]; /* G */ 226 term[2] = factor[2] * dst[2]; /* B */ 227 break; 228 case PIPE_BLENDFACTOR_DST_ALPHA: 229 term[0] = factor[0] * dst[3]; /* R */ 230 term[1] = factor[1] * dst[3]; /* G */ 231 term[2] = factor[2] * dst[3]; /* B */ 232 break; 233 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 234 temp = MIN2(src[3], 1.0f - dst[3]); 235 term[0] = factor[0] * temp; /* R */ 236 term[1] = factor[1] * temp; /* G */ 237 term[2] = factor[2] * temp; /* B */ 238 break; 239 case PIPE_BLENDFACTOR_CONST_COLOR: 240 term[0] = factor[0] * con[0]; /* R */ 241 term[1] = factor[1] * con[1]; /* G */ 242 term[2] = factor[2] * con[2]; /* B */ 243 break; 244 case PIPE_BLENDFACTOR_CONST_ALPHA: 245 term[0] = factor[0] * con[3]; /* R */ 246 term[1] = factor[1] * con[3]; /* G */ 247 term[2] = factor[2] * con[3]; /* B */ 248 break; 249 case PIPE_BLENDFACTOR_SRC1_COLOR: 250 term[0] = factor[0] * src1[0]; /* R */ 251 term[1] = factor[1] * src1[1]; /* G */ 252 term[2] = factor[2] * src1[2]; /* B */ 253 break; 254 case PIPE_BLENDFACTOR_SRC1_ALPHA: 255 term[0] = factor[0] * src1[3]; /* R */ 256 term[1] = factor[1] * src1[3]; /* G */ 257 term[2] = factor[2] * src1[3]; /* B */ 258 break; 259 case PIPE_BLENDFACTOR_ZERO: 260 term[0] = 0.0f; /* R */ 261 term[1] = 0.0f; /* G */ 262 term[2] = 0.0f; /* B */ 263 break; 264 case PIPE_BLENDFACTOR_INV_SRC_COLOR: 265 term[0] = factor[0] * (1.0f - src[0]); /* R */ 266 term[1] = factor[1] * (1.0f - src[1]); /* G */ 267 term[2] = factor[2] * (1.0f - src[2]); /* B */ 268 break; 269 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: 270 term[0] = factor[0] * (1.0f - src[3]); /* R */ 271 term[1] = factor[1] * (1.0f - src[3]); /* G */ 272 term[2] = factor[2] * (1.0f - src[3]); /* B */ 273 break; 274 case PIPE_BLENDFACTOR_INV_DST_ALPHA: 275 term[0] = factor[0] * (1.0f - dst[3]); /* R */ 276 term[1] = factor[1] * (1.0f - dst[3]); /* G */ 277 term[2] = factor[2] * (1.0f - dst[3]); /* B */ 278 break; 279 case PIPE_BLENDFACTOR_INV_DST_COLOR: 280 term[0] = factor[0] * (1.0f - dst[0]); /* R */ 281 term[1] = factor[1] * (1.0f - dst[1]); /* G */ 282 term[2] = factor[2] * (1.0f - dst[2]); /* B */ 283 break; 284 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 285 term[0] = factor[0] * (1.0f - con[0]); /* R */ 286 term[1] = factor[1] * (1.0f - con[1]); /* G */ 287 term[2] = factor[2] * (1.0f - con[2]); /* B */ 288 break; 289 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 290 term[0] = factor[0] * (1.0f - con[3]); /* R */ 291 term[1] = factor[1] * (1.0f - con[3]); /* G */ 292 term[2] = factor[2] * (1.0f - con[3]); /* B */ 293 break; 294 case PIPE_BLENDFACTOR_INV_SRC1_COLOR: 295 term[0] = factor[0] * (1.0f - src1[0]); /* R */ 296 term[1] = factor[1] * (1.0f - src1[1]); /* G */ 297 term[2] = factor[2] * (1.0f - src1[2]); /* B */ 298 break; 299 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: 300 term[0] = factor[0] * (1.0f - src1[3]); /* R */ 301 term[1] = factor[1] * (1.0f - src1[3]); /* G */ 302 term[2] = factor[2] * (1.0f - src1[3]); /* B */ 303 break; 304 default: 305 assert(0); 306 } 307 308 /* 309 * Compute src/first term A 310 */ 311 switch (alpha_factor) { 312 case PIPE_BLENDFACTOR_ONE: 313 term[3] = factor[3]; /* A */ 314 break; 315 case PIPE_BLENDFACTOR_SRC_COLOR: 316 case PIPE_BLENDFACTOR_SRC_ALPHA: 317 term[3] = factor[3] * src[3]; /* A */ 318 break; 319 case PIPE_BLENDFACTOR_DST_COLOR: 320 case PIPE_BLENDFACTOR_DST_ALPHA: 321 term[3] = factor[3] * dst[3]; /* A */ 322 break; 323 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 324 term[3] = src[3]; /* A */ 325 break; 326 case PIPE_BLENDFACTOR_CONST_COLOR: 327 case PIPE_BLENDFACTOR_CONST_ALPHA: 328 term[3] = factor[3] * con[3]; /* A */ 329 break; 330 case PIPE_BLENDFACTOR_SRC1_COLOR: 331 case PIPE_BLENDFACTOR_SRC1_ALPHA: 332 term[3] = factor[3] * src1[3]; /* A */ 333 break; 334 case PIPE_BLENDFACTOR_ZERO: 335 term[3] = 0.0f; /* A */ 336 break; 337 case PIPE_BLENDFACTOR_INV_SRC_COLOR: 338 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: 339 term[3] = factor[3] * (1.0f - src[3]); /* A */ 340 break; 341 case PIPE_BLENDFACTOR_INV_DST_COLOR: 342 case PIPE_BLENDFACTOR_INV_DST_ALPHA: 343 term[3] = factor[3] * (1.0f - dst[3]); /* A */ 344 break; 345 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 346 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 347 term[3] = factor[3] * (1.0f - con[3]); 348 break; 349 case PIPE_BLENDFACTOR_INV_SRC1_COLOR: 350 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: 351 term[3] = factor[3] * (1.0f - src1[3]); /* A */ 352 break; 353 default: 354 assert(0); 355 } 356} 357 358 359static void 360compute_blend_ref(const struct pipe_blend_state *blend, 361 const double *src, 362 const double *src1, 363 const double *dst, 364 const double *con, 365 double *res) 366{ 367 double src_term[4]; 368 double dst_term[4]; 369 370 compute_blend_ref_term(blend->rt[0].rgb_src_factor, blend->rt[0].alpha_src_factor, 371 src, src, src1, dst, con, src_term); 372 compute_blend_ref_term(blend->rt[0].rgb_dst_factor, blend->rt[0].alpha_dst_factor, 373 dst, src, src1, dst, con, dst_term); 374 375 /* 376 * Combine RGB terms 377 */ 378 switch (blend->rt[0].rgb_func) { 379 case PIPE_BLEND_ADD: 380 res[0] = src_term[0] + dst_term[0]; /* R */ 381 res[1] = src_term[1] + dst_term[1]; /* G */ 382 res[2] = src_term[2] + dst_term[2]; /* B */ 383 break; 384 case PIPE_BLEND_SUBTRACT: 385 res[0] = src_term[0] - dst_term[0]; /* R */ 386 res[1] = src_term[1] - dst_term[1]; /* G */ 387 res[2] = src_term[2] - dst_term[2]; /* B */ 388 break; 389 case PIPE_BLEND_REVERSE_SUBTRACT: 390 res[0] = dst_term[0] - src_term[0]; /* R */ 391 res[1] = dst_term[1] - src_term[1]; /* G */ 392 res[2] = dst_term[2] - src_term[2]; /* B */ 393 break; 394 case PIPE_BLEND_MIN: 395 res[0] = MIN2(src_term[0], dst_term[0]); /* R */ 396 res[1] = MIN2(src_term[1], dst_term[1]); /* G */ 397 res[2] = MIN2(src_term[2], dst_term[2]); /* B */ 398 break; 399 case PIPE_BLEND_MAX: 400 res[0] = MAX2(src_term[0], dst_term[0]); /* R */ 401 res[1] = MAX2(src_term[1], dst_term[1]); /* G */ 402 res[2] = MAX2(src_term[2], dst_term[2]); /* B */ 403 break; 404 default: 405 assert(0); 406 } 407 408 /* 409 * Combine A terms 410 */ 411 switch (blend->rt[0].alpha_func) { 412 case PIPE_BLEND_ADD: 413 res[3] = src_term[3] + dst_term[3]; /* A */ 414 break; 415 case PIPE_BLEND_SUBTRACT: 416 res[3] = src_term[3] - dst_term[3]; /* A */ 417 break; 418 case PIPE_BLEND_REVERSE_SUBTRACT: 419 res[3] = dst_term[3] - src_term[3]; /* A */ 420 break; 421 case PIPE_BLEND_MIN: 422 res[3] = MIN2(src_term[3], dst_term[3]); /* A */ 423 break; 424 case PIPE_BLEND_MAX: 425 res[3] = MAX2(src_term[3], dst_term[3]); /* A */ 426 break; 427 default: 428 assert(0); 429 } 430} 431 432 433PIPE_ALIGN_STACK 434static boolean 435test_one(unsigned verbose, 436 FILE *fp, 437 const struct pipe_blend_state *blend, 438 struct lp_type type) 439{ 440 LLVMContextRef context; 441 struct gallivm_state *gallivm; 442 LLVMValueRef func = NULL; 443 blend_test_ptr_t blend_test_ptr; 444 boolean success; 445 const unsigned n = LP_TEST_NUM_SAMPLES; 446 int64_t cycles[LP_TEST_NUM_SAMPLES]; 447 double cycles_avg = 0.0; 448 unsigned i, j; 449 const unsigned stride = lp_type_width(type)/8; 450 451 if(verbose >= 1) 452 dump_blend_type(stdout, blend, type); 453 454 context = LLVMContextCreate(); 455#if LLVM_VERSION_MAJOR >= 15 456 LLVMContextSetOpaquePointers(context, false); 457#endif 458 gallivm = gallivm_create("test_module", context, NULL); 459 460 func = add_blend_test(gallivm, blend, type); 461 462 gallivm_compile_module(gallivm); 463 464 blend_test_ptr = (blend_test_ptr_t)gallivm_jit_function(gallivm, func); 465 466 gallivm_free_ir(gallivm); 467 468 success = TRUE; 469 470 { 471 uint8_t *src, *src1, *dst, *con, *res, *ref; 472 src = align_malloc(stride, stride); 473 src1 = align_malloc(stride, stride); 474 dst = align_malloc(stride, stride); 475 con = align_malloc(stride, stride); 476 res = align_malloc(stride, stride); 477 ref = align_malloc(stride, stride); 478 479 for(i = 0; i < n && success; ++i) { 480 int64_t start_counter = 0; 481 int64_t end_counter = 0; 482 483 random_vec(type, src); 484 random_vec(type, src1); 485 random_vec(type, dst); 486 random_vec(type, con); 487 488 { 489 double fsrc[LP_MAX_VECTOR_LENGTH]; 490 double fsrc1[LP_MAX_VECTOR_LENGTH]; 491 double fdst[LP_MAX_VECTOR_LENGTH]; 492 double fcon[LP_MAX_VECTOR_LENGTH]; 493 double fref[LP_MAX_VECTOR_LENGTH]; 494 495 read_vec(type, src, fsrc); 496 read_vec(type, src1, fsrc1); 497 read_vec(type, dst, fdst); 498 read_vec(type, con, fcon); 499 500 for(j = 0; j < type.length; j += 4) 501 compute_blend_ref(blend, fsrc + j, fsrc1 + j, fdst + j, fcon + j, fref + j); 502 503 write_vec(type, ref, fref); 504 } 505 506 start_counter = rdtsc(); 507 blend_test_ptr(src, src1, dst, con, res); 508 end_counter = rdtsc(); 509 510 cycles[i] = end_counter - start_counter; 511 512 if(!compare_vec(type, res, ref)) { 513 success = FALSE; 514 515 if(verbose < 1) 516 dump_blend_type(stderr, blend, type); 517 fprintf(stderr, "MISMATCH\n"); 518 519 fprintf(stderr, " Src: "); 520 dump_vec(stderr, type, src); 521 fprintf(stderr, "\n"); 522 523 fprintf(stderr, " Src1: "); 524 dump_vec(stderr, type, src1); 525 fprintf(stderr, "\n"); 526 527 fprintf(stderr, " Dst: "); 528 dump_vec(stderr, type, dst); 529 fprintf(stderr, "\n"); 530 531 fprintf(stderr, " Con: "); 532 dump_vec(stderr, type, con); 533 fprintf(stderr, "\n"); 534 535 fprintf(stderr, " Res: "); 536 dump_vec(stderr, type, res); 537 fprintf(stderr, "\n"); 538 539 fprintf(stderr, " Ref: "); 540 dump_vec(stderr, type, ref); 541 fprintf(stderr, "\n"); 542 } 543 } 544 align_free(src); 545 align_free(src1); 546 align_free(dst); 547 align_free(con); 548 align_free(res); 549 align_free(ref); 550 } 551 552 /* 553 * Unfortunately the output of cycle counter is not very reliable as it comes 554 * -- sometimes we get outliers (due IRQs perhaps?) which are 555 * better removed to avoid random or biased data. 556 */ 557 { 558 double sum = 0.0, sum2 = 0.0; 559 double avg, std; 560 unsigned m; 561 562 for(i = 0; i < n; ++i) { 563 sum += cycles[i]; 564 sum2 += cycles[i]*cycles[i]; 565 } 566 567 avg = sum/n; 568 std = sqrtf((sum2 - n*avg*avg)/n); 569 570 m = 0; 571 sum = 0.0; 572 for(i = 0; i < n; ++i) { 573 if(fabs(cycles[i] - avg) <= 4.0*std) { 574 sum += cycles[i]; 575 ++m; 576 } 577 } 578 579 cycles_avg = sum/m; 580 581 } 582 583 if(fp) 584 write_tsv_row(fp, blend, type, cycles_avg, success); 585 586 gallivm_destroy(gallivm); 587 LLVMContextDispose(context); 588 589 return success; 590} 591 592 593const unsigned 594blend_factors[] = { 595 PIPE_BLENDFACTOR_ZERO, 596 PIPE_BLENDFACTOR_ONE, 597 PIPE_BLENDFACTOR_SRC_COLOR, 598 PIPE_BLENDFACTOR_SRC_ALPHA, 599 PIPE_BLENDFACTOR_DST_COLOR, 600 PIPE_BLENDFACTOR_DST_ALPHA, 601 PIPE_BLENDFACTOR_CONST_COLOR, 602 PIPE_BLENDFACTOR_CONST_ALPHA, 603 PIPE_BLENDFACTOR_SRC1_COLOR, 604 PIPE_BLENDFACTOR_SRC1_ALPHA, 605 PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE, 606 PIPE_BLENDFACTOR_INV_SRC_COLOR, 607 PIPE_BLENDFACTOR_INV_SRC_ALPHA, 608 PIPE_BLENDFACTOR_INV_DST_COLOR, 609 PIPE_BLENDFACTOR_INV_DST_ALPHA, 610 PIPE_BLENDFACTOR_INV_CONST_COLOR, 611 PIPE_BLENDFACTOR_INV_CONST_ALPHA, 612 PIPE_BLENDFACTOR_INV_SRC1_COLOR, 613 PIPE_BLENDFACTOR_INV_SRC1_ALPHA, 614}; 615 616 617const unsigned 618blend_funcs[] = { 619 PIPE_BLEND_ADD, 620 PIPE_BLEND_SUBTRACT, 621 PIPE_BLEND_REVERSE_SUBTRACT, 622 PIPE_BLEND_MIN, 623 PIPE_BLEND_MAX 624}; 625 626 627const struct lp_type blend_types[] = { 628 /* float, fixed, sign, norm, width, len */ 629 { TRUE, FALSE, TRUE, FALSE, 32, 4 }, /* f32 x 4 */ 630 { FALSE, FALSE, FALSE, TRUE, 8, 16 }, /* u8n x 16 */ 631}; 632 633 634const unsigned num_funcs = ARRAY_SIZE(blend_funcs); 635const unsigned num_factors = ARRAY_SIZE(blend_factors); 636const unsigned num_types = ARRAY_SIZE(blend_types); 637 638 639boolean 640test_all(unsigned verbose, FILE *fp) 641{ 642 const unsigned *rgb_func; 643 const unsigned *rgb_src_factor; 644 const unsigned *rgb_dst_factor; 645 const unsigned *alpha_func; 646 const unsigned *alpha_src_factor; 647 const unsigned *alpha_dst_factor; 648 struct pipe_blend_state blend; 649 const struct lp_type *type; 650 boolean success = TRUE; 651 652 for(rgb_func = blend_funcs; rgb_func < &blend_funcs[num_funcs]; ++rgb_func) { 653 for(alpha_func = blend_funcs; alpha_func < &blend_funcs[num_funcs]; ++alpha_func) { 654 for(rgb_src_factor = blend_factors; rgb_src_factor < &blend_factors[num_factors]; ++rgb_src_factor) { 655 for(rgb_dst_factor = blend_factors; rgb_dst_factor <= rgb_src_factor; ++rgb_dst_factor) { 656 for(alpha_src_factor = blend_factors; alpha_src_factor < &blend_factors[num_factors]; ++alpha_src_factor) { 657 for(alpha_dst_factor = blend_factors; alpha_dst_factor <= alpha_src_factor; ++alpha_dst_factor) { 658 for(type = blend_types; type < &blend_types[num_types]; ++type) { 659 660 if(*rgb_dst_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE || 661 *alpha_dst_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE) 662 continue; 663 664 memset(&blend, 0, sizeof blend); 665 blend.rt[0].blend_enable = 1; 666 blend.rt[0].rgb_func = *rgb_func; 667 blend.rt[0].rgb_src_factor = *rgb_src_factor; 668 blend.rt[0].rgb_dst_factor = *rgb_dst_factor; 669 blend.rt[0].alpha_func = *alpha_func; 670 blend.rt[0].alpha_src_factor = *alpha_src_factor; 671 blend.rt[0].alpha_dst_factor = *alpha_dst_factor; 672 blend.rt[0].colormask = PIPE_MASK_RGBA; 673 674 if(!test_one(verbose, fp, &blend, *type)) 675 success = FALSE; 676 677 } 678 } 679 } 680 } 681 } 682 } 683 } 684 685 return success; 686} 687 688 689boolean 690test_some(unsigned verbose, FILE *fp, 691 unsigned long n) 692{ 693 const unsigned *rgb_func; 694 const unsigned *rgb_src_factor; 695 const unsigned *rgb_dst_factor; 696 const unsigned *alpha_func; 697 const unsigned *alpha_src_factor; 698 const unsigned *alpha_dst_factor; 699 struct pipe_blend_state blend; 700 const struct lp_type *type; 701 unsigned long i; 702 boolean success = TRUE; 703 704 for(i = 0; i < n; ++i) { 705 rgb_func = &blend_funcs[rand() % num_funcs]; 706 alpha_func = &blend_funcs[rand() % num_funcs]; 707 rgb_src_factor = &blend_factors[rand() % num_factors]; 708 alpha_src_factor = &blend_factors[rand() % num_factors]; 709 710 do { 711 rgb_dst_factor = &blend_factors[rand() % num_factors]; 712 } while(*rgb_dst_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE); 713 714 do { 715 alpha_dst_factor = &blend_factors[rand() % num_factors]; 716 } while(*alpha_dst_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE); 717 718 type = &blend_types[rand() % num_types]; 719 720 memset(&blend, 0, sizeof blend); 721 blend.rt[0].blend_enable = 1; 722 blend.rt[0].rgb_func = *rgb_func; 723 blend.rt[0].rgb_src_factor = *rgb_src_factor; 724 blend.rt[0].rgb_dst_factor = *rgb_dst_factor; 725 blend.rt[0].alpha_func = *alpha_func; 726 blend.rt[0].alpha_src_factor = *alpha_src_factor; 727 blend.rt[0].alpha_dst_factor = *alpha_dst_factor; 728 blend.rt[0].colormask = PIPE_MASK_RGBA; 729 730 if(!test_one(verbose, fp, &blend, *type)) 731 success = FALSE; 732 } 733 734 return success; 735} 736 737 738boolean 739test_single(unsigned verbose, FILE *fp) 740{ 741 printf("no test_single()"); 742 return TRUE; 743} 744