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