From 24a692ce832161d3b794110dd82b1508d38a0887 Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 12 Sep 2011 08:58:44 +0200 Subject: git update 12 sep 2011 --- mesalib/src/gallium/auxiliary/util/u_blitter.c | 52 +- mesalib/src/glsl/ast.h | 2 +- mesalib/src/glsl/ast_to_hir.cpp | 6 + mesalib/src/glsl/builtin_stubs.cpp | 77 +- mesalib/src/glsl/glcpp/glcpp.c | 243 +- mesalib/src/glsl/ir_function_detect_recursion.cpp | 4 + mesalib/src/glsl/lower_jumps.cpp | 1 + mesalib/src/glsl/opt_discard_simplification.cpp | 1 + mesalib/src/glsl/opt_if_simplification.cpp | 189 +- mesalib/src/glsl/standalone_scaffolding.cpp | 1 + mesalib/src/mesa/drivers/dri/common/depthtmp.h | 548 ++-- mesalib/src/mesa/drivers/dri/common/dri_util.c | 12 +- mesalib/src/mesa/drivers/dri/common/spantmp2.h | 20 + mesalib/src/mesa/drivers/dri/common/utils.c | 1532 +++++----- mesalib/src/mesa/drivers/dri/common/utils.h | 221 +- mesalib/src/mesa/drivers/dri/swrast/swrast.c | 19 +- mesalib/src/mesa/main/extensions.c | 8 +- mesalib/src/mesa/main/nvprogram.c | 2 +- mesalib/src/mesa/main/nvprogram.h | 238 +- mesalib/src/mesa/main/teximage.h | 571 ++-- mesalib/src/mesa/program/ir_to_mesa.cpp | 17 +- mesalib/src/mesa/program/nvvertparse.c | 2918 ++++++++++---------- mesalib/src/mesa/state_tracker/st_extensions.c | 11 +- mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 33 +- mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c | 2 + mesalib/src/mesa/swrast/s_spantemp.h | 449 +-- pixman/configure.ac | 13 +- pixman/pixman/pixman-arm-neon-asm.S | 139 +- pixman/pixman/pixman-bits-image.c | 58 +- pixman/test/Makefile.am | 2 +- pixman/test/utils.c | 112 + pixman/test/utils.h | 3 + 32 files changed, 3865 insertions(+), 3639 deletions(-) diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.c b/mesalib/src/gallium/auxiliary/util/u_blitter.c index d8e46f07c..d69fb1a11 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.c +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.c @@ -480,10 +480,11 @@ static void blitter_set_texcoords_3d(struct blitter_context_priv *ctx, unsigned level, unsigned zslice, unsigned x1, unsigned y1, - unsigned x2, unsigned y2) + unsigned x2, unsigned y2, + boolean normalized) { int i; - float r = zslice / (float)u_minify(src->depth0, level); + float r = normalized ? zslice / (float)u_minify(src->depth0, level) : zslice; blitter_set_texcoords_2d(ctx, src, level, x1, y1, x2, y2); @@ -491,6 +492,21 @@ static void blitter_set_texcoords_3d(struct blitter_context_priv *ctx, ctx->vertices[i][1][2] = r; /*r*/ } +static void blitter_set_texcoords_1d_array(struct blitter_context_priv *ctx, + struct pipe_resource *src, + unsigned level, + unsigned zslice, + unsigned x1, unsigned x2) +{ + int i; + float r = zslice; + + blitter_set_texcoords_2d(ctx, src, level, x1, 0, x2, 0); + + for (i = 0; i < 4; i++) + ctx->vertices[i][1][1] = r; /*r*/ +} + static void blitter_set_texcoords_cube(struct blitter_context_priv *ctx, struct pipe_resource *src, unsigned level, unsigned face, @@ -576,6 +592,10 @@ pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target) return TGSI_TEXTURE_3D; case PIPE_TEXTURE_CUBE: return TGSI_TEXTURE_CUBE; + case PIPE_TEXTURE_1D_ARRAY: + return TGSI_TEXTURE_1D_ARRAY; + case PIPE_TEXTURE_2D_ARRAY: + return TGSI_TEXTURE_2D_ARRAY; default: assert(0 && "unexpected texture target"); return TGSI_TEXTURE_UNKNOWN; @@ -861,17 +881,31 @@ void util_blitter_copy_texture(struct blitter_context *blitter, break; /* Draw the quad with the generic codepath. */ - case PIPE_TEXTURE_3D: - case PIPE_TEXTURE_CUBE: + default: /* Set texture coordinates. */ - if (src->target == PIPE_TEXTURE_3D) + switch (src->target) { + case PIPE_TEXTURE_1D_ARRAY: + blitter_set_texcoords_1d_array(ctx, src, srclevel, srcbox->y, + srcbox->x, srcbox->x + width); + break; + + case PIPE_TEXTURE_2D_ARRAY: + case PIPE_TEXTURE_3D: blitter_set_texcoords_3d(ctx, src, srclevel, srcbox->z, srcbox->x, srcbox->y, - srcbox->x + width, srcbox->y + height); - else + srcbox->x + width, srcbox->y + height, + src->target == PIPE_TEXTURE_3D); + break; + + case PIPE_TEXTURE_CUBE: blitter_set_texcoords_cube(ctx, src, srclevel, srcbox->z, srcbox->x, srcbox->y, srcbox->x + width, srcbox->y + height); + break; + + default: + assert(0); + } /* Draw. */ blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0); @@ -880,10 +914,6 @@ void util_blitter_copy_texture(struct blitter_context *blitter, util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, 2); break; - - default: - assert(0); - return; } blitter_restore_CSOs(ctx); diff --git a/mesalib/src/glsl/ast.h b/mesalib/src/glsl/ast.h index d1de22718..532347df4 100644 --- a/mesalib/src/glsl/ast.h +++ b/mesalib/src/glsl/ast.h @@ -372,7 +372,7 @@ struct ast_type_qualifier { * \note * This field is only valid if \c explicit_location is set. */ - unsigned location; + int location; /** * Return true if and only if an interpolation qualifier is present. diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index 777f190a4..484786c5f 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -3014,6 +3014,12 @@ ast_function::hir(exec_list *instructions, const char *const name = identifier; + /* New functions are always added to the top-level IR instruction stream, + * so this instruction list pointer is ignored. See also emit_function + * (called below). + */ + (void) instructions; + /* From page 21 (page 27 of the PDF) of the GLSL 1.20 spec, * * "Function declarations (prototypes) cannot occur inside of functions; diff --git a/mesalib/src/glsl/builtin_stubs.cpp b/mesalib/src/glsl/builtin_stubs.cpp index 4c360b832..dfa5d324e 100644 --- a/mesalib/src/glsl/builtin_stubs.cpp +++ b/mesalib/src/glsl/builtin_stubs.cpp @@ -1,38 +1,39 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include -#include "glsl_parser_extras.h" - -/* A dummy file. When compiling prototypes, we don't care about builtins. - * We really don't want to half-compile builtin_functions.cpp and fail, though. - */ -void -_mesa_glsl_release_functions(void) -{ -} - -void -_mesa_glsl_initialize_functions(_mesa_glsl_parse_state *state) -{ -} +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include "glsl_parser_extras.h" + +/* A dummy file. When compiling prototypes, we don't care about builtins. + * We really don't want to half-compile builtin_functions.cpp and fail, though. + */ +void +_mesa_glsl_release_functions(void) +{ +} + +void +_mesa_glsl_initialize_functions(_mesa_glsl_parse_state *state) +{ + (void) state; +} diff --git a/mesalib/src/glsl/glcpp/glcpp.c b/mesalib/src/glsl/glcpp/glcpp.c index 63eb061c2..e461a6502 100644 --- a/mesalib/src/glsl/glcpp/glcpp.c +++ b/mesalib/src/glsl/glcpp/glcpp.c @@ -1,121 +1,122 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include -#include "glcpp.h" -#include "main/mtypes.h" -#include "main/shaderobj.h" - -extern int yydebug; - -void -_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr, - struct gl_shader *sh) -{ - *ptr = sh; -} - -/* Read from fp until EOF and return a string of everything read. - */ -static char * -load_text_fp (void *ctx, FILE *fp) -{ -#define CHUNK 4096 - char *text = NULL; - size_t text_size = 0; - size_t total_read = 0; - size_t bytes; - - while (1) { - if (total_read + CHUNK + 1 > text_size) { - text_size = text_size ? text_size * 2 : CHUNK + 1; - text = reralloc_size (ctx, text, text_size); - if (text == NULL) { - fprintf (stderr, "Out of memory\n"); - return NULL; - } - } - bytes = fread (text + total_read, 1, CHUNK, fp); - total_read += bytes; - - if (bytes < CHUNK) { - break; - } - } - - text[total_read] = '\0'; - - return text; -} - -static char * -load_text_file(void *ctx, const char *filename) -{ - char *text; - FILE *fp; - - if (filename == NULL || strcmp (filename, "-") == 0) - return load_text_fp (ctx, stdin); - - fp = fopen (filename, "r"); - if (fp == NULL) { - fprintf (stderr, "Failed to open file %s: %s\n", - filename, strerror (errno)); - return NULL; - } - - text = load_text_fp (ctx, fp); - - fclose(fp); - - return text; -} - -int -main (int argc, char *argv[]) -{ - char *filename = NULL; - void *ctx = ralloc(NULL, void*); - char *info_log = ralloc_strdup(ctx, ""); - const char *shader; - int ret; - - if (argc) { - filename = argv[1]; - } - - shader = load_text_file (ctx, filename); - if (shader == NULL) - return 1; - - ret = preprocess(ctx, &shader, &info_log, NULL, API_OPENGL); - - printf("%s", shader); - fprintf(stderr, "%s", info_log); - - ralloc_free(ctx); - - return ret; -} +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include "glcpp.h" +#include "main/mtypes.h" +#include "main/shaderobj.h" + +extern int yydebug; + +void +_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr, + struct gl_shader *sh) +{ + (void) ctx; + *ptr = sh; +} + +/* Read from fp until EOF and return a string of everything read. + */ +static char * +load_text_fp (void *ctx, FILE *fp) +{ +#define CHUNK 4096 + char *text = NULL; + size_t text_size = 0; + size_t total_read = 0; + size_t bytes; + + while (1) { + if (total_read + CHUNK + 1 > text_size) { + text_size = text_size ? text_size * 2 : CHUNK + 1; + text = reralloc_size (ctx, text, text_size); + if (text == NULL) { + fprintf (stderr, "Out of memory\n"); + return NULL; + } + } + bytes = fread (text + total_read, 1, CHUNK, fp); + total_read += bytes; + + if (bytes < CHUNK) { + break; + } + } + + text[total_read] = '\0'; + + return text; +} + +static char * +load_text_file(void *ctx, const char *filename) +{ + char *text; + FILE *fp; + + if (filename == NULL || strcmp (filename, "-") == 0) + return load_text_fp (ctx, stdin); + + fp = fopen (filename, "r"); + if (fp == NULL) { + fprintf (stderr, "Failed to open file %s: %s\n", + filename, strerror (errno)); + return NULL; + } + + text = load_text_fp (ctx, fp); + + fclose(fp); + + return text; +} + +int +main (int argc, char *argv[]) +{ + char *filename = NULL; + void *ctx = ralloc(NULL, void*); + char *info_log = ralloc_strdup(ctx, ""); + const char *shader; + int ret; + + if (argc) { + filename = argv[1]; + } + + shader = load_text_file (ctx, filename); + if (shader == NULL) + return 1; + + ret = preprocess(ctx, &shader, &info_log, NULL, API_OPENGL); + + printf("%s", shader); + fprintf(stderr, "%s", info_log); + + ralloc_free(ctx); + + return ret; +} diff --git a/mesalib/src/glsl/ir_function_detect_recursion.cpp b/mesalib/src/glsl/ir_function_detect_recursion.cpp index 8f805bf1b..890bc455f 100644 --- a/mesalib/src/glsl/ir_function_detect_recursion.cpp +++ b/mesalib/src/glsl/ir_function_detect_recursion.cpp @@ -289,6 +289,8 @@ emit_errors_unlinked(const void *key, void *data, void *closure) function *f = (function *) data; YYLTYPE loc; + (void) key; + char *proto = prototype_string(f->sig->return_type, f->sig->function_name(), &f->sig->parameters); @@ -308,6 +310,8 @@ emit_errors_linked(const void *key, void *data, void *closure) (struct gl_shader_program *) closure; function *f = (function *) data; + (void) key; + char *proto = prototype_string(f->sig->return_type, f->sig->function_name(), &f->sig->parameters); diff --git a/mesalib/src/glsl/lower_jumps.cpp b/mesalib/src/glsl/lower_jumps.cpp index 61874990a..92813f567 100644 --- a/mesalib/src/glsl/lower_jumps.cpp +++ b/mesalib/src/glsl/lower_jumps.cpp @@ -438,6 +438,7 @@ struct ir_lower_jumps_visitor : public ir_control_flow_visitor { * satisfied, because discard statements can't contain other * statements. */ + (void) ir; } enum jump_strength get_jump_strength(ir_instruction* ir) diff --git a/mesalib/src/glsl/opt_discard_simplification.cpp b/mesalib/src/glsl/opt_discard_simplification.cpp index a19947ddd..ba4981bae 100644 --- a/mesalib/src/glsl/opt_discard_simplification.cpp +++ b/mesalib/src/glsl/opt_discard_simplification.cpp @@ -138,6 +138,7 @@ is_only_instruction(ir_discard *discard) ir_visitor_status discard_simplifier::visit_enter(ir_assignment *ir) { + (void) ir; return visit_continue_with_parent; } diff --git a/mesalib/src/glsl/opt_if_simplification.cpp b/mesalib/src/glsl/opt_if_simplification.cpp index 2d8858e49..940dd08d5 100644 --- a/mesalib/src/glsl/opt_if_simplification.cpp +++ b/mesalib/src/glsl/opt_if_simplification.cpp @@ -1,94 +1,95 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -/** - * \file opt_if_simplification.cpp - * - * Moves constant branches of if statements out to the surrounding - * instruction stream. - */ - -#include "ir.h" - -class ir_if_simplification_visitor : public ir_hierarchical_visitor { -public: - ir_if_simplification_visitor() - { - this->made_progress = false; - } - - ir_visitor_status visit_leave(ir_if *); - ir_visitor_status visit_enter(ir_assignment *); - - bool made_progress; -}; - -/* We only care about the top level "if" instructions, so don't - * descend into expressions. - */ -ir_visitor_status -ir_if_simplification_visitor::visit_enter(ir_assignment *ir) -{ - return visit_continue_with_parent; -} - -bool -do_if_simplification(exec_list *instructions) -{ - ir_if_simplification_visitor v; - - v.run(instructions); - return v.made_progress; -} - - -ir_visitor_status -ir_if_simplification_visitor::visit_leave(ir_if *ir) -{ - /* FINISHME: Ideally there would be a way to note that the condition results - * FINISHME: in a constant before processing both of the other subtrees. - * FINISHME: This can probably be done with some flags, but it would take - * FINISHME: some work to get right. - */ - ir_constant *condition_constant = ir->condition->constant_expression_value(); - if (condition_constant) { - /* Move the contents of the one branch of the conditional - * that matters out. - */ - if (condition_constant->value.b[0]) { - foreach_iter(exec_list_iterator, then_iter, ir->then_instructions) { - ir_instruction *then_ir = (ir_instruction *)then_iter.get(); - ir->insert_before(then_ir); - } - } else { - foreach_iter(exec_list_iterator, else_iter, ir->else_instructions) { - ir_instruction *else_ir = (ir_instruction *)else_iter.get(); - ir->insert_before(else_ir); - } - } - ir->remove(); - this->made_progress = true; - } - - return visit_continue; -} +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file opt_if_simplification.cpp + * + * Moves constant branches of if statements out to the surrounding + * instruction stream. + */ + +#include "ir.h" + +class ir_if_simplification_visitor : public ir_hierarchical_visitor { +public: + ir_if_simplification_visitor() + { + this->made_progress = false; + } + + ir_visitor_status visit_leave(ir_if *); + ir_visitor_status visit_enter(ir_assignment *); + + bool made_progress; +}; + +/* We only care about the top level "if" instructions, so don't + * descend into expressions. + */ +ir_visitor_status +ir_if_simplification_visitor::visit_enter(ir_assignment *ir) +{ + (void) ir; + return visit_continue_with_parent; +} + +bool +do_if_simplification(exec_list *instructions) +{ + ir_if_simplification_visitor v; + + v.run(instructions); + return v.made_progress; +} + + +ir_visitor_status +ir_if_simplification_visitor::visit_leave(ir_if *ir) +{ + /* FINISHME: Ideally there would be a way to note that the condition results + * FINISHME: in a constant before processing both of the other subtrees. + * FINISHME: This can probably be done with some flags, but it would take + * FINISHME: some work to get right. + */ + ir_constant *condition_constant = ir->condition->constant_expression_value(); + if (condition_constant) { + /* Move the contents of the one branch of the conditional + * that matters out. + */ + if (condition_constant->value.b[0]) { + foreach_iter(exec_list_iterator, then_iter, ir->then_instructions) { + ir_instruction *then_ir = (ir_instruction *)then_iter.get(); + ir->insert_before(then_ir); + } + } else { + foreach_iter(exec_list_iterator, else_iter, ir->else_instructions) { + ir_instruction *else_ir = (ir_instruction *)else_iter.get(); + ir->insert_before(else_ir); + } + } + ir->remove(); + this->made_progress = true; + } + + return visit_continue; +} diff --git a/mesalib/src/glsl/standalone_scaffolding.cpp b/mesalib/src/glsl/standalone_scaffolding.cpp index bbd7bb913..72aa1e428 100644 --- a/mesalib/src/glsl/standalone_scaffolding.cpp +++ b/mesalib/src/glsl/standalone_scaffolding.cpp @@ -37,6 +37,7 @@ void _mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr, struct gl_shader *sh) { + (void) ctx; *ptr = sh; } diff --git a/mesalib/src/mesa/drivers/dri/common/depthtmp.h b/mesalib/src/mesa/drivers/dri/common/depthtmp.h index 8e751d7b2..c6e2bb75c 100644 --- a/mesalib/src/mesa/drivers/dri/common/depthtmp.h +++ b/mesalib/src/mesa/drivers/dri/common/depthtmp.h @@ -1,270 +1,278 @@ - -/* - * Notes: - * 1. These functions plug into the gl_renderbuffer structure. - * 2. The 'values' parameter always points to GLuint values, regardless of - * the actual Z buffer depth. - */ - - -#include "spantmp_common.h" - -#ifndef DBG -#define DBG 0 -#endif - -#ifndef HAVE_HW_DEPTH_SPANS -#define HAVE_HW_DEPTH_SPANS 0 -#endif - -#ifndef HAVE_HW_DEPTH_PIXELS -#define HAVE_HW_DEPTH_PIXELS 0 -#endif - -static void TAG(WriteDepthSpan)( struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, GLint x, GLint y, - const void *values, - const GLubyte mask[] ) -{ - HW_WRITE_LOCK() - { - const VALUE_TYPE *depth = (const VALUE_TYPE *) values; - GLint x1; - GLint n1; - LOCAL_DEPTH_VARS; - - y = Y_FLIP( y ); - -#if HAVE_HW_DEPTH_SPANS - (void) x1; (void) n1; - - if ( DBG ) fprintf( stderr, "WriteDepthSpan 0..%d (x1 %d)\n", - (int)n, (int)x ); - - WRITE_DEPTH_SPAN(); -#else - HW_CLIPLOOP() - { - GLint i = 0; - CLIPSPAN( x, y, n, x1, n1, i ); - - if ( DBG ) fprintf( stderr, "WriteDepthSpan %d..%d (x1 %d) (mask %p)\n", - (int)i, (int)n1, (int)x1, mask ); - - if ( mask ) { - for ( ; n1>0 ; i++, x1++, n1-- ) { - if ( mask[i] ) WRITE_DEPTH( x1, y, depth[i] ); - } - } else { - for ( ; n1>0 ; i++, x1++, n1-- ) { - WRITE_DEPTH( x1, y, depth[i] ); - } - } - } - HW_ENDCLIPLOOP(); -#endif - } - HW_WRITE_UNLOCK(); -} - - -#if HAVE_HW_DEPTH_SPANS -/* implement MonoWriteDepthSpan() in terms of WriteDepthSpan() */ -static void -TAG(WriteMonoDepthSpan)( struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint n, GLint x, GLint y, - const void *value, const GLubyte mask[] ) -{ - const GLuint depthVal = *((GLuint *) value); - GLuint depths[MAX_WIDTH]; - GLuint i; - for (i = 0; i < n; i++) - depths[i] = depthVal; - TAG(WriteDepthSpan)(ctx, rb, n, x, y, depths, mask); -} -#else -static void TAG(WriteMonoDepthSpan)( struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, GLint x, GLint y, - const void *value, - const GLubyte mask[] ) -{ - HW_WRITE_LOCK() - { - const GLuint depth = *((GLuint *) value); - GLint x1; - GLint n1; - LOCAL_DEPTH_VARS; - - y = Y_FLIP( y ); - - HW_CLIPLOOP() - { - GLint i = 0; - CLIPSPAN( x, y, n, x1, n1, i ); - - if ( DBG ) fprintf( stderr, "%s %d..%d (x1 %d) = %u\n", - __FUNCTION__, (int)i, (int)n1, (int)x1, (GLuint)depth ); - - if ( mask ) { - for ( ; n1>0 ; i++, x1++, n1-- ) { - if ( mask[i] ) WRITE_DEPTH( x1, y, depth ); - } - } else { - for ( ; n1>0 ; x1++, n1-- ) { - WRITE_DEPTH( x1, y, depth ); - } - } - } - HW_ENDCLIPLOOP(); - } - HW_WRITE_UNLOCK(); -} -#endif - - -static void TAG(WriteDepthPixels)( struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, - const GLint x[], - const GLint y[], - const void *values, - const GLubyte mask[] ) -{ - HW_WRITE_LOCK() - { - const VALUE_TYPE *depth = (const VALUE_TYPE *) values; - GLuint i; - LOCAL_DEPTH_VARS; - - if ( DBG ) fprintf( stderr, "WriteDepthPixels\n" ); - -#if HAVE_HW_DEPTH_PIXELS - (void) i; - - WRITE_DEPTH_PIXELS(); -#else - HW_CLIPLOOP() - { - if ( mask ) { - for ( i = 0 ; i < n ; i++ ) { - if ( mask[i] ) { - const int fy = Y_FLIP( y[i] ); - if ( CLIPPIXEL( x[i], fy ) ) - WRITE_DEPTH( x[i], fy, depth[i] ); - } - } - } - else { - for ( i = 0 ; i < n ; i++ ) { - const int fy = Y_FLIP( y[i] ); - if ( CLIPPIXEL( x[i], fy ) ) - WRITE_DEPTH( x[i], fy, depth[i] ); - } - } - } - HW_ENDCLIPLOOP(); -#endif - } - HW_WRITE_UNLOCK(); -} - - -/* Read depth spans and pixels - */ -static void TAG(ReadDepthSpan)( struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, GLint x, GLint y, - void *values ) -{ - HW_READ_LOCK() - { - VALUE_TYPE *depth = (VALUE_TYPE *) values; - GLint x1, n1; - LOCAL_DEPTH_VARS; - - y = Y_FLIP( y ); - - if ( DBG ) fprintf( stderr, "ReadDepthSpan\n" ); - -#if HAVE_HW_DEPTH_SPANS - (void) x1; (void) n1; - - READ_DEPTH_SPAN(); -#else - HW_CLIPLOOP() - { - GLint i = 0; - CLIPSPAN( x, y, n, x1, n1, i ); - for ( ; n1>0 ; i++, n1-- ) { - READ_DEPTH( depth[i], x+i, y ); - } - } - HW_ENDCLIPLOOP(); -#endif - } - HW_READ_UNLOCK(); -} - -static void TAG(ReadDepthPixels)( struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, - const GLint x[], const GLint y[], - void *values ) -{ - HW_READ_LOCK() - { - VALUE_TYPE *depth = (VALUE_TYPE *) values; - GLuint i; - LOCAL_DEPTH_VARS; - - if ( DBG ) fprintf( stderr, "ReadDepthPixels\n" ); - -#if HAVE_HW_DEPTH_PIXELS - (void) i; - - READ_DEPTH_PIXELS(); -#else - HW_CLIPLOOP() - { - for ( i = 0 ; i < n ;i++ ) { - int fy = Y_FLIP( y[i] ); - if ( CLIPPIXEL( x[i], fy ) ) - READ_DEPTH( depth[i], x[i], fy ); - } - } - HW_ENDCLIPLOOP(); -#endif - } - HW_READ_UNLOCK(); -} - - -/** - * Initialize the given renderbuffer's span routines to point to - * the depth/z functions we generated above. - */ -static void TAG(InitDepthPointers)(struct gl_renderbuffer *rb) -{ - rb->GetRow = TAG(ReadDepthSpan); - rb->GetValues = TAG(ReadDepthPixels); - rb->PutRow = TAG(WriteDepthSpan); - rb->PutRowRGB = NULL; - rb->PutMonoRow = TAG(WriteMonoDepthSpan); - rb->PutValues = TAG(WriteDepthPixels); - rb->PutMonoValues = NULL; -} - - -#if HAVE_HW_DEPTH_SPANS -#undef WRITE_DEPTH_SPAN -#undef WRITE_DEPTH_PIXELS -#undef READ_DEPTH_SPAN -#undef READ_DEPTH_PIXELS -#else -#undef WRITE_DEPTH -#undef READ_DEPTH -#endif -#undef TAG -#undef VALUE_TYPE + +/* + * Notes: + * 1. These functions plug into the gl_renderbuffer structure. + * 2. The 'values' parameter always points to GLuint values, regardless of + * the actual Z buffer depth. + */ + + +#include "spantmp_common.h" + +#ifndef DBG +#define DBG 0 +#endif + +#ifndef HAVE_HW_DEPTH_SPANS +#define HAVE_HW_DEPTH_SPANS 0 +#endif + +#ifndef HAVE_HW_DEPTH_PIXELS +#define HAVE_HW_DEPTH_PIXELS 0 +#endif + +static void TAG(WriteDepthSpan)( struct gl_context *ctx, + struct gl_renderbuffer *rb, + GLuint n, GLint x, GLint y, + const void *values, + const GLubyte mask[] ) +{ + HW_WRITE_LOCK() + { + const VALUE_TYPE *depth = (const VALUE_TYPE *) values; + GLint x1; + GLint n1; + LOCAL_DEPTH_VARS; + + y = Y_FLIP( y ); + +#if HAVE_HW_DEPTH_SPANS + (void) x1; (void) n1; + + if ( DBG ) fprintf( stderr, "WriteDepthSpan 0..%d (x1 %d)\n", + (int)n, (int)x ); + + WRITE_DEPTH_SPAN(); +#else + HW_CLIPLOOP() + { + GLint i = 0; + CLIPSPAN( x, y, n, x1, n1, i ); + + if ( DBG ) fprintf( stderr, "WriteDepthSpan %d..%d (x1 %d) (mask %p)\n", + (int)i, (int)n1, (int)x1, mask ); + + if ( mask ) { + for ( ; n1>0 ; i++, x1++, n1-- ) { + if ( mask[i] ) WRITE_DEPTH( x1, y, depth[i] ); + } + } else { + for ( ; n1>0 ; i++, x1++, n1-- ) { + WRITE_DEPTH( x1, y, depth[i] ); + } + } + } + HW_ENDCLIPLOOP(); +#endif + } + HW_WRITE_UNLOCK(); + + (void) ctx; +} + + +#if HAVE_HW_DEPTH_SPANS +/* implement MonoWriteDepthSpan() in terms of WriteDepthSpan() */ +static void +TAG(WriteMonoDepthSpan)( struct gl_context *ctx, struct gl_renderbuffer *rb, + GLuint n, GLint x, GLint y, + const void *value, const GLubyte mask[] ) +{ + const GLuint depthVal = *((GLuint *) value); + GLuint depths[MAX_WIDTH]; + GLuint i; + for (i = 0; i < n; i++) + depths[i] = depthVal; + TAG(WriteDepthSpan)(ctx, rb, n, x, y, depths, mask); +} +#else +static void TAG(WriteMonoDepthSpan)( struct gl_context *ctx, + struct gl_renderbuffer *rb, + GLuint n, GLint x, GLint y, + const void *value, + const GLubyte mask[] ) +{ + HW_WRITE_LOCK() + { + const GLuint depth = *((GLuint *) value); + GLint x1; + GLint n1; + LOCAL_DEPTH_VARS; + + y = Y_FLIP( y ); + + HW_CLIPLOOP() + { + GLint i = 0; + CLIPSPAN( x, y, n, x1, n1, i ); + + if ( DBG ) fprintf( stderr, "%s %d..%d (x1 %d) = %u\n", + __FUNCTION__, (int)i, (int)n1, (int)x1, (GLuint)depth ); + + if ( mask ) { + for ( ; n1>0 ; i++, x1++, n1-- ) { + if ( mask[i] ) WRITE_DEPTH( x1, y, depth ); + } + } else { + for ( ; n1>0 ; x1++, n1-- ) { + WRITE_DEPTH( x1, y, depth ); + } + } + } + HW_ENDCLIPLOOP(); + } + HW_WRITE_UNLOCK(); + + (void) ctx; +} +#endif + + +static void TAG(WriteDepthPixels)( struct gl_context *ctx, + struct gl_renderbuffer *rb, + GLuint n, + const GLint x[], + const GLint y[], + const void *values, + const GLubyte mask[] ) +{ + HW_WRITE_LOCK() + { + const VALUE_TYPE *depth = (const VALUE_TYPE *) values; + GLuint i; + LOCAL_DEPTH_VARS; + + if ( DBG ) fprintf( stderr, "WriteDepthPixels\n" ); + +#if HAVE_HW_DEPTH_PIXELS + (void) i; + + WRITE_DEPTH_PIXELS(); +#else + HW_CLIPLOOP() + { + if ( mask ) { + for ( i = 0 ; i < n ; i++ ) { + if ( mask[i] ) { + const int fy = Y_FLIP( y[i] ); + if ( CLIPPIXEL( x[i], fy ) ) + WRITE_DEPTH( x[i], fy, depth[i] ); + } + } + } + else { + for ( i = 0 ; i < n ; i++ ) { + const int fy = Y_FLIP( y[i] ); + if ( CLIPPIXEL( x[i], fy ) ) + WRITE_DEPTH( x[i], fy, depth[i] ); + } + } + } + HW_ENDCLIPLOOP(); +#endif + } + HW_WRITE_UNLOCK(); + + (void) ctx; +} + + +/* Read depth spans and pixels + */ +static void TAG(ReadDepthSpan)( struct gl_context *ctx, + struct gl_renderbuffer *rb, + GLuint n, GLint x, GLint y, + void *values ) +{ + HW_READ_LOCK() + { + VALUE_TYPE *depth = (VALUE_TYPE *) values; + GLint x1, n1; + LOCAL_DEPTH_VARS; + + y = Y_FLIP( y ); + + if ( DBG ) fprintf( stderr, "ReadDepthSpan\n" ); + +#if HAVE_HW_DEPTH_SPANS + (void) x1; (void) n1; + + READ_DEPTH_SPAN(); +#else + HW_CLIPLOOP() + { + GLint i = 0; + CLIPSPAN( x, y, n, x1, n1, i ); + for ( ; n1>0 ; i++, n1-- ) { + READ_DEPTH( depth[i], x+i, y ); + } + } + HW_ENDCLIPLOOP(); +#endif + } + HW_READ_UNLOCK(); +} + +static void TAG(ReadDepthPixels)( struct gl_context *ctx, + struct gl_renderbuffer *rb, + GLuint n, + const GLint x[], const GLint y[], + void *values ) +{ + HW_READ_LOCK() + { + VALUE_TYPE *depth = (VALUE_TYPE *) values; + GLuint i; + LOCAL_DEPTH_VARS; + + if ( DBG ) fprintf( stderr, "ReadDepthPixels\n" ); + +#if HAVE_HW_DEPTH_PIXELS + (void) i; + + READ_DEPTH_PIXELS(); +#else + HW_CLIPLOOP() + { + for ( i = 0 ; i < n ;i++ ) { + int fy = Y_FLIP( y[i] ); + if ( CLIPPIXEL( x[i], fy ) ) + READ_DEPTH( depth[i], x[i], fy ); + } + } + HW_ENDCLIPLOOP(); +#endif + } + HW_READ_UNLOCK(); + + (void) ctx; +} + + +/** + * Initialize the given renderbuffer's span routines to point to + * the depth/z functions we generated above. + */ +static void TAG(InitDepthPointers)(struct gl_renderbuffer *rb) +{ + rb->GetRow = TAG(ReadDepthSpan); + rb->GetValues = TAG(ReadDepthPixels); + rb->PutRow = TAG(WriteDepthSpan); + rb->PutRowRGB = NULL; + rb->PutMonoRow = TAG(WriteMonoDepthSpan); + rb->PutValues = TAG(WriteDepthPixels); + rb->PutMonoValues = NULL; +} + + +#if HAVE_HW_DEPTH_SPANS +#undef WRITE_DEPTH_SPAN +#undef WRITE_DEPTH_PIXELS +#undef READ_DEPTH_SPAN +#undef READ_DEPTH_PIXELS +#else +#undef WRITE_DEPTH +#undef READ_DEPTH +#endif +#undef TAG +#undef VALUE_TYPE diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.c b/mesalib/src/mesa/drivers/dri/common/dri_util.c index 82638fa72..6d6401934 100644 --- a/mesalib/src/mesa/drivers/dri/common/dri_util.c +++ b/mesalib/src/mesa/drivers/dri/common/dri_util.c @@ -418,6 +418,7 @@ driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config, * supported either. */ (void) attrs; + (void) renderType; pdp = malloc(sizeof *pdp); if (!pdp) { @@ -594,8 +595,10 @@ driDestroyContext(__DRIcontext *pcp) /** * Create the per-drawable private driver information. * - * \param render_type Type of rendering target. \c GLX_RGBA is the only + * \param render_type Type of rendering target. \c GLX_RGBA_TYPE is the only * type likely to ever be supported for direct-rendering. + * However, \c GLX_RGBA_FLOAT_TYPE_ARB may eventually be + * supported by some drivers. * \param shared Context with which to share textures, etc. or NULL * * \returns An opaque pointer to the per-context private information on @@ -616,6 +619,8 @@ driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config, __DRIcontext *pcp; void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL; + (void) render_type; + pcp = malloc(sizeof *pcp); if (!pcp) return NULL; @@ -700,6 +705,9 @@ dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config, static int driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask) { + (void) dest; + (void) src; + (void) mask; return GL_FALSE; } @@ -806,6 +814,8 @@ driCreateNewScreen(int scrn, static const __DRIextension *emptyExtensionList[] = { NULL }; __DRIscreen *psp; + (void) loaderPrivate; + if (driDriverAPI.InitScreen == NULL) return NULL; diff --git a/mesalib/src/mesa/drivers/dri/common/spantmp2.h b/mesalib/src/mesa/drivers/dri/common/spantmp2.h index abd79562f..83cfbb164 100644 --- a/mesalib/src/mesa/drivers/dri/common/spantmp2.h +++ b/mesalib/src/mesa/drivers/dri/common/spantmp2.h @@ -465,6 +465,8 @@ static void TAG(WriteRGBASpan)( struct gl_context *ctx, GLuint n, GLint x, GLint y, const void *values, const GLubyte mask[] ) { + (void) ctx; + HW_WRITE_LOCK() { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; @@ -508,6 +510,8 @@ static void TAG(WriteRGBSpan)( struct gl_context *ctx, GLuint n, GLint x, GLint y, const void *values, const GLubyte mask[] ) { + (void) ctx; + HW_WRITE_LOCK() { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; @@ -547,6 +551,8 @@ static void TAG(WriteRGBAPixels)( struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], const void *values, const GLubyte mask[] ) { + (void) ctx; + HW_WRITE_LOCK() { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; @@ -593,6 +599,8 @@ static void TAG(WriteMonoRGBASpan)( struct gl_context *ctx, GLuint n, GLint x, GLint y, const void *value, const GLubyte mask[] ) { + (void) ctx; + HW_WRITE_LOCK() { const GLubyte *color = (const GLubyte *) value; @@ -634,6 +642,8 @@ static void TAG(WriteMonoRGBAPixels)( struct gl_context *ctx, const void *value, const GLubyte mask[] ) { + (void) ctx; + HW_WRITE_LOCK() { const GLubyte *color = (const GLubyte *) value; @@ -673,6 +683,8 @@ static void TAG(ReadRGBASpan)( struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint n, GLint x, GLint y, void *values) { + (void) ctx; + HW_READ_LOCK() { GLubyte (*rgba)[4] = (GLubyte (*)[4]) values; @@ -713,6 +725,8 @@ static void TAG2(ReadRGBASpan,_MMX)( struct gl_context *ctx, __asm__ __volatile__( "emms" ); #endif + (void) ctx; + HW_READ_LOCK() { GLubyte (*rgba)[4] = (GLubyte (*)[4]) values; @@ -757,6 +771,8 @@ static void TAG2(ReadRGBASpan,_SSE2)( struct gl_context *ctx, GLuint n, GLint x, GLint y, void *values) { + (void) ctx; + HW_READ_LOCK() { GLubyte (*rgba)[4] = (GLubyte (*)[4]) values; @@ -799,6 +815,8 @@ static void TAG2(ReadRGBASpan,_SSE)( struct gl_context *ctx, __asm__ __volatile__( "emms" ); #endif + (void) ctx; + HW_READ_LOCK() { GLubyte (*rgba)[4] = (GLubyte (*)[4]) values; @@ -834,6 +852,8 @@ static void TAG(ReadRGBAPixels)( struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], void *values ) { + (void) ctx; + HW_READ_LOCK() { GLubyte (*rgba)[4] = (GLubyte (*)[4]) values; diff --git a/mesalib/src/mesa/drivers/dri/common/utils.c b/mesalib/src/mesa/drivers/dri/common/utils.c index 539296d1a..54156d34a 100644 --- a/mesalib/src/mesa/drivers/dri/common/utils.c +++ b/mesalib/src/mesa/drivers/dri/common/utils.c @@ -1,823 +1,709 @@ -/* - * (C) Copyright IBM Corporation 2002, 2004 - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/** - * \file utils.c - * Utility functions for DRI drivers. - * - * \author Ian Romanick - */ - -#include -#include -#include "main/mtypes.h" -#include "main/cpuinfo.h" -#include "main/extensions.h" -#include "utils.h" - - -/** - * Print message to \c stderr if the \c LIBGL_DEBUG environment variable - * is set. - * - * Is called from the drivers. - * - * \param f \c printf like format string. - */ -void -__driUtilMessage(const char *f, ...) -{ - va_list args; - - if (getenv("LIBGL_DEBUG")) { - fprintf(stderr, "libGL: "); - va_start(args, f); - vfprintf(stderr, f, args); - va_end(args); - fprintf(stderr, "\n"); - } -} - - -unsigned -driParseDebugString( const char * debug, - const struct dri_debug_control * control ) -{ - unsigned flag; - - - flag = 0; - if ( debug != NULL ) { - while( control->string != NULL ) { - if ( !strcmp( debug, "all" ) || - strstr( debug, control->string ) != NULL ) { - flag |= control->flag; - } - - control++; - } - } - - return flag; -} - - - -/** - * Create the \c GL_RENDERER string for DRI drivers. - * - * Almost all DRI drivers use a \c GL_RENDERER string of the form: - * - * "Mesa DRI " - * - * Using the supplied chip name, driver data, and AGP speed, this function - * creates the string. - * - * \param buffer Buffer to hold the \c GL_RENDERER string. - * \param hardware_name Name of the hardware. - * \param agp_mode AGP mode (speed). - * - * \returns - * The length of the string stored in \c buffer. This does \b not include - * the terminating \c NUL character. - */ -unsigned -driGetRendererString( char * buffer, const char * hardware_name, - GLuint agp_mode ) -{ - unsigned offset; - char *cpu; - - offset = sprintf( buffer, "Mesa DRI %s", hardware_name ); - - /* Append any AGP-specific information. - */ - switch ( agp_mode ) { - case 1: - case 2: - case 4: - case 8: - offset += sprintf( & buffer[ offset ], " AGP %ux", agp_mode ); - break; - - default: - break; - } - - /* Append any CPU-specific information. - */ - cpu = _mesa_get_cpu_string(); - if (cpu) { - offset += sprintf(buffer + offset, " %s", cpu); - free(cpu); - } - - return offset; -} - - - - -#define need_GL_ARB_copy_buffer -#define need_GL_ARB_draw_buffers -#define need_GL_ARB_multisample -#define need_GL_ARB_texture_compression -#define need_GL_ARB_transpose_matrix -#define need_GL_ARB_vertex_buffer_object -#define need_GL_ARB_window_pos -#define need_GL_EXT_compiled_vertex_array -#define need_GL_EXT_multi_draw_arrays -#define need_GL_EXT_polygon_offset -#define need_GL_EXT_texture_object -#define need_GL_EXT_vertex_array -#define need_GL_IBM_multimode_draw_arrays -#define need_GL_MESA_window_pos - -/* These are needed in *all* drivers because Mesa internally implements - * certain functionality in terms of functions provided by these extensions. - * For example, glBlendFunc is implemented by calling glBlendFuncSeparateEXT. - */ -#define need_GL_EXT_blend_func_separate -#define need_GL_NV_vertex_program - -#include "main/remap_helper.h" - -static const struct dri_extension all_mesa_extensions[] = { - { "GL_ARB_copy_buffer", GL_ARB_copy_buffer_functions }, - { "GL_ARB_draw_buffers", GL_ARB_draw_buffers_functions }, - { "GL_ARB_multisample", GL_ARB_multisample_functions }, - { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions }, - { "GL_ARB_transpose_matrix", GL_ARB_transpose_matrix_functions }, - { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions}, - { "GL_ARB_window_pos", GL_ARB_window_pos_functions }, - { "GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions }, - { "GL_EXT_compiled_vertex_array", GL_EXT_compiled_vertex_array_functions }, - { "GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions }, - { "GL_EXT_polygon_offset", GL_EXT_polygon_offset_functions }, - { "GL_EXT_texture_object", GL_EXT_texture_object_functions }, - { "GL_EXT_vertex_array", GL_EXT_vertex_array_functions }, - { "GL_IBM_multimode_draw_arrays", GL_IBM_multimode_draw_arrays_functions }, - { "GL_MESA_window_pos", GL_MESA_window_pos_functions }, - { "GL_NV_vertex_program", GL_NV_vertex_program_functions }, - { NULL, NULL } -}; - - -/** - * Enable and map extensions supported by the driver. - * - * When ctx is NULL, extensions are not enabled, but their functions - * are still mapped. When extensions_to_enable is NULL, all static - * functions known to mesa core are mapped. - * - * \bug - * ARB_imaging isn't handled properly. In Mesa, enabling ARB_imaging also - * enables all the sub-extensions that are folded into it. This means that - * we need to add entry-points (via \c driInitSingleExtension) for those - * new functions here. - */ -void driInitExtensions( struct gl_context * ctx, - const struct dri_extension * extensions_to_enable, - GLboolean enable_imaging ) -{ - static int first_time = 1; - unsigned i; - - if ( first_time ) { - first_time = 0; - driInitExtensions( NULL, all_mesa_extensions, GL_FALSE ); - } - - if ( (ctx != NULL) && enable_imaging ) { - _mesa_enable_imaging_extensions( ctx ); - } - - /* The caller is too lazy to list any extension */ - if ( extensions_to_enable == NULL ) { - /* Map the static functions. Together with those mapped by remap - * table, this should cover everything mesa core knows. - */ - _mesa_map_static_functions(); - return; - } - - for ( i = 0 ; extensions_to_enable[i].name != NULL ; i++ ) { - driInitSingleExtension( ctx, & extensions_to_enable[i] ); - } -} - - - - -/** - * Enable and map functions for a single extension - * - * \param ctx Context where extension is to be enabled. - * \param ext Extension that is to be enabled. - * - * \sa driInitExtensions, _mesa_enable_extension, _mesa_map_function_array - */ -void driInitSingleExtension( struct gl_context * ctx, - const struct dri_extension * ext ) -{ - if ( ext->functions != NULL ) { - _mesa_map_function_array(ext->functions); - } - - if ( ctx != NULL ) { - _mesa_enable_extension( ctx, ext->name ); - } -} - - -/** - * Utility function used by drivers to test the verions of other components. - * - * \param driver_name Name of the driver. Used in error messages. - * \param driActual Actual DRI version supplied __driCreateNewScreen. - * \param driExpected Minimum DRI version required by the driver. - * \param ddxActual Actual DDX version supplied __driCreateNewScreen. - * \param ddxExpected Minimum DDX minor and range of DDX major version required by the driver. - * \param drmActual Actual DRM version supplied __driCreateNewScreen. - * \param drmExpected Minimum DRM version required by the driver. - * - * \returns \c GL_TRUE if all version requirements are met. Otherwise, - * \c GL_FALSE is returned. - * - * \sa __driCreateNewScreen, driCheckDriDdxDrmVersions2 - * - * \todo - * Now that the old \c driCheckDriDdxDrmVersions function is gone, this - * function and \c driCheckDriDdxDrmVersions2 should be renamed. - */ -GLboolean -driCheckDriDdxDrmVersions3(const char * driver_name, - const __DRIversion * driActual, - const __DRIversion * driExpected, - const __DRIversion * ddxActual, - const __DRIutilversion2 * ddxExpected, - const __DRIversion * drmActual, - const __DRIversion * drmExpected) -{ - static const char format[] = "%s DRI driver expected %s version %d.%d.x " - "but got version %d.%d.%d\n"; - static const char format2[] = "%s DRI driver expected %s version %d-%d.%d.x " - "but got version %d.%d.%d\n"; - - - /* Check the DRI version */ - if ( (driActual->major != driExpected->major) - || (driActual->minor < driExpected->minor) ) { - fprintf(stderr, format, driver_name, "DRI", - driExpected->major, driExpected->minor, - driActual->major, driActual->minor, driActual->patch); - return GL_FALSE; - } - - /* Check that the DDX driver version is compatible */ - if ( (ddxActual->major < ddxExpected->major_min) - || (ddxActual->major > ddxExpected->major_max) - || (ddxActual->minor < ddxExpected->minor) ) { - fprintf(stderr, format2, driver_name, "DDX", - ddxExpected->major_min, ddxExpected->major_max, ddxExpected->minor, - ddxActual->major, ddxActual->minor, ddxActual->patch); - return GL_FALSE; - } - - /* Check that the DRM driver version is compatible */ - if ( (drmActual->major != drmExpected->major) - || (drmActual->minor < drmExpected->minor) ) { - fprintf(stderr, format, driver_name, "DRM", - drmExpected->major, drmExpected->minor, - drmActual->major, drmActual->minor, drmActual->patch); - return GL_FALSE; - } - - return GL_TRUE; -} - -GLboolean -driCheckDriDdxDrmVersions2(const char * driver_name, - const __DRIversion * driActual, - const __DRIversion * driExpected, - const __DRIversion * ddxActual, - const __DRIversion * ddxExpected, - const __DRIversion * drmActual, - const __DRIversion * drmExpected) -{ - __DRIutilversion2 ddx_expected; - ddx_expected.major_min = ddxExpected->major; - ddx_expected.major_max = ddxExpected->major; - ddx_expected.minor = ddxExpected->minor; - ddx_expected.patch = ddxExpected->patch; - return driCheckDriDdxDrmVersions3(driver_name, driActual, - driExpected, ddxActual, & ddx_expected, - drmActual, drmExpected); -} - -GLboolean driClipRectToFramebuffer( const struct gl_framebuffer *buffer, - GLint *x, GLint *y, - GLsizei *width, GLsizei *height ) -{ - /* left clipping */ - if (*x < buffer->_Xmin) { - *width -= (buffer->_Xmin - *x); - *x = buffer->_Xmin; - } - - /* right clipping */ - if (*x + *width > buffer->_Xmax) - *width -= (*x + *width - buffer->_Xmax - 1); - - if (*width <= 0) - return GL_FALSE; - - /* bottom clipping */ - if (*y < buffer->_Ymin) { - *height -= (buffer->_Ymin - *y); - *y = buffer->_Ymin; - } - - /* top clipping */ - if (*y + *height > buffer->_Ymax) - *height -= (*y + *height - buffer->_Ymax - 1); - - if (*height <= 0) - return GL_FALSE; - - return GL_TRUE; -} - -/** - * Creates a set of \c struct gl_config that a driver will expose. - * - * A set of \c struct gl_config will be created based on the supplied - * parameters. The number of modes processed will be 2 * - * \c num_depth_stencil_bits * \c num_db_modes. - * - * For the most part, data is just copied from \c depth_bits, \c stencil_bits, - * \c db_modes, and \c visType into each \c struct gl_config element. - * However, the meanings of \c fb_format and \c fb_type require further - * explanation. The \c fb_format specifies which color components are in - * each pixel and what the default order is. For example, \c GL_RGB specifies - * that red, green, blue are available and red is in the "most significant" - * position and blue is in the "least significant". The \c fb_type specifies - * the bit sizes of each component and the actual ordering. For example, if - * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11] - * are the blue value, bits [10:5] are the green value, and bits [4:0] are - * the red value. - * - * One sublte issue is the combination of \c GL_RGB or \c GL_BGR and either - * of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the - * \c struct gl_config structure is \b identical to the \c GL_RGBA or - * \c GL_BGRA case, except the \c alphaMask is zero. This means that, as - * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8 - * still uses 32-bits. - * - * If in doubt, look at the tables used in the function. - * - * \param ptr_to_modes Pointer to a pointer to a linked list of - * \c struct gl_config. Upon completion, a pointer to - * the next element to be process will be stored here. - * If the function fails and returns \c GL_FALSE, this - * value will be unmodified, but some elements in the - * linked list may be modified. - * \param fb_format Format of the framebuffer. Currently only \c GL_RGB, - * \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported. - * \param fb_type Type of the pixels in the framebuffer. Currently only - * \c GL_UNSIGNED_SHORT_5_6_5, - * \c GL_UNSIGNED_SHORT_5_6_5_REV, - * \c GL_UNSIGNED_INT_8_8_8_8, and - * \c GL_UNSIGNED_INT_8_8_8_8_REV are supported. - * \param depth_bits Array of depth buffer sizes to be exposed. - * \param stencil_bits Array of stencil buffer sizes to be exposed. - * \param num_depth_stencil_bits Number of entries in both \c depth_bits and - * \c stencil_bits. - * \param db_modes Array of buffer swap modes. If an element has a - * value of \c GLX_NONE, then it represents a - * single-buffered mode. Other valid values are - * \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and - * \c GLX_SWAP_UNDEFINED_OML. See the - * GLX_OML_swap_method extension spec for more details. - * \param num_db_modes Number of entries in \c db_modes. - * \param msaa_samples Array of msaa sample count. 0 represents a visual - * without a multisample buffer. - * \param num_msaa_modes Number of entries in \c msaa_samples. - * \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or - * \c GLX_DIRECT_COLOR. - * - * \returns - * \c GL_TRUE on success or \c GL_FALSE on failure. Currently the only - * cause of failure is a bad parameter (i.e., unsupported \c fb_format or - * \c fb_type). - * - * \todo - * There is currently no way to support packed RGB modes (i.e., modes with - * exactly 3 bytes per pixel) or floating-point modes. This could probably - * be done by creating some new, private enums with clever names likes - * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32, - * \c GL_4HALF_16_16_16_16, etc. We can cross that bridge when we come to it. - */ -__DRIconfig ** -driCreateConfigs(GLenum fb_format, GLenum fb_type, - const uint8_t * depth_bits, const uint8_t * stencil_bits, - unsigned num_depth_stencil_bits, - const GLenum * db_modes, unsigned num_db_modes, - const uint8_t * msaa_samples, unsigned num_msaa_modes, - GLboolean enable_accum) -{ - static const uint8_t bits_table[4][4] = { - /* R G B A */ - { 3, 3, 2, 0 }, /* Any GL_UNSIGNED_BYTE_3_3_2 */ - { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */ - { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */ - { 8, 8, 8, 8 } /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */ - }; - - static const uint32_t masks_table_rgb[6][4] = { - { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 3_3_2 */ - { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 2_3_3_REV */ - { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */ - { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */ - { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000 }, /* 8_8_8_8 */ - { 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 } /* 8_8_8_8_REV */ - }; - - static const uint32_t masks_table_rgba[6][4] = { - { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 3_3_2 */ - { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 2_3_3_REV */ - { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */ - { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */ - { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF }, /* 8_8_8_8 */ - { 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 }, /* 8_8_8_8_REV */ - }; - - static const uint32_t masks_table_bgr[6][4] = { - { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 3_3_2 */ - { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 2_3_3_REV */ - { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */ - { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */ - { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000 }, /* 8_8_8_8 */ - { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, /* 8_8_8_8_REV */ - }; - - static const uint32_t masks_table_bgra[6][4] = { - { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 3_3_2 */ - { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 2_3_3_REV */ - { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */ - { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */ - { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF }, /* 8_8_8_8 */ - { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }, /* 8_8_8_8_REV */ - }; - - static const uint8_t bytes_per_pixel[6] = { - 1, /* 3_3_2 */ - 1, /* 2_3_3_REV */ - 2, /* 5_6_5 */ - 2, /* 5_6_5_REV */ - 4, /* 8_8_8_8 */ - 4 /* 8_8_8_8_REV */ - }; - - const uint8_t * bits; - const uint32_t * masks; - int index; - __DRIconfig **configs, **c; - struct gl_config *modes; - unsigned i, j, k, h; - unsigned num_modes; - unsigned num_accum_bits = (enable_accum) ? 2 : 1; - - switch ( fb_type ) { - case GL_UNSIGNED_BYTE_3_3_2: - index = 0; - break; - case GL_UNSIGNED_BYTE_2_3_3_REV: - index = 1; - break; - case GL_UNSIGNED_SHORT_5_6_5: - index = 2; - break; - case GL_UNSIGNED_SHORT_5_6_5_REV: - index = 3; - break; - case GL_UNSIGNED_INT_8_8_8_8: - index = 4; - break; - case GL_UNSIGNED_INT_8_8_8_8_REV: - index = 5; - break; - default: - fprintf( stderr, "[%s:%u] Unknown framebuffer type 0x%04x.\n", - __FUNCTION__, __LINE__, fb_type ); - return NULL; - } - - - /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and - * the _REV versions. - * - * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA. - */ - - switch ( fb_format ) { - case GL_RGB: - masks = masks_table_rgb[ index ]; - break; - - case GL_RGBA: - masks = masks_table_rgba[ index ]; - break; - - case GL_BGR: - masks = masks_table_bgr[ index ]; - break; - - case GL_BGRA: - masks = masks_table_bgra[ index ]; - break; - - default: - fprintf( stderr, "[%s:%u] Unknown framebuffer format 0x%04x.\n", - __FUNCTION__, __LINE__, fb_format ); - return NULL; - } - - switch ( bytes_per_pixel[ index ] ) { - case 1: - bits = bits_table[0]; - break; - case 2: - bits = bits_table[1]; - break; - default: - bits = ((fb_format == GL_RGB) || (fb_format == GL_BGR)) - ? bits_table[2] - : bits_table[3]; - break; - } - - num_modes = num_depth_stencil_bits * num_db_modes * num_accum_bits * num_msaa_modes; - configs = calloc(1, (num_modes + 1) * sizeof *configs); - if (configs == NULL) - return NULL; - - c = configs; - for ( k = 0 ; k < num_depth_stencil_bits ; k++ ) { - for ( i = 0 ; i < num_db_modes ; i++ ) { - for ( h = 0 ; h < num_msaa_modes; h++ ) { - for ( j = 0 ; j < num_accum_bits ; j++ ) { - *c = malloc (sizeof **c); - modes = &(*c)->modes; - c++; - - memset(modes, 0, sizeof *modes); - modes->redBits = bits[0]; - modes->greenBits = bits[1]; - modes->blueBits = bits[2]; - modes->alphaBits = bits[3]; - modes->redMask = masks[0]; - modes->greenMask = masks[1]; - modes->blueMask = masks[2]; - modes->alphaMask = masks[3]; - modes->rgbBits = modes->redBits + modes->greenBits - + modes->blueBits + modes->alphaBits; - - modes->accumRedBits = 16 * j; - modes->accumGreenBits = 16 * j; - modes->accumBlueBits = 16 * j; - modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0; - modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG; - - modes->stencilBits = stencil_bits[k]; - modes->depthBits = depth_bits[k]; - - modes->transparentPixel = GLX_NONE; - modes->transparentRed = GLX_DONT_CARE; - modes->transparentGreen = GLX_DONT_CARE; - modes->transparentBlue = GLX_DONT_CARE; - modes->transparentAlpha = GLX_DONT_CARE; - modes->transparentIndex = GLX_DONT_CARE; - modes->rgbMode = GL_TRUE; - - if ( db_modes[i] == GLX_NONE ) { - modes->doubleBufferMode = GL_FALSE; - } - else { - modes->doubleBufferMode = GL_TRUE; - modes->swapMethod = db_modes[i]; - } - - modes->samples = msaa_samples[h]; - modes->sampleBuffers = modes->samples ? 1 : 0; - - - modes->haveAccumBuffer = ((modes->accumRedBits + - modes->accumGreenBits + - modes->accumBlueBits + - modes->accumAlphaBits) > 0); - modes->haveDepthBuffer = (modes->depthBits > 0); - modes->haveStencilBuffer = (modes->stencilBits > 0); - - modes->bindToTextureRgb = GL_TRUE; - modes->bindToTextureRgba = GL_TRUE; - modes->bindToMipmapTexture = GL_FALSE; - modes->bindToTextureTargets = - __DRI_ATTRIB_TEXTURE_1D_BIT | - __DRI_ATTRIB_TEXTURE_2D_BIT | - __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT; - - modes->sRGBCapable = GL_FALSE; - } - } - } - } - *c = NULL; - - return configs; -} - -__DRIconfig **driConcatConfigs(__DRIconfig **a, - __DRIconfig **b) -{ - __DRIconfig **all; - int i, j, index; - - i = 0; - while (a[i] != NULL) - i++; - j = 0; - while (b[j] != NULL) - j++; - - all = malloc((i + j + 1) * sizeof *all); - index = 0; - for (i = 0; a[i] != NULL; i++) - all[index++] = a[i]; - for (j = 0; b[j] != NULL; j++) - all[index++] = b[j]; - all[index++] = NULL; - - free(a); - free(b); - - return all; -} - -#define __ATTRIB(attrib, field) \ - { attrib, offsetof(struct gl_config, field) } - -static const struct { unsigned int attrib, offset; } attribMap[] = { - __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits), - __ATTRIB(__DRI_ATTRIB_LEVEL, level), - __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits), - __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits), - __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits), - __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits), - __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits), - __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits), - __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits), - __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits), - __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits), - __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits), - __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers), - __ATTRIB(__DRI_ATTRIB_SAMPLES, samples), - __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode), - __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode), - __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers), - __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel), - __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentPixel), - __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed), - __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen), - __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue), - __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha), - __ATTRIB(__DRI_ATTRIB_FLOAT_MODE, floatMode), - __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask), - __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask), - __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask), - __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask), - __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth), - __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight), - __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels), - __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth), - __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight), - __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod), - __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb), - __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba), - __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, bindToMipmapTexture), - __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS, bindToTextureTargets), - __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted), - __ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE, sRGBCapable), - - /* The struct field doesn't matter here, these are handled by the - * switch in driGetConfigAttribIndex. We need them in the array - * so the iterator includes them though.*/ - __ATTRIB(__DRI_ATTRIB_RENDER_TYPE, level), - __ATTRIB(__DRI_ATTRIB_CONFIG_CAVEAT, level), - __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, level) -}; - -#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) - - -/** - * Return the value of a configuration attribute. The attribute is - * indicated by the index. - */ -static int -driGetConfigAttribIndex(const __DRIconfig *config, - unsigned int index, unsigned int *value) -{ - switch (attribMap[index].attrib) { - case __DRI_ATTRIB_RENDER_TYPE: - /* no support for color index mode */ - *value = __DRI_ATTRIB_RGBA_BIT; - break; - case __DRI_ATTRIB_CONFIG_CAVEAT: - if (config->modes.visualRating == GLX_NON_CONFORMANT_CONFIG) - *value = __DRI_ATTRIB_NON_CONFORMANT_CONFIG; - else if (config->modes.visualRating == GLX_SLOW_CONFIG) - *value = __DRI_ATTRIB_SLOW_BIT; - else - *value = 0; - break; - case __DRI_ATTRIB_SWAP_METHOD: - /* XXX no return value??? */ - break; - - case __DRI_ATTRIB_FLOAT_MODE: - /* this field is not int-sized */ - *value = config->modes.floatMode; - break; - - default: - /* any other int-sized field */ - *value = *(unsigned int *) - ((char *) &config->modes + attribMap[index].offset); - - break; - } - - return GL_TRUE; -} - - -/** - * Get the value of a configuration attribute. - * \param attrib the attribute (one of the _DRI_ATTRIB_x tokens) - * \param value returns the attribute's value - * \return 1 for success, 0 for failure - */ -int -driGetConfigAttrib(const __DRIconfig *config, - unsigned int attrib, unsigned int *value) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(attribMap); i++) - if (attribMap[i].attrib == attrib) - return driGetConfigAttribIndex(config, i, value); - - return GL_FALSE; -} - - -/** - * Get a configuration attribute name and value, given an index. - * \param index which field of the __DRIconfig to query - * \param attrib returns the attribute name (one of the _DRI_ATTRIB_x tokens) - * \param value returns the attribute's value - * \return 1 for success, 0 for failure - */ -int -driIndexConfigAttrib(const __DRIconfig *config, int index, - unsigned int *attrib, unsigned int *value) -{ - if (index >= 0 && index < ARRAY_SIZE(attribMap)) { - *attrib = attribMap[index].attrib; - return driGetConfigAttribIndex(config, index, value); - } - - return GL_FALSE; -} +/* + * (C) Copyright IBM Corporation 2002, 2004 + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file utils.c + * Utility functions for DRI drivers. + * + * \author Ian Romanick + */ + +#include +#include +#include "main/mtypes.h" +#include "main/cpuinfo.h" +#include "main/extensions.h" +#include "utils.h" + + +/** + * Print message to \c stderr if the \c LIBGL_DEBUG environment variable + * is set. + * + * Is called from the drivers. + * + * \param f \c printf like format string. + */ +void +__driUtilMessage(const char *f, ...) +{ + va_list args; + + if (getenv("LIBGL_DEBUG")) { + fprintf(stderr, "libGL: "); + va_start(args, f); + vfprintf(stderr, f, args); + va_end(args); + fprintf(stderr, "\n"); + } +} + + +unsigned +driParseDebugString( const char * debug, + const struct dri_debug_control * control ) +{ + unsigned flag; + + + flag = 0; + if ( debug != NULL ) { + while( control->string != NULL ) { + if ( !strcmp( debug, "all" ) || + strstr( debug, control->string ) != NULL ) { + flag |= control->flag; + } + + control++; + } + } + + return flag; +} + + + +/** + * Create the \c GL_RENDERER string for DRI drivers. + * + * Almost all DRI drivers use a \c GL_RENDERER string of the form: + * + * "Mesa DRI " + * + * Using the supplied chip name, driver data, and AGP speed, this function + * creates the string. + * + * \param buffer Buffer to hold the \c GL_RENDERER string. + * \param hardware_name Name of the hardware. + * \param agp_mode AGP mode (speed). + * + * \returns + * The length of the string stored in \c buffer. This does \b not include + * the terminating \c NUL character. + */ +unsigned +driGetRendererString( char * buffer, const char * hardware_name, + GLuint agp_mode ) +{ + unsigned offset; + char *cpu; + + offset = sprintf( buffer, "Mesa DRI %s", hardware_name ); + + /* Append any AGP-specific information. + */ + switch ( agp_mode ) { + case 1: + case 2: + case 4: + case 8: + offset += sprintf( & buffer[ offset ], " AGP %ux", agp_mode ); + break; + + default: + break; + } + + /* Append any CPU-specific information. + */ + cpu = _mesa_get_cpu_string(); + if (cpu) { + offset += sprintf(buffer + offset, " %s", cpu); + free(cpu); + } + + return offset; +} + + +/** + * Utility function used by drivers to test the verions of other components. + * + * \param driver_name Name of the driver. Used in error messages. + * \param driActual Actual DRI version supplied __driCreateNewScreen. + * \param driExpected Minimum DRI version required by the driver. + * \param ddxActual Actual DDX version supplied __driCreateNewScreen. + * \param ddxExpected Minimum DDX minor and range of DDX major version required by the driver. + * \param drmActual Actual DRM version supplied __driCreateNewScreen. + * \param drmExpected Minimum DRM version required by the driver. + * + * \returns \c GL_TRUE if all version requirements are met. Otherwise, + * \c GL_FALSE is returned. + * + * \sa __driCreateNewScreen, driCheckDriDdxDrmVersions2 + * + * \todo + * Now that the old \c driCheckDriDdxDrmVersions function is gone, this + * function and \c driCheckDriDdxDrmVersions2 should be renamed. + */ +GLboolean +driCheckDriDdxDrmVersions3(const char * driver_name, + const __DRIversion * driActual, + const __DRIversion * driExpected, + const __DRIversion * ddxActual, + const __DRIutilversion2 * ddxExpected, + const __DRIversion * drmActual, + const __DRIversion * drmExpected) +{ + static const char format[] = "%s DRI driver expected %s version %d.%d.x " + "but got version %d.%d.%d\n"; + static const char format2[] = "%s DRI driver expected %s version %d-%d.%d.x " + "but got version %d.%d.%d\n"; + + + /* Check the DRI version */ + if ( (driActual->major != driExpected->major) + || (driActual->minor < driExpected->minor) ) { + fprintf(stderr, format, driver_name, "DRI", + driExpected->major, driExpected->minor, + driActual->major, driActual->minor, driActual->patch); + return GL_FALSE; + } + + /* Check that the DDX driver version is compatible */ + if ( (ddxActual->major < ddxExpected->major_min) + || (ddxActual->major > ddxExpected->major_max) + || (ddxActual->minor < ddxExpected->minor) ) { + fprintf(stderr, format2, driver_name, "DDX", + ddxExpected->major_min, ddxExpected->major_max, ddxExpected->minor, + ddxActual->major, ddxActual->minor, ddxActual->patch); + return GL_FALSE; + } + + /* Check that the DRM driver version is compatible */ + if ( (drmActual->major != drmExpected->major) + || (drmActual->minor < drmExpected->minor) ) { + fprintf(stderr, format, driver_name, "DRM", + drmExpected->major, drmExpected->minor, + drmActual->major, drmActual->minor, drmActual->patch); + return GL_FALSE; + } + + return GL_TRUE; +} + +GLboolean +driCheckDriDdxDrmVersions2(const char * driver_name, + const __DRIversion * driActual, + const __DRIversion * driExpected, + const __DRIversion * ddxActual, + const __DRIversion * ddxExpected, + const __DRIversion * drmActual, + const __DRIversion * drmExpected) +{ + __DRIutilversion2 ddx_expected; + ddx_expected.major_min = ddxExpected->major; + ddx_expected.major_max = ddxExpected->major; + ddx_expected.minor = ddxExpected->minor; + ddx_expected.patch = ddxExpected->patch; + return driCheckDriDdxDrmVersions3(driver_name, driActual, + driExpected, ddxActual, & ddx_expected, + drmActual, drmExpected); +} + +GLboolean driClipRectToFramebuffer( const struct gl_framebuffer *buffer, + GLint *x, GLint *y, + GLsizei *width, GLsizei *height ) +{ + /* left clipping */ + if (*x < buffer->_Xmin) { + *width -= (buffer->_Xmin - *x); + *x = buffer->_Xmin; + } + + /* right clipping */ + if (*x + *width > buffer->_Xmax) + *width -= (*x + *width - buffer->_Xmax - 1); + + if (*width <= 0) + return GL_FALSE; + + /* bottom clipping */ + if (*y < buffer->_Ymin) { + *height -= (buffer->_Ymin - *y); + *y = buffer->_Ymin; + } + + /* top clipping */ + if (*y + *height > buffer->_Ymax) + *height -= (*y + *height - buffer->_Ymax - 1); + + if (*height <= 0) + return GL_FALSE; + + return GL_TRUE; +} + +/** + * Creates a set of \c struct gl_config that a driver will expose. + * + * A set of \c struct gl_config will be created based on the supplied + * parameters. The number of modes processed will be 2 * + * \c num_depth_stencil_bits * \c num_db_modes. + * + * For the most part, data is just copied from \c depth_bits, \c stencil_bits, + * \c db_modes, and \c visType into each \c struct gl_config element. + * However, the meanings of \c fb_format and \c fb_type require further + * explanation. The \c fb_format specifies which color components are in + * each pixel and what the default order is. For example, \c GL_RGB specifies + * that red, green, blue are available and red is in the "most significant" + * position and blue is in the "least significant". The \c fb_type specifies + * the bit sizes of each component and the actual ordering. For example, if + * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11] + * are the blue value, bits [10:5] are the green value, and bits [4:0] are + * the red value. + * + * One sublte issue is the combination of \c GL_RGB or \c GL_BGR and either + * of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the + * \c struct gl_config structure is \b identical to the \c GL_RGBA or + * \c GL_BGRA case, except the \c alphaMask is zero. This means that, as + * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8 + * still uses 32-bits. + * + * If in doubt, look at the tables used in the function. + * + * \param ptr_to_modes Pointer to a pointer to a linked list of + * \c struct gl_config. Upon completion, a pointer to + * the next element to be process will be stored here. + * If the function fails and returns \c GL_FALSE, this + * value will be unmodified, but some elements in the + * linked list may be modified. + * \param fb_format Format of the framebuffer. Currently only \c GL_RGB, + * \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported. + * \param fb_type Type of the pixels in the framebuffer. Currently only + * \c GL_UNSIGNED_SHORT_5_6_5, + * \c GL_UNSIGNED_SHORT_5_6_5_REV, + * \c GL_UNSIGNED_INT_8_8_8_8, and + * \c GL_UNSIGNED_INT_8_8_8_8_REV are supported. + * \param depth_bits Array of depth buffer sizes to be exposed. + * \param stencil_bits Array of stencil buffer sizes to be exposed. + * \param num_depth_stencil_bits Number of entries in both \c depth_bits and + * \c stencil_bits. + * \param db_modes Array of buffer swap modes. If an element has a + * value of \c GLX_NONE, then it represents a + * single-buffered mode. Other valid values are + * \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and + * \c GLX_SWAP_UNDEFINED_OML. See the + * GLX_OML_swap_method extension spec for more details. + * \param num_db_modes Number of entries in \c db_modes. + * \param msaa_samples Array of msaa sample count. 0 represents a visual + * without a multisample buffer. + * \param num_msaa_modes Number of entries in \c msaa_samples. + * \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or + * \c GLX_DIRECT_COLOR. + * + * \returns + * \c GL_TRUE on success or \c GL_FALSE on failure. Currently the only + * cause of failure is a bad parameter (i.e., unsupported \c fb_format or + * \c fb_type). + * + * \todo + * There is currently no way to support packed RGB modes (i.e., modes with + * exactly 3 bytes per pixel) or floating-point modes. This could probably + * be done by creating some new, private enums with clever names likes + * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32, + * \c GL_4HALF_16_16_16_16, etc. We can cross that bridge when we come to it. + */ +__DRIconfig ** +driCreateConfigs(GLenum fb_format, GLenum fb_type, + const uint8_t * depth_bits, const uint8_t * stencil_bits, + unsigned num_depth_stencil_bits, + const GLenum * db_modes, unsigned num_db_modes, + const uint8_t * msaa_samples, unsigned num_msaa_modes, + GLboolean enable_accum) +{ + static const uint8_t bits_table[4][4] = { + /* R G B A */ + { 3, 3, 2, 0 }, /* Any GL_UNSIGNED_BYTE_3_3_2 */ + { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */ + { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */ + { 8, 8, 8, 8 } /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */ + }; + + static const uint32_t masks_table_rgb[6][4] = { + { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 3_3_2 */ + { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 2_3_3_REV */ + { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */ + { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */ + { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000 }, /* 8_8_8_8 */ + { 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 } /* 8_8_8_8_REV */ + }; + + static const uint32_t masks_table_rgba[6][4] = { + { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 3_3_2 */ + { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 2_3_3_REV */ + { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */ + { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */ + { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF }, /* 8_8_8_8 */ + { 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 }, /* 8_8_8_8_REV */ + }; + + static const uint32_t masks_table_bgr[6][4] = { + { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 3_3_2 */ + { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 2_3_3_REV */ + { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */ + { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */ + { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000 }, /* 8_8_8_8 */ + { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, /* 8_8_8_8_REV */ + }; + + static const uint32_t masks_table_bgra[6][4] = { + { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 3_3_2 */ + { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 2_3_3_REV */ + { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */ + { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */ + { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF }, /* 8_8_8_8 */ + { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }, /* 8_8_8_8_REV */ + }; + + static const uint8_t bytes_per_pixel[6] = { + 1, /* 3_3_2 */ + 1, /* 2_3_3_REV */ + 2, /* 5_6_5 */ + 2, /* 5_6_5_REV */ + 4, /* 8_8_8_8 */ + 4 /* 8_8_8_8_REV */ + }; + + const uint8_t * bits; + const uint32_t * masks; + int index; + __DRIconfig **configs, **c; + struct gl_config *modes; + unsigned i, j, k, h; + unsigned num_modes; + unsigned num_accum_bits = (enable_accum) ? 2 : 1; + + switch ( fb_type ) { + case GL_UNSIGNED_BYTE_3_3_2: + index = 0; + break; + case GL_UNSIGNED_BYTE_2_3_3_REV: + index = 1; + break; + case GL_UNSIGNED_SHORT_5_6_5: + index = 2; + break; + case GL_UNSIGNED_SHORT_5_6_5_REV: + index = 3; + break; + case GL_UNSIGNED_INT_8_8_8_8: + index = 4; + break; + case GL_UNSIGNED_INT_8_8_8_8_REV: + index = 5; + break; + default: + fprintf( stderr, "[%s:%u] Unknown framebuffer type 0x%04x.\n", + __FUNCTION__, __LINE__, fb_type ); + return NULL; + } + + + /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and + * the _REV versions. + * + * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA. + */ + + switch ( fb_format ) { + case GL_RGB: + masks = masks_table_rgb[ index ]; + break; + + case GL_RGBA: + masks = masks_table_rgba[ index ]; + break; + + case GL_BGR: + masks = masks_table_bgr[ index ]; + break; + + case GL_BGRA: + masks = masks_table_bgra[ index ]; + break; + + default: + fprintf( stderr, "[%s:%u] Unknown framebuffer format 0x%04x.\n", + __FUNCTION__, __LINE__, fb_format ); + return NULL; + } + + switch ( bytes_per_pixel[ index ] ) { + case 1: + bits = bits_table[0]; + break; + case 2: + bits = bits_table[1]; + break; + default: + bits = ((fb_format == GL_RGB) || (fb_format == GL_BGR)) + ? bits_table[2] + : bits_table[3]; + break; + } + + num_modes = num_depth_stencil_bits * num_db_modes * num_accum_bits * num_msaa_modes; + configs = calloc(1, (num_modes + 1) * sizeof *configs); + if (configs == NULL) + return NULL; + + c = configs; + for ( k = 0 ; k < num_depth_stencil_bits ; k++ ) { + for ( i = 0 ; i < num_db_modes ; i++ ) { + for ( h = 0 ; h < num_msaa_modes; h++ ) { + for ( j = 0 ; j < num_accum_bits ; j++ ) { + *c = malloc (sizeof **c); + modes = &(*c)->modes; + c++; + + memset(modes, 0, sizeof *modes); + modes->redBits = bits[0]; + modes->greenBits = bits[1]; + modes->blueBits = bits[2]; + modes->alphaBits = bits[3]; + modes->redMask = masks[0]; + modes->greenMask = masks[1]; + modes->blueMask = masks[2]; + modes->alphaMask = masks[3]; + modes->rgbBits = modes->redBits + modes->greenBits + + modes->blueBits + modes->alphaBits; + + modes->accumRedBits = 16 * j; + modes->accumGreenBits = 16 * j; + modes->accumBlueBits = 16 * j; + modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0; + modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG; + + modes->stencilBits = stencil_bits[k]; + modes->depthBits = depth_bits[k]; + + modes->transparentPixel = GLX_NONE; + modes->transparentRed = GLX_DONT_CARE; + modes->transparentGreen = GLX_DONT_CARE; + modes->transparentBlue = GLX_DONT_CARE; + modes->transparentAlpha = GLX_DONT_CARE; + modes->transparentIndex = GLX_DONT_CARE; + modes->rgbMode = GL_TRUE; + + if ( db_modes[i] == GLX_NONE ) { + modes->doubleBufferMode = GL_FALSE; + } + else { + modes->doubleBufferMode = GL_TRUE; + modes->swapMethod = db_modes[i]; + } + + modes->samples = msaa_samples[h]; + modes->sampleBuffers = modes->samples ? 1 : 0; + + + modes->haveAccumBuffer = ((modes->accumRedBits + + modes->accumGreenBits + + modes->accumBlueBits + + modes->accumAlphaBits) > 0); + modes->haveDepthBuffer = (modes->depthBits > 0); + modes->haveStencilBuffer = (modes->stencilBits > 0); + + modes->bindToTextureRgb = GL_TRUE; + modes->bindToTextureRgba = GL_TRUE; + modes->bindToMipmapTexture = GL_FALSE; + modes->bindToTextureTargets = + __DRI_ATTRIB_TEXTURE_1D_BIT | + __DRI_ATTRIB_TEXTURE_2D_BIT | + __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT; + + modes->sRGBCapable = GL_FALSE; + } + } + } + } + *c = NULL; + + return configs; +} + +__DRIconfig **driConcatConfigs(__DRIconfig **a, + __DRIconfig **b) +{ + __DRIconfig **all; + int i, j, index; + + i = 0; + while (a[i] != NULL) + i++; + j = 0; + while (b[j] != NULL) + j++; + + all = malloc((i + j + 1) * sizeof *all); + index = 0; + for (i = 0; a[i] != NULL; i++) + all[index++] = a[i]; + for (j = 0; b[j] != NULL; j++) + all[index++] = b[j]; + all[index++] = NULL; + + free(a); + free(b); + + return all; +} + +#define __ATTRIB(attrib, field) \ + { attrib, offsetof(struct gl_config, field) } + +static const struct { unsigned int attrib, offset; } attribMap[] = { + __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits), + __ATTRIB(__DRI_ATTRIB_LEVEL, level), + __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits), + __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits), + __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits), + __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits), + __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits), + __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits), + __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits), + __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits), + __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits), + __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits), + __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers), + __ATTRIB(__DRI_ATTRIB_SAMPLES, samples), + __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode), + __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode), + __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentPixel), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue), + __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha), + __ATTRIB(__DRI_ATTRIB_FLOAT_MODE, floatMode), + __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask), + __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask), + __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask), + __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask), + __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth), + __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight), + __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels), + __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth), + __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight), + __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod), + __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb), + __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba), + __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, bindToMipmapTexture), + __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS, bindToTextureTargets), + __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted), + __ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE, sRGBCapable), + + /* The struct field doesn't matter here, these are handled by the + * switch in driGetConfigAttribIndex. We need them in the array + * so the iterator includes them though.*/ + __ATTRIB(__DRI_ATTRIB_RENDER_TYPE, level), + __ATTRIB(__DRI_ATTRIB_CONFIG_CAVEAT, level), + __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, level) +}; + +#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) + + +/** + * Return the value of a configuration attribute. The attribute is + * indicated by the index. + */ +static int +driGetConfigAttribIndex(const __DRIconfig *config, + unsigned int index, unsigned int *value) +{ + switch (attribMap[index].attrib) { + case __DRI_ATTRIB_RENDER_TYPE: + /* no support for color index mode */ + *value = __DRI_ATTRIB_RGBA_BIT; + break; + case __DRI_ATTRIB_CONFIG_CAVEAT: + if (config->modes.visualRating == GLX_NON_CONFORMANT_CONFIG) + *value = __DRI_ATTRIB_NON_CONFORMANT_CONFIG; + else if (config->modes.visualRating == GLX_SLOW_CONFIG) + *value = __DRI_ATTRIB_SLOW_BIT; + else + *value = 0; + break; + case __DRI_ATTRIB_SWAP_METHOD: + /* XXX no return value??? */ + break; + + case __DRI_ATTRIB_FLOAT_MODE: + /* this field is not int-sized */ + *value = config->modes.floatMode; + break; + + default: + /* any other int-sized field */ + *value = *(unsigned int *) + ((char *) &config->modes + attribMap[index].offset); + + break; + } + + return GL_TRUE; +} + + +/** + * Get the value of a configuration attribute. + * \param attrib the attribute (one of the _DRI_ATTRIB_x tokens) + * \param value returns the attribute's value + * \return 1 for success, 0 for failure + */ +int +driGetConfigAttrib(const __DRIconfig *config, + unsigned int attrib, unsigned int *value) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(attribMap); i++) + if (attribMap[i].attrib == attrib) + return driGetConfigAttribIndex(config, i, value); + + return GL_FALSE; +} + + +/** + * Get a configuration attribute name and value, given an index. + * \param index which field of the __DRIconfig to query + * \param attrib returns the attribute name (one of the _DRI_ATTRIB_x tokens) + * \param value returns the attribute's value + * \return 1 for success, 0 for failure + */ +int +driIndexConfigAttrib(const __DRIconfig *config, int index, + unsigned int *attrib, unsigned int *value) +{ + if (index >= 0 && index < ARRAY_SIZE(attribMap)) { + *attrib = attribMap[index].attrib; + return driGetConfigAttribIndex(config, index, value); + } + + return GL_FALSE; +} diff --git a/mesalib/src/mesa/drivers/dri/common/utils.h b/mesalib/src/mesa/drivers/dri/common/utils.h index 10fb23de9..100d0dd51 100644 --- a/mesalib/src/mesa/drivers/dri/common/utils.h +++ b/mesalib/src/mesa/drivers/dri/common/utils.h @@ -1,123 +1,98 @@ -/* - * (C) Copyright IBM Corporation 2002, 2004 - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Ian Romanick - */ - -#ifndef DRI_DEBUG_H -#define DRI_DEBUG_H - -#include -#include -#include "main/context.h" -#include "main/remap.h" - -typedef struct __DRIutilversionRec2 __DRIutilversion2; - -struct dri_debug_control { - const char * string; - unsigned flag; -}; - -/** - * Description of the API for an extension to OpenGL. - */ -struct dri_extension { - /** - * Name of the extension. - */ - const char * name; - - - /** - * Pointer to a list of \c dri_extension_function structures. The list - * is terminated by a structure with a \c NULL - * \c dri_extension_function::strings pointer. - */ - const struct gl_function_remap * functions; -}; - -/** - * Used to store a version which includes a major range instead of a single - * major version number. - */ -struct __DRIutilversionRec2 { - int major_min; /** min allowed Major version number. */ - int major_max; /** max allowed Major version number. */ - int minor; /**< Minor version number. */ - int patch; /**< Patch-level. */ -}; - -extern void -__driUtilMessage(const char *f, ...); - -extern unsigned driParseDebugString( const char * debug, - const struct dri_debug_control * control ); - -extern unsigned driGetRendererString( char * buffer, - const char * hardware_name, GLuint agp_mode ); - -extern void driInitExtensions( struct gl_context * ctx, - const struct dri_extension * card_extensions, GLboolean enable_imaging ); - -extern void driInitSingleExtension( struct gl_context * ctx, - const struct dri_extension * ext ); - -extern GLboolean driCheckDriDdxDrmVersions2(const char * driver_name, - const __DRIversion * driActual, const __DRIversion * driExpected, - const __DRIversion * ddxActual, const __DRIversion * ddxExpected, - const __DRIversion * drmActual, const __DRIversion * drmExpected); - -extern GLboolean driCheckDriDdxDrmVersions3(const char * driver_name, - const __DRIversion * driActual, const __DRIversion * driExpected, - const __DRIversion * ddxActual, const __DRIutilversion2 * ddxExpected, - const __DRIversion * drmActual, const __DRIversion * drmExpected); - -extern GLboolean driClipRectToFramebuffer( const struct gl_framebuffer *buffer, - GLint *x, GLint *y, - GLsizei *width, GLsizei *height ); - -struct __DRIconfigRec { - struct gl_config modes; -}; - -extern __DRIconfig ** -driCreateConfigs(GLenum fb_format, GLenum fb_type, - const uint8_t * depth_bits, const uint8_t * stencil_bits, - unsigned num_depth_stencil_bits, - const GLenum * db_modes, unsigned num_db_modes, - const uint8_t * msaa_samples, unsigned num_msaa_modes, - GLboolean enable_accum); - -__DRIconfig **driConcatConfigs(__DRIconfig **a, - __DRIconfig **b); - -int -driGetConfigAttrib(const __DRIconfig *config, - unsigned int attrib, unsigned int *value); -int -driIndexConfigAttrib(const __DRIconfig *config, int index, - unsigned int *attrib, unsigned int *value); - -#endif /* DRI_DEBUG_H */ +/* + * (C) Copyright IBM Corporation 2002, 2004 + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Ian Romanick + */ + +#ifndef DRI_DEBUG_H +#define DRI_DEBUG_H + +#include +#include +#include "main/context.h" + +typedef struct __DRIutilversionRec2 __DRIutilversion2; + +struct dri_debug_control { + const char * string; + unsigned flag; +}; + +/** + * Used to store a version which includes a major range instead of a single + * major version number. + */ +struct __DRIutilversionRec2 { + int major_min; /** min allowed Major version number. */ + int major_max; /** max allowed Major version number. */ + int minor; /**< Minor version number. */ + int patch; /**< Patch-level. */ +}; + +extern void +__driUtilMessage(const char *f, ...); + +extern unsigned driParseDebugString( const char * debug, + const struct dri_debug_control * control ); + +extern unsigned driGetRendererString( char * buffer, + const char * hardware_name, GLuint agp_mode ); + +extern GLboolean driCheckDriDdxDrmVersions2(const char * driver_name, + const __DRIversion * driActual, const __DRIversion * driExpected, + const __DRIversion * ddxActual, const __DRIversion * ddxExpected, + const __DRIversion * drmActual, const __DRIversion * drmExpected); + +extern GLboolean driCheckDriDdxDrmVersions3(const char * driver_name, + const __DRIversion * driActual, const __DRIversion * driExpected, + const __DRIversion * ddxActual, const __DRIutilversion2 * ddxExpected, + const __DRIversion * drmActual, const __DRIversion * drmExpected); + +extern GLboolean driClipRectToFramebuffer( const struct gl_framebuffer *buffer, + GLint *x, GLint *y, + GLsizei *width, GLsizei *height ); + +struct __DRIconfigRec { + struct gl_config modes; +}; + +extern __DRIconfig ** +driCreateConfigs(GLenum fb_format, GLenum fb_type, + const uint8_t * depth_bits, const uint8_t * stencil_bits, + unsigned num_depth_stencil_bits, + const GLenum * db_modes, unsigned num_db_modes, + const uint8_t * msaa_samples, unsigned num_msaa_modes, + GLboolean enable_accum); + +__DRIconfig **driConcatConfigs(__DRIconfig **a, + __DRIconfig **b); + +int +driGetConfigAttrib(const __DRIconfig *config, + unsigned int attrib, unsigned int *value); +int +driIndexConfigAttrib(const __DRIconfig *config, int index, + unsigned int *attrib, unsigned int *value); + +#endif /* DRI_DEBUG_H */ diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast.c b/mesalib/src/mesa/drivers/dri/swrast/swrast.c index 719b406ec..6c94947a0 100644 --- a/mesalib/src/mesa/drivers/dri/swrast/swrast.c +++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c @@ -135,6 +135,9 @@ swrastFillInModes(__DRIscreen *psp, uint8_t stencil_bits_array[4]; uint8_t msaa_samples_array[1]; + (void) psp; + (void) have_back_buffer; + depth_bits_array[0] = 0; depth_bits_array[1] = 0; depth_bits_array[2] = depth_bits; @@ -215,6 +218,7 @@ static void dri_destroy_screen(__DRIscreen * sPriv) { TRACE; + (void) sPriv; } @@ -278,6 +282,9 @@ swrast_alloc_front_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, TRACE; + (void) ctx; + (void) internalFormat; + rb->Data = NULL; rb->Width = width; rb->Height = height; @@ -376,6 +383,9 @@ dri_create_buffer(__DRIscreen * sPriv, TRACE; + (void) sPriv; + (void) isPixmap; + drawable = CALLOC_STRUCT(dri_drawable); if (drawable == NULL) goto drawable_fail; @@ -537,6 +547,10 @@ viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h) struct gl_framebuffer *draw = ctx->WinSysDrawBuffer; struct gl_framebuffer *read = ctx->WinSysReadBuffer; + (void) x; + (void) y; + (void) w; + (void) h; swrast_check_and_update_window_size(ctx, draw); swrast_check_and_update_window_size(ctx, read); } @@ -609,9 +623,6 @@ InitExtensionsES2(struct gl_context *ctx) { int i; - /* Can't use driInitExtensions() since it uses extensions from - * main/remap_helper.h when called the first time. */ - for (i = 0; es2_extensions[i]; i++) _mesa_enable_extension(ctx, es2_extensions[i]); } @@ -681,8 +692,6 @@ dri_create_context(gl_api api, _mesa_enable_1_5_extensions(mesaCtx); _mesa_enable_2_0_extensions(mesaCtx); _mesa_enable_2_1_extensions(mesaCtx); - - driInitExtensions( mesaCtx, NULL, GL_FALSE ); break; case API_OPENGLES: _mesa_enable_1_3_extensions(mesaCtx); diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index 1903a503c..9cec15b58 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -37,6 +37,8 @@ #include "mfeatures.h" #include "mtypes.h" +#define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1)) + enum { DISABLE = 0, GL = 1 << API_OPENGL, @@ -769,11 +771,11 @@ get_extension_override( struct gl_context *ctx ) if (env_const == NULL) { /* Return the empty string rather than NULL. This simplifies the logic * of client functions. */ - return calloc(1, sizeof(char)); + return calloc(4, sizeof(char)); } /* extra_exts: List of unrecognized extensions. */ - extra_exts = calloc(strlen(env_const), sizeof(char)); + extra_exts = calloc(ALIGN(strlen(env_const) + 2, 4), sizeof(char)); /* Copy env_const because strtok() is destructive. */ env = strdup(env_const); @@ -907,7 +909,7 @@ _mesa_make_extension_string(struct gl_context *ctx) if (extra_extensions != NULL) length += 1 + strlen(extra_extensions); /* +1 for space */ - exts = (char *) calloc(length + 1, sizeof(char)); + exts = (char *) calloc(ALIGN(length + 1, 4), sizeof(char)); if (exts == NULL) { free(extra_extensions); return NULL; diff --git a/mesalib/src/mesa/main/nvprogram.c b/mesalib/src/mesa/main/nvprogram.c index 7ff7645b7..a0e89b10f 100644 --- a/mesalib/src/mesa/main/nvprogram.c +++ b/mesalib/src/mesa/main/nvprogram.c @@ -560,7 +560,7 @@ _mesa_emit_nv_temp_initialization(struct gl_context *ctx, } void -_mesa_setup_nv_temporary_count(struct gl_context *ctx, struct gl_program *program) +_mesa_setup_nv_temporary_count(struct gl_program *program) { GLuint i; diff --git a/mesalib/src/mesa/main/nvprogram.h b/mesalib/src/mesa/main/nvprogram.h index 3d12b4e33..fc579a9fe 100644 --- a/mesalib/src/mesa/main/nvprogram.h +++ b/mesalib/src/mesa/main/nvprogram.h @@ -1,119 +1,119 @@ -/* - * Mesa 3-D graphics library - * Version: 5.1 - * - * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Brian Paul - */ - - -#ifndef NVPROGRAM_H -#define NVPROGRAM_H - -#include "glheader.h" - -struct gl_context; -struct gl_program; - -extern void GLAPIENTRY -_mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params); - -extern GLboolean GLAPIENTRY -_mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids, GLboolean *residences); - -extern void GLAPIENTRY -_mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids); - -extern void GLAPIENTRY -_mesa_GetProgramParameterfvNV(GLenum target, GLuint index, GLenum pname, GLfloat *params); - -extern void GLAPIENTRY -_mesa_GetProgramParameterdvNV(GLenum target, GLuint index, GLenum pname, GLdouble *params); - -extern void GLAPIENTRY -_mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params); - -extern void GLAPIENTRY -_mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program); - -extern void GLAPIENTRY -_mesa_GetTrackMatrixivNV(GLenum target, GLuint address, GLenum pname, GLint *params); - -extern void GLAPIENTRY -_mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params); - -extern void GLAPIENTRY -_mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params); - -extern void GLAPIENTRY -_mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params); - -extern void GLAPIENTRY -_mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer); - -extern void GLAPIENTRY -_mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len, const GLubyte *program); - -extern void GLAPIENTRY -_mesa_ProgramParameters4dvNV(GLenum target, GLuint index, GLsizei num, - const GLdouble *params); - -extern void GLAPIENTRY -_mesa_ProgramParameters4fvNV(GLenum target, GLuint index, GLsizei num, - const GLfloat *params); - -extern void GLAPIENTRY -_mesa_TrackMatrixNV(GLenum target, GLuint address, GLenum matrix, GLenum transform); - - -extern void GLAPIENTRY -_mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name, - GLfloat x, GLfloat y, GLfloat z, GLfloat w); - -extern void GLAPIENTRY -_mesa_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name, - const float v[]); - -extern void GLAPIENTRY -_mesa_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name, - GLdouble x, GLdouble y, GLdouble z, GLdouble w); - -extern void GLAPIENTRY -_mesa_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name, - const double v[]); - -extern void GLAPIENTRY -_mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name, - GLfloat *params); - -extern void GLAPIENTRY -_mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name, - GLdouble *params); - -extern void -_mesa_setup_nv_temporary_count(struct gl_context *ctx, struct gl_program *program); - -extern void -_mesa_emit_nv_temp_initialization(struct gl_context *ctx, - struct gl_program *program); - -#endif +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Brian Paul + */ + + +#ifndef NVPROGRAM_H +#define NVPROGRAM_H + +#include "glheader.h" + +struct gl_context; +struct gl_program; + +extern void GLAPIENTRY +_mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params); + +extern GLboolean GLAPIENTRY +_mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids, GLboolean *residences); + +extern void GLAPIENTRY +_mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids); + +extern void GLAPIENTRY +_mesa_GetProgramParameterfvNV(GLenum target, GLuint index, GLenum pname, GLfloat *params); + +extern void GLAPIENTRY +_mesa_GetProgramParameterdvNV(GLenum target, GLuint index, GLenum pname, GLdouble *params); + +extern void GLAPIENTRY +_mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program); + +extern void GLAPIENTRY +_mesa_GetTrackMatrixivNV(GLenum target, GLuint address, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params); + +extern void GLAPIENTRY +_mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params); + +extern void GLAPIENTRY +_mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer); + +extern void GLAPIENTRY +_mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len, const GLubyte *program); + +extern void GLAPIENTRY +_mesa_ProgramParameters4dvNV(GLenum target, GLuint index, GLsizei num, + const GLdouble *params); + +extern void GLAPIENTRY +_mesa_ProgramParameters4fvNV(GLenum target, GLuint index, GLsizei num, + const GLfloat *params); + +extern void GLAPIENTRY +_mesa_TrackMatrixNV(GLenum target, GLuint address, GLenum matrix, GLenum transform); + + +extern void GLAPIENTRY +_mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name, + GLfloat x, GLfloat y, GLfloat z, GLfloat w); + +extern void GLAPIENTRY +_mesa_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name, + const float v[]); + +extern void GLAPIENTRY +_mesa_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name, + GLdouble x, GLdouble y, GLdouble z, GLdouble w); + +extern void GLAPIENTRY +_mesa_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name, + const double v[]); + +extern void GLAPIENTRY +_mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name, + GLfloat *params); + +extern void GLAPIENTRY +_mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name, + GLdouble *params); + +extern void +_mesa_setup_nv_temporary_count(struct gl_program *program); + +extern void +_mesa_emit_nv_temp_initialization(struct gl_context *ctx, + struct gl_program *program); + +#endif diff --git a/mesalib/src/mesa/main/teximage.h b/mesalib/src/mesa/main/teximage.h index b59961eaf..8ef1d4560 100644 --- a/mesalib/src/mesa/main/teximage.h +++ b/mesalib/src/mesa/main/teximage.h @@ -1,285 +1,286 @@ -/** - * \file teximage.h - * Texture images manipulation functions. - */ - -/* - * Mesa 3-D graphics library - * Version: 6.5 - * - * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - - -#ifndef TEXIMAGE_H -#define TEXIMAGE_H - - -#include "mtypes.h" -#include "formats.h" - - -extern void * -_mesa_alloc_texmemory(GLsizei bytes); - -extern void -_mesa_free_texmemory(void *m); - - -/** \name Internal functions */ -/*@{*/ - -extern GLint -_mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ); - - -extern GLboolean -_mesa_is_proxy_texture(GLenum target); - - -extern struct gl_texture_image * -_mesa_new_texture_image( struct gl_context *ctx ); - - -extern void -_mesa_delete_texture_image( struct gl_context *ctx, - struct gl_texture_image *teximage ); - -extern void -_mesa_free_texture_image_data( struct gl_context *ctx, - struct gl_texture_image *texImage ); - - -extern void -_mesa_init_teximage_fields(struct gl_context *ctx, GLenum target, - struct gl_texture_image *img, - GLsizei width, GLsizei height, GLsizei depth, - GLint border, GLenum internalFormat, - gl_format format); - - -extern gl_format -_mesa_choose_texture_format(struct gl_context *ctx, - struct gl_texture_object *texObj, - GLenum target, GLint level, - GLenum internalFormat, GLenum format, GLenum type); - - -extern void -_mesa_clear_texture_image(struct gl_context *ctx, - struct gl_texture_image *texImage); - - -extern void -_mesa_set_tex_image(struct gl_texture_object *tObj, - GLenum target, GLint level, - struct gl_texture_image *texImage); - - -extern struct gl_texture_object * -_mesa_select_tex_object(struct gl_context *ctx, - const struct gl_texture_unit *texUnit, - GLenum target); - -extern struct gl_texture_object * -_mesa_get_current_tex_object(struct gl_context *ctx, GLenum target); - - -extern struct gl_texture_image * -_mesa_select_tex_image(struct gl_context *ctx, - const struct gl_texture_object *texObj, - GLenum target, GLint level); - - -extern struct gl_texture_image * -_mesa_get_tex_image(struct gl_context *ctx, struct gl_texture_object *texObj, - GLenum target, GLint level); - - -extern struct gl_texture_image * -_mesa_get_proxy_tex_image(struct gl_context *ctx, GLenum target, GLint level); - - -extern GLint -_mesa_max_texture_levels(struct gl_context *ctx, GLenum target); - - -extern GLboolean -_mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level, - GLint internalFormat, GLenum format, GLenum type, - GLint width, GLint height, GLint depth, GLint border); - - -extern GLuint -_mesa_tex_target_to_face(GLenum target); - -extern GLint -_mesa_get_texture_dimensions(GLenum target); - -/** - * Lock a texture for updating. See also _mesa_lock_context_textures(). - */ -static INLINE void -_mesa_lock_texture(struct gl_context *ctx, struct gl_texture_object *texObj) -{ - _glthread_LOCK_MUTEX(ctx->Shared->TexMutex); - ctx->Shared->TextureStateStamp++; - (void) texObj; -} - -static INLINE void -_mesa_unlock_texture(struct gl_context *ctx, struct gl_texture_object *texObj) -{ - _glthread_UNLOCK_MUTEX(ctx->Shared->TexMutex); -} - -/*@}*/ - - -/** \name API entry point functions */ -/*@{*/ - -extern void GLAPIENTRY -_mesa_TexImage1D( GLenum target, GLint level, GLint internalformat, - GLsizei width, GLint border, - GLenum format, GLenum type, const GLvoid *pixels ); - - -extern void GLAPIENTRY -_mesa_TexImage2D( GLenum target, GLint level, GLint internalformat, - GLsizei width, GLsizei height, GLint border, - GLenum format, GLenum type, const GLvoid *pixels ); - - -extern void GLAPIENTRY -_mesa_TexImage3D( GLenum target, GLint level, GLint internalformat, - GLsizei width, GLsizei height, GLsizei depth, GLint border, - GLenum format, GLenum type, const GLvoid *pixels ); - - -extern void GLAPIENTRY -_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalformat, - GLsizei width, GLsizei height, GLsizei depth, - GLint border, GLenum format, GLenum type, - const GLvoid *pixels ); - -extern void GLAPIENTRY -_mesa_EGLImageTargetTexture2DOES( GLenum target, GLeglImageOES image ); - -extern void GLAPIENTRY -_mesa_TexSubImage1D( GLenum target, GLint level, GLint xoffset, - GLsizei width, - GLenum format, GLenum type, - const GLvoid *pixels ); - - -extern void GLAPIENTRY -_mesa_TexSubImage2D( GLenum target, GLint level, - GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - const GLvoid *pixels ); - - -extern void GLAPIENTRY -_mesa_TexSubImage3D( GLenum target, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, - const GLvoid *pixels ); - - -extern void GLAPIENTRY -_mesa_CopyTexImage1D( GLenum target, GLint level, GLenum internalformat, - GLint x, GLint y, GLsizei width, GLint border ); - - -extern void GLAPIENTRY -_mesa_CopyTexImage2D( GLenum target, GLint level, - GLenum internalformat, GLint x, GLint y, - GLsizei width, GLsizei height, GLint border ); - - -extern void GLAPIENTRY -_mesa_CopyTexSubImage1D( GLenum target, GLint level, GLint xoffset, - GLint x, GLint y, GLsizei width ); - - -extern void GLAPIENTRY -_mesa_CopyTexSubImage2D( GLenum target, GLint level, - GLint xoffset, GLint yoffset, - GLint x, GLint y, GLsizei width, GLsizei height ); - - -extern void GLAPIENTRY -_mesa_CopyTexSubImage3D( GLenum target, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLint x, GLint y, GLsizei width, GLsizei height ); - - - -extern void GLAPIENTRY -_mesa_CompressedTexImage1DARB(GLenum target, GLint level, - GLenum internalformat, GLsizei width, - GLint border, GLsizei imageSize, - const GLvoid *data); - -extern void GLAPIENTRY -_mesa_CompressedTexImage2DARB(GLenum target, GLint level, - GLenum internalformat, GLsizei width, - GLsizei height, GLint border, GLsizei imageSize, - const GLvoid *data); - -extern void GLAPIENTRY -_mesa_CompressedTexImage3DARB(GLenum target, GLint level, - GLenum internalformat, GLsizei width, - GLsizei height, GLsizei depth, GLint border, - GLsizei imageSize, const GLvoid *data); - -#ifdef VMS -#define _mesa_CompressedTexSubImage1DARB _mesa_CompressedTexSubImage1DAR -#define _mesa_CompressedTexSubImage2DARB _mesa_CompressedTexSubImage2DAR -#define _mesa_CompressedTexSubImage3DARB _mesa_CompressedTexSubImage3DAR -#endif -extern void GLAPIENTRY -_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, - GLsizei width, GLenum format, - GLsizei imageSize, const GLvoid *data); - -extern void GLAPIENTRY -_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, - GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLsizei imageSize, - const GLvoid *data); - -extern void GLAPIENTRY -_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, - GLint yoffset, GLint zoffset, GLsizei width, - GLsizei height, GLsizei depth, GLenum format, - GLsizei imageSize, const GLvoid *data); - - -extern void GLAPIENTRY -_mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer); - - -/*@}*/ - -#endif +/** + * \file teximage.h + * Texture images manipulation functions. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef TEXIMAGE_H +#define TEXIMAGE_H + + +#include "mtypes.h" +#include "formats.h" + + +extern void * +_mesa_alloc_texmemory(GLsizei bytes); + +extern void +_mesa_free_texmemory(void *m); + + +/** \name Internal functions */ +/*@{*/ + +extern GLint +_mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ); + + +extern GLboolean +_mesa_is_proxy_texture(GLenum target); + + +extern struct gl_texture_image * +_mesa_new_texture_image( struct gl_context *ctx ); + + +extern void +_mesa_delete_texture_image( struct gl_context *ctx, + struct gl_texture_image *teximage ); + +extern void +_mesa_free_texture_image_data( struct gl_context *ctx, + struct gl_texture_image *texImage ); + + +extern void +_mesa_init_teximage_fields(struct gl_context *ctx, GLenum target, + struct gl_texture_image *img, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, GLenum internalFormat, + gl_format format); + + +extern gl_format +_mesa_choose_texture_format(struct gl_context *ctx, + struct gl_texture_object *texObj, + GLenum target, GLint level, + GLenum internalFormat, GLenum format, GLenum type); + + +extern void +_mesa_clear_texture_image(struct gl_context *ctx, + struct gl_texture_image *texImage); + + +extern void +_mesa_set_tex_image(struct gl_texture_object *tObj, + GLenum target, GLint level, + struct gl_texture_image *texImage); + + +extern struct gl_texture_object * +_mesa_select_tex_object(struct gl_context *ctx, + const struct gl_texture_unit *texUnit, + GLenum target); + +extern struct gl_texture_object * +_mesa_get_current_tex_object(struct gl_context *ctx, GLenum target); + + +extern struct gl_texture_image * +_mesa_select_tex_image(struct gl_context *ctx, + const struct gl_texture_object *texObj, + GLenum target, GLint level); + + +extern struct gl_texture_image * +_mesa_get_tex_image(struct gl_context *ctx, struct gl_texture_object *texObj, + GLenum target, GLint level); + + +extern struct gl_texture_image * +_mesa_get_proxy_tex_image(struct gl_context *ctx, GLenum target, GLint level); + + +extern GLint +_mesa_max_texture_levels(struct gl_context *ctx, GLenum target); + + +extern GLboolean +_mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level, + GLint internalFormat, GLenum format, GLenum type, + GLint width, GLint height, GLint depth, GLint border); + + +extern GLuint +_mesa_tex_target_to_face(GLenum target); + +extern GLint +_mesa_get_texture_dimensions(GLenum target); + +/** + * Lock a texture for updating. See also _mesa_lock_context_textures(). + */ +static INLINE void +_mesa_lock_texture(struct gl_context *ctx, struct gl_texture_object *texObj) +{ + _glthread_LOCK_MUTEX(ctx->Shared->TexMutex); + ctx->Shared->TextureStateStamp++; + (void) texObj; +} + +static INLINE void +_mesa_unlock_texture(struct gl_context *ctx, struct gl_texture_object *texObj) +{ + (void) texObj; + _glthread_UNLOCK_MUTEX(ctx->Shared->TexMutex); +} + +/*@}*/ + + +/** \name API entry point functions */ +/*@{*/ + +extern void GLAPIENTRY +_mesa_TexImage1D( GLenum target, GLint level, GLint internalformat, + GLsizei width, GLint border, + GLenum format, GLenum type, const GLvoid *pixels ); + + +extern void GLAPIENTRY +_mesa_TexImage2D( GLenum target, GLint level, GLint internalformat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, const GLvoid *pixels ); + + +extern void GLAPIENTRY +_mesa_TexImage3D( GLenum target, GLint level, GLint internalformat, + GLsizei width, GLsizei height, GLsizei depth, GLint border, + GLenum format, GLenum type, const GLvoid *pixels ); + + +extern void GLAPIENTRY +_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, GLenum format, GLenum type, + const GLvoid *pixels ); + +extern void GLAPIENTRY +_mesa_EGLImageTargetTexture2DOES( GLenum target, GLeglImageOES image ); + +extern void GLAPIENTRY +_mesa_TexSubImage1D( GLenum target, GLint level, GLint xoffset, + GLsizei width, + GLenum format, GLenum type, + const GLvoid *pixels ); + + +extern void GLAPIENTRY +_mesa_TexSubImage2D( GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels ); + + +extern void GLAPIENTRY +_mesa_TexSubImage3D( GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + const GLvoid *pixels ); + + +extern void GLAPIENTRY +_mesa_CopyTexImage1D( GLenum target, GLint level, GLenum internalformat, + GLint x, GLint y, GLsizei width, GLint border ); + + +extern void GLAPIENTRY +_mesa_CopyTexImage2D( GLenum target, GLint level, + GLenum internalformat, GLint x, GLint y, + GLsizei width, GLsizei height, GLint border ); + + +extern void GLAPIENTRY +_mesa_CopyTexSubImage1D( GLenum target, GLint level, GLint xoffset, + GLint x, GLint y, GLsizei width ); + + +extern void GLAPIENTRY +_mesa_CopyTexSubImage2D( GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint x, GLint y, GLsizei width, GLsizei height ); + + +extern void GLAPIENTRY +_mesa_CopyTexSubImage3D( GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, GLsizei width, GLsizei height ); + + + +extern void GLAPIENTRY +_mesa_CompressedTexImage1DARB(GLenum target, GLint level, + GLenum internalformat, GLsizei width, + GLint border, GLsizei imageSize, + const GLvoid *data); + +extern void GLAPIENTRY +_mesa_CompressedTexImage2DARB(GLenum target, GLint level, + GLenum internalformat, GLsizei width, + GLsizei height, GLint border, GLsizei imageSize, + const GLvoid *data); + +extern void GLAPIENTRY +_mesa_CompressedTexImage3DARB(GLenum target, GLint level, + GLenum internalformat, GLsizei width, + GLsizei height, GLsizei depth, GLint border, + GLsizei imageSize, const GLvoid *data); + +#ifdef VMS +#define _mesa_CompressedTexSubImage1DARB _mesa_CompressedTexSubImage1DAR +#define _mesa_CompressedTexSubImage2DARB _mesa_CompressedTexSubImage2DAR +#define _mesa_CompressedTexSubImage3DARB _mesa_CompressedTexSubImage3DAR +#endif +extern void GLAPIENTRY +_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, + GLsizei width, GLenum format, + GLsizei imageSize, const GLvoid *data); + +extern void GLAPIENTRY +_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLsizei imageSize, + const GLvoid *data); + +extern void GLAPIENTRY +_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, GLenum format, + GLsizei imageSize, const GLvoid *data); + + +extern void GLAPIENTRY +_mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer); + + +/*@}*/ + +#endif diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp index 9813c4ae8..69a84de39 100644 --- a/mesalib/src/mesa/program/ir_to_mesa.cpp +++ b/mesalib/src/mesa/program/ir_to_mesa.cpp @@ -2156,6 +2156,8 @@ ir_to_mesa_visitor::visit(ir_texture *ir) break; } + const glsl_type *sampler_type = ir->sampler->type; + if (ir->projector) { if (opcode == OPCODE_TEX) { /* Slot the projector in as the last component of the coord. */ @@ -2187,6 +2189,9 @@ ir_to_mesa_visitor::visit(ir_texture *ir) tmp_src = get_temp(glsl_type::vec4_type); dst_reg tmp_dst = dst_reg(tmp_src); + /* Projective division not allowed for array samplers. */ + assert(!sampler_type->sampler_array); + tmp_dst.writemask = WRITEMASK_Z; emit(ir, OPCODE_MOV, tmp_dst, this->result); @@ -2211,7 +2216,15 @@ ir_to_mesa_visitor::visit(ir_texture *ir) * coord. */ ir->shadow_comparitor->accept(this); - coord_dst.writemask = WRITEMASK_Z; + + /* XXX This will need to be updated for cubemap array samplers. */ + if (sampler_type->sampler_dimensionality == GLSL_SAMPLER_DIM_2D && + sampler_type->sampler_array) { + coord_dst.writemask = WRITEMASK_W; + } else { + coord_dst.writemask = WRITEMASK_Z; + } + emit(ir, OPCODE_MOV, coord_dst, this->result); coord_dst.writemask = WRITEMASK_XYZW; } @@ -2235,8 +2248,6 @@ ir_to_mesa_visitor::visit(ir_texture *ir) this->shader_program, this->prog); - const glsl_type *sampler_type = ir->sampler->type; - switch (sampler_type->sampler_dimensionality) { case GLSL_SAMPLER_DIM_1D: inst->tex_target = (sampler_type->sampler_array) diff --git a/mesalib/src/mesa/program/nvvertparse.c b/mesalib/src/mesa/program/nvvertparse.c index 8f7199a99..91fe2c48b 100644 --- a/mesalib/src/mesa/program/nvvertparse.c +++ b/mesalib/src/mesa/program/nvvertparse.c @@ -1,1459 +1,1459 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5.2 - * - * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/** - * \file nvvertparse.c - * NVIDIA vertex program parser. - * \author Brian Paul - */ - -/* - * Regarding GL_NV_vertex_program, GL_NV_vertex_program1_1: - * - * Portions of this software may use or implement intellectual - * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims - * any and all warranties with respect to such intellectual property, - * including any use thereof or modifications thereto. - */ - -#include "main/glheader.h" -#include "main/context.h" -#include "main/imports.h" -#include "main/nvprogram.h" -#include "nvvertparse.h" -#include "prog_instruction.h" -#include "prog_parameter.h" -#include "prog_print.h" -#include "program.h" - - -/** - * Current parsing state. This structure is passed among the parsing - * functions and keeps track of the current parser position and various - * program attributes. - */ -struct parse_state { - struct gl_context *ctx; - const GLubyte *start; - const GLubyte *pos; - const GLubyte *curLine; - GLboolean isStateProgram; - GLboolean isPositionInvariant; - GLboolean isVersion1_1; - GLbitfield inputsRead; - GLbitfield outputsWritten; - GLboolean anyProgRegsWritten; - GLboolean indirectRegisterFiles; - GLuint numInst; /* number of instructions parsed */ -}; - - -/* - * Called whenever we find an error during parsing. - */ -static void -record_error(struct parse_state *parseState, const char *msg, int lineNo) -{ -#ifdef DEBUG - GLint line, column; - const GLubyte *lineStr; - lineStr = _mesa_find_line_column(parseState->start, - parseState->pos, &line, &column); - _mesa_debug(parseState->ctx, - "nvfragparse.c(%d): line %d, column %d:%s (%s)\n", - lineNo, line, column, (char *) lineStr, msg); - free((void *) lineStr); -#else - (void) lineNo; -#endif - - /* Check that no error was already recorded. Only record the first one. */ - if (parseState->ctx->Program.ErrorString[0] == 0) { - _mesa_set_program_error(parseState->ctx, - parseState->pos - parseState->start, - msg); - } -} - - -#define RETURN_ERROR \ -do { \ - record_error(parseState, "Unexpected end of input.", __LINE__); \ - return GL_FALSE; \ -} while(0) - -#define RETURN_ERROR1(msg) \ -do { \ - record_error(parseState, msg, __LINE__); \ - return GL_FALSE; \ -} while(0) - -#define RETURN_ERROR2(msg1, msg2) \ -do { \ - char err[1000]; \ - sprintf(err, "%s %s", msg1, msg2); \ - record_error(parseState, err, __LINE__); \ - return GL_FALSE; \ -} while(0) - - - - - -static GLboolean IsLetter(GLubyte b) -{ - return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z'); -} - - -static GLboolean IsDigit(GLubyte b) -{ - return b >= '0' && b <= '9'; -} - - -static GLboolean IsWhitespace(GLubyte b) -{ - return b == ' ' || b == '\t' || b == '\n' || b == '\r'; -} - - -/** - * Starting at 'str' find the next token. A token can be an integer, - * an identifier or punctuation symbol. - * \return <= 0 we found an error, else, return number of characters parsed. - */ -static GLint -GetToken(struct parse_state *parseState, GLubyte *token) -{ - const GLubyte *str = parseState->pos; - GLint i = 0, j = 0; - - token[0] = 0; - - /* skip whitespace and comments */ - while (str[i] && (IsWhitespace(str[i]) || str[i] == '#')) { - if (str[i] == '#') { - /* skip comment */ - while (str[i] && (str[i] != '\n' && str[i] != '\r')) { - i++; - } - if (str[i] == '\n' || str[i] == '\r') - parseState->curLine = str + i + 1; - } - else { - /* skip whitespace */ - if (str[i] == '\n' || str[i] == '\r') - parseState->curLine = str + i + 1; - i++; - } - } - - if (str[i] == 0) - return -i; - - /* try matching an integer */ - while (str[i] && IsDigit(str[i])) { - token[j++] = str[i++]; - } - if (j > 0 || !str[i]) { - token[j] = 0; - return i; - } - - /* try matching an identifier */ - if (IsLetter(str[i])) { - while (str[i] && (IsLetter(str[i]) || IsDigit(str[i]))) { - token[j++] = str[i++]; - } - token[j] = 0; - return i; - } - - /* punctuation character */ - if (str[i]) { - token[0] = str[i++]; - token[1] = 0; - return i; - } - - /* end of input */ - token[0] = 0; - return i; -} - - -/** - * Get next token from input stream and increment stream pointer past token. - */ -static GLboolean -Parse_Token(struct parse_state *parseState, GLubyte *token) -{ - GLint i; - i = GetToken(parseState, token); - if (i <= 0) { - parseState->pos += (-i); - return GL_FALSE; - } - parseState->pos += i; - return GL_TRUE; -} - - -/** - * Get next token from input stream but don't increment stream pointer. - */ -static GLboolean -Peek_Token(struct parse_state *parseState, GLubyte *token) -{ - GLint i, len; - i = GetToken(parseState, token); - if (i <= 0) { - parseState->pos += (-i); - return GL_FALSE; - } - len = (GLint) strlen((const char *) token); - parseState->pos += (i - len); - return GL_TRUE; -} - - -/** - * Try to match 'pattern' as the next token after any whitespace/comments. - * Advance the current parsing position only if we match the pattern. - * \return GL_TRUE if pattern is matched, GL_FALSE otherwise. - */ -static GLboolean -Parse_String(struct parse_state *parseState, const char *pattern) -{ - const GLubyte *m; - GLint i; - - /* skip whitespace and comments */ - while (IsWhitespace(*parseState->pos) || *parseState->pos == '#') { - if (*parseState->pos == '#') { - while (*parseState->pos && (*parseState->pos != '\n' && *parseState->pos != '\r')) { - parseState->pos += 1; - } - if (*parseState->pos == '\n' || *parseState->pos == '\r') - parseState->curLine = parseState->pos + 1; - } - else { - /* skip whitespace */ - if (*parseState->pos == '\n' || *parseState->pos == '\r') - parseState->curLine = parseState->pos + 1; - parseState->pos += 1; - } - } - - /* Try to match the pattern */ - m = parseState->pos; - for (i = 0; pattern[i]; i++) { - if (*m != (GLubyte) pattern[i]) - return GL_FALSE; - m += 1; - } - parseState->pos = m; - - return GL_TRUE; /* success */ -} - - -/**********************************************************************/ - -static const char *InputRegisters[MAX_NV_VERTEX_PROGRAM_INPUTS + 1] = { - "OPOS", "WGHT", "NRML", "COL0", "COL1", "FOGC", "6", "7", - "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL -}; - -static const char *OutputRegisters[MAX_NV_VERTEX_PROGRAM_OUTPUTS + 1] = { - "HPOS", "COL0", "COL1", "FOGC", - "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", - "PSIZ", "BFC0", "BFC1", NULL -}; - - - -/** - * Parse a temporary register: Rnn - */ -static GLboolean -Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum) -{ - GLubyte token[100]; - - /* Should be 'R##' */ - if (!Parse_Token(parseState, token)) - RETURN_ERROR; - if (token[0] != 'R') - RETURN_ERROR1("Expected R##"); - - if (IsDigit(token[1])) { - GLint reg = atoi((char *) (token + 1)); - if (reg >= MAX_NV_VERTEX_PROGRAM_TEMPS) - RETURN_ERROR1("Bad temporary register name"); - *tempRegNum = reg; - } - else { - RETURN_ERROR1("Bad temporary register name"); - } - - return GL_TRUE; -} - - -/** - * Parse address register "A0.x" - */ -static GLboolean -Parse_AddrReg(struct parse_state *parseState) -{ - /* match 'A0' */ - if (!Parse_String(parseState, "A0")) - RETURN_ERROR; - - /* match '.' */ - if (!Parse_String(parseState, ".")) - RETURN_ERROR; - - /* match 'x' */ - if (!Parse_String(parseState, "x")) - RETURN_ERROR; - - return GL_TRUE; -} - - -/** - * Parse absolute program parameter register "c[##]" - */ -static GLboolean -Parse_AbsParamReg(struct parse_state *parseState, GLint *regNum) -{ - GLubyte token[100]; - - if (!Parse_String(parseState, "c")) - RETURN_ERROR; - - if (!Parse_String(parseState, "[")) - RETURN_ERROR; - - if (!Parse_Token(parseState, token)) - RETURN_ERROR; - - if (IsDigit(token[0])) { - /* a numbered program parameter register */ - GLint reg = atoi((char *) token); - if (reg >= MAX_NV_VERTEX_PROGRAM_PARAMS) - RETURN_ERROR1("Bad program parameter number"); - *regNum = reg; - } - else { - RETURN_ERROR; - } - - if (!Parse_String(parseState, "]")) - RETURN_ERROR; - - return GL_TRUE; -} - - -static GLboolean -Parse_ParamReg(struct parse_state *parseState, struct prog_src_register *srcReg) -{ - GLubyte token[100]; - - if (!Parse_String(parseState, "c")) - RETURN_ERROR; - - if (!Parse_String(parseState, "[")) - RETURN_ERROR; - - if (!Peek_Token(parseState, token)) - RETURN_ERROR; - - if (IsDigit(token[0])) { - /* a numbered program parameter register */ - GLint reg; - (void) Parse_Token(parseState, token); - reg = atoi((char *) token); - if (reg >= MAX_NV_VERTEX_PROGRAM_PARAMS) - RETURN_ERROR1("Bad program parameter number"); - srcReg->File = PROGRAM_ENV_PARAM; - srcReg->Index = reg; - } - else if (strcmp((const char *) token, "A0") == 0) { - /* address register "A0.x" */ - if (!Parse_AddrReg(parseState)) - RETURN_ERROR; - - srcReg->RelAddr = GL_TRUE; - srcReg->File = PROGRAM_ENV_PARAM; - parseState->indirectRegisterFiles |= (1 << srcReg->File); - /* Look for +/-N offset */ - if (!Peek_Token(parseState, token)) - RETURN_ERROR; - - if (token[0] == '-' || token[0] == '+') { - const GLubyte sign = token[0]; - (void) Parse_Token(parseState, token); /* consume +/- */ - - /* an integer should be next */ - if (!Parse_Token(parseState, token)) - RETURN_ERROR; - - if (IsDigit(token[0])) { - const GLint k = atoi((char *) token); - if (sign == '-') { - if (k > 64) - RETURN_ERROR1("Bad address offset"); - srcReg->Index = -k; - } - else { - if (k > 63) - RETURN_ERROR1("Bad address offset"); - srcReg->Index = k; - } - } - else { - RETURN_ERROR; - } - } - else { - /* probably got a ']', catch it below */ - } - } - else { - RETURN_ERROR; - } - - /* Match closing ']' */ - if (!Parse_String(parseState, "]")) - RETURN_ERROR; - - return GL_TRUE; -} - - -/** - * Parse v[#] or v[] - */ -static GLboolean -Parse_AttribReg(struct parse_state *parseState, GLint *tempRegNum) -{ - GLubyte token[100]; - GLint j; - - /* Match 'v' */ - if (!Parse_String(parseState, "v")) - RETURN_ERROR; - - /* Match '[' */ - if (!Parse_String(parseState, "[")) - RETURN_ERROR; - - /* match number or named register */ - if (!Parse_Token(parseState, token)) - RETURN_ERROR; - - if (parseState->isStateProgram && token[0] != '0') - RETURN_ERROR1("Only v[0] accessible in vertex state programs"); - - if (IsDigit(token[0])) { - GLint reg = atoi((char *) token); - if (reg >= MAX_NV_VERTEX_PROGRAM_INPUTS) - RETURN_ERROR1("Bad vertex attribute register name"); - *tempRegNum = reg; - } - else { - for (j = 0; InputRegisters[j]; j++) { - if (strcmp((const char *) token, InputRegisters[j]) == 0) { - *tempRegNum = j; - break; - } - } - if (!InputRegisters[j]) { - /* unknown input register label */ - RETURN_ERROR2("Bad register name", token); - } - } - - /* Match '[' */ - if (!Parse_String(parseState, "]")) - RETURN_ERROR; - - return GL_TRUE; -} - - -static GLboolean -Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum) -{ - GLubyte token[100]; - GLint start, j; - - /* Match 'o' */ - if (!Parse_String(parseState, "o")) - RETURN_ERROR; - - /* Match '[' */ - if (!Parse_String(parseState, "[")) - RETURN_ERROR; - - /* Get output reg name */ - if (!Parse_Token(parseState, token)) - RETURN_ERROR; - - if (parseState->isPositionInvariant) - start = 1; /* skip HPOS register name */ - else - start = 0; - - /* try to match an output register name */ - for (j = start; OutputRegisters[j]; j++) { - if (strcmp((const char *) token, OutputRegisters[j]) == 0) { - *outputRegNum = j; - break; - } - } - if (!OutputRegisters[j]) - RETURN_ERROR1("Unrecognized output register name"); - - /* Match ']' */ - if (!Parse_String(parseState, "]")) - RETURN_ERROR1("Expected ]"); - - return GL_TRUE; -} - - -static GLboolean -Parse_MaskedDstReg(struct parse_state *parseState, struct prog_dst_register *dstReg) -{ - GLubyte token[100]; - GLint idx; - - /* Dst reg can be R or o[n] */ - if (!Peek_Token(parseState, token)) - RETURN_ERROR; - - if (token[0] == 'R') { - /* a temporary register */ - dstReg->File = PROGRAM_TEMPORARY; - if (!Parse_TempReg(parseState, &idx)) - RETURN_ERROR; - dstReg->Index = idx; - } - else if (!parseState->isStateProgram && token[0] == 'o') { - /* an output register */ - dstReg->File = PROGRAM_OUTPUT; - if (!Parse_OutputReg(parseState, &idx)) - RETURN_ERROR; - dstReg->Index = idx; - } - else if (parseState->isStateProgram && token[0] == 'c' && - parseState->isStateProgram) { - /* absolute program parameter register */ - /* Only valid for vertex state programs */ - dstReg->File = PROGRAM_ENV_PARAM; - if (!Parse_AbsParamReg(parseState, &idx)) - RETURN_ERROR; - dstReg->Index = idx; - } - else { - RETURN_ERROR1("Bad destination register name"); - } - - /* Parse optional write mask */ - if (!Peek_Token(parseState, token)) - RETURN_ERROR; - - if (token[0] == '.') { - /* got a mask */ - GLint k = 0; - - if (!Parse_String(parseState, ".")) - RETURN_ERROR; - - if (!Parse_Token(parseState, token)) - RETURN_ERROR; - - dstReg->WriteMask = 0; - - if (token[k] == 'x') { - dstReg->WriteMask |= WRITEMASK_X; - k++; - } - if (token[k] == 'y') { - dstReg->WriteMask |= WRITEMASK_Y; - k++; - } - if (token[k] == 'z') { - dstReg->WriteMask |= WRITEMASK_Z; - k++; - } - if (token[k] == 'w') { - dstReg->WriteMask |= WRITEMASK_W; - k++; - } - if (k == 0) { - RETURN_ERROR1("Bad writemask character"); - } - return GL_TRUE; - } - else { - dstReg->WriteMask = WRITEMASK_XYZW; - return GL_TRUE; - } -} - - -static GLboolean -Parse_SwizzleSrcReg(struct parse_state *parseState, struct prog_src_register *srcReg) -{ - GLubyte token[100]; - GLint idx; - - srcReg->RelAddr = GL_FALSE; - - /* check for '-' */ - if (!Peek_Token(parseState, token)) - RETURN_ERROR; - if (token[0] == '-') { - (void) Parse_String(parseState, "-"); - srcReg->Negate = NEGATE_XYZW; - if (!Peek_Token(parseState, token)) - RETURN_ERROR; - } - else { - srcReg->Negate = NEGATE_NONE; - } - - /* Src reg can be R, c[n], c[n +/- offset], or a named vertex attrib */ - if (token[0] == 'R') { - srcReg->File = PROGRAM_TEMPORARY; - if (!Parse_TempReg(parseState, &idx)) - RETURN_ERROR; - srcReg->Index = idx; - } - else if (token[0] == 'c') { - if (!Parse_ParamReg(parseState, srcReg)) - RETURN_ERROR; - } - else if (token[0] == 'v') { - srcReg->File = PROGRAM_INPUT; - if (!Parse_AttribReg(parseState, &idx)) - RETURN_ERROR; - srcReg->Index = idx; - } - else { - RETURN_ERROR2("Bad source register name", token); - } - - /* init swizzle fields */ - srcReg->Swizzle = SWIZZLE_NOOP; - - /* Look for optional swizzle suffix */ - if (!Peek_Token(parseState, token)) - RETURN_ERROR; - if (token[0] == '.') { - (void) Parse_String(parseState, "."); /* consume . */ - - if (!Parse_Token(parseState, token)) - RETURN_ERROR; - - if (token[1] == 0) { - /* single letter swizzle */ - if (token[0] == 'x') - srcReg->Swizzle = SWIZZLE_XXXX; - else if (token[0] == 'y') - srcReg->Swizzle = SWIZZLE_YYYY; - else if (token[0] == 'z') - srcReg->Swizzle = SWIZZLE_ZZZZ; - else if (token[0] == 'w') - srcReg->Swizzle = SWIZZLE_WWWW; - else - RETURN_ERROR1("Expected x, y, z, or w"); - } - else { - /* 2, 3 or 4-component swizzle */ - GLint k; - - srcReg->Swizzle = 0; - - for (k = 0; token[k] && k < 5; k++) { - if (token[k] == 'x') - srcReg->Swizzle |= 0 << (k*3); - else if (token[k] == 'y') - srcReg->Swizzle |= 1 << (k*3); - else if (token[k] == 'z') - srcReg->Swizzle |= 2 << (k*3); - else if (token[k] == 'w') - srcReg->Swizzle |= 3 << (k*3); - else - RETURN_ERROR; - } - if (k >= 5) - RETURN_ERROR; - } - } - - return GL_TRUE; -} - - -static GLboolean -Parse_ScalarSrcReg(struct parse_state *parseState, struct prog_src_register *srcReg) -{ - GLubyte token[100]; - GLint idx; - - srcReg->RelAddr = GL_FALSE; - - /* check for '-' */ - if (!Peek_Token(parseState, token)) - RETURN_ERROR; - if (token[0] == '-') { - srcReg->Negate = NEGATE_XYZW; - (void) Parse_String(parseState, "-"); /* consume '-' */ - if (!Peek_Token(parseState, token)) - RETURN_ERROR; - } - else { - srcReg->Negate = NEGATE_NONE; - } - - /* Src reg can be R, c[n], c[n +/- offset], or a named vertex attrib */ - if (token[0] == 'R') { - srcReg->File = PROGRAM_TEMPORARY; - if (!Parse_TempReg(parseState, &idx)) - RETURN_ERROR; - srcReg->Index = idx; - } - else if (token[0] == 'c') { - if (!Parse_ParamReg(parseState, srcReg)) - RETURN_ERROR; - } - else if (token[0] == 'v') { - srcReg->File = PROGRAM_INPUT; - if (!Parse_AttribReg(parseState, &idx)) - RETURN_ERROR; - srcReg->Index = idx; - } - else { - RETURN_ERROR2("Bad source register name", token); - } - - /* Look for .[xyzw] suffix */ - if (!Parse_String(parseState, ".")) - RETURN_ERROR; - - if (!Parse_Token(parseState, token)) - RETURN_ERROR; - - if (token[0] == 'x' && token[1] == 0) { - srcReg->Swizzle = 0; - } - else if (token[0] == 'y' && token[1] == 0) { - srcReg->Swizzle = 1; - } - else if (token[0] == 'z' && token[1] == 0) { - srcReg->Swizzle = 2; - } - else if (token[0] == 'w' && token[1] == 0) { - srcReg->Swizzle = 3; - } - else { - RETURN_ERROR1("Bad scalar source suffix"); - } - - return GL_TRUE; -} - - -static GLint -Parse_UnaryOpInstruction(struct parse_state *parseState, - struct prog_instruction *inst, - enum prog_opcode opcode) -{ - if (opcode == OPCODE_ABS && !parseState->isVersion1_1) - RETURN_ERROR1("ABS illegal for vertex program 1.0"); - - inst->Opcode = opcode; - - /* dest reg */ - if (!Parse_MaskedDstReg(parseState, &inst->DstReg)) - RETURN_ERROR; - - /* comma */ - if (!Parse_String(parseState, ",")) - RETURN_ERROR; - - /* src arg */ - if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0])) - RETURN_ERROR; - - /* semicolon */ - if (!Parse_String(parseState, ";")) - RETURN_ERROR; - - return GL_TRUE; -} - - -static GLboolean -Parse_BiOpInstruction(struct parse_state *parseState, - struct prog_instruction *inst, - enum prog_opcode opcode) -{ - if (opcode == OPCODE_DPH && !parseState->isVersion1_1) - RETURN_ERROR1("DPH illegal for vertex program 1.0"); - if (opcode == OPCODE_SUB && !parseState->isVersion1_1) - RETURN_ERROR1("SUB illegal for vertex program 1.0"); - - inst->Opcode = opcode; - - /* dest reg */ - if (!Parse_MaskedDstReg(parseState, &inst->DstReg)) - RETURN_ERROR; - - /* comma */ - if (!Parse_String(parseState, ",")) - RETURN_ERROR; - - /* first src arg */ - if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0])) - RETURN_ERROR; - - /* comma */ - if (!Parse_String(parseState, ",")) - RETURN_ERROR; - - /* second src arg */ - if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[1])) - RETURN_ERROR; - - /* semicolon */ - if (!Parse_String(parseState, ";")) - RETURN_ERROR; - - /* make sure we don't reference more than one program parameter register */ - if (inst->SrcReg[0].File == PROGRAM_ENV_PARAM && - inst->SrcReg[1].File == PROGRAM_ENV_PARAM && - inst->SrcReg[0].Index != inst->SrcReg[1].Index) - RETURN_ERROR1("Can't reference two program parameter registers"); - - /* make sure we don't reference more than one vertex attribute register */ - if (inst->SrcReg[0].File == PROGRAM_INPUT && - inst->SrcReg[1].File == PROGRAM_INPUT && - inst->SrcReg[0].Index != inst->SrcReg[1].Index) - RETURN_ERROR1("Can't reference two vertex attribute registers"); - - return GL_TRUE; -} - - -static GLboolean -Parse_TriOpInstruction(struct parse_state *parseState, - struct prog_instruction *inst, - enum prog_opcode opcode) -{ - inst->Opcode = opcode; - - /* dest reg */ - if (!Parse_MaskedDstReg(parseState, &inst->DstReg)) - RETURN_ERROR; - - /* comma */ - if (!Parse_String(parseState, ",")) - RETURN_ERROR; - - /* first src arg */ - if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0])) - RETURN_ERROR; - - /* comma */ - if (!Parse_String(parseState, ",")) - RETURN_ERROR; - - /* second src arg */ - if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[1])) - RETURN_ERROR; - - /* comma */ - if (!Parse_String(parseState, ",")) - RETURN_ERROR; - - /* third src arg */ - if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[2])) - RETURN_ERROR; - - /* semicolon */ - if (!Parse_String(parseState, ";")) - RETURN_ERROR; - - /* make sure we don't reference more than one program parameter register */ - if ((inst->SrcReg[0].File == PROGRAM_ENV_PARAM && - inst->SrcReg[1].File == PROGRAM_ENV_PARAM && - inst->SrcReg[0].Index != inst->SrcReg[1].Index) || - (inst->SrcReg[0].File == PROGRAM_ENV_PARAM && - inst->SrcReg[2].File == PROGRAM_ENV_PARAM && - inst->SrcReg[0].Index != inst->SrcReg[2].Index) || - (inst->SrcReg[1].File == PROGRAM_ENV_PARAM && - inst->SrcReg[2].File == PROGRAM_ENV_PARAM && - inst->SrcReg[1].Index != inst->SrcReg[2].Index)) - RETURN_ERROR1("Can only reference one program register"); - - /* make sure we don't reference more than one vertex attribute register */ - if ((inst->SrcReg[0].File == PROGRAM_INPUT && - inst->SrcReg[1].File == PROGRAM_INPUT && - inst->SrcReg[0].Index != inst->SrcReg[1].Index) || - (inst->SrcReg[0].File == PROGRAM_INPUT && - inst->SrcReg[2].File == PROGRAM_INPUT && - inst->SrcReg[0].Index != inst->SrcReg[2].Index) || - (inst->SrcReg[1].File == PROGRAM_INPUT && - inst->SrcReg[2].File == PROGRAM_INPUT && - inst->SrcReg[1].Index != inst->SrcReg[2].Index)) - RETURN_ERROR1("Can only reference one input register"); - - return GL_TRUE; -} - - -static GLboolean -Parse_ScalarInstruction(struct parse_state *parseState, - struct prog_instruction *inst, - enum prog_opcode opcode) -{ - if (opcode == OPCODE_RCC && !parseState->isVersion1_1) - RETURN_ERROR1("RCC illegal for vertex program 1.0"); - - inst->Opcode = opcode; - - /* dest reg */ - if (!Parse_MaskedDstReg(parseState, &inst->DstReg)) - RETURN_ERROR; - - /* comma */ - if (!Parse_String(parseState, ",")) - RETURN_ERROR; - - /* first src arg */ - if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0])) - RETURN_ERROR; - - /* semicolon */ - if (!Parse_String(parseState, ";")) - RETURN_ERROR; - - return GL_TRUE; -} - - -static GLboolean -Parse_AddressInstruction(struct parse_state *parseState, struct prog_instruction *inst) -{ - inst->Opcode = OPCODE_ARL; - - /* Make ARB_vp backends happy */ - inst->DstReg.File = PROGRAM_ADDRESS; - inst->DstReg.WriteMask = WRITEMASK_X; - inst->DstReg.Index = 0; - - /* dest A0 reg */ - if (!Parse_AddrReg(parseState)) - RETURN_ERROR; - - /* comma */ - if (!Parse_String(parseState, ",")) - RETURN_ERROR; - - /* parse src reg */ - if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0])) - RETURN_ERROR; - - /* semicolon */ - if (!Parse_String(parseState, ";")) - RETURN_ERROR; - - return GL_TRUE; -} - - -static GLboolean -Parse_EndInstruction(struct parse_state *parseState, struct prog_instruction *inst) -{ - GLubyte token[100]; - - inst->Opcode = OPCODE_END; - - /* this should fail! */ - if (Parse_Token(parseState, token)) - RETURN_ERROR2("Unexpected token after END:", token); - else - return GL_TRUE; -} - - -/** - * The PRINT instruction is Mesa-specific and is meant as a debugging aid for - * the vertex program developer. - * The NV_vertex_program extension grammar is modified as follows: - * - * ::= - * | ... - * | - * - * ::= "PRINT" - * | "PRINT" "," - * | "PRINT" "," - */ -static GLboolean -Parse_PrintInstruction(struct parse_state *parseState, struct prog_instruction *inst) -{ - const GLubyte *str; - GLubyte *msg; - GLuint len; - GLubyte token[100]; - struct prog_src_register *srcReg = &inst->SrcReg[0]; - GLint idx; - - inst->Opcode = OPCODE_PRINT; - - /* The first argument is a literal string 'just like this' */ - if (!Parse_String(parseState, "'")) - RETURN_ERROR; - - str = parseState->pos; - for (len = 0; str[len] != '\''; len++) /* find closing quote */ - ; - parseState->pos += len + 1; - msg = (GLubyte*) malloc(len + 1); - - memcpy(msg, str, len); - msg[len] = 0; - inst->Data = msg; - - /* comma */ - if (Parse_String(parseState, ",")) { - - /* The second argument is a register name */ - if (!Peek_Token(parseState, token)) - RETURN_ERROR; - - srcReg->RelAddr = GL_FALSE; - srcReg->Negate = NEGATE_NONE; - srcReg->Swizzle = SWIZZLE_NOOP; - - /* Register can be R, c[n], c[n +/- offset], a named vertex attrib, - * or an o[n] output register. - */ - if (token[0] == 'R') { - srcReg->File = PROGRAM_TEMPORARY; - if (!Parse_TempReg(parseState, &idx)) - RETURN_ERROR; - srcReg->Index = idx; - } - else if (token[0] == 'c') { - srcReg->File = PROGRAM_ENV_PARAM; - if (!Parse_ParamReg(parseState, srcReg)) - RETURN_ERROR; - } - else if (token[0] == 'v') { - srcReg->File = PROGRAM_INPUT; - if (!Parse_AttribReg(parseState, &idx)) - RETURN_ERROR; - srcReg->Index = idx; - } - else if (token[0] == 'o') { - srcReg->File = PROGRAM_OUTPUT; - if (!Parse_OutputReg(parseState, &idx)) - RETURN_ERROR; - srcReg->Index = idx; - } - else { - RETURN_ERROR2("Bad source register name", token); - } - } - else { - srcReg->File = PROGRAM_UNDEFINED; - } - - /* semicolon */ - if (!Parse_String(parseState, ";")) - RETURN_ERROR; - - return GL_TRUE; -} - - -static GLboolean -Parse_OptionSequence(struct parse_state *parseState, - struct prog_instruction program[]) -{ - (void) program; - while (1) { - if (!Parse_String(parseState, "OPTION")) - return GL_TRUE; /* ok, not an OPTION statement */ - if (Parse_String(parseState, "NV_position_invariant")) { - parseState->isPositionInvariant = GL_TRUE; - } - else { - RETURN_ERROR1("unexpected OPTION statement"); - } - if (!Parse_String(parseState, ";")) - return GL_FALSE; - } -} - - -static GLboolean -Parse_InstructionSequence(struct parse_state *parseState, - struct prog_instruction program[]) -{ - while (1) { - struct prog_instruction *inst = program + parseState->numInst; - - /* Initialize the instruction */ - _mesa_init_instructions(inst, 1); - - if (Parse_String(parseState, "MOV")) { - if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_MOV)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "LIT")) { - if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_LIT)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "ABS")) { - if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_ABS)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "MUL")) { - if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MUL)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "ADD")) { - if (!Parse_BiOpInstruction(parseState, inst, OPCODE_ADD)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "DP3")) { - if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DP3)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "DP4")) { - if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DP4)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "DST")) { - if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DST)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "MIN")) { - if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MIN)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "MAX")) { - if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MAX)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "SLT")) { - if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SLT)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "SGE")) { - if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SGE)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "DPH")) { - if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DPH)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "SUB")) { - if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SUB)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "MAD")) { - if (!Parse_TriOpInstruction(parseState, inst, OPCODE_MAD)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "RCP")) { - if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RCP)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "RSQ")) { - if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RSQ)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "EXP")) { - if (!Parse_ScalarInstruction(parseState, inst, OPCODE_EXP)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "LOG")) { - if (!Parse_ScalarInstruction(parseState, inst, OPCODE_LOG)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "RCC")) { - if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RCC)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "ARL")) { - if (!Parse_AddressInstruction(parseState, inst)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "PRINT")) { - if (!Parse_PrintInstruction(parseState, inst)) - RETURN_ERROR; - } - else if (Parse_String(parseState, "END")) { - if (!Parse_EndInstruction(parseState, inst)) - RETURN_ERROR; - else { - parseState->numInst++; - return GL_TRUE; /* all done */ - } - } - else { - /* bad instruction name */ - RETURN_ERROR1("Unexpected token"); - } - - /* examine input/output registers */ - if (inst->DstReg.File == PROGRAM_OUTPUT) - parseState->outputsWritten |= (1 << inst->DstReg.Index); - else if (inst->DstReg.File == PROGRAM_ENV_PARAM) - parseState->anyProgRegsWritten = GL_TRUE; - - if (inst->SrcReg[0].File == PROGRAM_INPUT) - parseState->inputsRead |= (1 << inst->SrcReg[0].Index); - if (inst->SrcReg[1].File == PROGRAM_INPUT) - parseState->inputsRead |= (1 << inst->SrcReg[1].Index); - if (inst->SrcReg[2].File == PROGRAM_INPUT) - parseState->inputsRead |= (1 << inst->SrcReg[2].Index); - - parseState->numInst++; - - if (parseState->numInst >= MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS) - RETURN_ERROR1("Program too long"); - } - - RETURN_ERROR; -} - - -static GLboolean -Parse_Program(struct parse_state *parseState, - struct prog_instruction instBuffer[]) -{ - if (parseState->isVersion1_1) { - if (!Parse_OptionSequence(parseState, instBuffer)) { - return GL_FALSE; - } - } - return Parse_InstructionSequence(parseState, instBuffer); -} - - -/** - * Parse/compile the 'str' returning the compiled 'program'. - * ctx->Program.ErrorPos will be -1 if successful. Otherwise, ErrorPos - * indicates the position of the error in 'str'. - */ -void -_mesa_parse_nv_vertex_program(struct gl_context *ctx, GLenum dstTarget, - const GLubyte *str, GLsizei len, - struct gl_vertex_program *program) -{ - struct parse_state parseState; - struct prog_instruction instBuffer[MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS]; - struct prog_instruction *newInst; - GLenum target; - GLubyte *programString; - - /* Make a null-terminated copy of the program string */ - programString = (GLubyte *) MALLOC(len + 1); - if (!programString) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); - return; - } - memcpy(programString, str, len); - programString[len] = 0; - - /* Get ready to parse */ - parseState.ctx = ctx; - parseState.start = programString; - parseState.isPositionInvariant = GL_FALSE; - parseState.isVersion1_1 = GL_FALSE; - parseState.numInst = 0; - parseState.inputsRead = 0; - parseState.outputsWritten = 0; - parseState.anyProgRegsWritten = GL_FALSE; - parseState.indirectRegisterFiles = 0x0; - - /* Reset error state */ - _mesa_set_program_error(ctx, -1, NULL); - - /* check the program header */ - if (strncmp((const char *) programString, "!!VP1.0", 7) == 0) { - target = GL_VERTEX_PROGRAM_NV; - parseState.pos = programString + 7; - parseState.isStateProgram = GL_FALSE; - } - else if (strncmp((const char *) programString, "!!VP1.1", 7) == 0) { - target = GL_VERTEX_PROGRAM_NV; - parseState.pos = programString + 7; - parseState.isStateProgram = GL_FALSE; - parseState.isVersion1_1 = GL_TRUE; - } - else if (strncmp((const char *) programString, "!!VSP1.0", 8) == 0) { - target = GL_VERTEX_STATE_PROGRAM_NV; - parseState.pos = programString + 8; - parseState.isStateProgram = GL_TRUE; - } - else { - /* invalid header */ - ctx->Program.ErrorPos = 0; - _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)"); - return; - } - - /* make sure target and header match */ - if (target != dstTarget) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glLoadProgramNV(target mismatch)"); - return; - } - - - if (Parse_Program(&parseState, instBuffer)) { - gl_state_index state_tokens[STATE_LENGTH] = {0, 0, 0, 0, 0}; - int i; - - /* successful parse! */ - - if (parseState.isStateProgram) { - if (!parseState.anyProgRegsWritten) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glLoadProgramNV(c[#] not written)"); - return; - } - } - else { - if (!parseState.isPositionInvariant && - !(parseState.outputsWritten & (1 << VERT_RESULT_HPOS))) { - /* bit 1 = HPOS register */ - _mesa_error(ctx, GL_INVALID_OPERATION, - "glLoadProgramNV(HPOS not written)"); - return; - } - } - - /* copy the compiled instructions */ - assert(parseState.numInst <= MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS); - newInst = _mesa_alloc_instructions(parseState.numInst); - if (!newInst) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); - free(programString); - return; /* out of memory */ - } - _mesa_copy_instructions(newInst, instBuffer, parseState.numInst); - - /* install the program */ - program->Base.Target = target; - if (program->Base.String) { - free(program->Base.String); - } - program->Base.String = programString; - program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB; - if (program->Base.Instructions) { - free(program->Base.Instructions); - } - program->Base.Instructions = newInst; - program->Base.InputsRead = parseState.inputsRead; - if (parseState.isPositionInvariant) - program->Base.InputsRead |= VERT_BIT_POS; - program->Base.NumInstructions = parseState.numInst; - program->Base.OutputsWritten = parseState.outputsWritten; - program->IsPositionInvariant = parseState.isPositionInvariant; - program->IsNVProgram = GL_TRUE; - -#ifdef DEBUG_foo - printf("--- glLoadProgramNV result ---\n"); - _mesa_fprint_program_opt(stdout, &program->Base, PROG_PRINT_NV, 0); - printf("------------------------------\n"); -#endif - - if (program->Base.Parameters) - _mesa_free_parameter_list(program->Base.Parameters); - - program->Base.Parameters = _mesa_new_parameter_list (); - program->Base.NumParameters = 0; - - program->Base.IndirectRegisterFiles = parseState.indirectRegisterFiles; - - state_tokens[0] = STATE_VERTEX_PROGRAM; - state_tokens[1] = STATE_ENV; - /* Add refs to all of the potential params, in order. If we want to not - * upload everything, _mesa_layout_parameters is the answer. - */ - for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS; i++) { - GLint index; - state_tokens[2] = i; - index = _mesa_add_state_reference(program->Base.Parameters, - state_tokens); - assert(index == i); - } - program->Base.NumParameters = program->Base.Parameters->NumParameters; - - _mesa_setup_nv_temporary_count(ctx, &program->Base); - _mesa_emit_nv_temp_initialization(ctx, &program->Base); - } - else { - /* Error! */ - _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV"); - /* NOTE: _mesa_set_program_error would have been called already */ - /* GL_NV_vertex_program isn't supposed to set the error string - * so we reset it here. - */ - _mesa_set_program_error(ctx, ctx->Program.ErrorPos, NULL); - } -} - - -const char * -_mesa_nv_vertex_input_register_name(GLuint i) -{ - ASSERT(i < MAX_NV_VERTEX_PROGRAM_INPUTS); - return InputRegisters[i]; -} - - -const char * -_mesa_nv_vertex_output_register_name(GLuint i) -{ - ASSERT(i < MAX_NV_VERTEX_PROGRAM_OUTPUTS); - return OutputRegisters[i]; -} - +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file nvvertparse.c + * NVIDIA vertex program parser. + * \author Brian Paul + */ + +/* + * Regarding GL_NV_vertex_program, GL_NV_vertex_program1_1: + * + * Portions of this software may use or implement intellectual + * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims + * any and all warranties with respect to such intellectual property, + * including any use thereof or modifications thereto. + */ + +#include "main/glheader.h" +#include "main/context.h" +#include "main/imports.h" +#include "main/nvprogram.h" +#include "nvvertparse.h" +#include "prog_instruction.h" +#include "prog_parameter.h" +#include "prog_print.h" +#include "program.h" + + +/** + * Current parsing state. This structure is passed among the parsing + * functions and keeps track of the current parser position and various + * program attributes. + */ +struct parse_state { + struct gl_context *ctx; + const GLubyte *start; + const GLubyte *pos; + const GLubyte *curLine; + GLboolean isStateProgram; + GLboolean isPositionInvariant; + GLboolean isVersion1_1; + GLbitfield inputsRead; + GLbitfield outputsWritten; + GLboolean anyProgRegsWritten; + GLboolean indirectRegisterFiles; + GLuint numInst; /* number of instructions parsed */ +}; + + +/* + * Called whenever we find an error during parsing. + */ +static void +record_error(struct parse_state *parseState, const char *msg, int lineNo) +{ +#ifdef DEBUG + GLint line, column; + const GLubyte *lineStr; + lineStr = _mesa_find_line_column(parseState->start, + parseState->pos, &line, &column); + _mesa_debug(parseState->ctx, + "nvfragparse.c(%d): line %d, column %d:%s (%s)\n", + lineNo, line, column, (char *) lineStr, msg); + free((void *) lineStr); +#else + (void) lineNo; +#endif + + /* Check that no error was already recorded. Only record the first one. */ + if (parseState->ctx->Program.ErrorString[0] == 0) { + _mesa_set_program_error(parseState->ctx, + parseState->pos - parseState->start, + msg); + } +} + + +#define RETURN_ERROR \ +do { \ + record_error(parseState, "Unexpected end of input.", __LINE__); \ + return GL_FALSE; \ +} while(0) + +#define RETURN_ERROR1(msg) \ +do { \ + record_error(parseState, msg, __LINE__); \ + return GL_FALSE; \ +} while(0) + +#define RETURN_ERROR2(msg1, msg2) \ +do { \ + char err[1000]; \ + sprintf(err, "%s %s", msg1, msg2); \ + record_error(parseState, err, __LINE__); \ + return GL_FALSE; \ +} while(0) + + + + + +static GLboolean IsLetter(GLubyte b) +{ + return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z'); +} + + +static GLboolean IsDigit(GLubyte b) +{ + return b >= '0' && b <= '9'; +} + + +static GLboolean IsWhitespace(GLubyte b) +{ + return b == ' ' || b == '\t' || b == '\n' || b == '\r'; +} + + +/** + * Starting at 'str' find the next token. A token can be an integer, + * an identifier or punctuation symbol. + * \return <= 0 we found an error, else, return number of characters parsed. + */ +static GLint +GetToken(struct parse_state *parseState, GLubyte *token) +{ + const GLubyte *str = parseState->pos; + GLint i = 0, j = 0; + + token[0] = 0; + + /* skip whitespace and comments */ + while (str[i] && (IsWhitespace(str[i]) || str[i] == '#')) { + if (str[i] == '#') { + /* skip comment */ + while (str[i] && (str[i] != '\n' && str[i] != '\r')) { + i++; + } + if (str[i] == '\n' || str[i] == '\r') + parseState->curLine = str + i + 1; + } + else { + /* skip whitespace */ + if (str[i] == '\n' || str[i] == '\r') + parseState->curLine = str + i + 1; + i++; + } + } + + if (str[i] == 0) + return -i; + + /* try matching an integer */ + while (str[i] && IsDigit(str[i])) { + token[j++] = str[i++]; + } + if (j > 0 || !str[i]) { + token[j] = 0; + return i; + } + + /* try matching an identifier */ + if (IsLetter(str[i])) { + while (str[i] && (IsLetter(str[i]) || IsDigit(str[i]))) { + token[j++] = str[i++]; + } + token[j] = 0; + return i; + } + + /* punctuation character */ + if (str[i]) { + token[0] = str[i++]; + token[1] = 0; + return i; + } + + /* end of input */ + token[0] = 0; + return i; +} + + +/** + * Get next token from input stream and increment stream pointer past token. + */ +static GLboolean +Parse_Token(struct parse_state *parseState, GLubyte *token) +{ + GLint i; + i = GetToken(parseState, token); + if (i <= 0) { + parseState->pos += (-i); + return GL_FALSE; + } + parseState->pos += i; + return GL_TRUE; +} + + +/** + * Get next token from input stream but don't increment stream pointer. + */ +static GLboolean +Peek_Token(struct parse_state *parseState, GLubyte *token) +{ + GLint i, len; + i = GetToken(parseState, token); + if (i <= 0) { + parseState->pos += (-i); + return GL_FALSE; + } + len = (GLint) strlen((const char *) token); + parseState->pos += (i - len); + return GL_TRUE; +} + + +/** + * Try to match 'pattern' as the next token after any whitespace/comments. + * Advance the current parsing position only if we match the pattern. + * \return GL_TRUE if pattern is matched, GL_FALSE otherwise. + */ +static GLboolean +Parse_String(struct parse_state *parseState, const char *pattern) +{ + const GLubyte *m; + GLint i; + + /* skip whitespace and comments */ + while (IsWhitespace(*parseState->pos) || *parseState->pos == '#') { + if (*parseState->pos == '#') { + while (*parseState->pos && (*parseState->pos != '\n' && *parseState->pos != '\r')) { + parseState->pos += 1; + } + if (*parseState->pos == '\n' || *parseState->pos == '\r') + parseState->curLine = parseState->pos + 1; + } + else { + /* skip whitespace */ + if (*parseState->pos == '\n' || *parseState->pos == '\r') + parseState->curLine = parseState->pos + 1; + parseState->pos += 1; + } + } + + /* Try to match the pattern */ + m = parseState->pos; + for (i = 0; pattern[i]; i++) { + if (*m != (GLubyte) pattern[i]) + return GL_FALSE; + m += 1; + } + parseState->pos = m; + + return GL_TRUE; /* success */ +} + + +/**********************************************************************/ + +static const char *InputRegisters[MAX_NV_VERTEX_PROGRAM_INPUTS + 1] = { + "OPOS", "WGHT", "NRML", "COL0", "COL1", "FOGC", "6", "7", + "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL +}; + +static const char *OutputRegisters[MAX_NV_VERTEX_PROGRAM_OUTPUTS + 1] = { + "HPOS", "COL0", "COL1", "FOGC", + "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", + "PSIZ", "BFC0", "BFC1", NULL +}; + + + +/** + * Parse a temporary register: Rnn + */ +static GLboolean +Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum) +{ + GLubyte token[100]; + + /* Should be 'R##' */ + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + if (token[0] != 'R') + RETURN_ERROR1("Expected R##"); + + if (IsDigit(token[1])) { + GLint reg = atoi((char *) (token + 1)); + if (reg >= MAX_NV_VERTEX_PROGRAM_TEMPS) + RETURN_ERROR1("Bad temporary register name"); + *tempRegNum = reg; + } + else { + RETURN_ERROR1("Bad temporary register name"); + } + + return GL_TRUE; +} + + +/** + * Parse address register "A0.x" + */ +static GLboolean +Parse_AddrReg(struct parse_state *parseState) +{ + /* match 'A0' */ + if (!Parse_String(parseState, "A0")) + RETURN_ERROR; + + /* match '.' */ + if (!Parse_String(parseState, ".")) + RETURN_ERROR; + + /* match 'x' */ + if (!Parse_String(parseState, "x")) + RETURN_ERROR; + + return GL_TRUE; +} + + +/** + * Parse absolute program parameter register "c[##]" + */ +static GLboolean +Parse_AbsParamReg(struct parse_state *parseState, GLint *regNum) +{ + GLubyte token[100]; + + if (!Parse_String(parseState, "c")) + RETURN_ERROR; + + if (!Parse_String(parseState, "[")) + RETURN_ERROR; + + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + + if (IsDigit(token[0])) { + /* a numbered program parameter register */ + GLint reg = atoi((char *) token); + if (reg >= MAX_NV_VERTEX_PROGRAM_PARAMS) + RETURN_ERROR1("Bad program parameter number"); + *regNum = reg; + } + else { + RETURN_ERROR; + } + + if (!Parse_String(parseState, "]")) + RETURN_ERROR; + + return GL_TRUE; +} + + +static GLboolean +Parse_ParamReg(struct parse_state *parseState, struct prog_src_register *srcReg) +{ + GLubyte token[100]; + + if (!Parse_String(parseState, "c")) + RETURN_ERROR; + + if (!Parse_String(parseState, "[")) + RETURN_ERROR; + + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + + if (IsDigit(token[0])) { + /* a numbered program parameter register */ + GLint reg; + (void) Parse_Token(parseState, token); + reg = atoi((char *) token); + if (reg >= MAX_NV_VERTEX_PROGRAM_PARAMS) + RETURN_ERROR1("Bad program parameter number"); + srcReg->File = PROGRAM_ENV_PARAM; + srcReg->Index = reg; + } + else if (strcmp((const char *) token, "A0") == 0) { + /* address register "A0.x" */ + if (!Parse_AddrReg(parseState)) + RETURN_ERROR; + + srcReg->RelAddr = GL_TRUE; + srcReg->File = PROGRAM_ENV_PARAM; + parseState->indirectRegisterFiles |= (1 << srcReg->File); + /* Look for +/-N offset */ + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + + if (token[0] == '-' || token[0] == '+') { + const GLubyte sign = token[0]; + (void) Parse_Token(parseState, token); /* consume +/- */ + + /* an integer should be next */ + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + + if (IsDigit(token[0])) { + const GLint k = atoi((char *) token); + if (sign == '-') { + if (k > 64) + RETURN_ERROR1("Bad address offset"); + srcReg->Index = -k; + } + else { + if (k > 63) + RETURN_ERROR1("Bad address offset"); + srcReg->Index = k; + } + } + else { + RETURN_ERROR; + } + } + else { + /* probably got a ']', catch it below */ + } + } + else { + RETURN_ERROR; + } + + /* Match closing ']' */ + if (!Parse_String(parseState, "]")) + RETURN_ERROR; + + return GL_TRUE; +} + + +/** + * Parse v[#] or v[] + */ +static GLboolean +Parse_AttribReg(struct parse_state *parseState, GLint *tempRegNum) +{ + GLubyte token[100]; + GLint j; + + /* Match 'v' */ + if (!Parse_String(parseState, "v")) + RETURN_ERROR; + + /* Match '[' */ + if (!Parse_String(parseState, "[")) + RETURN_ERROR; + + /* match number or named register */ + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + + if (parseState->isStateProgram && token[0] != '0') + RETURN_ERROR1("Only v[0] accessible in vertex state programs"); + + if (IsDigit(token[0])) { + GLint reg = atoi((char *) token); + if (reg >= MAX_NV_VERTEX_PROGRAM_INPUTS) + RETURN_ERROR1("Bad vertex attribute register name"); + *tempRegNum = reg; + } + else { + for (j = 0; InputRegisters[j]; j++) { + if (strcmp((const char *) token, InputRegisters[j]) == 0) { + *tempRegNum = j; + break; + } + } + if (!InputRegisters[j]) { + /* unknown input register label */ + RETURN_ERROR2("Bad register name", token); + } + } + + /* Match '[' */ + if (!Parse_String(parseState, "]")) + RETURN_ERROR; + + return GL_TRUE; +} + + +static GLboolean +Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum) +{ + GLubyte token[100]; + GLint start, j; + + /* Match 'o' */ + if (!Parse_String(parseState, "o")) + RETURN_ERROR; + + /* Match '[' */ + if (!Parse_String(parseState, "[")) + RETURN_ERROR; + + /* Get output reg name */ + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + + if (parseState->isPositionInvariant) + start = 1; /* skip HPOS register name */ + else + start = 0; + + /* try to match an output register name */ + for (j = start; OutputRegisters[j]; j++) { + if (strcmp((const char *) token, OutputRegisters[j]) == 0) { + *outputRegNum = j; + break; + } + } + if (!OutputRegisters[j]) + RETURN_ERROR1("Unrecognized output register name"); + + /* Match ']' */ + if (!Parse_String(parseState, "]")) + RETURN_ERROR1("Expected ]"); + + return GL_TRUE; +} + + +static GLboolean +Parse_MaskedDstReg(struct parse_state *parseState, struct prog_dst_register *dstReg) +{ + GLubyte token[100]; + GLint idx; + + /* Dst reg can be R or o[n] */ + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + + if (token[0] == 'R') { + /* a temporary register */ + dstReg->File = PROGRAM_TEMPORARY; + if (!Parse_TempReg(parseState, &idx)) + RETURN_ERROR; + dstReg->Index = idx; + } + else if (!parseState->isStateProgram && token[0] == 'o') { + /* an output register */ + dstReg->File = PROGRAM_OUTPUT; + if (!Parse_OutputReg(parseState, &idx)) + RETURN_ERROR; + dstReg->Index = idx; + } + else if (parseState->isStateProgram && token[0] == 'c' && + parseState->isStateProgram) { + /* absolute program parameter register */ + /* Only valid for vertex state programs */ + dstReg->File = PROGRAM_ENV_PARAM; + if (!Parse_AbsParamReg(parseState, &idx)) + RETURN_ERROR; + dstReg->Index = idx; + } + else { + RETURN_ERROR1("Bad destination register name"); + } + + /* Parse optional write mask */ + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + + if (token[0] == '.') { + /* got a mask */ + GLint k = 0; + + if (!Parse_String(parseState, ".")) + RETURN_ERROR; + + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + + dstReg->WriteMask = 0; + + if (token[k] == 'x') { + dstReg->WriteMask |= WRITEMASK_X; + k++; + } + if (token[k] == 'y') { + dstReg->WriteMask |= WRITEMASK_Y; + k++; + } + if (token[k] == 'z') { + dstReg->WriteMask |= WRITEMASK_Z; + k++; + } + if (token[k] == 'w') { + dstReg->WriteMask |= WRITEMASK_W; + k++; + } + if (k == 0) { + RETURN_ERROR1("Bad writemask character"); + } + return GL_TRUE; + } + else { + dstReg->WriteMask = WRITEMASK_XYZW; + return GL_TRUE; + } +} + + +static GLboolean +Parse_SwizzleSrcReg(struct parse_state *parseState, struct prog_src_register *srcReg) +{ + GLubyte token[100]; + GLint idx; + + srcReg->RelAddr = GL_FALSE; + + /* check for '-' */ + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + if (token[0] == '-') { + (void) Parse_String(parseState, "-"); + srcReg->Negate = NEGATE_XYZW; + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + } + else { + srcReg->Negate = NEGATE_NONE; + } + + /* Src reg can be R, c[n], c[n +/- offset], or a named vertex attrib */ + if (token[0] == 'R') { + srcReg->File = PROGRAM_TEMPORARY; + if (!Parse_TempReg(parseState, &idx)) + RETURN_ERROR; + srcReg->Index = idx; + } + else if (token[0] == 'c') { + if (!Parse_ParamReg(parseState, srcReg)) + RETURN_ERROR; + } + else if (token[0] == 'v') { + srcReg->File = PROGRAM_INPUT; + if (!Parse_AttribReg(parseState, &idx)) + RETURN_ERROR; + srcReg->Index = idx; + } + else { + RETURN_ERROR2("Bad source register name", token); + } + + /* init swizzle fields */ + srcReg->Swizzle = SWIZZLE_NOOP; + + /* Look for optional swizzle suffix */ + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + if (token[0] == '.') { + (void) Parse_String(parseState, "."); /* consume . */ + + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + + if (token[1] == 0) { + /* single letter swizzle */ + if (token[0] == 'x') + srcReg->Swizzle = SWIZZLE_XXXX; + else if (token[0] == 'y') + srcReg->Swizzle = SWIZZLE_YYYY; + else if (token[0] == 'z') + srcReg->Swizzle = SWIZZLE_ZZZZ; + else if (token[0] == 'w') + srcReg->Swizzle = SWIZZLE_WWWW; + else + RETURN_ERROR1("Expected x, y, z, or w"); + } + else { + /* 2, 3 or 4-component swizzle */ + GLint k; + + srcReg->Swizzle = 0; + + for (k = 0; token[k] && k < 5; k++) { + if (token[k] == 'x') + srcReg->Swizzle |= 0 << (k*3); + else if (token[k] == 'y') + srcReg->Swizzle |= 1 << (k*3); + else if (token[k] == 'z') + srcReg->Swizzle |= 2 << (k*3); + else if (token[k] == 'w') + srcReg->Swizzle |= 3 << (k*3); + else + RETURN_ERROR; + } + if (k >= 5) + RETURN_ERROR; + } + } + + return GL_TRUE; +} + + +static GLboolean +Parse_ScalarSrcReg(struct parse_state *parseState, struct prog_src_register *srcReg) +{ + GLubyte token[100]; + GLint idx; + + srcReg->RelAddr = GL_FALSE; + + /* check for '-' */ + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + if (token[0] == '-') { + srcReg->Negate = NEGATE_XYZW; + (void) Parse_String(parseState, "-"); /* consume '-' */ + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + } + else { + srcReg->Negate = NEGATE_NONE; + } + + /* Src reg can be R, c[n], c[n +/- offset], or a named vertex attrib */ + if (token[0] == 'R') { + srcReg->File = PROGRAM_TEMPORARY; + if (!Parse_TempReg(parseState, &idx)) + RETURN_ERROR; + srcReg->Index = idx; + } + else if (token[0] == 'c') { + if (!Parse_ParamReg(parseState, srcReg)) + RETURN_ERROR; + } + else if (token[0] == 'v') { + srcReg->File = PROGRAM_INPUT; + if (!Parse_AttribReg(parseState, &idx)) + RETURN_ERROR; + srcReg->Index = idx; + } + else { + RETURN_ERROR2("Bad source register name", token); + } + + /* Look for .[xyzw] suffix */ + if (!Parse_String(parseState, ".")) + RETURN_ERROR; + + if (!Parse_Token(parseState, token)) + RETURN_ERROR; + + if (token[0] == 'x' && token[1] == 0) { + srcReg->Swizzle = 0; + } + else if (token[0] == 'y' && token[1] == 0) { + srcReg->Swizzle = 1; + } + else if (token[0] == 'z' && token[1] == 0) { + srcReg->Swizzle = 2; + } + else if (token[0] == 'w' && token[1] == 0) { + srcReg->Swizzle = 3; + } + else { + RETURN_ERROR1("Bad scalar source suffix"); + } + + return GL_TRUE; +} + + +static GLint +Parse_UnaryOpInstruction(struct parse_state *parseState, + struct prog_instruction *inst, + enum prog_opcode opcode) +{ + if (opcode == OPCODE_ABS && !parseState->isVersion1_1) + RETURN_ERROR1("ABS illegal for vertex program 1.0"); + + inst->Opcode = opcode; + + /* dest reg */ + if (!Parse_MaskedDstReg(parseState, &inst->DstReg)) + RETURN_ERROR; + + /* comma */ + if (!Parse_String(parseState, ",")) + RETURN_ERROR; + + /* src arg */ + if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0])) + RETURN_ERROR; + + /* semicolon */ + if (!Parse_String(parseState, ";")) + RETURN_ERROR; + + return GL_TRUE; +} + + +static GLboolean +Parse_BiOpInstruction(struct parse_state *parseState, + struct prog_instruction *inst, + enum prog_opcode opcode) +{ + if (opcode == OPCODE_DPH && !parseState->isVersion1_1) + RETURN_ERROR1("DPH illegal for vertex program 1.0"); + if (opcode == OPCODE_SUB && !parseState->isVersion1_1) + RETURN_ERROR1("SUB illegal for vertex program 1.0"); + + inst->Opcode = opcode; + + /* dest reg */ + if (!Parse_MaskedDstReg(parseState, &inst->DstReg)) + RETURN_ERROR; + + /* comma */ + if (!Parse_String(parseState, ",")) + RETURN_ERROR; + + /* first src arg */ + if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0])) + RETURN_ERROR; + + /* comma */ + if (!Parse_String(parseState, ",")) + RETURN_ERROR; + + /* second src arg */ + if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[1])) + RETURN_ERROR; + + /* semicolon */ + if (!Parse_String(parseState, ";")) + RETURN_ERROR; + + /* make sure we don't reference more than one program parameter register */ + if (inst->SrcReg[0].File == PROGRAM_ENV_PARAM && + inst->SrcReg[1].File == PROGRAM_ENV_PARAM && + inst->SrcReg[0].Index != inst->SrcReg[1].Index) + RETURN_ERROR1("Can't reference two program parameter registers"); + + /* make sure we don't reference more than one vertex attribute register */ + if (inst->SrcReg[0].File == PROGRAM_INPUT && + inst->SrcReg[1].File == PROGRAM_INPUT && + inst->SrcReg[0].Index != inst->SrcReg[1].Index) + RETURN_ERROR1("Can't reference two vertex attribute registers"); + + return GL_TRUE; +} + + +static GLboolean +Parse_TriOpInstruction(struct parse_state *parseState, + struct prog_instruction *inst, + enum prog_opcode opcode) +{ + inst->Opcode = opcode; + + /* dest reg */ + if (!Parse_MaskedDstReg(parseState, &inst->DstReg)) + RETURN_ERROR; + + /* comma */ + if (!Parse_String(parseState, ",")) + RETURN_ERROR; + + /* first src arg */ + if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0])) + RETURN_ERROR; + + /* comma */ + if (!Parse_String(parseState, ",")) + RETURN_ERROR; + + /* second src arg */ + if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[1])) + RETURN_ERROR; + + /* comma */ + if (!Parse_String(parseState, ",")) + RETURN_ERROR; + + /* third src arg */ + if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[2])) + RETURN_ERROR; + + /* semicolon */ + if (!Parse_String(parseState, ";")) + RETURN_ERROR; + + /* make sure we don't reference more than one program parameter register */ + if ((inst->SrcReg[0].File == PROGRAM_ENV_PARAM && + inst->SrcReg[1].File == PROGRAM_ENV_PARAM && + inst->SrcReg[0].Index != inst->SrcReg[1].Index) || + (inst->SrcReg[0].File == PROGRAM_ENV_PARAM && + inst->SrcReg[2].File == PROGRAM_ENV_PARAM && + inst->SrcReg[0].Index != inst->SrcReg[2].Index) || + (inst->SrcReg[1].File == PROGRAM_ENV_PARAM && + inst->SrcReg[2].File == PROGRAM_ENV_PARAM && + inst->SrcReg[1].Index != inst->SrcReg[2].Index)) + RETURN_ERROR1("Can only reference one program register"); + + /* make sure we don't reference more than one vertex attribute register */ + if ((inst->SrcReg[0].File == PROGRAM_INPUT && + inst->SrcReg[1].File == PROGRAM_INPUT && + inst->SrcReg[0].Index != inst->SrcReg[1].Index) || + (inst->SrcReg[0].File == PROGRAM_INPUT && + inst->SrcReg[2].File == PROGRAM_INPUT && + inst->SrcReg[0].Index != inst->SrcReg[2].Index) || + (inst->SrcReg[1].File == PROGRAM_INPUT && + inst->SrcReg[2].File == PROGRAM_INPUT && + inst->SrcReg[1].Index != inst->SrcReg[2].Index)) + RETURN_ERROR1("Can only reference one input register"); + + return GL_TRUE; +} + + +static GLboolean +Parse_ScalarInstruction(struct parse_state *parseState, + struct prog_instruction *inst, + enum prog_opcode opcode) +{ + if (opcode == OPCODE_RCC && !parseState->isVersion1_1) + RETURN_ERROR1("RCC illegal for vertex program 1.0"); + + inst->Opcode = opcode; + + /* dest reg */ + if (!Parse_MaskedDstReg(parseState, &inst->DstReg)) + RETURN_ERROR; + + /* comma */ + if (!Parse_String(parseState, ",")) + RETURN_ERROR; + + /* first src arg */ + if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0])) + RETURN_ERROR; + + /* semicolon */ + if (!Parse_String(parseState, ";")) + RETURN_ERROR; + + return GL_TRUE; +} + + +static GLboolean +Parse_AddressInstruction(struct parse_state *parseState, struct prog_instruction *inst) +{ + inst->Opcode = OPCODE_ARL; + + /* Make ARB_vp backends happy */ + inst->DstReg.File = PROGRAM_ADDRESS; + inst->DstReg.WriteMask = WRITEMASK_X; + inst->DstReg.Index = 0; + + /* dest A0 reg */ + if (!Parse_AddrReg(parseState)) + RETURN_ERROR; + + /* comma */ + if (!Parse_String(parseState, ",")) + RETURN_ERROR; + + /* parse src reg */ + if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0])) + RETURN_ERROR; + + /* semicolon */ + if (!Parse_String(parseState, ";")) + RETURN_ERROR; + + return GL_TRUE; +} + + +static GLboolean +Parse_EndInstruction(struct parse_state *parseState, struct prog_instruction *inst) +{ + GLubyte token[100]; + + inst->Opcode = OPCODE_END; + + /* this should fail! */ + if (Parse_Token(parseState, token)) + RETURN_ERROR2("Unexpected token after END:", token); + else + return GL_TRUE; +} + + +/** + * The PRINT instruction is Mesa-specific and is meant as a debugging aid for + * the vertex program developer. + * The NV_vertex_program extension grammar is modified as follows: + * + * ::= + * | ... + * | + * + * ::= "PRINT" + * | "PRINT" "," + * | "PRINT" "," + */ +static GLboolean +Parse_PrintInstruction(struct parse_state *parseState, struct prog_instruction *inst) +{ + const GLubyte *str; + GLubyte *msg; + GLuint len; + GLubyte token[100]; + struct prog_src_register *srcReg = &inst->SrcReg[0]; + GLint idx; + + inst->Opcode = OPCODE_PRINT; + + /* The first argument is a literal string 'just like this' */ + if (!Parse_String(parseState, "'")) + RETURN_ERROR; + + str = parseState->pos; + for (len = 0; str[len] != '\''; len++) /* find closing quote */ + ; + parseState->pos += len + 1; + msg = (GLubyte*) malloc(len + 1); + + memcpy(msg, str, len); + msg[len] = 0; + inst->Data = msg; + + /* comma */ + if (Parse_String(parseState, ",")) { + + /* The second argument is a register name */ + if (!Peek_Token(parseState, token)) + RETURN_ERROR; + + srcReg->RelAddr = GL_FALSE; + srcReg->Negate = NEGATE_NONE; + srcReg->Swizzle = SWIZZLE_NOOP; + + /* Register can be R, c[n], c[n +/- offset], a named vertex attrib, + * or an o[n] output register. + */ + if (token[0] == 'R') { + srcReg->File = PROGRAM_TEMPORARY; + if (!Parse_TempReg(parseState, &idx)) + RETURN_ERROR; + srcReg->Index = idx; + } + else if (token[0] == 'c') { + srcReg->File = PROGRAM_ENV_PARAM; + if (!Parse_ParamReg(parseState, srcReg)) + RETURN_ERROR; + } + else if (token[0] == 'v') { + srcReg->File = PROGRAM_INPUT; + if (!Parse_AttribReg(parseState, &idx)) + RETURN_ERROR; + srcReg->Index = idx; + } + else if (token[0] == 'o') { + srcReg->File = PROGRAM_OUTPUT; + if (!Parse_OutputReg(parseState, &idx)) + RETURN_ERROR; + srcReg->Index = idx; + } + else { + RETURN_ERROR2("Bad source register name", token); + } + } + else { + srcReg->File = PROGRAM_UNDEFINED; + } + + /* semicolon */ + if (!Parse_String(parseState, ";")) + RETURN_ERROR; + + return GL_TRUE; +} + + +static GLboolean +Parse_OptionSequence(struct parse_state *parseState, + struct prog_instruction program[]) +{ + (void) program; + while (1) { + if (!Parse_String(parseState, "OPTION")) + return GL_TRUE; /* ok, not an OPTION statement */ + if (Parse_String(parseState, "NV_position_invariant")) { + parseState->isPositionInvariant = GL_TRUE; + } + else { + RETURN_ERROR1("unexpected OPTION statement"); + } + if (!Parse_String(parseState, ";")) + return GL_FALSE; + } +} + + +static GLboolean +Parse_InstructionSequence(struct parse_state *parseState, + struct prog_instruction program[]) +{ + while (1) { + struct prog_instruction *inst = program + parseState->numInst; + + /* Initialize the instruction */ + _mesa_init_instructions(inst, 1); + + if (Parse_String(parseState, "MOV")) { + if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_MOV)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "LIT")) { + if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_LIT)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "ABS")) { + if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_ABS)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "MUL")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MUL)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "ADD")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_ADD)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "DP3")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DP3)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "DP4")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DP4)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "DST")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DST)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "MIN")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MIN)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "MAX")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MAX)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "SLT")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SLT)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "SGE")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SGE)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "DPH")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DPH)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "SUB")) { + if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SUB)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "MAD")) { + if (!Parse_TriOpInstruction(parseState, inst, OPCODE_MAD)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "RCP")) { + if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RCP)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "RSQ")) { + if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RSQ)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "EXP")) { + if (!Parse_ScalarInstruction(parseState, inst, OPCODE_EXP)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "LOG")) { + if (!Parse_ScalarInstruction(parseState, inst, OPCODE_LOG)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "RCC")) { + if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RCC)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "ARL")) { + if (!Parse_AddressInstruction(parseState, inst)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "PRINT")) { + if (!Parse_PrintInstruction(parseState, inst)) + RETURN_ERROR; + } + else if (Parse_String(parseState, "END")) { + if (!Parse_EndInstruction(parseState, inst)) + RETURN_ERROR; + else { + parseState->numInst++; + return GL_TRUE; /* all done */ + } + } + else { + /* bad instruction name */ + RETURN_ERROR1("Unexpected token"); + } + + /* examine input/output registers */ + if (inst->DstReg.File == PROGRAM_OUTPUT) + parseState->outputsWritten |= (1 << inst->DstReg.Index); + else if (inst->DstReg.File == PROGRAM_ENV_PARAM) + parseState->anyProgRegsWritten = GL_TRUE; + + if (inst->SrcReg[0].File == PROGRAM_INPUT) + parseState->inputsRead |= (1 << inst->SrcReg[0].Index); + if (inst->SrcReg[1].File == PROGRAM_INPUT) + parseState->inputsRead |= (1 << inst->SrcReg[1].Index); + if (inst->SrcReg[2].File == PROGRAM_INPUT) + parseState->inputsRead |= (1 << inst->SrcReg[2].Index); + + parseState->numInst++; + + if (parseState->numInst >= MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS) + RETURN_ERROR1("Program too long"); + } + + RETURN_ERROR; +} + + +static GLboolean +Parse_Program(struct parse_state *parseState, + struct prog_instruction instBuffer[]) +{ + if (parseState->isVersion1_1) { + if (!Parse_OptionSequence(parseState, instBuffer)) { + return GL_FALSE; + } + } + return Parse_InstructionSequence(parseState, instBuffer); +} + + +/** + * Parse/compile the 'str' returning the compiled 'program'. + * ctx->Program.ErrorPos will be -1 if successful. Otherwise, ErrorPos + * indicates the position of the error in 'str'. + */ +void +_mesa_parse_nv_vertex_program(struct gl_context *ctx, GLenum dstTarget, + const GLubyte *str, GLsizei len, + struct gl_vertex_program *program) +{ + struct parse_state parseState; + struct prog_instruction instBuffer[MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS]; + struct prog_instruction *newInst; + GLenum target; + GLubyte *programString; + + /* Make a null-terminated copy of the program string */ + programString = (GLubyte *) MALLOC(len + 1); + if (!programString) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); + return; + } + memcpy(programString, str, len); + programString[len] = 0; + + /* Get ready to parse */ + parseState.ctx = ctx; + parseState.start = programString; + parseState.isPositionInvariant = GL_FALSE; + parseState.isVersion1_1 = GL_FALSE; + parseState.numInst = 0; + parseState.inputsRead = 0; + parseState.outputsWritten = 0; + parseState.anyProgRegsWritten = GL_FALSE; + parseState.indirectRegisterFiles = 0x0; + + /* Reset error state */ + _mesa_set_program_error(ctx, -1, NULL); + + /* check the program header */ + if (strncmp((const char *) programString, "!!VP1.0", 7) == 0) { + target = GL_VERTEX_PROGRAM_NV; + parseState.pos = programString + 7; + parseState.isStateProgram = GL_FALSE; + } + else if (strncmp((const char *) programString, "!!VP1.1", 7) == 0) { + target = GL_VERTEX_PROGRAM_NV; + parseState.pos = programString + 7; + parseState.isStateProgram = GL_FALSE; + parseState.isVersion1_1 = GL_TRUE; + } + else if (strncmp((const char *) programString, "!!VSP1.0", 8) == 0) { + target = GL_VERTEX_STATE_PROGRAM_NV; + parseState.pos = programString + 8; + parseState.isStateProgram = GL_TRUE; + } + else { + /* invalid header */ + ctx->Program.ErrorPos = 0; + _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)"); + return; + } + + /* make sure target and header match */ + if (target != dstTarget) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glLoadProgramNV(target mismatch)"); + return; + } + + + if (Parse_Program(&parseState, instBuffer)) { + gl_state_index state_tokens[STATE_LENGTH] = {0, 0, 0, 0, 0}; + int i; + + /* successful parse! */ + + if (parseState.isStateProgram) { + if (!parseState.anyProgRegsWritten) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glLoadProgramNV(c[#] not written)"); + return; + } + } + else { + if (!parseState.isPositionInvariant && + !(parseState.outputsWritten & (1 << VERT_RESULT_HPOS))) { + /* bit 1 = HPOS register */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glLoadProgramNV(HPOS not written)"); + return; + } + } + + /* copy the compiled instructions */ + assert(parseState.numInst <= MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS); + newInst = _mesa_alloc_instructions(parseState.numInst); + if (!newInst) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); + free(programString); + return; /* out of memory */ + } + _mesa_copy_instructions(newInst, instBuffer, parseState.numInst); + + /* install the program */ + program->Base.Target = target; + if (program->Base.String) { + free(program->Base.String); + } + program->Base.String = programString; + program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB; + if (program->Base.Instructions) { + free(program->Base.Instructions); + } + program->Base.Instructions = newInst; + program->Base.InputsRead = parseState.inputsRead; + if (parseState.isPositionInvariant) + program->Base.InputsRead |= VERT_BIT_POS; + program->Base.NumInstructions = parseState.numInst; + program->Base.OutputsWritten = parseState.outputsWritten; + program->IsPositionInvariant = parseState.isPositionInvariant; + program->IsNVProgram = GL_TRUE; + +#ifdef DEBUG_foo + printf("--- glLoadProgramNV result ---\n"); + _mesa_fprint_program_opt(stdout, &program->Base, PROG_PRINT_NV, 0); + printf("------------------------------\n"); +#endif + + if (program->Base.Parameters) + _mesa_free_parameter_list(program->Base.Parameters); + + program->Base.Parameters = _mesa_new_parameter_list (); + program->Base.NumParameters = 0; + + program->Base.IndirectRegisterFiles = parseState.indirectRegisterFiles; + + state_tokens[0] = STATE_VERTEX_PROGRAM; + state_tokens[1] = STATE_ENV; + /* Add refs to all of the potential params, in order. If we want to not + * upload everything, _mesa_layout_parameters is the answer. + */ + for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS; i++) { + GLint index; + state_tokens[2] = i; + index = _mesa_add_state_reference(program->Base.Parameters, + state_tokens); + assert(index == i); + } + program->Base.NumParameters = program->Base.Parameters->NumParameters; + + _mesa_setup_nv_temporary_count(&program->Base); + _mesa_emit_nv_temp_initialization(ctx, &program->Base); + } + else { + /* Error! */ + _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV"); + /* NOTE: _mesa_set_program_error would have been called already */ + /* GL_NV_vertex_program isn't supposed to set the error string + * so we reset it here. + */ + _mesa_set_program_error(ctx, ctx->Program.ErrorPos, NULL); + } +} + + +const char * +_mesa_nv_vertex_input_register_name(GLuint i) +{ + ASSERT(i < MAX_NV_VERTEX_PROGRAM_INPUTS); + return InputRegisters[i]; +} + + +const char * +_mesa_nv_vertex_output_register_name(GLuint i) +{ + ASSERT(i < MAX_NV_VERTEX_PROGRAM_OUTPUTS); + return OutputRegisters[i]; +} + diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index a41e9e872..0ad9e1286 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -85,6 +85,9 @@ void st_init_limits(struct st_context *st) c->MaxTextureRectSize = _min(1 << (c->MaxTextureLevels - 1), MAX_TEXTURE_RECT_SIZE); + c->MaxArrayTextureLayers + = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS); + c->MaxTextureImageUnits = _min(screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS), MAX_TEXTURE_IMAGE_UNITS); @@ -170,6 +173,12 @@ void st_init_limits(struct st_context *st) /* raise MaxParameters if native support is higher */ pc->MaxParameters = MAX2(pc->MaxParameters, pc->MaxNativeParameters); + /* Gallium doesn't really care about local vs. env parameters so use the + * same limits. + */ + pc->MaxLocalParams = pc->MaxParameters; + pc->MaxEnvParams = pc->MaxParameters; + options->EmitNoNoise = TRUE; /* TODO: make these more fine-grained if anyone needs it */ @@ -499,7 +508,7 @@ void st_init_extensions(struct st_context *st) } /* GL_EXT_texture_array */ - if (screen->get_param(screen, PIPE_CAP_ARRAY_TEXTURES)) { + if (screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS) > 1) { ctx->Extensions.EXT_texture_array = GL_TRUE; ctx->Extensions.MESA_texture_array = GL_TRUE; } diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 9394bea00..892169822 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -519,7 +519,7 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op, inst->function = NULL; - if (op == TGSI_OPCODE_ARL) + if (op == TGSI_OPCODE_ARL || op == TGSI_OPCODE_UARL) this->num_address_regs = 1; /* Update indirect addressing status used by TGSI */ @@ -746,16 +746,12 @@ void glsl_to_tgsi_visitor::emit_arl(ir_instruction *ir, st_dst_reg dst, st_src_reg src0) { - st_src_reg tmp = get_temp(glsl_type::float_type); + int op = TGSI_OPCODE_ARL; - if (src0.type == GLSL_TYPE_INT) - emit(NULL, TGSI_OPCODE_I2F, st_dst_reg(tmp), src0); - else if (src0.type == GLSL_TYPE_UINT) - emit(NULL, TGSI_OPCODE_U2F, st_dst_reg(tmp), src0); - else - tmp = src0; - - emit(NULL, TGSI_OPCODE_ARL, dst, tmp); + if (src0.type == GLSL_TYPE_INT || src0.type == GLSL_TYPE_UINT) + op = TGSI_OPCODE_UARL; + + emit(NULL, op, dst, src0); } /** @@ -2558,6 +2554,8 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) break; } + const glsl_type *sampler_type = ir->sampler->type; + if (ir->projector) { if (opcode == TGSI_OPCODE_TEX) { /* Slot the projector in as the last component of the coord. */ @@ -2589,6 +2587,9 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) tmp_src = get_temp(glsl_type::vec4_type); st_dst_reg tmp_dst = st_dst_reg(tmp_src); + /* Projective division not allowed for array samplers. */ + assert(!sampler_type->sampler_array); + tmp_dst.writemask = WRITEMASK_Z; emit(ir, TGSI_OPCODE_MOV, tmp_dst, this->result); @@ -2613,7 +2614,15 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) * coord. */ ir->shadow_comparitor->accept(this); - coord_dst.writemask = WRITEMASK_Z; + + /* XXX This will need to be updated for cubemap array samplers. */ + if (sampler_type->sampler_dimensionality == GLSL_SAMPLER_DIM_2D && + sampler_type->sampler_array) { + coord_dst.writemask = WRITEMASK_W; + } else { + coord_dst.writemask = WRITEMASK_Z; + } + emit(ir, TGSI_OPCODE_MOV, coord_dst, this->result); coord_dst.writemask = WRITEMASK_XYZW; } @@ -2651,8 +2660,6 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) inst->tex_offsets[0].SwizzleZ = GET_SWZ(offset.swizzle, 2); } - const glsl_type *sampler_type = ir->sampler->type; - switch (sampler_type->sampler_dimensionality) { case GLSL_SAMPLER_DIM_1D: inst->tex_target = (sampler_type->sampler_array) diff --git a/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c b/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c index f4263c64c..b4111b00d 100644 --- a/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c +++ b/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c @@ -276,6 +276,8 @@ translate_texture_target( GLuint textarget, case TEXTURE_1D_INDEX: return TGSI_TEXTURE_SHADOW1D; case TEXTURE_2D_INDEX: return TGSI_TEXTURE_SHADOW2D; case TEXTURE_RECT_INDEX: return TGSI_TEXTURE_SHADOWRECT; + case TEXTURE_1D_ARRAY_INDEX: return TGSI_TEXTURE_SHADOW1D_ARRAY; + case TEXTURE_2D_ARRAY_INDEX: return TGSI_TEXTURE_SHADOW2D_ARRAY; default: break; } } diff --git a/mesalib/src/mesa/swrast/s_spantemp.h b/mesalib/src/mesa/swrast/s_spantemp.h index 125d19638..517c2eb3f 100644 --- a/mesalib/src/mesa/swrast/s_spantemp.h +++ b/mesalib/src/mesa/swrast/s_spantemp.h @@ -1,221 +1,228 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5.1 - * - * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - - -/* - * Templates for the span/pixel-array write/read functions called via - * the gl_renderbuffer's GetRow, GetValues, PutRow, PutMonoRow, PutValues - * and PutMonoValues functions. - * - * Define the following macros before including this file: - * NAME(BASE) to generate the function name (i.e. add prefix or suffix) - * RB_TYPE the renderbuffer DataType - * SPAN_VARS to declare any local variables - * INIT_PIXEL_PTR(P, X, Y) to initialize a pointer to a pixel - * INC_PIXEL_PTR(P) to increment a pixel pointer by one pixel - * STORE_PIXEL(DST, X, Y, VALUE) to store pixel values in buffer - * FETCH_PIXEL(DST, SRC) to fetch pixel values from buffer - * - * Note that in the STORE_PIXEL macros, we also pass in the (X,Y) coordinates - * for the pixels to be stored. This is useful when dithering and probably - * ignored otherwise. - */ - -#include "main/macros.h" - - -#if !defined(RB_COMPONENTS) -#define RB_COMPONENTS 4 -#endif - - -static void -NAME(get_row)( struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint count, GLint x, GLint y, void *values ) -{ -#ifdef SPAN_VARS - SPAN_VARS -#endif - RB_TYPE (*dest)[RB_COMPONENTS] = (RB_TYPE (*)[RB_COMPONENTS]) values; - GLuint i; - INIT_PIXEL_PTR(pixel, x, y); - for (i = 0; i < count; i++) { - FETCH_PIXEL(dest[i], pixel); - INC_PIXEL_PTR(pixel); - } - (void) rb; -} - - -static void -NAME(get_values)( struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint count, const GLint x[], const GLint y[], void *values ) -{ -#ifdef SPAN_VARS - SPAN_VARS -#endif - RB_TYPE (*dest)[RB_COMPONENTS] = (RB_TYPE (*)[RB_COMPONENTS]) values; - GLuint i; - for (i = 0; i < count; i++) { - INIT_PIXEL_PTR(pixel, x[i], y[i]); - FETCH_PIXEL(dest[i], pixel); - } - (void) rb; -} - - -static void -NAME(put_row)( struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint count, GLint x, GLint y, - const void *values, const GLubyte mask[] ) -{ -#ifdef SPAN_VARS - SPAN_VARS -#endif - const RB_TYPE (*src)[RB_COMPONENTS] = (const RB_TYPE (*)[RB_COMPONENTS]) values; - GLuint i; - INIT_PIXEL_PTR(pixel, x, y); - if (mask) { - for (i = 0; i < count; i++) { - if (mask[i]) { - STORE_PIXEL(pixel, x + i, y, src[i]); - } - INC_PIXEL_PTR(pixel); - } - } - else { - for (i = 0; i < count; i++) { - STORE_PIXEL(pixel, x + i, y, src[i]); - INC_PIXEL_PTR(pixel); - } - } - (void) rb; -} - - -static void -NAME(put_row_rgb)( struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint count, GLint x, GLint y, - const void *values, const GLubyte mask[] ) -{ -#ifdef SPAN_VARS - SPAN_VARS -#endif - const RB_TYPE (*src)[3] = (const RB_TYPE (*)[3]) values; - GLuint i; - INIT_PIXEL_PTR(pixel, x, y); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { -#ifdef STORE_PIXEL_RGB - STORE_PIXEL_RGB(pixel, x + i, y, src[i]); -#else - STORE_PIXEL(pixel, x + i, y, src[i]); -#endif - } - INC_PIXEL_PTR(pixel); - } - (void) rb; -} - - -static void -NAME(put_mono_row)( struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint count, GLint x, GLint y, - const void *value, const GLubyte mask[] ) -{ -#ifdef SPAN_VARS - SPAN_VARS -#endif - const RB_TYPE *src = (const RB_TYPE *) value; - GLuint i; - INIT_PIXEL_PTR(pixel, x, y); - if (mask) { - for (i = 0; i < count; i++) { - if (mask[i]) { - STORE_PIXEL(pixel, x + i, y, src); - } - INC_PIXEL_PTR(pixel); - } - } - else { - for (i = 0; i < count; i++) { - STORE_PIXEL(pixel, x + i, y, src); - INC_PIXEL_PTR(pixel); - } - } - (void) rb; -} - - -static void -NAME(put_values)( struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint count, const GLint x[], const GLint y[], - const void *values, const GLubyte mask[] ) -{ -#ifdef SPAN_VARS - SPAN_VARS -#endif - const RB_TYPE (*src)[RB_COMPONENTS] = (const RB_TYPE (*)[RB_COMPONENTS]) values; - GLuint i; - ASSERT(mask); - for (i = 0; i < count; i++) { - if (mask[i]) { - INIT_PIXEL_PTR(pixel, x[i], y[i]); - STORE_PIXEL(pixel, x[i], y[i], src[i]); - } - } - (void) rb; -} - - -static void -NAME(put_mono_values)( struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint count, const GLint x[], const GLint y[], - const void *value, const GLubyte mask[] ) -{ -#ifdef SPAN_VARS - SPAN_VARS -#endif - const RB_TYPE *src = (const RB_TYPE *) value; - GLuint i; - ASSERT(mask); - for (i = 0; i < count; i++) { - if (mask[i]) { - INIT_PIXEL_PTR(pixel, x[i], y[i]); - STORE_PIXEL(pixel, x[i], y[i], src); - } - } - (void) rb; -} - - -#undef NAME -#undef RB_TYPE -#undef RB_COMPONENTS -#undef SPAN_VARS -#undef INIT_PIXEL_PTR -#undef INC_PIXEL_PTR -#undef STORE_PIXEL -#undef STORE_PIXEL_RGB -#undef FETCH_PIXEL +/* + * Mesa 3-D graphics library + * Version: 6.5.1 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * Templates for the span/pixel-array write/read functions called via + * the gl_renderbuffer's GetRow, GetValues, PutRow, PutMonoRow, PutValues + * and PutMonoValues functions. + * + * Define the following macros before including this file: + * NAME(BASE) to generate the function name (i.e. add prefix or suffix) + * RB_TYPE the renderbuffer DataType + * SPAN_VARS to declare any local variables + * INIT_PIXEL_PTR(P, X, Y) to initialize a pointer to a pixel + * INC_PIXEL_PTR(P) to increment a pixel pointer by one pixel + * STORE_PIXEL(DST, X, Y, VALUE) to store pixel values in buffer + * FETCH_PIXEL(DST, SRC) to fetch pixel values from buffer + * + * Note that in the STORE_PIXEL macros, we also pass in the (X,Y) coordinates + * for the pixels to be stored. This is useful when dithering and probably + * ignored otherwise. + */ + +#include "main/macros.h" + + +#if !defined(RB_COMPONENTS) +#define RB_COMPONENTS 4 +#endif + + +static void +NAME(get_row)( struct gl_context *ctx, struct gl_renderbuffer *rb, + GLuint count, GLint x, GLint y, void *values ) +{ +#ifdef SPAN_VARS + SPAN_VARS +#endif + RB_TYPE (*dest)[RB_COMPONENTS] = (RB_TYPE (*)[RB_COMPONENTS]) values; + GLuint i; + INIT_PIXEL_PTR(pixel, x, y); + for (i = 0; i < count; i++) { + FETCH_PIXEL(dest[i], pixel); + INC_PIXEL_PTR(pixel); + } + (void) rb; + (void) ctx; +} + + +static void +NAME(get_values)( struct gl_context *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], void *values ) +{ +#ifdef SPAN_VARS + SPAN_VARS +#endif + RB_TYPE (*dest)[RB_COMPONENTS] = (RB_TYPE (*)[RB_COMPONENTS]) values; + GLuint i; + for (i = 0; i < count; i++) { + INIT_PIXEL_PTR(pixel, x[i], y[i]); + FETCH_PIXEL(dest[i], pixel); + } + (void) rb; + (void) ctx; +} + + +static void +NAME(put_row)( struct gl_context *ctx, struct gl_renderbuffer *rb, + GLuint count, GLint x, GLint y, + const void *values, const GLubyte mask[] ) +{ +#ifdef SPAN_VARS + SPAN_VARS +#endif + const RB_TYPE (*src)[RB_COMPONENTS] = (const RB_TYPE (*)[RB_COMPONENTS]) values; + GLuint i; + INIT_PIXEL_PTR(pixel, x, y); + if (mask) { + for (i = 0; i < count; i++) { + if (mask[i]) { + STORE_PIXEL(pixel, x + i, y, src[i]); + } + INC_PIXEL_PTR(pixel); + } + } + else { + for (i = 0; i < count; i++) { + STORE_PIXEL(pixel, x + i, y, src[i]); + INC_PIXEL_PTR(pixel); + } + } + (void) rb; + (void) ctx; +} + + +static void +NAME(put_row_rgb)( struct gl_context *ctx, struct gl_renderbuffer *rb, + GLuint count, GLint x, GLint y, + const void *values, const GLubyte mask[] ) +{ +#ifdef SPAN_VARS + SPAN_VARS +#endif + const RB_TYPE (*src)[3] = (const RB_TYPE (*)[3]) values; + GLuint i; + INIT_PIXEL_PTR(pixel, x, y); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { +#ifdef STORE_PIXEL_RGB + STORE_PIXEL_RGB(pixel, x + i, y, src[i]); +#else + STORE_PIXEL(pixel, x + i, y, src[i]); +#endif + } + INC_PIXEL_PTR(pixel); + } + (void) rb; + (void) ctx; +} + + +static void +NAME(put_mono_row)( struct gl_context *ctx, struct gl_renderbuffer *rb, + GLuint count, GLint x, GLint y, + const void *value, const GLubyte mask[] ) +{ +#ifdef SPAN_VARS + SPAN_VARS +#endif + const RB_TYPE *src = (const RB_TYPE *) value; + GLuint i; + INIT_PIXEL_PTR(pixel, x, y); + if (mask) { + for (i = 0; i < count; i++) { + if (mask[i]) { + STORE_PIXEL(pixel, x + i, y, src); + } + INC_PIXEL_PTR(pixel); + } + } + else { + for (i = 0; i < count; i++) { + STORE_PIXEL(pixel, x + i, y, src); + INC_PIXEL_PTR(pixel); + } + } + (void) rb; + (void) ctx; +} + + +static void +NAME(put_values)( struct gl_context *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], + const void *values, const GLubyte mask[] ) +{ +#ifdef SPAN_VARS + SPAN_VARS +#endif + const RB_TYPE (*src)[RB_COMPONENTS] = (const RB_TYPE (*)[RB_COMPONENTS]) values; + GLuint i; + ASSERT(mask); + for (i = 0; i < count; i++) { + if (mask[i]) { + INIT_PIXEL_PTR(pixel, x[i], y[i]); + STORE_PIXEL(pixel, x[i], y[i], src[i]); + } + } + (void) rb; + (void) ctx; +} + + +static void +NAME(put_mono_values)( struct gl_context *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], + const void *value, const GLubyte mask[] ) +{ +#ifdef SPAN_VARS + SPAN_VARS +#endif + const RB_TYPE *src = (const RB_TYPE *) value; + GLuint i; + ASSERT(mask); + for (i = 0; i < count; i++) { + if (mask[i]) { + INIT_PIXEL_PTR(pixel, x[i], y[i]); + STORE_PIXEL(pixel, x[i], y[i], src); + } + } + (void) rb; + (void) ctx; +} + + +#undef NAME +#undef RB_TYPE +#undef RB_COMPONENTS +#undef SPAN_VARS +#undef INIT_PIXEL_PTR +#undef INC_PIXEL_PTR +#undef STORE_PIXEL +#undef STORE_PIXEL_RGB +#undef FETCH_PIXEL diff --git a/pixman/configure.ac b/pixman/configure.ac index 4c62102be..21613e135 100644 --- a/pixman/configure.ac +++ b/pixman/configure.ac @@ -54,7 +54,7 @@ AC_PREREQ([2.57]) m4_define([pixman_major], 0) m4_define([pixman_minor], 23) -m4_define([pixman_micro], 3) +m4_define([pixman_micro], 5) m4_define([pixman_version],[pixman_major.pixman_minor.pixman_micro]) @@ -801,6 +801,17 @@ fi AC_MSG_RESULT($support_for_attribute_constructor) AC_SUBST(TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR) +dnl ================== +dnl libpng + +AC_CHECK_LIB([png], [png_write_info], [have_libpng=yes], [have_libpng=no]) + +if test x$have_libpng = xyes; then + AC_DEFINE([HAVE_LIBPNG], [1], [Whether we have libpng]) +fi + +AC_SUBST(HAVE_LIBPNG) + AC_OUTPUT([pixman-1.pc pixman-1-uninstalled.pc Makefile diff --git a/pixman/pixman/pixman-arm-neon-asm.S b/pixman/pixman/pixman-arm-neon-asm.S index 3dc14d79d..3fcd07dc3 100644 --- a/pixman/pixman/pixman-arm-neon-asm.S +++ b/pixman/pixman/pixman-arm-neon-asm.S @@ -706,13 +706,55 @@ generate_composite_function_single_scanline \ /******************************************************************************/ -/* TODO: expand macros and do better instructions scheduling */ +.macro pixman_composite_over_n_8888_process_pixblock_head + /* deinterleaved source pixels in {d0, d1, d2, d3} */ + /* inverted alpha in {d24} */ + /* destination pixels in {d4, d5, d6, d7} */ + vmull.u8 q8, d24, d4 + vmull.u8 q9, d24, d5 + vmull.u8 q10, d24, d6 + vmull.u8 q11, d24, d7 +.endm + +.macro pixman_composite_over_n_8888_process_pixblock_tail + vrshr.u16 q14, q8, #8 + vrshr.u16 q15, q9, #8 + vrshr.u16 q2, q10, #8 + vrshr.u16 q3, q11, #8 + vraddhn.u16 d28, q14, q8 + vraddhn.u16 d29, q15, q9 + vraddhn.u16 d30, q2, q10 + vraddhn.u16 d31, q3, q11 + vqadd.u8 q14, q0, q14 + vqadd.u8 q15, q1, q15 +.endm + .macro pixman_composite_over_n_8888_process_pixblock_tail_head - pixman_composite_over_8888_8888_process_pixblock_tail + vrshr.u16 q14, q8, #8 + vrshr.u16 q15, q9, #8 + vrshr.u16 q2, q10, #8 + vrshr.u16 q3, q11, #8 + vraddhn.u16 d28, q14, q8 + vraddhn.u16 d29, q15, q9 + vraddhn.u16 d30, q2, q10 + vraddhn.u16 d31, q3, q11 vld4.8 {d4, d5, d6, d7}, [DST_R, :128]! - vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! - pixman_composite_over_8888_8888_process_pixblock_head - cache_preload 8, 8 + vqadd.u8 q14, q0, q14 + PF add PF_X, PF_X, #8 + PF tst PF_CTL, #0x0F + PF addne PF_X, PF_X, #8 + PF subne PF_CTL, PF_CTL, #1 + vqadd.u8 q15, q1, q15 + PF cmp PF_X, ORIG_W + vmull.u8 q8, d24, d4 + PF pld, [PF_DST, PF_X, lsl #dst_bpp_shift] + vmull.u8 q9, d24, d5 + PF subge PF_X, PF_X, ORIG_W + vmull.u8 q10, d24, d6 + PF subges PF_CTL, PF_CTL, #0x10 + vmull.u8 q11, d24, d7 + PF ldrgeb DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! + vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! .endm .macro pixman_composite_over_n_8888_init @@ -722,6 +764,7 @@ generate_composite_function_single_scanline \ vdup.8 d1, d3[1] vdup.8 d2, d3[2] vdup.8 d3, d3[3] + vmvn.8 d24, d3 /* get inverted alpha */ .endm generate_composite_function \ @@ -1183,49 +1226,83 @@ generate_composite_function \ /* mask is in d24 (d25, d26, d27 are unused) */ /* in */ - vmull.u8 q0, d24, d8 - vmull.u8 q1, d24, d9 - vmull.u8 q6, d24, d10 - vmull.u8 q7, d24, d11 - vrshr.u16 q10, q0, #8 - vrshr.u16 q11, q1, #8 - vrshr.u16 q12, q6, #8 - vrshr.u16 q13, q7, #8 - vraddhn.u16 d0, q0, q10 - vraddhn.u16 d1, q1, q11 - vraddhn.u16 d2, q6, q12 - vraddhn.u16 d3, q7, q13 - vmvn.8 d24, d3 /* get inverted alpha */ + vmull.u8 q6, d24, d8 + vmull.u8 q7, d24, d9 + vmull.u8 q8, d24, d10 + vmull.u8 q9, d24, d11 + vrshr.u16 q10, q6, #8 + vrshr.u16 q11, q7, #8 + vrshr.u16 q12, q8, #8 + vrshr.u16 q13, q9, #8 + vraddhn.u16 d0, q6, q10 + vraddhn.u16 d1, q7, q11 + vraddhn.u16 d2, q8, q12 + vraddhn.u16 d3, q9, q13 + vmvn.8 d25, d3 /* get inverted alpha */ /* source: d0 - blue, d1 - green, d2 - red, d3 - alpha */ /* destination: d4 - blue, d5 - green, d6 - red, d7 - alpha */ /* now do alpha blending */ - vmull.u8 q8, d24, d4 - vmull.u8 q9, d24, d5 - vmull.u8 q10, d24, d6 - vmull.u8 q11, d24, d7 + vmull.u8 q8, d25, d4 + vmull.u8 q9, d25, d5 + vmull.u8 q10, d25, d6 + vmull.u8 q11, d25, d7 .endm .macro pixman_composite_over_n_8_8888_process_pixblock_tail vrshr.u16 q14, q8, #8 vrshr.u16 q15, q9, #8 - vrshr.u16 q12, q10, #8 - vrshr.u16 q13, q11, #8 + vrshr.u16 q6, q10, #8 + vrshr.u16 q7, q11, #8 vraddhn.u16 d28, q14, q8 vraddhn.u16 d29, q15, q9 - vraddhn.u16 d30, q12, q10 - vraddhn.u16 d31, q13, q11 + vraddhn.u16 d30, q6, q10 + vraddhn.u16 d31, q7, q11 vqadd.u8 q14, q0, q14 vqadd.u8 q15, q1, q15 .endm -/* TODO: expand macros and do better instructions scheduling */ .macro pixman_composite_over_n_8_8888_process_pixblock_tail_head - pixman_composite_over_n_8_8888_process_pixblock_tail - vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! + vrshr.u16 q14, q8, #8 vld4.8 {d4, d5, d6, d7}, [DST_R, :128]! + vrshr.u16 q15, q9, #8 fetch_mask_pixblock - cache_preload 8, 8 - pixman_composite_over_n_8_8888_process_pixblock_head + vrshr.u16 q6, q10, #8 + PF add PF_X, PF_X, #8 + vrshr.u16 q7, q11, #8 + PF tst PF_CTL, #0x0F + vraddhn.u16 d28, q14, q8 + PF addne PF_X, PF_X, #8 + vraddhn.u16 d29, q15, q9 + PF subne PF_CTL, PF_CTL, #1 + vraddhn.u16 d30, q6, q10 + PF cmp PF_X, ORIG_W + vraddhn.u16 d31, q7, q11 + PF pld, [PF_DST, PF_X, lsl #dst_bpp_shift] + vmull.u8 q6, d24, d8 + PF pld, [PF_MASK, PF_X, lsl #mask_bpp_shift] + vmull.u8 q7, d24, d9 + PF subge PF_X, PF_X, ORIG_W + vmull.u8 q8, d24, d10 + PF subges PF_CTL, PF_CTL, #0x10 + vmull.u8 q9, d24, d11 + PF ldrgeb DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! + vqadd.u8 q14, q0, q14 + PF ldrgeb DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]! + vqadd.u8 q15, q1, q15 + vrshr.u16 q10, q6, #8 + vrshr.u16 q11, q7, #8 + vrshr.u16 q12, q8, #8 + vrshr.u16 q13, q9, #8 + vraddhn.u16 d0, q6, q10 + vraddhn.u16 d1, q7, q11 + vraddhn.u16 d2, q8, q12 + vraddhn.u16 d3, q9, q13 + vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! + vmvn.8 d25, d3 + vmull.u8 q8, d25, d4 + vmull.u8 q9, d25, d5 + vmull.u8 q10, d25, d6 + vmull.u8 q11, d25, d7 .endm .macro pixman_composite_over_n_8_8888_init diff --git a/pixman/pixman/pixman-bits-image.c b/pixman/pixman/pixman-bits-image.c index f540c76e1..f382c65ad 100644 --- a/pixman/pixman/pixman-bits-image.c +++ b/pixman/pixman/pixman-bits-image.c @@ -935,17 +935,16 @@ MAKE_FETCHERS (reflect_r5g6b5, r5g6b5, PIXMAN_REPEAT_REFLECT) MAKE_FETCHERS (normal_r5g6b5, r5g6b5, PIXMAN_REPEAT_NORMAL) static void -bits_image_fetch_solid_32 (pixman_image_t * image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t * mask) +replicate_pixel_32 (bits_image_t * bits, + int x, + int y, + int width, + uint32_t * buffer) { uint32_t color; uint32_t *end; - color = image->bits.fetch_pixel_32 (&image->bits, 0, 0); + color = bits->fetch_pixel_32 (bits, x, y); end = buffer + width; while (buffer < end) @@ -953,24 +952,45 @@ bits_image_fetch_solid_32 (pixman_image_t * image, } static void -bits_image_fetch_solid_64 (pixman_image_t * image, - int x, - int y, - int width, - uint32_t * b, - const uint32_t * unused) +replicate_pixel_64 (bits_image_t * bits, + int x, + int y, + int width, + uint32_t * b) { uint64_t color; uint64_t *buffer = (uint64_t *)b; uint64_t *end; - color = image->bits.fetch_pixel_64 (&image->bits, 0, 0); + color = bits->fetch_pixel_64 (bits, x, y); end = buffer + width; while (buffer < end) *(buffer++) = color; } +static void +bits_image_fetch_solid_32 (pixman_image_t * image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t * mask) +{ + replicate_pixel_32 (&image->bits, 0, 0, width, buffer); +} + +static void +bits_image_fetch_solid_64 (pixman_image_t * image, + int x, + int y, + int width, + uint32_t * b, + const uint32_t * unused) +{ + replicate_pixel_64 (&image->bits, 0, 0, width, b); +} + static void bits_image_fetch_untransformed_repeat_none (bits_image_t *image, pixman_bool_t wide, @@ -1031,6 +1051,16 @@ bits_image_fetch_untransformed_repeat_normal (bits_image_t *image, while (y >= image->height) y -= image->height; + if (image->width == 1) + { + if (wide) + replicate_pixel_64 (image, 0, y, width, buffer); + else + replicate_pixel_32 (image, 0, y, width, buffer); + + return; + } + while (width) { while (x < 0) diff --git a/pixman/test/Makefile.am b/pixman/test/Makefile.am index 9f61fc9e4..52ef8ad96 100644 --- a/pixman/test/Makefile.am +++ b/pixman/test/Makefile.am @@ -1,6 +1,6 @@ AM_CFLAGS = @OPENMP_CFLAGS@ AM_LDFLAGS = @OPENMP_CFLAGS@ @TESTPROGS_EXTRA_LDFLAGS@ -LDADD = $(top_builddir)/pixman/libpixman-1.la -lm +LDADD = $(top_builddir)/pixman/libpixman-1.la -lm -lpng INCLUDES = -I$(top_srcdir)/pixman -I$(top_builddir)/pixman TESTPROGRAMS = \ diff --git a/pixman/test/utils.c b/pixman/test/utils.c index 44188ea90..adabd75dd 100644 --- a/pixman/test/utils.c +++ b/pixman/test/utils.c @@ -21,6 +21,10 @@ #include #endif +#ifdef HAVE_LIBPNG +#include +#endif + /* Random number seed */ @@ -335,6 +339,114 @@ make_random_bytes (int n_bytes) return bytes; } +#ifdef HAVE_LIBPNG + +static void +pngify_pixels (uint32_t *pixels, int n_pixels) +{ + int i; + + for (i = 0; i < n_pixels; ++i) + { + uint32_t p = pixels[i]; + uint8_t *out = (uint8_t *)&(pixels[i]); + uint8_t a, r, g, b; + + a = (p & 0xff000000) >> 24; + r = (p & 0x00ff0000) >> 16; + g = (p & 0x0000ff00) >> 8; + b = (p & 0x000000ff) >> 0; + + if (a != 0) + { + r = (r * 255) / a; + g = (g * 255) / a; + b = (b * 255) / a; + } + + *out++ = r; + *out++ = g; + *out++ = b; + *out++ = a; + } +} + +pixman_bool_t +write_png (pixman_image_t *image, const char *filename) +{ + int width = pixman_image_get_width (image); + int height = pixman_image_get_height (image); + int stride = width * 4; + uint32_t *data = malloc (height * stride); + pixman_image_t *copy; + png_struct *write_struct; + png_info *info_struct; + pixman_bool_t result = FALSE; + FILE *f = fopen (filename, "wb"); + png_bytep *row_pointers; + int i; + + if (!f) + return FALSE; + + row_pointers = malloc (height * sizeof (png_bytep)); + + copy = pixman_image_create_bits ( + PIXMAN_a8r8g8b8, width, height, data, stride); + + pixman_image_composite32 ( + PIXMAN_OP_SRC, image, NULL, copy, 0, 0, 0, 0, 0, 0, width, height); + + pngify_pixels (data, height * width); + + for (i = 0; i < height; ++i) + row_pointers[i] = (png_bytep)(data + i * width); + + if (!(write_struct = png_create_write_struct ( + PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) + goto out1; + + if (!(info_struct = png_create_info_struct (write_struct))) + goto out2; + + png_init_io (write_struct, f); + + png_set_IHDR (write_struct, info_struct, width, height, + 8, PNG_COLOR_TYPE_RGB_ALPHA, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, + PNG_FILTER_TYPE_BASE); + + png_write_info (write_struct, info_struct); + + png_write_image (write_struct, row_pointers); + + png_write_end (write_struct, NULL); + + result = TRUE; + +out2: + png_destroy_write_struct (&write_struct, &info_struct); + +out1: + if (fclose (f) != 0) + result = FALSE; + + pixman_image_unref (copy); + free (row_pointers); + free (data); + return result; +} + +#else /* no libpng */ + +pixman_bool_t +write_png (pixman_image_t *image, const char *filename) +{ + return FALSE; +} + +#endif + /* * A function, which can be used as a core part of the test programs, * intended to detect various problems with the help of fuzzing input diff --git a/pixman/test/utils.h b/pixman/test/utils.h index f0c9c300c..3790483db 100644 --- a/pixman/test/utils.h +++ b/pixman/test/utils.h @@ -105,6 +105,9 @@ fail_after (int seconds, const char *msg); /* If possible, enable traps for floating point exceptions */ void enable_fp_exceptions(void); +pixman_bool_t +write_png (pixman_image_t *image, const char *filename); + /* A pair of macros which can help to detect corruption of * floating point registers after a function call. This may * happen if _mm_empty() call is forgotten in MMX/SSE2 fast -- cgit v1.2.3