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 (at) vmware.com> 34 * 35 * Blend computation code derived from code written by 36 * @author Brian Paul <brian (at) 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 48 typedef void (*blend_test_ptr_t)(const void *src, const void *src1, 49 const void *dst, const void *con, void *res); 50 51 52 void 53 write_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 73 static void 74 write_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_dump_blend_func(blend->rt[0].rgb_func, TRUE), 99 util_dump_blend_factor(blend->rt[0].rgb_src_factor, TRUE), 100 util_dump_blend_factor(blend->rt[0].rgb_dst_factor, TRUE), 101 util_dump_blend_func(blend->rt[0].alpha_func, TRUE), 102 util_dump_blend_factor(blend->rt[0].alpha_src_factor, TRUE), 103 util_dump_blend_factor(blend->rt[0].alpha_dst_factor, TRUE)); 104 105 fflush(fp); 106 } 107 108 109 static void 110 dump_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_dump_blend_func(blend->rt[0].rgb_func, TRUE), 123 "rgb_src_factor", util_dump_blend_factor(blend->rt[0].rgb_src_factor, TRUE), 124 "rgb_dst_factor", util_dump_blend_factor(blend->rt[0].rgb_dst_factor, TRUE), 125 "alpha_func", util_dump_blend_func(blend->rt[0].alpha_func, TRUE), 126 "alpha_src_factor", util_dump_blend_factor(blend->rt[0].alpha_src_factor, TRUE), 127 "alpha_dst_factor", util_dump_blend_factor(blend->rt[0].alpha_dst_factor, TRUE)); 128 129 fprintf(fp, " ...\n"); 130 fflush(fp); 131 } 132 133 134 static LLVMValueRef 135 add_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 195 static void 196 compute_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 359 static void 360 compute_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 433 PIPE_ALIGN_STACK 434 static boolean 435 test_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 gallivm = gallivm_create("test_module", context); 456 457 func = add_blend_test(gallivm, blend, type); 458 459 gallivm_compile_module(gallivm); 460 461 blend_test_ptr = (blend_test_ptr_t)gallivm_jit_function(gallivm, func); 462 463 gallivm_free_ir(gallivm); 464 465 success = TRUE; 466 467 { 468 uint8_t *src, *src1, *dst, *con, *res, *ref; 469 src = align_malloc(stride, stride); 470 src1 = align_malloc(stride, stride); 471 dst = align_malloc(stride, stride); 472 con = align_malloc(stride, stride); 473 res = align_malloc(stride, stride); 474 ref = align_malloc(stride, stride); 475 476 for(i = 0; i < n && success; ++i) { 477 int64_t start_counter = 0; 478 int64_t end_counter = 0; 479 480 random_vec(type, src); 481 random_vec(type, src1); 482 random_vec(type, dst); 483 random_vec(type, con); 484 485 { 486 double fsrc[LP_MAX_VECTOR_LENGTH]; 487 double fsrc1[LP_MAX_VECTOR_LENGTH]; 488 double fdst[LP_MAX_VECTOR_LENGTH]; 489 double fcon[LP_MAX_VECTOR_LENGTH]; 490 double fref[LP_MAX_VECTOR_LENGTH]; 491 492 read_vec(type, src, fsrc); 493 read_vec(type, src1, fsrc1); 494 read_vec(type, dst, fdst); 495 read_vec(type, con, fcon); 496 497 for(j = 0; j < type.length; j += 4) 498 compute_blend_ref(blend, fsrc + j, fsrc1 + j, fdst + j, fcon + j, fref + j); 499 500 write_vec(type, ref, fref); 501 } 502 503 start_counter = rdtsc(); 504 blend_test_ptr(src, src1, dst, con, res); 505 end_counter = rdtsc(); 506 507 cycles[i] = end_counter - start_counter; 508 509 if(!compare_vec(type, res, ref)) { 510 success = FALSE; 511 512 if(verbose < 1) 513 dump_blend_type(stderr, blend, type); 514 fprintf(stderr, "MISMATCH\n"); 515 516 fprintf(stderr, " Src: "); 517 dump_vec(stderr, type, src); 518 fprintf(stderr, "\n"); 519 520 fprintf(stderr, " Src1: "); 521 dump_vec(stderr, type, src1); 522 fprintf(stderr, "\n"); 523 524 fprintf(stderr, " Dst: "); 525 dump_vec(stderr, type, dst); 526 fprintf(stderr, "\n"); 527 528 fprintf(stderr, " Con: "); 529 dump_vec(stderr, type, con); 530 fprintf(stderr, "\n"); 531 532 fprintf(stderr, " Res: "); 533 dump_vec(stderr, type, res); 534 fprintf(stderr, "\n"); 535 536 fprintf(stderr, " Ref: "); 537 dump_vec(stderr, type, ref); 538 fprintf(stderr, "\n"); 539 } 540 } 541 align_free(src); 542 align_free(src1); 543 align_free(dst); 544 align_free(con); 545 align_free(res); 546 align_free(ref); 547 } 548 549 /* 550 * Unfortunately the output of cycle counter is not very reliable as it comes 551 * -- sometimes we get outliers (due IRQs perhaps?) which are 552 * better removed to avoid random or biased data. 553 */ 554 { 555 double sum = 0.0, sum2 = 0.0; 556 double avg, std; 557 unsigned m; 558 559 for(i = 0; i < n; ++i) { 560 sum += cycles[i]; 561 sum2 += cycles[i]*cycles[i]; 562 } 563 564 avg = sum/n; 565 std = sqrtf((sum2 - n*avg*avg)/n); 566 567 m = 0; 568 sum = 0.0; 569 for(i = 0; i < n; ++i) { 570 if(fabs(cycles[i] - avg) <= 4.0*std) { 571 sum += cycles[i]; 572 ++m; 573 } 574 } 575 576 cycles_avg = sum/m; 577 578 } 579 580 if(fp) 581 write_tsv_row(fp, blend, type, cycles_avg, success); 582 583 gallivm_destroy(gallivm); 584 LLVMContextDispose(context); 585 586 return success; 587 } 588 589 590 const unsigned 591 blend_factors[] = { 592 PIPE_BLENDFACTOR_ZERO, 593 PIPE_BLENDFACTOR_ONE, 594 PIPE_BLENDFACTOR_SRC_COLOR, 595 PIPE_BLENDFACTOR_SRC_ALPHA, 596 PIPE_BLENDFACTOR_DST_COLOR, 597 PIPE_BLENDFACTOR_DST_ALPHA, 598 PIPE_BLENDFACTOR_CONST_COLOR, 599 PIPE_BLENDFACTOR_CONST_ALPHA, 600 PIPE_BLENDFACTOR_SRC1_COLOR, 601 PIPE_BLENDFACTOR_SRC1_ALPHA, 602 PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE, 603 PIPE_BLENDFACTOR_INV_SRC_COLOR, 604 PIPE_BLENDFACTOR_INV_SRC_ALPHA, 605 PIPE_BLENDFACTOR_INV_DST_COLOR, 606 PIPE_BLENDFACTOR_INV_DST_ALPHA, 607 PIPE_BLENDFACTOR_INV_CONST_COLOR, 608 PIPE_BLENDFACTOR_INV_CONST_ALPHA, 609 PIPE_BLENDFACTOR_INV_SRC1_COLOR, 610 PIPE_BLENDFACTOR_INV_SRC1_ALPHA, 611 }; 612 613 614 const unsigned 615 blend_funcs[] = { 616 PIPE_BLEND_ADD, 617 PIPE_BLEND_SUBTRACT, 618 PIPE_BLEND_REVERSE_SUBTRACT, 619 PIPE_BLEND_MIN, 620 PIPE_BLEND_MAX 621 }; 622 623 624 const struct lp_type blend_types[] = { 625 /* float, fixed, sign, norm, width, len */ 626 { TRUE, FALSE, TRUE, FALSE, 32, 4 }, /* f32 x 4 */ 627 { FALSE, FALSE, FALSE, TRUE, 8, 16 }, /* u8n x 16 */ 628 }; 629 630 631 const unsigned num_funcs = ARRAY_SIZE(blend_funcs); 632 const unsigned num_factors = ARRAY_SIZE(blend_factors); 633 const unsigned num_types = ARRAY_SIZE(blend_types); 634 635 636 boolean 637 test_all(unsigned verbose, FILE *fp) 638 { 639 const unsigned *rgb_func; 640 const unsigned *rgb_src_factor; 641 const unsigned *rgb_dst_factor; 642 const unsigned *alpha_func; 643 const unsigned *alpha_src_factor; 644 const unsigned *alpha_dst_factor; 645 struct pipe_blend_state blend; 646 const struct lp_type *type; 647 boolean success = TRUE; 648 649 for(rgb_func = blend_funcs; rgb_func < &blend_funcs[num_funcs]; ++rgb_func) { 650 for(alpha_func = blend_funcs; alpha_func < &blend_funcs[num_funcs]; ++alpha_func) { 651 for(rgb_src_factor = blend_factors; rgb_src_factor < &blend_factors[num_factors]; ++rgb_src_factor) { 652 for(rgb_dst_factor = blend_factors; rgb_dst_factor <= rgb_src_factor; ++rgb_dst_factor) { 653 for(alpha_src_factor = blend_factors; alpha_src_factor < &blend_factors[num_factors]; ++alpha_src_factor) { 654 for(alpha_dst_factor = blend_factors; alpha_dst_factor <= alpha_src_factor; ++alpha_dst_factor) { 655 for(type = blend_types; type < &blend_types[num_types]; ++type) { 656 657 if(*rgb_dst_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE || 658 *alpha_dst_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE) 659 continue; 660 661 memset(&blend, 0, sizeof blend); 662 blend.rt[0].blend_enable = 1; 663 blend.rt[0].rgb_func = *rgb_func; 664 blend.rt[0].rgb_src_factor = *rgb_src_factor; 665 blend.rt[0].rgb_dst_factor = *rgb_dst_factor; 666 blend.rt[0].alpha_func = *alpha_func; 667 blend.rt[0].alpha_src_factor = *alpha_src_factor; 668 blend.rt[0].alpha_dst_factor = *alpha_dst_factor; 669 blend.rt[0].colormask = PIPE_MASK_RGBA; 670 671 if(!test_one(verbose, fp, &blend, *type)) 672 success = FALSE; 673 674 } 675 } 676 } 677 } 678 } 679 } 680 } 681 682 return success; 683 } 684 685 686 boolean 687 test_some(unsigned verbose, FILE *fp, 688 unsigned long n) 689 { 690 const unsigned *rgb_func; 691 const unsigned *rgb_src_factor; 692 const unsigned *rgb_dst_factor; 693 const unsigned *alpha_func; 694 const unsigned *alpha_src_factor; 695 const unsigned *alpha_dst_factor; 696 struct pipe_blend_state blend; 697 const struct lp_type *type; 698 unsigned long i; 699 boolean success = TRUE; 700 701 for(i = 0; i < n; ++i) { 702 rgb_func = &blend_funcs[rand() % num_funcs]; 703 alpha_func = &blend_funcs[rand() % num_funcs]; 704 rgb_src_factor = &blend_factors[rand() % num_factors]; 705 alpha_src_factor = &blend_factors[rand() % num_factors]; 706 707 do { 708 rgb_dst_factor = &blend_factors[rand() % num_factors]; 709 } while(*rgb_dst_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE); 710 711 do { 712 alpha_dst_factor = &blend_factors[rand() % num_factors]; 713 } while(*alpha_dst_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE); 714 715 type = &blend_types[rand() % num_types]; 716 717 memset(&blend, 0, sizeof blend); 718 blend.rt[0].blend_enable = 1; 719 blend.rt[0].rgb_func = *rgb_func; 720 blend.rt[0].rgb_src_factor = *rgb_src_factor; 721 blend.rt[0].rgb_dst_factor = *rgb_dst_factor; 722 blend.rt[0].alpha_func = *alpha_func; 723 blend.rt[0].alpha_src_factor = *alpha_src_factor; 724 blend.rt[0].alpha_dst_factor = *alpha_dst_factor; 725 blend.rt[0].colormask = PIPE_MASK_RGBA; 726 727 if(!test_one(verbose, fp, &blend, *type)) 728 success = FALSE; 729 } 730 731 return success; 732 } 733 734 735 boolean 736 test_single(unsigned verbose, FILE *fp) 737 { 738 printf("no test_single()"); 739 return TRUE; 740 } 741