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
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
write_tsv_header(FILE * fp)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
write_tsv_row(FILE * fp,const struct pipe_blend_state * blend,struct lp_type type,double cycles,boolean success)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_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
109 static void
dump_blend_type(FILE * fp,const struct pipe_blend_state * blend,struct lp_type type)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_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
134 static LLVMValueRef
add_blend_test(struct gallivm_state * gallivm,const struct pipe_blend_state * blend,struct lp_type type)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
compute_blend_ref_term(unsigned rgb_factor,unsigned alpha_factor,const double * factor,const double * src,const double * src1,const double * dst,const double * con,double * term)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
compute_blend_ref(const struct pipe_blend_state * blend,const double * src,const double * src1,const double * dst,const double * con,double * res)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
test_one(unsigned verbose,FILE * fp,const struct pipe_blend_state * blend,struct lp_type type)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 #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
593 const unsigned
594 blend_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
617 const unsigned
618 blend_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
627 const 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
634 const unsigned num_funcs = ARRAY_SIZE(blend_funcs);
635 const unsigned num_factors = ARRAY_SIZE(blend_factors);
636 const unsigned num_types = ARRAY_SIZE(blend_types);
637
638
639 boolean
test_all(unsigned verbose,FILE * fp)640 test_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
689 boolean
test_some(unsigned verbose,FILE * fp,unsigned long n)690 test_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
738 boolean
test_single(unsigned verbose,FILE * fp)739 test_single(unsigned verbose, FILE *fp)
740 {
741 printf("no test_single()");
742 return TRUE;
743 }
744