*/
-#include <stdlib.h>
-#include <stdio.h>
-#include <float.h>
+#include "lp_bld_type.h"
+#include "lp_bld_blend.h"
+#include "lp_bld_debug.h"
+#include "lp_test.h"
-#include <llvm-c/Core.h>
-#include <llvm-c/Analysis.h>
-#include <llvm-c/ExecutionEngine.h>
-#include <llvm-c/Target.h>
-#include <llvm-c/BitWriter.h>
-#include <llvm-c/Transforms/Scalar.h>
-#include "pipe/p_state.h"
-#include "util/u_format.h"
-#include "util/u_math.h"
+enum vector_mode
+{
+ AoS = 0,
+ SoA = 1
+};
-#include "lp_bld.h"
-#include "lp_bld_arit.h"
+typedef void (*blend_test_ptr_t)(const void *src, const void *dst, const void *con, void *res);
-unsigned verbose = 0;
+void
+write_tsv_header(FILE *fp)
+{
+ fprintf(fp,
+ "result\t"
+ "cycles_per_channel\t"
+ "mode\t"
+ "type\t"
+ "sep_func\t"
+ "sep_src_factor\t"
+ "sep_dst_factor\t"
+ "rgb_func\t"
+ "rgb_src_factor\t"
+ "rgb_dst_factor\t"
+ "alpha_func\t"
+ "alpha_src_factor\t"
+ "alpha_dst_factor\n");
+
+ fflush(fp);
+}
-typedef void (*blend_test_ptr_t)(const void *src, const void *dst, const void *con, void *res);
+
+static void
+write_tsv_row(FILE *fp,
+ const struct pipe_blend_state *blend,
+ enum vector_mode mode,
+ struct lp_type type,
+ double cycles,
+ boolean success)
+{
+ fprintf(fp, "%s\t", success ? "pass" : "fail");
+
+ if (mode == AoS) {
+ fprintf(fp, "%.1f\t", cycles / type.length);
+ fprintf(fp, "aos\t");
+ }
+
+ if (mode == SoA) {
+ fprintf(fp, "%.1f\t", cycles / (4 * type.length));
+ fprintf(fp, "soa\t");
+ }
+
+ fprintf(fp, "%s%u%sx%u\t",
+ type.floating ? "f" : (type.fixed ? "h" : (type.sign ? "s" : "u")),
+ type.width,
+ type.norm ? "n" : "",
+ type.length);
+
+ fprintf(fp,
+ "%s\t%s\t%s\t",
+ blend->rgb_func != blend->alpha_func ? "true" : "false",
+ blend->rgb_src_factor != blend->alpha_src_factor ? "true" : "false",
+ blend->rgb_dst_factor != blend->alpha_dst_factor ? "true" : "false");
+
+ fprintf(fp,
+ "%s\t%s\t%s\t%s\t%s\t%s\n",
+ debug_dump_blend_func(blend->rgb_func, TRUE),
+ debug_dump_blend_factor(blend->rgb_src_factor, TRUE),
+ debug_dump_blend_factor(blend->rgb_dst_factor, TRUE),
+ debug_dump_blend_func(blend->alpha_func, TRUE),
+ debug_dump_blend_factor(blend->alpha_src_factor, TRUE),
+ debug_dump_blend_factor(blend->alpha_dst_factor, TRUE));
+
+ fflush(fp);
+}
+
+
+static void
+dump_blend_type(FILE *fp,
+ const struct pipe_blend_state *blend,
+ enum vector_mode mode,
+ struct lp_type type)
+{
+ fprintf(fp, "%s", mode ? "soa" : "aos");
+
+ fprintf(fp, " type=%s%u%sx%u",
+ type.floating ? "f" : (type.fixed ? "h" : (type.sign ? "s" : "u")),
+ type.width,
+ type.norm ? "n" : "",
+ type.length);
+
+ fprintf(fp,
+ " %s=%s %s=%s %s=%s %s=%s %s=%s %s=%s",
+ "rgb_func", debug_dump_blend_func(blend->rgb_func, TRUE),
+ "rgb_src_factor", debug_dump_blend_factor(blend->rgb_src_factor, TRUE),
+ "rgb_dst_factor", debug_dump_blend_factor(blend->rgb_dst_factor, TRUE),
+ "alpha_func", debug_dump_blend_func(blend->alpha_func, TRUE),
+ "alpha_src_factor", debug_dump_blend_factor(blend->alpha_src_factor, TRUE),
+ "alpha_dst_factor", debug_dump_blend_factor(blend->alpha_dst_factor, TRUE));
+
+ fprintf(fp, " ...\n");
+ fflush(fp);
+}
static LLVMValueRef
add_blend_test(LLVMModuleRef module,
const struct pipe_blend_state *blend,
- union lp_type type)
+ enum vector_mode mode,
+ struct lp_type type)
{
+ LLVMTypeRef ret_type;
LLVMTypeRef vec_type;
LLVMTypeRef args[4];
LLVMValueRef func;
LLVMValueRef res_ptr;
LLVMBasicBlockRef block;
LLVMBuilderRef builder;
- LLVMValueRef src;
- LLVMValueRef dst;
- LLVMValueRef con;
- LLVMValueRef res;
+ ret_type = LLVMInt64Type();
vec_type = lp_build_vec_type(type);
args[3] = args[2] = args[1] = args[0] = LLVMPointerType(vec_type, 0);
builder = LLVMCreateBuilder();
LLVMPositionBuilderAtEnd(builder, block);
- src = LLVMBuildLoad(builder, src_ptr, "src");
- dst = LLVMBuildLoad(builder, dst_ptr, "dst");
- con = LLVMBuildLoad(builder, const_ptr, "const");
+ if (mode == AoS) {
+ LLVMValueRef src;
+ LLVMValueRef dst;
+ LLVMValueRef con;
+ LLVMValueRef res;
+
+ src = LLVMBuildLoad(builder, src_ptr, "src");
+ dst = LLVMBuildLoad(builder, dst_ptr, "dst");
+ con = LLVMBuildLoad(builder, const_ptr, "const");
- res = lp_build_blend(builder, blend, type, src, dst, con, 3);
+ res = lp_build_blend_aos(builder, blend, type, src, dst, con, 3);
- LLVMSetValueName(res, "res");
+ lp_build_name(res, "res");
- LLVMBuildStore(builder, res, res_ptr);
+ LLVMBuildStore(builder, res, res_ptr);
+ }
- LLVMBuildRetVoid(builder);
+ if (mode == SoA) {
+ LLVMValueRef src[4];
+ LLVMValueRef dst[4];
+ LLVMValueRef con[4];
+ LLVMValueRef res[4];
+ unsigned i;
+
+ for(i = 0; i < 4; ++i) {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
+ src[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, src_ptr, &index, 1, ""), "");
+ dst[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dst_ptr, &index, 1, ""), "");
+ con[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, const_ptr, &index, 1, ""), "");
+ lp_build_name(src[i], "src.%c", "rgba"[i]);
+ lp_build_name(con[i], "con.%c", "rgba"[i]);
+ lp_build_name(dst[i], "dst.%c", "rgba"[i]);
+ }
- LLVMDisposeBuilder(builder);
- return func;
-}
+ lp_build_blend_soa(builder, blend, type, src, dst, con, res);
+ for(i = 0; i < 4; ++i) {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
+ lp_build_name(res[i], "res.%c", "rgba"[i]);
+ LLVMBuildStore(builder, res[i], LLVMBuildGEP(builder, res_ptr, &index, 1, ""));
+ }
+ }
-static float
-random_float(void)
-{
- return (float)((double)random()/(double)RAND_MAX);
+ LLVMBuildRetVoid(builder);;
+
+ LLVMDisposeBuilder(builder);
+ return func;
}
static void
compute_blend_ref_term(unsigned rgb_factor,
unsigned alpha_factor,
- const float *factor,
- const float *src,
- const float *dst,
- const float *con,
- float *term)
+ const double *factor,
+ const double *src,
+ const double *dst,
+ const double *con,
+ double *term)
{
- float temp;
+ double temp;
switch (rgb_factor) {
case PIPE_BLENDFACTOR_ONE:
static void
compute_blend_ref(const struct pipe_blend_state *blend,
- const float *src,
- const float *dst,
- const float *con,
- float *res)
+ const double *src,
+ const double *dst,
+ const double *con,
+ double *res)
{
- float src_term[4];
- float dst_term[4];
+ double src_term[4];
+ double dst_term[4];
compute_blend_ref_term(blend->rgb_src_factor, blend->alpha_src_factor, src, src, dst, con, src_term);
compute_blend_ref_term(blend->rgb_dst_factor, blend->alpha_dst_factor, dst, src, dst, con, dst_term);
}
+PIPE_ALIGN_STACK
static boolean
-test_one(const struct pipe_blend_state *blend,
- union lp_type type)
+test_one(unsigned verbose,
+ FILE *fp,
+ const struct pipe_blend_state *blend,
+ enum vector_mode mode,
+ struct lp_type type)
{
LLVMModuleRef module = NULL;
LLVMValueRef func = NULL;
char *error = NULL;
blend_test_ptr_t blend_test_ptr;
boolean success;
- unsigned i, j, k;
+ const unsigned n = LP_TEST_NUM_SAMPLES;
+ int64_t cycles[LP_TEST_NUM_SAMPLES];
+ double cycles_avg = 0.0;
+ unsigned i, j;
+
+ if(verbose >= 1)
+ dump_blend_type(stdout, blend, mode, type);
module = LLVMModuleCreateWithName("test");
- func = add_blend_test(module, blend, type);
+ func = add_blend_test(module, blend, mode, type);
if(LLVMVerifyModule(module, LLVMPrintMessageAction, &error)) {
LLVMDumpModule(module);
provider = LLVMCreateModuleProviderForExistingModule(module);
if (LLVMCreateJITCompiler(&engine, provider, 1, &error)) {
+ if(verbose < 1)
+ dump_blend_type(stderr, blend, mode, type);
fprintf(stderr, "%s\n", error);
LLVMDisposeMessage(error);
abort();
(void)pass;
#endif
+ if(verbose >= 2)
+ LLVMDumpModule(module);
+
blend_test_ptr = (blend_test_ptr_t)LLVMGetPointerToGlobal(engine, func);
if(verbose >= 2)
- LLVMDumpModule(module);
+ lp_disassemble(blend_test_ptr);
success = TRUE;
- for(i = 0; i < 10; ++i) {
- if(type.floating && type.width == 32) {
- float src[LP_MAX_VECTOR_LENGTH];
- float dst[LP_MAX_VECTOR_LENGTH];
- float con[LP_MAX_VECTOR_LENGTH];
- float ref[LP_MAX_VECTOR_LENGTH];
- float res[LP_MAX_VECTOR_LENGTH];
-
- for(j = 0; j < type.length; ++j) {
- src[j] = random_float();
- dst[j] = random_float();
- con[j] = random_float();
+ for(i = 0; i < n && success; ++i) {
+ if(mode == AoS) {
+ PIPE_ALIGN_VAR(16) uint8_t src[LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t dst[LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t con[LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t res[LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t ref[LP_NATIVE_VECTOR_WIDTH/8];
+ int64_t start_counter = 0;
+ int64_t end_counter = 0;
+
+ random_vec(type, src);
+ random_vec(type, dst);
+ random_vec(type, con);
+
+ {
+ double fsrc[LP_MAX_VECTOR_LENGTH];
+ double fdst[LP_MAX_VECTOR_LENGTH];
+ double fcon[LP_MAX_VECTOR_LENGTH];
+ double fref[LP_MAX_VECTOR_LENGTH];
+
+ read_vec(type, src, fsrc);
+ read_vec(type, dst, fdst);
+ read_vec(type, con, fcon);
+
+ for(j = 0; j < type.length; j += 4)
+ compute_blend_ref(blend, fsrc + j, fdst + j, fcon + j, fref + j);
+
+ write_vec(type, ref, fref);
}
- for(j = 0; j < type.length; j += 4)
- compute_blend_ref(blend, src + j, dst + j, con + j, ref + j);
-
+ start_counter = rdtsc();
blend_test_ptr(src, dst, con, res);
+ end_counter = rdtsc();
+
+ cycles[i] = end_counter - start_counter;
+
+ if(!compare_vec(type, res, ref)) {
+ success = FALSE;
- for(j = 0; j < type.length; ++j)
- if(fabs(res[j] - ref[j]) > FLT_EPSILON)
- success = FALSE;
+ if(verbose < 1)
+ dump_blend_type(stderr, blend, mode, type);
+ fprintf(stderr, "MISMATCH\n");
- if (!success) {
- fprintf(stderr, "FAILED\n");
- fprintf(stderr, " Result: ");
- for(j = 0; j < type.length; ++j)
- fprintf(stderr, " %f", res[j]);
+ fprintf(stderr, " Src: ");
+ dump_vec(stderr, type, src);
fprintf(stderr, "\n");
- fprintf(stderr, " Expected: ");
- for(j = 0; j < type.length; ++j)
- fprintf(stderr, " %f", ref[j]);
+
+ fprintf(stderr, " Dst: ");
+ dump_vec(stderr, type, dst);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " Con: ");
+ dump_vec(stderr, type, con);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " Res: ");
+ dump_vec(stderr, type, res);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " Ref: ");
+ dump_vec(stderr, type, ref);
fprintf(stderr, "\n");
}
}
- else if(!type.floating && !type.fixed && !type.sign && type.norm && type.width == 8) {
- uint8_t src[LP_MAX_VECTOR_LENGTH];
- uint8_t dst[LP_MAX_VECTOR_LENGTH];
- uint8_t con[LP_MAX_VECTOR_LENGTH];
- uint8_t ref[LP_MAX_VECTOR_LENGTH];
- uint8_t res[LP_MAX_VECTOR_LENGTH];
-
- for(j = 0; j < type.length; ++j) {
- src[j] = random() & 0xff;
- dst[j] = random() & 0xff;
- con[j] = random() & 0xff;
- }
- for(j = 0; j < type.length; j += 4) {
- float srcf[4];
- float dstf[4];
- float conf[4];
- float reff[4];
+ if(mode == SoA) {
+ const unsigned stride = type.length*type.width/8;
+ PIPE_ALIGN_VAR(16) uint8_t src[4*LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t dst[4*LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t con[4*LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t res[4*LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t ref[4*LP_NATIVE_VECTOR_WIDTH/8];
+ int64_t start_counter = 0;
+ int64_t end_counter = 0;
+ boolean mismatch;
+
+ for(j = 0; j < 4; ++j) {
+ random_vec(type, src + j*stride);
+ random_vec(type, dst + j*stride);
+ random_vec(type, con + j*stride);
+ }
- for(k = 0; k < 4; ++k) {
- srcf[k] = (1.0f/255.0f)*src[j + k];
- dstf[k] = (1.0f/255.0f)*dst[j + k];
- conf[k] = (1.0f/255.0f)*con[j + k];
- }
+ {
+ double fsrc[4];
+ double fdst[4];
+ double fcon[4];
+ double fref[4];
+ unsigned k;
+
+ for(k = 0; k < type.length; ++k) {
+ for(j = 0; j < 4; ++j) {
+ fsrc[j] = read_elem(type, src + j*stride, k);
+ fdst[j] = read_elem(type, dst + j*stride, k);
+ fcon[j] = read_elem(type, con + j*stride, k);
+ }
- compute_blend_ref(blend, srcf, dstf, conf, reff);
+ compute_blend_ref(blend, fsrc, fdst, fcon, fref);
- for(k = 0; k < 4; ++k)
- ref[j + k] = (uint8_t)(reff[k]*255.0f + 0.5f);
+ for(j = 0; j < 4; ++j)
+ write_elem(type, ref + j*stride, k, fref[j]);
+ }
}
+ start_counter = rdtsc();
blend_test_ptr(src, dst, con, res);
-
- for(j = 0; j < type.length; ++j) {
- int delta = (int)res[j] - (int)ref[j];
- if (delta < 0)
- delta = -delta;
- if(delta > 1)
- success = FALSE;
+ end_counter = rdtsc();
+
+ cycles[i] = end_counter - start_counter;
+
+ mismatch = FALSE;
+ for (j = 0; j < 4; ++j)
+ if(!compare_vec(type, res + j*stride, ref + j*stride))
+ mismatch = TRUE;
+
+ if (mismatch) {
+ success = FALSE;
+
+ if(verbose < 1)
+ dump_blend_type(stderr, blend, mode, type);
+ fprintf(stderr, "MISMATCH\n");
+ for(j = 0; j < 4; ++j) {
+ char channel = "RGBA"[j];
+ fprintf(stderr, " Src%c: ", channel);
+ dump_vec(stderr, type, src + j*stride);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " Dst%c: ", channel);
+ dump_vec(stderr, type, dst + j*stride);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " Con%c: ", channel);
+ dump_vec(stderr, type, con + j*stride);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " Res%c: ", channel);
+ dump_vec(stderr, type, res + j*stride);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " Ref%c: ", channel);
+ dump_vec(stderr, type, ref + j*stride);
+ fprintf(stderr, "\n");
+ }
}
+ }
+ }
- if (!success) {
- fprintf(stderr, "FAILED\n");
- fprintf(stderr, " Result: ");
- for(j = 0; j < type.length; ++j)
- fprintf(stderr, " %3u", res[j]);
- fprintf(stderr, "\n");
- fprintf(stderr, " Expected: ");
- for(j = 0; j < type.length; ++j)
- fprintf(stderr, " %3u", ref[j]);
- fprintf(stderr, "\n");
+ /*
+ * Unfortunately the output of cycle counter is not very reliable as it comes
+ * -- sometimes we get outliers (due IRQs perhaps?) which are
+ * better removed to avoid random or biased data.
+ */
+ {
+ double sum = 0.0, sum2 = 0.0;
+ double avg, std;
+ unsigned m;
+
+ for(i = 0; i < n; ++i) {
+ sum += cycles[i];
+ sum2 += cycles[i]*cycles[i];
+ }
+
+ avg = sum/n;
+ std = sqrtf((sum2 - n*avg*avg)/n);
+
+ m = 0;
+ sum = 0.0;
+ for(i = 0; i < n; ++i) {
+ if(fabs(cycles[i] - avg) <= 4.0*std) {
+ sum += cycles[i];
+ ++m;
}
}
- else
- assert(0);
- if (!success) {
+ cycles_avg = sum/m;
+
+ }
+
+ if(fp)
+ write_tsv_row(fp, blend, mode, type, cycles_avg, success);
+
+ if (!success) {
+ if(verbose < 2)
LLVMDumpModule(module);
- LLVMWriteBitcodeToFile(module, "blend.bc");
- fprintf(stderr, "blend.bc written\n");
- abort();
- break;
- }
+ LLVMWriteBitcodeToFile(module, "blend.bc");
+ fprintf(stderr, "blend.bc written\n");
+ fprintf(stderr, "Invoke as \"llc -o - blend.bc\"\n");
+ abort();
}
LLVMFreeMachineCodeForFunction(engine, func);
}
-struct value_name_pair
-{
- unsigned value;
- const char *name;
-};
-
-
-const struct value_name_pair
+const unsigned
blend_factors[] = {
- {PIPE_BLENDFACTOR_ZERO , "zero"},
- {PIPE_BLENDFACTOR_ONE , "one"},
- {PIPE_BLENDFACTOR_SRC_COLOR , "src_color"},
- {PIPE_BLENDFACTOR_SRC_ALPHA , "src_alpha"},
- {PIPE_BLENDFACTOR_DST_COLOR , "dst_color"},
- {PIPE_BLENDFACTOR_DST_ALPHA , "dst_alpha"},
- {PIPE_BLENDFACTOR_CONST_COLOR , "const_color"},
- {PIPE_BLENDFACTOR_CONST_ALPHA , "const_alpha"},
+ PIPE_BLENDFACTOR_ZERO,
+ PIPE_BLENDFACTOR_ONE,
+ PIPE_BLENDFACTOR_SRC_COLOR,
+ PIPE_BLENDFACTOR_SRC_ALPHA,
+ PIPE_BLENDFACTOR_DST_COLOR,
+ PIPE_BLENDFACTOR_DST_ALPHA,
+ PIPE_BLENDFACTOR_CONST_COLOR,
+ PIPE_BLENDFACTOR_CONST_ALPHA,
#if 0
- {PIPE_BLENDFACTOR_SRC1_COLOR , "src1_color"},
- {PIPE_BLENDFACTOR_SRC1_ALPHA , "src1_alpha"},
+ PIPE_BLENDFACTOR_SRC1_COLOR,
+ PIPE_BLENDFACTOR_SRC1_ALPHA,
#endif
- {PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE , "src_alpha_saturate"},
- {PIPE_BLENDFACTOR_INV_SRC_COLOR , "inv_src_color"},
- {PIPE_BLENDFACTOR_INV_SRC_ALPHA , "inv_src_alpha"},
- {PIPE_BLENDFACTOR_INV_DST_COLOR , "inv_dst_color"},
- {PIPE_BLENDFACTOR_INV_DST_ALPHA , "inv_dst_alpha"},
- {PIPE_BLENDFACTOR_INV_CONST_COLOR , "inv_const_color"},
- {PIPE_BLENDFACTOR_INV_CONST_ALPHA , "inv_const_alpha"},
+ PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE,
+ PIPE_BLENDFACTOR_INV_SRC_COLOR,
+ PIPE_BLENDFACTOR_INV_SRC_ALPHA,
+ PIPE_BLENDFACTOR_INV_DST_COLOR,
+ PIPE_BLENDFACTOR_INV_DST_ALPHA,
+ PIPE_BLENDFACTOR_INV_CONST_COLOR,
+ PIPE_BLENDFACTOR_INV_CONST_ALPHA,
#if 0
- {PIPE_BLENDFACTOR_INV_SRC1_COLOR , "inv_src1_color"},
- {PIPE_BLENDFACTOR_INV_SRC1_ALPHA , "inv_src1_alpha"}
+ PIPE_BLENDFACTOR_INV_SRC1_COLOR,
+ PIPE_BLENDFACTOR_INV_SRC1_ALPHA,
#endif
};
-const struct value_name_pair
+const unsigned
blend_funcs[] = {
- {PIPE_BLEND_ADD , "add"},
- {PIPE_BLEND_SUBTRACT , "sub"},
- {PIPE_BLEND_REVERSE_SUBTRACT , "rev_sub"},
- {PIPE_BLEND_MIN , "min"},
- {PIPE_BLEND_MAX , "max"}
+ PIPE_BLEND_ADD,
+ PIPE_BLEND_SUBTRACT,
+ PIPE_BLEND_REVERSE_SUBTRACT,
+ PIPE_BLEND_MIN,
+ PIPE_BLEND_MAX
};
-const union lp_type blend_types[] = {
+const struct lp_type blend_types[] = {
/* float, fixed, sign, norm, width, len */
- {{ TRUE, FALSE, TRUE, TRUE, 32, 4 }}, /* f32 x 4 */
- {{ FALSE, FALSE, FALSE, TRUE, 8, 16 }}, /* u8n x 16 */
+ { TRUE, FALSE, FALSE, TRUE, 32, 4 }, /* f32 x 4 */
+ { FALSE, FALSE, FALSE, TRUE, 8, 16 }, /* u8n x 16 */
};
const unsigned num_types = sizeof(blend_types)/sizeof(blend_types[0]);
-static boolean
-test_all(void)
+boolean
+test_all(unsigned verbose, FILE *fp)
{
- const struct value_name_pair *rgb_func;
- const struct value_name_pair *rgb_src_factor;
- const struct value_name_pair *rgb_dst_factor;
- const struct value_name_pair *alpha_func;
- const struct value_name_pair *alpha_src_factor;
- const struct value_name_pair *alpha_dst_factor;
+ const unsigned *rgb_func;
+ const unsigned *rgb_src_factor;
+ const unsigned *rgb_dst_factor;
+ const unsigned *alpha_func;
+ const unsigned *alpha_src_factor;
+ const unsigned *alpha_dst_factor;
struct pipe_blend_state blend;
- const union lp_type *type;
+ enum vector_mode mode;
+ const struct lp_type *type;
bool success = TRUE;
for(rgb_func = blend_funcs; rgb_func < &blend_funcs[num_funcs]; ++rgb_func) {
for(rgb_dst_factor = blend_factors; rgb_dst_factor <= rgb_src_factor; ++rgb_dst_factor) {
for(alpha_src_factor = blend_factors; alpha_src_factor < &blend_factors[num_factors]; ++alpha_src_factor) {
for(alpha_dst_factor = blend_factors; alpha_dst_factor <= alpha_src_factor; ++alpha_dst_factor) {
- for(type = blend_types; type < &blend_types[num_types]; ++type) {
-
- if(rgb_dst_factor->value == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE ||
- alpha_dst_factor->value == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE)
- continue;
-
- if(verbose >= 1)
- fprintf(stderr,
- "%s=%s %s=%s %s=%s %s=%s %s=%s %s=%s ...\n",
- "rgb_func", rgb_func->name,
- "rgb_src_factor", rgb_src_factor->name,
- "rgb_dst_factor", rgb_dst_factor->name,
- "alpha_func", alpha_func->name,
- "alpha_src_factor", alpha_src_factor->name,
- "alpha_dst_factor", alpha_dst_factor->name);
-
- memset(&blend, 0, sizeof blend);
- blend.blend_enable = 1;
- blend.rgb_func = rgb_func->value;
- blend.rgb_src_factor = rgb_src_factor->value;
- blend.rgb_dst_factor = rgb_dst_factor->value;
- blend.alpha_func = alpha_func->value;
- blend.alpha_src_factor = alpha_src_factor->value;
- blend.alpha_dst_factor = alpha_dst_factor->value;
-
- if(!test_one(&blend, *type))
- success = FALSE;
-
+ for(mode = 0; mode < 2; ++mode) {
+ for(type = blend_types; type < &blend_types[num_types]; ++type) {
+
+ if(*rgb_dst_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE ||
+ *alpha_dst_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE)
+ continue;
+
+ memset(&blend, 0, sizeof blend);
+ blend.blend_enable = 1;
+ blend.rgb_func = *rgb_func;
+ blend.rgb_src_factor = *rgb_src_factor;
+ blend.rgb_dst_factor = *rgb_dst_factor;
+ blend.alpha_func = *alpha_func;
+ blend.alpha_src_factor = *alpha_src_factor;
+ blend.alpha_dst_factor = *alpha_dst_factor;
+ blend.colormask = PIPE_MASK_RGBA;
+
+ if(!test_one(verbose, fp, &blend, mode, *type))
+ success = FALSE;
+
+ }
}
}
}
}
-static boolean
-test_some(unsigned long n)
+boolean
+test_some(unsigned verbose, FILE *fp, unsigned long n)
{
- const struct value_name_pair *rgb_func;
- const struct value_name_pair *rgb_src_factor;
- const struct value_name_pair *rgb_dst_factor;
- const struct value_name_pair *alpha_func;
- const struct value_name_pair *alpha_src_factor;
- const struct value_name_pair *alpha_dst_factor;
+ const unsigned *rgb_func;
+ const unsigned *rgb_src_factor;
+ const unsigned *rgb_dst_factor;
+ const unsigned *alpha_func;
+ const unsigned *alpha_src_factor;
+ const unsigned *alpha_dst_factor;
struct pipe_blend_state blend;
- const union lp_type *type;
+ enum vector_mode mode;
+ const struct lp_type *type;
unsigned long i;
bool success = TRUE;
for(i = 0; i < n; ++i) {
- rgb_func = &blend_funcs[random() % num_funcs];
- alpha_func = &blend_funcs[random() % num_funcs];
- rgb_src_factor = &blend_factors[random() % num_factors];
- alpha_src_factor = &blend_factors[random() % num_factors];
+ rgb_func = &blend_funcs[rand() % num_funcs];
+ alpha_func = &blend_funcs[rand() % num_funcs];
+ rgb_src_factor = &blend_factors[rand() % num_factors];
+ alpha_src_factor = &blend_factors[rand() % num_factors];
do {
- rgb_dst_factor = &blend_factors[random() % num_factors];
- } while(rgb_dst_factor->value == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE);
+ rgb_dst_factor = &blend_factors[rand() % num_factors];
+ } while(*rgb_dst_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE);
do {
- alpha_dst_factor = &blend_factors[random() % num_factors];
- } while(alpha_dst_factor->value == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE);
-
- for(type = blend_types; type < &blend_types[num_types]; ++type) {
-
- if(verbose >= 1)
- fprintf(stderr,
- "%s=%s %s=%s %s=%s %s=%s %s=%s %s=%s ...\n",
- "rgb_func", rgb_func->name,
- "rgb_src_factor", rgb_src_factor->name,
- "rgb_dst_factor", rgb_dst_factor->name,
- "alpha_func", alpha_func->name,
- "alpha_src_factor", alpha_src_factor->name,
- "alpha_dst_factor", alpha_dst_factor->name);
-
- memset(&blend, 0, sizeof blend);
- blend.blend_enable = 1;
- blend.rgb_func = rgb_func->value;
- blend.rgb_src_factor = rgb_src_factor->value;
- blend.rgb_dst_factor = rgb_dst_factor->value;
- blend.alpha_func = alpha_func->value;
- blend.alpha_src_factor = alpha_src_factor->value;
- blend.alpha_dst_factor = alpha_dst_factor->value;
-
- if(!test_one(&blend, *type))
- success = FALSE;
+ alpha_dst_factor = &blend_factors[rand() % num_factors];
+ } while(*alpha_dst_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE);
- }
- }
-
- return success;
-}
+ mode = rand() & 1;
+ type = &blend_types[rand() % num_types];
-int main(int argc, char **argv)
-{
- unsigned long n = 1000;
- unsigned i;
- boolean success;
+ memset(&blend, 0, sizeof blend);
+ blend.blend_enable = 1;
+ blend.rgb_func = *rgb_func;
+ blend.rgb_src_factor = *rgb_src_factor;
+ blend.rgb_dst_factor = *rgb_dst_factor;
+ blend.alpha_func = *alpha_func;
+ blend.alpha_src_factor = *alpha_src_factor;
+ blend.alpha_dst_factor = *alpha_dst_factor;
+ blend.colormask = PIPE_MASK_RGBA;
- for(i = 1; i < argc; ++i) {
- if(strcmp(argv[i], "-v") == 0)
- ++verbose;
- else
- n = atoi(argv[i]);
+ if(!test_one(verbose, fp, &blend, mode, *type))
+ success = FALSE;
}
-
- if(n)
- success = test_some(n);
- else
- success = test_all();
- return success ? 0 : 1;
+ return success;
}