Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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