• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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