diff options
Diffstat (limited to 'src/gallium')
42 files changed, 772 insertions, 358 deletions
diff --git a/src/gallium/Makefile.template b/src/gallium/Makefile.template index 2e3da436cd..63983c5220 100644 --- a/src/gallium/Makefile.template +++ b/src/gallium/Makefile.template @@ -41,7 +41,7 @@ depend: $(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES) $(SYMLINKS) # Emacs tags tags: - etags `find . -name \*.[ch]` `find ../include` + etags `find . -name \*.[ch]` `find $(TOP)/src/gallium/include -name \*.h` # Remove .o and backup files clean: diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.c b/src/gallium/auxiliary/tgsi/tgsi_build.c index 010d501c60..e0cfc54420 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_build.c +++ b/src/gallium/auxiliary/tgsi/tgsi_build.c @@ -482,6 +482,8 @@ tgsi_default_full_instruction( void ) full_instruction.FullSrcRegisters[i] = tgsi_default_full_src_register(); } + full_instruction.Flags = 0x0; + return full_instruction; } diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.c b/src/gallium/auxiliary/tgsi/tgsi_dump.c index f36b1114a9..05b07a3a73 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_dump.c +++ b/src/gallium/auxiliary/tgsi/tgsi_dump.c @@ -33,12 +33,19 @@ #include "tgsi_info.h" #include "tgsi_iterate.h" + +/** Number of spaces to indent for IF/LOOP/etc */ +static const int indent_spaces = 3; + + struct dump_ctx { struct tgsi_iterate_context iter; uint instno; + uint indentation; + void (*printf)(struct dump_ctx *ctx, const char *format, ...); }; @@ -328,6 +335,14 @@ tgsi_dump_immediate( iter_immediate( &ctx.iter, (struct tgsi_full_immediate *)imm ); } +static void +indent(struct dump_ctx *ctx) +{ + uint i; + for (i = 0; i < ctx->indentation; i++) + TXT(" "); +} + static boolean iter_instruction( struct tgsi_iterate_context *iter, @@ -341,6 +356,15 @@ iter_instruction( INSTID( instno ); TXT( ": " ); + + /* update indentation */ + if (inst->Instruction.Opcode == TGSI_OPCODE_ENDIF || + inst->Instruction.Opcode == TGSI_OPCODE_ENDFOR || + inst->Instruction.Opcode == TGSI_OPCODE_ENDLOOP) { + ctx->indentation -= indent_spaces; + } + indent(ctx); + TXT( tgsi_get_opcode_info( inst->Instruction.Opcode )->mnemonic ); switch (inst->Instruction.Saturate) { @@ -481,6 +505,14 @@ iter_instruction( break; } + /* update indentation */ + if (inst->Instruction.Opcode == TGSI_OPCODE_IF || + inst->Instruction.Opcode == TGSI_OPCODE_ELSE || + inst->Instruction.Opcode == TGSI_OPCODE_BGNFOR || + inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP) { + ctx->indentation += indent_spaces; + } + EOL(); return TRUE; @@ -495,6 +527,7 @@ tgsi_dump_instruction( ctx.instno = instno; ctx.printf = dump_ctx_printf; + ctx.indentation = 0; iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst ); } @@ -527,6 +560,7 @@ tgsi_dump( ctx.instno = 0; ctx.printf = dump_ctx_printf; + ctx.indentation = 0; tgsi_iterate_shader( tokens, &ctx.iter ); } @@ -579,6 +613,7 @@ tgsi_dump_str( ctx.base.instno = 0; ctx.base.printf = &str_dump_ctx_printf; + ctx.base.indentation = 0; ctx.str = str; ctx.str[0] = 0; diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c index 951ecfd552..711e86d6ed 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.c +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c @@ -62,6 +62,9 @@ #define FAST_MATH 1 +/** for tgsi_full_instruction::Flags */ +#define SOA_DEPENDENCY_FLAG 0x1 + #define TILE_TOP_LEFT 0 #define TILE_TOP_RIGHT 1 #define TILE_BOTTOM_LEFT 2 @@ -182,7 +185,7 @@ print_temp(const struct tgsi_exec_machine *mach, uint index) * MOV t3, t2; * The second instruction will have the wrong value for t0 if executed as-is. */ -static boolean +boolean tgsi_check_soa_dependencies(const struct tgsi_full_instruction *inst) { uint i, chan; @@ -328,19 +331,24 @@ tgsi_exec_machine_bind_shader( * sizeof(struct tgsi_full_instruction)); maxInstructions += 10; } - memcpy(instructions + numInstructions, - &parse.FullToken.FullInstruction, - sizeof(instructions[0])); -#if 0 if (tgsi_check_soa_dependencies(&parse.FullToken.FullInstruction)) { - debug_printf("SOA dependency in instruction:\n"); - tgsi_dump_instruction(&parse.FullToken.FullInstruction, - numInstructions); + uint opcode = parse.FullToken.FullInstruction.Instruction.Opcode; + parse.FullToken.FullInstruction.Flags = SOA_DEPENDENCY_FLAG; + /* XXX we only handle SOA dependencies properly for MOV/SWZ + * at this time! + */ + if (opcode != TGSI_OPCODE_MOV && opcode != TGSI_OPCODE_SWZ) { + debug_printf("Warning: SOA dependency in instruction" + " is not handled:\n"); + tgsi_dump_instruction(&parse.FullToken.FullInstruction, + numInstructions); + } } -#else - (void) tgsi_check_soa_dependencies; -#endif + + memcpy(instructions + numInstructions, + &parse.FullToken.FullInstruction, + sizeof(instructions[0])); numInstructions++; break; @@ -2024,9 +2032,23 @@ exec_instruction( case TGSI_OPCODE_MOV: case TGSI_OPCODE_SWZ: - FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { - FETCH( &r[0], 0, chan_index ); - STORE( &r[0], 0, chan_index ); + if (inst->Flags & SOA_DEPENDENCY_FLAG) { + /* Do all fetches into temp regs, then do all stores to avoid + * intermediate/accidental clobbering. This could be done all the + * time for MOV but for other instructions we'll need more temps... + */ + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[chan_index], 0, chan_index ); + } + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + STORE( &r[chan_index], 0, chan_index ); + } + } + else { + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + STORE( &r[0], 0, chan_index ); + } } break; diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h index 8a9100f4c3..fd9ef6f35d 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.h +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h @@ -272,6 +272,14 @@ tgsi_exec_machine_run( struct tgsi_exec_machine *mach ); +void +tgsi_exec_machine_free_data(struct tgsi_exec_machine *mach); + + +boolean +tgsi_check_soa_dependencies(const struct tgsi_full_instruction *inst); + + static INLINE void tgsi_set_kill_mask(struct tgsi_exec_machine *mach, unsigned mask) { diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.h b/src/gallium/auxiliary/tgsi/tgsi_parse.h index 1035bda1a8..a26ee5ba86 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_parse.h +++ b/src/gallium/auxiliary/tgsi/tgsi_parse.h @@ -87,6 +87,7 @@ struct tgsi_full_instruction struct tgsi_instruction_ext_texture InstructionExtTexture; struct tgsi_full_dst_register FullDstRegisters[TGSI_FULL_MAX_DST_REGISTERS]; struct tgsi_full_src_register FullSrcRegisters[TGSI_FULL_MAX_SRC_REGISTERS]; + uint Flags; /**< user-defined usage */ }; union tgsi_full_token diff --git a/src/gallium/auxiliary/tgsi/tgsi_ppc.c b/src/gallium/auxiliary/tgsi/tgsi_ppc.c index 2d6ad12ffb..4b1c7d4e01 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ppc.c +++ b/src/gallium/auxiliary/tgsi/tgsi_ppc.c @@ -1108,6 +1108,15 @@ static int emit_instruction(struct gen_context *gen, struct tgsi_full_instruction *inst) { + + /* we don't handle saturation/clamping yet */ + if (inst->Instruction.Saturate != TGSI_SAT_NONE) + return 0; + + /* need to use extra temps to fix SOA dependencies : */ + if (tgsi_check_soa_dependencies(inst)) + return FALSE; + switch (inst->Instruction.Opcode) { case TGSI_OPCODE_MOV: case TGSI_OPCODE_SWZ: diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.c b/src/gallium/auxiliary/tgsi/tgsi_sse2.c index cfec5cfc01..46f2387c15 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_sse2.c +++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.c @@ -1747,6 +1747,14 @@ emit_instruction( if (indirect_temp_reference(inst)) return FALSE; + /* we don't handle saturation/clamping yet */ + if (inst->Instruction.Saturate != TGSI_SAT_NONE) + return FALSE; + + /* need to use extra temps to fix SOA dependencies : */ + if (tgsi_check_soa_dependencies(inst)) + return FALSE; + switch (inst->Instruction.Opcode) { case TGSI_OPCODE_ARL: FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) { diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c index ba84a82b2b..7922931361 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c @@ -31,6 +31,7 @@ #include "tgsi/tgsi_ureg.h" #include "tgsi/tgsi_dump.h" #include "util/u_memory.h" +#include "util/u_math.h" union tgsi_any_token { struct tgsi_version version; @@ -103,6 +104,7 @@ struct ureg_program unsigned nr_constants; unsigned nr_samplers; + unsigned nr_instructions; struct ureg_tokens domain[2]; }; @@ -301,7 +303,7 @@ out: */ struct ureg_src ureg_DECL_constant(struct ureg_program *ureg ) { - return ureg_src_register( TGSI_FILE_TEMPORARY, ureg->nr_constants++ ); + return ureg_src_register( TGSI_FILE_CONSTANT, ureg->nr_constants++ ); } @@ -392,7 +394,7 @@ struct ureg_src ureg_DECL_immediate( struct ureg_program *ureg, unsigned nr ) { unsigned i; - unsigned swizzle; + unsigned swizzle = 0; /* Could do a first pass where we examine all existing immediates * without expanding. @@ -525,7 +527,9 @@ ureg_emit_insn(struct ureg_program *ureg, out[0].insn.NumSrcRegs = num_src; out[0].insn.Padding = 0; out[0].insn.Extended = 0; - + + ureg->nr_instructions++; + return ureg->domain[DOMAIN_INSN].count - 1; } @@ -544,6 +548,31 @@ ureg_emit_label(struct ureg_program *ureg, out[0].value = 0; out[0].insn_ext_label.Type = TGSI_INSTRUCTION_EXT_TYPE_LABEL; + + *label_token = ureg->domain[DOMAIN_INSN].count - 1; +} + +/* Will return a number which can be used in a label to point to the + * next instruction to be emitted. + */ +unsigned +ureg_get_instruction_number( struct ureg_program *ureg ) +{ + return ureg->nr_instructions; +} + +/* Patch a given label (expressed as a token number) to point to a + * given instruction (expressed as an instruction number). + */ +void +ureg_fixup_label(struct ureg_program *ureg, + unsigned label_token, + unsigned instruction_number ) +{ + union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, label_token ); + + assert(out->insn_ext_label.Type == TGSI_INSTRUCTION_EXT_TYPE_LABEL); + out->insn_ext_label.Label = instruction_number; } @@ -571,6 +600,7 @@ ureg_fixup_insn_size(struct ureg_program *ureg, { union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, insn ); + assert(out->insn.Type == TGSI_TOKEN_TYPE_INSTRUCTION); out->insn.NrTokens = ureg->domain[DOMAIN_INSN].count - insn - 1; } @@ -710,8 +740,7 @@ static void copy_instructions( struct ureg_program *ureg ) static void -fixup_header_size(struct ureg_program *ureg, - unsigned insn ) +fixup_header_size(struct ureg_program *ureg ) { union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_DECL, 1 ); @@ -739,12 +768,11 @@ emit_header( struct ureg_program *ureg ) void *ureg_create_shader( struct ureg_program *ureg ) { struct pipe_shader_state state; - unsigned insn; emit_header( ureg ); emit_decls( ureg ); copy_instructions( ureg ); - fixup_header_size( ureg, insn ); + fixup_header_size( ureg ); if (ureg->domain[0].tokens == error_tokens || ureg->domain[1].tokens == error_tokens) { diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.h b/src/gallium/auxiliary/tgsi/tgsi_ureg.h index 0a976fd63b..5a48bb7a35 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ureg.h +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.h @@ -175,6 +175,33 @@ ureg_DECL_immediate1f( struct ureg_program *ureg, } /*********************************************************************** + * Functions for patching up labels + */ + + +/* Will return a number which can be used in a label to point to the + * next instruction to be emitted. + */ +unsigned +ureg_get_instruction_number( struct ureg_program *ureg ); + + +/* Patch a given label (expressed as a token number) to point to a + * given instruction (expressed as an instruction number). + * + * Labels are obtained from instruction emitters, eg ureg_CAL(). + * Instruction numbers are obtained from ureg_get_instruction_number(), + * above. + */ +void +ureg_fixup_label(struct ureg_program *ureg, + unsigned label_token, + unsigned instruction_number ); + + + + +/*********************************************************************** * Internal instruction helpers, don't call these directly: */ diff --git a/src/gallium/auxiliary/util/u_rect.c b/src/gallium/auxiliary/util/u_rect.c index 74259d453b..9866b6fc8a 100644 --- a/src/gallium/auxiliary/util/u_rect.c +++ b/src/gallium/auxiliary/util/u_rect.c @@ -43,7 +43,7 @@ * src_pitch may be negative to do vertical flip of pixels from source. */ void -pipe_copy_rect(ubyte * dst, +util_copy_rect(ubyte * dst, const struct pipe_format_block *block, unsigned dst_stride, unsigned dst_x, @@ -91,7 +91,7 @@ pipe_copy_rect(ubyte * dst, } void -pipe_fill_rect(ubyte * dst, +util_fill_rect(ubyte * dst, const struct pipe_format_block *block, unsigned dst_stride, unsigned dst_x, @@ -204,7 +204,7 @@ util_surface_copy(struct pipe_context *pipe, if (src_map && dst_map) { /* If do_flip, invert src_y position and pass negative src stride */ - pipe_copy_rect(dst_map, + util_copy_rect(dst_map, &dst_trans->block, dst_trans->stride, 0, 0, @@ -263,7 +263,7 @@ util_surface_fill(struct pipe_context *pipe, case 1: case 2: case 4: - pipe_fill_rect(dst_map, &dst_trans->block, dst_trans->stride, + util_fill_rect(dst_map, &dst_trans->block, dst_trans->stride, 0, 0, width, height, value); break; case 8: diff --git a/src/gallium/auxiliary/util/u_rect.h b/src/gallium/auxiliary/util/u_rect.h index 59e842e16d..daa50834d3 100644 --- a/src/gallium/auxiliary/util/u_rect.h +++ b/src/gallium/auxiliary/util/u_rect.h @@ -42,13 +42,13 @@ struct pipe_surface; extern void -pipe_copy_rect(ubyte * dst, const struct pipe_format_block *block, +util_copy_rect(ubyte * dst, const struct pipe_format_block *block, unsigned dst_stride, unsigned dst_x, unsigned dst_y, unsigned width, unsigned height, const ubyte * src, int src_stride, unsigned src_x, int src_y); extern void -pipe_fill_rect(ubyte * dst, const struct pipe_format_block *block, +util_fill_rect(ubyte * dst, const struct pipe_format_block *block, unsigned dst_stride, unsigned dst_x, unsigned dst_y, unsigned width, unsigned height, uint32_t value); diff --git a/src/gallium/auxiliary/util/u_tile.c b/src/gallium/auxiliary/util/u_tile.c index 422bc76003..9e76cfbb05 100644 --- a/src/gallium/auxiliary/util/u_tile.c +++ b/src/gallium/auxiliary/util/u_tile.c @@ -62,7 +62,7 @@ pipe_get_tile_raw(struct pipe_transfer *pt, if(!src) return; - pipe_copy_rect(dst, &pt->block, dst_stride, 0, 0, w, h, src, pt->stride, x, y); + util_copy_rect(dst, &pt->block, dst_stride, 0, 0, w, h, src, pt->stride, x, y); screen->transfer_unmap(screen, pt); } @@ -90,7 +90,7 @@ pipe_put_tile_raw(struct pipe_transfer *pt, if(!dst) return; - pipe_copy_rect(dst, &pt->block, pt->stride, x, y, w, h, src, src_stride, 0, 0); + util_copy_rect(dst, &pt->block, pt->stride, x, y, w, h, src, src_stride, 0, 0); screen->transfer_unmap(screen, pt); } diff --git a/src/gallium/drivers/i965simple/brw_surface.c b/src/gallium/drivers/i965simple/brw_surface.c index 511779dbfa..724a69b2ee 100644 --- a/src/gallium/drivers/i965simple/brw_surface.c +++ b/src/gallium/drivers/i965simple/brw_surface.c @@ -60,7 +60,7 @@ brw_surface_copy(struct pipe_context *pipe, src, PIPE_BUFFER_USAGE_CPU_READ ); - pipe_copy_rect(dst_map, + util_copy_rect(dst_map, &dst->block, dst->stride, dstx, dsty, @@ -99,7 +99,7 @@ brw_surface_fill(struct pipe_context *pipe, dst, PIPE_BUFFER_USAGE_CPU_WRITE ); - pipe_fill_rect(dst_map, &dst->block, dst->stride, dstx, dsty, width, height, value); + util_fill_rect(dst_map, &dst->block, dst->stride, dstx, dsty, width, height, value); pipe->screen->surface_unmap(pipe->screen, dst); } diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index 5cbc2c8f82..4de6e8cfa2 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -120,6 +120,7 @@ struct nv50_state { struct nouveau_stateobj *fragprog; struct nouveau_stateobj *vtxfmt; struct nouveau_stateobj *vtxbuf; + struct nouveau_stateobj *vtxattr; }; struct nv50_context { diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c index a879df2e6e..99d5b96e45 100644 --- a/src/gallium/drivers/nv50/nv50_state_validate.c +++ b/src/gallium/drivers/nv50/nv50_state_validate.c @@ -204,6 +204,8 @@ nv50_state_emit(struct nv50_context *nv50) if (nv50->state.dirty & NV50_NEW_ARRAYS) { so_emit(chan, nv50->state.vtxfmt); so_emit(chan, nv50->state.vtxbuf); + if (nv50->state.vtxattr) + so_emit(chan, nv50->state.vtxattr); } nv50->state.dirty = 0; diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c index 17283f3f41..36f1b24b2f 100644 --- a/src/gallium/drivers/nv50/nv50_vbo.c +++ b/src/gallium/drivers/nv50/nv50_vbo.c @@ -49,55 +49,80 @@ nv50_prim(unsigned mode) return NV50TCL_VERTEX_BEGIN_POINTS; } -static INLINE unsigned -nv50_vtxeltfmt(unsigned pf) +static INLINE uint32_t +nv50_vbo_type_to_hw(unsigned type) { - static const uint8_t vtxelt_32[4] = { 0x90, 0x20, 0x10, 0x08 }; - static const uint8_t vtxelt_16[4] = { 0xd8, 0x78, 0x28, 0x18 }; - static const uint8_t vtxelt_08[4] = { 0xe8, 0xc0, 0x98, 0x50 }; - - unsigned nf, c = 0; - - switch (pf_type(pf)) { + switch (type) { case PIPE_FORMAT_TYPE_FLOAT: - nf = NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_FLOAT; break; + return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_FLOAT; case PIPE_FORMAT_TYPE_UNORM: - nf = NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_UNORM; break; + return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_UNORM; case PIPE_FORMAT_TYPE_SNORM: - nf = NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_SNORM; break; + return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_SNORM; case PIPE_FORMAT_TYPE_USCALED: - nf = NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_USCALED; break; + return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_USCALED; case PIPE_FORMAT_TYPE_SSCALED: - nf = NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_SSCALED; break; + return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_SSCALED; + /* + case PIPE_FORMAT_TYPE_UINT: + return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_UINT; + case PIPE_FORMAT_TYPE_SINT: + return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_SINT; */ default: - NOUVEAU_ERR("invalid vbo type %d\n",pf_type(pf)); - assert(0); - nf = NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_FLOAT; - break; + return 0; } +} - if (pf_size_y(pf)) c++; - if (pf_size_z(pf)) c++; - if (pf_size_w(pf)) c++; +static INLINE uint32_t +nv50_vbo_size_to_hw(unsigned size, unsigned nr_c) +{ + static const uint32_t hw_values[] = { + 0, 0, 0, 0, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_8, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_8_8, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_8_8_8, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_8_8_8_8, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_16, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_16_16, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_16_16_16, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_16_16_16_16, + 0, 0, 0, 0, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_32, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_32_32, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_32_32_32, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_32_32_32_32 }; - if (pf_exp2(pf) == 3) { - switch (pf_size_x(pf)) { - case 1: return (nf | (vtxelt_08[c] << 16)); - case 2: return (nf | (vtxelt_16[c] << 16)); - case 4: return (nf | (vtxelt_32[c] << 16)); - default: - break; - } - } else - if (pf_exp2(pf) == 6 && pf_size_x(pf) == 1) { - NOUVEAU_ERR("unsupported vbo component size 64\n"); - assert(0); - return (nf | 0x08000000); + /* we'd also have R11G11B10 and R10G10B10A2 */ + + assert(nr_c > 0 && nr_c <= 4); + + if (size > 32) + return 0; + size >>= (3 - 2); + + return hw_values[size + (nr_c - 1)]; +} + +static INLINE uint32_t +nv50_vbo_vtxelt_to_hw(struct pipe_vertex_element *ve) +{ + uint32_t hw_type, hw_size; + enum pipe_format pf = ve->src_format; + unsigned size = pf_size_x(pf) << pf_exp2(pf); + + hw_type = nv50_vbo_type_to_hw(pf_type(pf)); + hw_size = nv50_vbo_size_to_hw(size, ve->nr_components); + + if (!hw_type || !hw_size) { + NOUVEAU_ERR("unsupported vbo format: %s\n", pf_name(pf)); + abort(); + return 0x24e80000; } - NOUVEAU_ERR("invalid vbo format %s\n",pf_name(pf)); - assert(0); - return (nf | 0x08000000); + if (pf_swizzle_x(pf) == 2) /* BGRA */ + hw_size |= (1 << 31); /* no real swizzle bits :-( */ + + return (hw_type | hw_size); } boolean @@ -252,18 +277,78 @@ nv50_draw_elements(struct pipe_context *pipe, return TRUE; } +static INLINE boolean +nv50_vbo_static_attrib(struct nv50_context *nv50, unsigned attrib, + struct nouveau_stateobj **pso, + struct pipe_vertex_element *ve, + struct pipe_vertex_buffer *vb) + +{ + struct nouveau_stateobj *so; + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_bo *bo = nouveau_bo(vb->buffer); + float *v; + int ret; + enum pipe_format pf = ve->src_format; + + if ((pf_type(pf) != PIPE_FORMAT_TYPE_FLOAT) || + (pf_size_x(pf) << pf_exp2(pf)) != 32) + return FALSE; + + ret = nouveau_bo_map(bo, NOUVEAU_BO_RD); + if (ret) + return FALSE; + v = (float *)(bo->map + (vb->buffer_offset + ve->src_offset)); + + so = *pso; + if (!so) + *pso = so = so_new(nv50->vtxelt_nr * 5, 0); + + switch (ve->nr_components) { + case 4: + so_method(so, tesla, NV50TCL_VTX_ATTR_4F_X(attrib), 4); + so_data (so, fui(v[0])); + so_data (so, fui(v[1])); + so_data (so, fui(v[2])); + so_data (so, fui(v[3])); + break; + case 3: + so_method(so, tesla, NV50TCL_VTX_ATTR_3F_X(attrib), 4); + so_data (so, fui(v[0])); + so_data (so, fui(v[1])); + so_data (so, fui(v[2])); + break; + case 2: + so_method(so, tesla, NV50TCL_VTX_ATTR_2F_X(attrib), 4); + so_data (so, fui(v[0])); + so_data (so, fui(v[1])); + break; + case 1: + so_method(so, tesla, NV50TCL_VTX_ATTR_1F(attrib), 4); + so_data (so, fui(v[0])); + break; + default: + nouveau_bo_unmap(bo); + return FALSE; + } + + nouveau_bo_unmap(bo); + return TRUE; +} + void nv50_vbo_validate(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; - struct nouveau_stateobj *vtxbuf, *vtxfmt; - int i; + struct nouveau_stateobj *vtxbuf, *vtxfmt, *vtxattr; + unsigned i; /* don't validate if Gallium took away our buffers */ if (nv50->vtxbuf_nr == 0) return; - vtxbuf = so_new(nv50->vtxelt_nr * 4, nv50->vtxelt_nr * 2); + vtxattr = NULL; + vtxbuf = so_new(nv50->vtxelt_nr * 7, nv50->vtxelt_nr * 4); vtxfmt = so_new(nv50->vtxelt_nr + 1, 0); so_method(vtxfmt, tesla, NV50TCL_VERTEX_ARRAY_ATTRIB(0), nv50->vtxelt_nr); @@ -273,8 +358,18 @@ nv50_vbo_validate(struct nv50_context *nv50) struct pipe_vertex_buffer *vb = &nv50->vtxbuf[ve->vertex_buffer_index]; struct nouveau_bo *bo = nouveau_bo(vb->buffer); + uint32_t hw = nv50_vbo_vtxelt_to_hw(ve); - so_data(vtxfmt, nv50_vtxeltfmt(ve->src_format) | i); + if (!vb->stride && + nv50_vbo_static_attrib(nv50, i, &vtxattr, ve, vb)) { + so_data(vtxfmt, hw | (1 << 4)); + + so_method(vtxbuf, tesla, + NV50TCL_VERTEX_ARRAY_FORMAT(i), 1); + so_data (vtxbuf, 0); + continue; + } + so_data(vtxfmt, hw | i); so_method(vtxbuf, tesla, NV50TCL_VERTEX_ARRAY_FORMAT(i), 3); so_data (vtxbuf, 0x20000000 | vb->stride); @@ -284,11 +379,22 @@ nv50_vbo_validate(struct nv50_context *nv50) so_reloc (vtxbuf, bo, vb->buffer_offset + ve->src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); + + /* vertex array limits */ + so_method(vtxbuf, tesla, 0x1080 + (i * 8), 2); + so_reloc (vtxbuf, bo, vb->buffer->size - 1, + NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD | + NOUVEAU_BO_HIGH, 0, 0); + so_reloc (vtxbuf, bo, vb->buffer->size - 1, + NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD | + NOUVEAU_BO_LOW, 0, 0); } so_ref (vtxfmt, &nv50->state.vtxfmt); so_ref (vtxbuf, &nv50->state.vtxbuf); + so_ref (vtxattr, &nv50->state.vtxattr); so_ref (NULL, &vtxbuf); so_ref (NULL, &vtxfmt); + so_ref (NULL, &vtxattr); } diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c index 00fae8d26f..d138866d33 100644 --- a/src/gallium/drivers/r300/r300_chipset.c +++ b/src/gallium/drivers/r300/r300_chipset.c @@ -30,9 +30,11 @@ void r300_parse_chipset(struct r300_capabilities* caps) { /* Reasonable defaults */ + caps->num_vert_fpus = 4; caps->has_tcl = getenv("RADEON_NO_TCL") ? FALSE : TRUE; caps->is_r500 = FALSE; - caps->num_vert_fpus = 4; + caps->high_second_pipe = FALSE; + /* Note: These are not ordered by PCI ID. I leave that task to GCC, * which will perform the ordering while collating jump tables. Instead, @@ -40,6 +42,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) switch (caps->pci_id) { case 0x4144: caps->family = CHIP_FAMILY_R300; + caps->high_second_pipe = TRUE; break; case 0x4145: @@ -50,6 +53,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x4E46: case 0x4E47: caps->family = CHIP_FAMILY_R300; + caps->high_second_pipe = TRUE; break; case 0x4150: @@ -66,6 +70,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x4E54: case 0x4E56: caps->family = CHIP_FAMILY_RV350; + caps->high_second_pipe = TRUE; break; case 0x4148: @@ -76,10 +81,12 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x4E49: case 0x4E4B: caps->family = CHIP_FAMILY_R350; + caps->high_second_pipe = TRUE; break; case 0x4E4A: caps->family = CHIP_FAMILY_R360; + caps->high_second_pipe = TRUE; break; case 0x5460: @@ -91,6 +98,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x5B64: case 0x5B65: caps->family = CHIP_FAMILY_RV370; + caps->high_second_pipe = TRUE; break; case 0x3150: @@ -99,6 +107,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x3E50: case 0x3E54: caps->family = CHIP_FAMILY_RV380; + caps->high_second_pipe = TRUE; break; case 0x4A48: diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h index 5b2e1f0568..322d4a57e4 100644 --- a/src/gallium/drivers/r300/r300_chipset.h +++ b/src/gallium/drivers/r300/r300_chipset.h @@ -34,6 +34,8 @@ struct r300_capabilities { int family; /* The number of vertex floating-point units */ int num_vert_fpus; + /* The number of fragment pipes */ + int num_frag_pipes; /* Whether or not TCL is physically present */ boolean has_tcl; /* Whether or not this is an RV515 or newer; R500s have many differences @@ -42,6 +44,8 @@ struct r300_capabilities { * - Blend color is split across two registers * - Universal Shader (US) block used for fragment shaders */ boolean is_r500; + /* Whether or not the second pixel pipe is accessed with the high bit */ + boolean high_second_pipe; }; /* Enumerations for legibility and telling which card we're running on. */ diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index c8510bc63e..da67bc29b8 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -88,9 +88,21 @@ static boolean r300_draw_arrays(struct pipe_context* pipe, unsigned mode, static void r300_destroy_context(struct pipe_context* context) { struct r300_context* r300 = r300_context(context); + struct r300_query* query, * temp; draw_destroy(r300->draw); + /* Free the OQ BO. */ + context->screen->buffer_destroy(r300->oqbo); + + /* If there are any queries pending or not destroyed, remove them now. */ + if (r300->query_list) { + foreach_s(query, temp, r300->query_list) { + remove_from_list(query); + FREE(query); + } + } + FREE(r300->blend_color_state); FREE(r300->rs_block); FREE(r300->scissor_state); @@ -145,6 +157,11 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300->context.is_texture_referenced = r300_is_texture_referenced; r300->context.is_buffer_referenced = r300_is_buffer_referenced; + r300->blend_color_state = CALLOC_STRUCT(r300_blend_color_state); + r300->rs_block = CALLOC_STRUCT(r300_rs_block); + r300->scissor_state = CALLOC_STRUCT(r300_scissor_state); + r300->viewport_state = CALLOC_STRUCT(r300_viewport_state); + /* Create a Draw. This is used for vert collation and SW TCL. */ r300->draw = draw_create(); /* Enable our renderer. */ @@ -155,10 +172,9 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, * transform in hardware, always. */ draw_set_viewport_state(r300->draw, &r300_viewport_identity); - r300->blend_color_state = CALLOC_STRUCT(r300_blend_color_state); - r300->rs_block = CALLOC_STRUCT(r300_rs_block); - r300->scissor_state = CALLOC_STRUCT(r300_scissor_state); - r300->viewport_state = CALLOC_STRUCT(r300_viewport_state); + /* Open up the OQ BO. */ + r300->oqbo = screen->buffer_create(screen, 4096, + PIPE_BUFFER_USAGE_VERTEX, 4096); r300_init_flush_functions(r300); diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index fc8a449893..f78492d4aa 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -25,9 +25,13 @@ #include "draw/draw_context.h" #include "draw/draw_vertex.h" + #include "pipe/p_context.h" + #include "tgsi/tgsi_scan.h" + #include "util/u_memory.h" +#include "util/u_simple_list.h" #include "r300_clear.h" #include "r300_query.h" @@ -150,6 +154,29 @@ struct r300_constant_buffer { unsigned count; }; +/* Query object. + * + * This is not a subclass of pipe_query because pipe_query is never + * actually fully defined. So, rather than have it as a member, and do + * subclass-style casting, we treat pipe_query as an opaque, and just + * trust that our state tracker does not ever mess up query objects. + */ +struct r300_query { + /* The kind of query. Currently only OQ is supported. */ + unsigned type; + /* Whether this query is currently active. Only active queries will + * get emitted into the command stream, and only active queries get + * tallied. */ + boolean active; + /* The current count of this query. Required to be at least 32 bits. */ + unsigned int count; + /* The offset of this query into the query buffer, in bytes. */ + unsigned offset; + /* Linked list members. */ + struct r300_query* prev; + struct r300_query* next; +}; + struct r300_texture { /* Parent class */ struct pipe_texture tex; @@ -203,6 +230,11 @@ struct r300_context { /* Offset into the VBO. */ size_t vbo_offset; + /* Occlusion query buffer. */ + struct pipe_buffer* oqbo; + /* Query list. */ + struct r300_query* query_list; + /* Various CSO state objects. */ /* Blend state. */ struct r300_blend_state* blend_state; diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 53256fc6dd..bd4d59e6f1 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -319,6 +319,79 @@ void r300_emit_fb_state(struct r300_context* r300, END_CS; } +void r300_emit_query_begin(struct r300_context* r300, + struct r300_query* query) +{ + CS_LOCALS(r300); + + /* XXX This will almost certainly not return good results + * for overlapping queries. */ + BEGIN_CS(2); + OUT_CS_REG(R300_ZB_ZPASS_DATA, 0); + END_CS; +} + +void r300_emit_query_end(struct r300_context* r300, + struct r300_query* query) +{ + struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps; + CS_LOCALS(r300); + + if (!r300->winsys->add_buffer(r300->winsys, r300->oqbo, + 0, RADEON_GEM_DOMAIN_GTT)) { + debug_printf("r300: There wasn't room for the OQ buffer!?" + " Oh noes!\n"); + } + + assert(caps->num_frag_pipes); + BEGIN_CS(6 * caps->num_frag_pipes + 2); + /* I'm not so sure I like this switch, but it's hard to be elegant + * when there's so many special cases... + * + * So here's the basic idea. For each pipe, enable writes to it only, + * then put out the relocation for ZPASS_ADDR, taking into account a + * 4-byte offset for each pipe. RV380 and older are special; they have + * only two pipes, and the second pipe's enable is on bit 3, not bit 1, + * so there's a chipset cap for that. */ + switch (caps->num_frag_pipes) { + case 4: + /* pipe 3 only */ + OUT_CS_REG(R300_SU_REG_DEST, 1 << 3); + OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); + OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 3), + 0, RADEON_GEM_DOMAIN_GTT, 0); + case 3: + /* pipe 2 only */ + OUT_CS_REG(R300_SU_REG_DEST, 1 << 2); + OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); + OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 2), + 0, RADEON_GEM_DOMAIN_GTT, 0); + case 2: + /* pipe 1 only */ + /* As mentioned above, accomodate RV380 and older. */ + OUT_CS_REG(R300_SU_REG_DEST, + 1 << (caps->high_second_pipe ? 3 : 1)); + OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); + OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 1), + 0, RADEON_GEM_DOMAIN_GTT, 0); + case 1: + /* pipe 0 only */ + OUT_CS_REG(R300_SU_REG_DEST, 1 << 0); + OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); + OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 0), + 0, RADEON_GEM_DOMAIN_GTT, 0); + default: + debug_printf("r300: Implementation error: Chipset reports %d" + " pixel pipes!\n", caps->num_frag_pipes); + assert(0); + } + + /* And, finally, reset it to normal... */ + OUT_CS_REG(R300_SU_REG_DEST, 0xF); + END_CS; + +} + void r300_emit_rs_state(struct r300_context* r300, struct r300_rs_state* rs) { CS_LOCALS(r300); @@ -615,6 +688,12 @@ validate: goto validate; } } + /* ...occlusion query buffer... */ + if (!r300->winsys->add_buffer(r300->winsys, r300->oqbo, + 0, RADEON_GEM_DOMAIN_GTT)) { + r300->context.flush(&r300->context, 0, NULL); + goto validate; + } /* ...and vertex buffer. */ if (r300->vbo) { if (!r300->winsys->add_buffer(r300->winsys, r300->vbo, diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c index 8fc61c2dec..1d5185b417 100644 --- a/src/gallium/drivers/r300/r300_query.c +++ b/src/gallium/drivers/r300/r300_query.c @@ -25,14 +25,30 @@ static struct pipe_query* r300_create_query(struct pipe_context* pipe, unsigned query_type) { - struct r300_query* q = CALLOC_STRUCT(r300_query); + struct r300_context* r300 = r300_context(pipe); + struct r300_screen* r300screen = r300_screen(r300->context.screen); + unsigned query_size = r300screen->caps->num_frag_pipes * 4; + struct r300_query* q, * qptr; + + q = CALLOC_STRUCT(r300_query); q->type = query_type; assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER); - /* XXX this is to force winsys to give us a GTT buffer */ - q->buf = pipe->screen->buffer_create(pipe->screen, 64, - PIPE_BUFFER_USAGE_VERTEX, 64); + q->active = FALSE; + + if (!r300->query_list) { + r300->query_list = q; + } else if (!is_empty_list(r300->query_list)) { + qptr = last_elem(r300->query_list); + q->offset = qptr->offset + query_size; + insert_at_tail(r300->query_list, q); + } + + /* XXX */ + if (q->offset >= 4096) { + q->offset = 0; + } return (struct pipe_query*)q; } @@ -40,6 +56,9 @@ static struct pipe_query* r300_create_query(struct pipe_context* pipe, static void r300_destroy_query(struct pipe_context* pipe, struct pipe_query* query) { + struct r300_query* q = (struct r300_query*)query; + + remove_from_list(q); FREE(query); } @@ -49,15 +68,15 @@ static void r300_begin_query(struct pipe_context* pipe, uint32_t* map; struct r300_context* r300 = r300_context(pipe); struct r300_query* q = (struct r300_query*)query; - CS_LOCALS(r300); - map = pipe_buffer_map(pipe->screen, q->buf, PIPE_BUFFER_USAGE_CPU_WRITE); + map = pipe->screen->buffer_map(pipe->screen, r300->oqbo, + PIPE_BUFFER_USAGE_CPU_WRITE); + map += q->offset / 4; *map = ~0; - pipe_buffer_unmap(pipe->screen, q->buf); + pipe->screen->buffer_unmap(pipe->screen, r300->oqbo); - BEGIN_CS(2); - OUT_CS_REG(R300_ZB_ZPASS_DATA, 0); - END_CS; + r300_emit_dirty_state(r300); + r300_emit_query_begin(r300, q); } static void r300_end_query(struct pipe_context* pipe, @@ -65,12 +84,9 @@ static void r300_end_query(struct pipe_context* pipe, { struct r300_context* r300 = r300_context(pipe); struct r300_query* q = (struct r300_query*)query; - CS_LOCALS(r300); - BEGIN_CS(4); - OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(q->buf, 0, 0, RADEON_GEM_DOMAIN_GTT, 0); - END_CS; + r300_emit_dirty_state(r300); + r300_emit_query_end(r300, q); } static boolean r300_get_query_result(struct pipe_context* pipe, @@ -78,22 +94,38 @@ static boolean r300_get_query_result(struct pipe_context* pipe, boolean wait, uint64_t* result) { + struct r300_context* r300 = r300_context(pipe); + struct r300_screen* r300screen = r300_screen(r300->context.screen); struct r300_query* q = (struct r300_query*)query; + unsigned flags = PIPE_BUFFER_USAGE_CPU_READ; uint32_t* map; uint32_t temp; + unsigned i; if (wait) { - /* Well, we're expected to just sit here and spin, so let's go ahead - * and flush so we can be sure that the card's spinning... */ - /* XXX double-check these params */ pipe->flush(pipe, 0, NULL); + } else { + flags |= PIPE_BUFFER_USAGE_DONTBLOCK; } - map = pipe_buffer_map(pipe->screen, q->buf, PIPE_BUFFER_USAGE_CPU_READ); - temp = *map; - pipe_buffer_unmap(pipe->screen, q->buf); + map = pipe->screen->buffer_map(pipe->screen, r300->oqbo, flags); + map += q->offset / 4; + for (i = 0; i < r300screen->caps->num_frag_pipes; i++) { + if (*map == ~0) { + /* Looks like our results aren't ready yet. */ + if (wait) { + debug_printf("r300: Despite waiting, OQ results haven't" + " come in yet.\n"); + } + temp = ~0; + break; + } + temp += *map; + map++; + } + pipe->screen->buffer_unmap(pipe->screen, r300->oqbo); - if (temp < 0) { + if (temp == ~0) { /* Our results haven't been written yet... */ return FALSE; } diff --git a/src/gallium/drivers/r300/r300_query.h b/src/gallium/drivers/r300/r300_query.h index 6a7646087a..4f50e8f844 100644 --- a/src/gallium/drivers/r300/r300_query.h +++ b/src/gallium/drivers/r300/r300_query.h @@ -29,13 +29,6 @@ struct r300_context; -struct r300_query { - /* The kind of query. Currently only OQ is supported. */ - unsigned type; - /* Buffer object where we want our results to reside. */ - struct pipe_buffer* buf; -}; - static INLINE struct r300_query* r300_query(struct pipe_query* q) { return (struct r300_query*)q; diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h index 6825d99870..03cd219cde 100644 --- a/src/gallium/drivers/r300/r300_reg.h +++ b/src/gallium/drivers/r300/r300_reg.h @@ -3312,6 +3312,10 @@ enum { #define R200_3D_DRAW_IMMD_2 0xC0003500 +/* XXX Oh look, stuff not brought over from docs yet */ + +#define R300_SU_REG_DEST 0x42C8 + #endif /* _R300_REG_H */ /* *INDENT-ON* */ diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 96a7304621..15740f6125 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -392,6 +392,7 @@ struct pipe_screen* r300_create_screen(struct r300_winsys* r300_winsys) return NULL; caps->pci_id = r300_winsys->pci_id; + caps->num_frag_pipes = r300_winsys->gb_pipes; r300_parse_chipset(caps); diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index a02fb34b2a..27680a3863 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -224,7 +224,8 @@ static void* dsa->alpha_reference = CLAMP(state->alpha.ref_value * 1023.0f, 0, 1023); } else { - dsa->z_buffer_top = R300_ZTOP_ENABLE; + /* XXX need to fix this to be dynamically set + dsa->z_buffer_top = R300_ZTOP_ENABLE; */ } return (void*)dsa; diff --git a/src/gallium/drivers/r300/r300_state_inlines.h b/src/gallium/drivers/r300/r300_state_inlines.h index 22c8e199ae..91b93fc367 100644 --- a/src/gallium/drivers/r300/r300_state_inlines.h +++ b/src/gallium/drivers/r300/r300_state_inlines.h @@ -353,6 +353,25 @@ static INLINE uint32_t r300_translate_out_fmt(enum pipe_format format) /* Non-CSO state. (For now.) */ +static INLINE uint32_t r300_translate_gb_pipes(int pipe_count) +{ + switch (pipe_count) { + case 1: + return R300_GB_TILE_PIPE_COUNT_RV300; + break; + case 2: + return R300_GB_TILE_PIPE_COUNT_R300; + break; + case 3: + return R300_GB_TILE_PIPE_COUNT_R420_3P; + break; + case 4: + return R300_GB_TILE_PIPE_COUNT_R420; + break; + } + return 0; +} + static INLINE uint32_t translate_vertex_data_type(int type) { switch (type) { case EMIT_1F: diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index d2893c3b9d..f18ad75a47 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -45,6 +45,9 @@ struct r300_winsys { /* PCI ID */ uint32_t pci_id; + /* GB pipe count */ + uint32_t gb_pipes; + /* GART size. */ uint32_t gart_size; diff --git a/src/gallium/drivers/trace/tr_dump.c b/src/gallium/drivers/trace/tr_dump.c index 643587ab42..7e2ccbcfdc 100644 --- a/src/gallium/drivers/trace/tr_dump.c +++ b/src/gallium/drivers/trace/tr_dump.c @@ -351,7 +351,7 @@ void trace_dump_call_begin_locked(const char *klass, const char *method) trace_dump_indent(1); trace_dump_writes("<call no=\'"); trace_dump_writef("%lu", call_no); - trace_dump_writes("\' class =\'"); + trace_dump_writes("\' class=\'"); trace_dump_escape(klass); trace_dump_writes("\' method=\'"); trace_dump_escape(method); diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h index 57e966ac3b..39620a7198 100644 --- a/src/gallium/include/pipe/p_context.h +++ b/src/gallium/include/pipe/p_context.h @@ -98,7 +98,7 @@ struct pipe_context { */ /*@{*/ struct pipe_query *(*create_query)( struct pipe_context *pipe, - unsigned query_type ); + unsigned query_type ); void (*destroy_query)(struct pipe_context *pipe, struct pipe_query *q); @@ -215,10 +215,12 @@ struct pipe_context { /** * Clear the specified set of currently bound buffers to specified values. + * The entire buffers are cleared (no scissor, no colormask, etc). * - * buffers is a bitfield of PIPE_CLEAR_* values. - * - * rgba is a pointer to an array of one float for each of r, g, b, a. + * \param buffers bitfield of PIPE_CLEAR_* values. + * \param rgba pointer to an array of one float for each of r, g, b, a. + * \param depth depth clear value in [0,1]. + * \param stencil stencil clear value */ void (*clear)(struct pipe_context *pipe, unsigned buffers, @@ -226,7 +228,9 @@ struct pipe_context { double depth, unsigned stencil); - /** Flush rendering (flags = bitmask of PIPE_FLUSH_x tokens) */ + /** Flush rendering + * \param flags bitmask of PIPE_FLUSH_x tokens) + */ void (*flush)( struct pipe_context *pipe, unsigned flags, struct pipe_fence_handle **fence ); @@ -242,10 +246,10 @@ struct pipe_context { * \param texture texture to check. * \param face cubemap face. Use 0 for non-cubemap texture. */ - unsigned int (*is_texture_referenced) (struct pipe_context *pipe, struct pipe_texture *texture, unsigned face, unsigned level); + /** * Check whether a buffer is referenced by an unflushed hw command. * The state-tracker uses this function to optimize away unnecessary @@ -255,7 +259,6 @@ struct pipe_context { * checked. * \param buf Buffer to check. */ - unsigned int (*is_buffer_referenced) (struct pipe_context *pipe, struct pipe_buffer *buf); }; diff --git a/src/gallium/include/pipe/p_inlines.h b/src/gallium/include/pipe/p_inlines.h index cf176c9209..a5c1e8270a 100644 --- a/src/gallium/include/pipe/p_inlines.h +++ b/src/gallium/include/pipe/p_inlines.h @@ -63,6 +63,13 @@ pipe_buffer_map(struct pipe_screen *screen, if(screen->buffer_map_range) { unsigned offset = 0; unsigned length = buf->size; + + /* XXX: Actually we should be using/detecting DISCARD + * instead of assuming that WRITE implies discard */ + if((usage & PIPE_BUFFER_USAGE_CPU_WRITE) && + !(usage & PIPE_BUFFER_USAGE_DISCARD)) + usage |= PIPE_BUFFER_USAGE_CPU_READ; + return screen->buffer_map_range(screen, buf, offset, length, usage); } else diff --git a/src/gallium/state_trackers/egl/egl_context.c b/src/gallium/state_trackers/egl/egl_context.c index 2c8f51cf38..52b6453d29 100644 --- a/src/gallium/state_trackers/egl/egl_context.c +++ b/src/gallium/state_trackers/egl/egl_context.c @@ -83,23 +83,16 @@ const struct dri_extension card_extensions[] = { {NULL, NULL} }; -EGLContext -drm_create_context(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list) +_EGLContext * +drm_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, _EGLContext *share_list, const EGLint *attrib_list) { struct drm_device *dev = (struct drm_device *)drv; struct drm_context *ctx; struct drm_context *share = NULL; struct st_context *st_share = NULL; - _EGLConfig *conf; int i; __GLcontextModes *visual; - conf = _eglLookupConfig(drv, dpy, config); - if (!conf) { - _eglError(EGL_BAD_CONFIG, "eglCreateContext"); - return EGL_NO_CONTEXT; - } - for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { switch (attrib_list[i]) { /* no attribs defined for now */ @@ -129,25 +122,20 @@ drm_create_context(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext if (!ctx->st) goto err_gl; - /* link to display */ - _eglLinkContext(&ctx->base, _eglLookupDisplay(dpy)); - assert(_eglGetContextHandle(&ctx->base)); - - return _eglGetContextHandle(&ctx->base); + return &ctx->base; err_gl: ctx->pipe->destroy(ctx->pipe); err_pipe: free(ctx); err_c: - return EGL_NO_CONTEXT; + return NULL; } EGLBoolean -drm_destroy_context(_EGLDriver *drv, EGLDisplay dpy, EGLContext context) +drm_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *context) { struct drm_context *c = lookup_drm_context(context); - _eglUnlinkContext(&c->base); if (!_eglIsContextBound(&c->base)) { st_destroy_context(c->st); c->pipe->destroy(c->pipe); @@ -157,7 +145,7 @@ drm_destroy_context(_EGLDriver *drv, EGLDisplay dpy, EGLContext context) } EGLBoolean -drm_make_current(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext context) +drm_make_current(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, _EGLSurface *read, _EGLContext *context) { struct drm_surface *readSurf = lookup_drm_surface(read); struct drm_surface *drawSurf = lookup_drm_surface(draw); diff --git a/src/gallium/state_trackers/egl/egl_surface.c b/src/gallium/state_trackers/egl/egl_surface.c index d4cd2d3c74..0cca68dc36 100644 --- a/src/gallium/state_trackers/egl/egl_surface.c +++ b/src/gallium/state_trackers/egl/egl_surface.c @@ -76,26 +76,8 @@ drm_create_texture(_EGLDriver *drv, struct pipe_surface *surface; struct pipe_texture *texture; struct pipe_texture templat; - struct pipe_buffer *buf; - unsigned stride = 1024; + struct pipe_buffer *buf = NULL; unsigned pitch = 0; - unsigned size = 0; - - /* ugly */ - if (stride < w) - stride = 2048; - - pitch = stride * 4; - size = h * 2 * pitch; - - buf = pipe_buffer_create(screen, - 0, /* alignment */ - PIPE_BUFFER_USAGE_GPU_READ_WRITE | - PIPE_BUFFER_USAGE_CPU_READ_WRITE, - size); - - if (!buf) - goto err_buf; memset(&templat, 0, sizeof(templat)); templat.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; @@ -108,13 +90,16 @@ drm_create_texture(_EGLDriver *drv, templat.height[0] = h; pf_get_block(templat.format, &templat.block); - texture = screen->texture_blanket(dev->screen, - &templat, - &pitch, - buf); + texture = screen->texture_create(dev->screen, + &templat); + if (!texture) goto err_tex; + dev->api->buffer_from_texture(dev->api, texture, &buf, &pitch); + if (!buf) + goto err_buf; + surface = screen->get_tex_surface(screen, texture, 0, @@ -125,7 +110,6 @@ drm_create_texture(_EGLDriver *drv, if (!surface) goto err_surf; - scrn->tex = texture; scrn->surface = surface; scrn->buffer = buf; @@ -142,9 +126,9 @@ err_handle: pipe_surface_reference(&surface, NULL); err_surf: pipe_texture_reference(&texture, NULL); +err_buf: err_tex: pipe_buffer_reference(&buf, NULL); -err_buf: return; } @@ -178,22 +162,22 @@ drm_takedown_shown_screen(_EGLDriver *drv, struct drm_screen *screen) screen->shown = 0; } -EGLSurface -drm_create_window_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list) +_EGLSurface * +drm_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativeWindowType window, const EGLint *attrib_list) { - return EGL_NO_SURFACE; + return NULL; } -EGLSurface -drm_create_pixmap_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list) +_EGLSurface * +drm_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativePixmapType pixmap, const EGLint *attrib_list) { - return EGL_NO_SURFACE; + return NULL; } -EGLSurface -drm_create_pbuffer_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, +_EGLSurface * +drm_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list) { int i; @@ -201,13 +185,6 @@ drm_create_pbuffer_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, int height = -1; struct drm_surface *surf = NULL; __GLcontextModes *visual; - _EGLConfig *conf; - - conf = _eglLookupConfig(drv, dpy, config); - if (!conf) { - _eglError(EGL_BAD_CONFIG, "eglCreatePbufferSurface"); - return EGL_NO_CONTEXT; - } for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { switch (attrib_list[i]) { @@ -225,7 +202,7 @@ drm_create_pbuffer_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, if (width < 1 || height < 1) { _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePbufferSurface"); - return EGL_NO_SURFACE; + return NULL; } surf = (struct drm_surface *) calloc(1, sizeof(struct drm_surface)); @@ -245,17 +222,16 @@ drm_create_pbuffer_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, (void*)surf); drm_visual_modes_destroy(visual); - _eglLinkSurface(&surf->base, _eglLookupDisplay(dpy)); - return surf->base.Handle; + return &surf->base; err_surf: free(surf); err: - return EGL_NO_SURFACE; + return NULL; } -EGLSurface -drm_create_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg, +_EGLSurface * +drm_create_screen_surface_mesa(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *cfg, const EGLint *attrib_list) { EGLSurface surf = drm_create_pbuffer_surface(drv, dpy, cfg, attrib_list); @@ -264,14 +240,13 @@ drm_create_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg, } EGLBoolean -drm_show_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy, - EGLScreenMESA screen, - EGLSurface surface, EGLModeMESA m) +drm_show_screen_surface_mesa(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLScreen *screen, + _EGLSurface *surface, _EGLMode *mode) { struct drm_device *dev = (struct drm_device *)drv; struct drm_surface *surf = lookup_drm_surface(surface); - struct drm_screen *scrn = lookup_drm_screen(dpy, screen); - _EGLMode *mode = _eglLookupMode(dpy, m); + struct drm_screen *scrn = lookup_drm_screen(screen); int ret; unsigned int i, k; @@ -361,11 +336,9 @@ err_bo: } EGLBoolean -drm_destroy_surface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) +drm_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface) { struct drm_surface *surf = lookup_drm_surface(surface); - _eglUnlinkSurface(&surf->base); - if (!_eglIsSurfaceBound(&surf->base)) { if (surf->screen) drm_takedown_shown_screen(drv, surf->screen); @@ -376,8 +349,9 @@ drm_destroy_surface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) } EGLBoolean -drm_swap_buffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) +drm_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw) { + struct drm_device *dev = (struct drm_device *)drv; struct drm_surface *surf = lookup_drm_surface(draw); struct pipe_surface *back_surf; @@ -395,7 +369,6 @@ drm_swap_buffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) st_notify_swapbuffers(surf->stfb); if (surf->screen) { - surf->user->pipe->flush(surf->user->pipe, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_TEXTURE_CACHE, NULL); surf->user->pipe->surface_copy(surf->user->pipe, surf->screen->surface, 0, 0, @@ -403,7 +376,15 @@ drm_swap_buffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) 0, 0, surf->w, surf->h); surf->user->pipe->flush(surf->user->pipe, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_TEXTURE_CACHE, NULL); - /* TODO stuff here */ + +#ifdef DRM_MODE_FEATURE_DIRTYFB + /* TODO query connector property to see if this is needed */ + drmModeDirtyFB(dev->drmFD, surf->screen->fbID, NULL, 0); +#else + (void)dev; +#endif + + /* TODO more stuff here */ } } diff --git a/src/gallium/state_trackers/egl/egl_tracker.c b/src/gallium/state_trackers/egl/egl_tracker.c index 521c91d895..57c81da767 100644 --- a/src/gallium/state_trackers/egl/egl_tracker.c +++ b/src/gallium/state_trackers/egl/egl_tracker.c @@ -6,6 +6,8 @@ #include <string.h> #include "egl_tracker.h" +#include <fcntl.h> + #include "egllog.h" #include "state_tracker/drm_api.h" @@ -21,12 +23,20 @@ extern const struct dri_extension card_extensions[]; * Exported functions */ +static void +drm_unload(_EGLDriver *drv) +{ + struct drm_device *dev = (struct drm_device *)drv; + dev->api->destroy(dev->api); + free(dev); +} + /** * The bootstrap function. Return a new drm_driver object and * plug in API functions. */ _EGLDriver * -_eglMain(_EGLDisplay *dpy, const char *args) +_eglMain(const char *args) { struct drm_device *drm; @@ -53,12 +63,8 @@ _eglMain(_EGLDisplay *dpy, const char *args) drm->base.API.ShowScreenSurfaceMESA = drm_show_screen_surface_mesa; drm->base.API.SwapBuffers = drm_swap_buffers; - drm->base.ClientAPIsMask = EGL_OPENGL_BIT /*| EGL_OPENGL_ES_BIT*/; drm->base.Name = "DRM/Gallium/Win"; - - /* enable supported extensions */ - drm->base.Extensions.MESA_screen_surface = EGL_TRUE; - drm->base.Extensions.MESA_copy_context = EGL_TRUE; + drm->base.Unload = drm_unload; return &drm->base; } @@ -128,10 +134,17 @@ drm_find_dpms(struct drm_device *dev, struct drm_screen *screen) screen->dpms = p; } +static int drm_open_minor(int minor) +{ + char buf[64]; + + sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor); + return open(buf, O_RDWR, 0); +} + EGLBoolean -drm_initialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor) +drm_initialize(_EGLDriver *drv, _EGLDisplay *disp, EGLint *major, EGLint *minor) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); struct drm_device *dev = (struct drm_device *)drv; struct drm_screen *screen = NULL; drmModeConnectorPtr connector = NULL; @@ -141,7 +154,8 @@ drm_initialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor) EGLint i; int fd; - fd = drmOpen("i915", NULL); + /* try the first node */ + fd = drm_open_minor(0); if (fd < 0) goto err_fd; @@ -200,7 +214,10 @@ drm_initialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor) _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_PBUFFER_BIT); _eglAddConfig(disp, config); - drv->Initialized = EGL_TRUE; + disp->ClientAPIsMask = EGL_OPENGL_BIT /*| EGL_OPENGL_ES_BIT*/; + /* enable supported extensions */ + disp->Extensions.MESA_screen_surface = EGL_TRUE; + disp->Extensions.MESA_copy_context = EGL_TRUE; *major = 1; *minor = 4; @@ -214,12 +231,14 @@ err_fd: } EGLBoolean -drm_terminate(_EGLDriver *drv, EGLDisplay dpy) +drm_terminate(_EGLDriver *drv, _EGLDisplay *dpy) { struct drm_device *dev = (struct drm_device *)drv; struct drm_screen *screen; int i = 0; + _eglReleaseDisplayResources(drv, dpy); + drmFreeVersion(dev->version); for (i = 0; i < dev->count_screens; i++) { @@ -236,12 +255,10 @@ drm_terminate(_EGLDriver *drv, EGLDisplay dpy) dev->screen->destroy(dev->screen); dev->winsys = NULL; - dev->api->destroy(dev->api); drmClose(dev->drmFD); - _eglCleanupDisplay(_eglLookupDisplay(dpy)); - free(dev); + _eglCleanupDisplay(dpy); return EGL_TRUE; } diff --git a/src/gallium/state_trackers/egl/egl_tracker.h b/src/gallium/state_trackers/egl/egl_tracker.h index 3b8836720d..25f70d885e 100644 --- a/src/gallium/state_trackers/egl/egl_tracker.h +++ b/src/gallium/state_trackers/egl/egl_tracker.h @@ -137,24 +137,21 @@ struct drm_screen static INLINE struct drm_context * -lookup_drm_context(EGLContext context) +lookup_drm_context(_EGLContext *c) { - _EGLContext *c = _eglLookupContext(context); return (struct drm_context *) c; } static INLINE struct drm_surface * -lookup_drm_surface(EGLSurface surface) +lookup_drm_surface(_EGLSurface *s) { - _EGLSurface *s = _eglLookupSurface(surface); return (struct drm_surface *) s; } static INLINE struct drm_screen * -lookup_drm_screen(EGLDisplay dpy, EGLScreenMESA screen) +lookup_drm_screen(_EGLScreen *s) { - _EGLScreen *s = _eglLookupScreen(dpy, screen); return (struct drm_screen *) s; } @@ -178,18 +175,18 @@ void drm_takedown_shown_screen(_EGLDriver *drv, struct drm_screen *screen); * All function exported to the egl side. */ /*@{*/ -EGLBoolean drm_initialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor); -EGLBoolean drm_terminate(_EGLDriver *drv, EGLDisplay dpy); -EGLContext drm_create_context(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list); -EGLBoolean drm_destroy_context(_EGLDriver *drv, EGLDisplay dpy, EGLContext context); -EGLSurface drm_create_window_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list); -EGLSurface drm_create_pixmap_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list); -EGLSurface drm_create_pbuffer_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); -EGLSurface drm_create_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg, const EGLint *attrib_list); -EGLBoolean drm_show_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface surface, EGLModeMESA m); -EGLBoolean drm_destroy_surface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface); -EGLBoolean drm_make_current(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext context); -EGLBoolean drm_swap_buffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw); +EGLBoolean drm_initialize(_EGLDriver *drv, _EGLDisplay *dpy, EGLint *major, EGLint *minor); +EGLBoolean drm_terminate(_EGLDriver *drv, _EGLDisplay *dpy); +_EGLContext *drm_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, _EGLContext *share_list, const EGLint *attrib_list); +EGLBoolean drm_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *context); +_EGLSurface *drm_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativeWindowType window, const EGLint *attrib_list); +_EGLSurface *drm_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativePixmapType pixmap, const EGLint *attrib_list); +_EGLSurface *drm_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list); +_EGLSurface *drm_create_screen_surface_mesa(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list); +EGLBoolean drm_show_screen_surface_mesa(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *screen, _EGLSurface *surface, _EGLMode *mode); +EGLBoolean drm_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface); +EGLBoolean drm_make_current(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, _EGLSurface *read, _EGLContext *context); +EGLBoolean drm_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw); /*@}*/ #endif diff --git a/src/gallium/state_trackers/glx/xlib/glx_api.c b/src/gallium/state_trackers/glx/xlib/glx_api.c index 96490dbeda..d1a98f8991 100644 --- a/src/gallium/state_trackers/glx/xlib/glx_api.c +++ b/src/gallium/state_trackers/glx/xlib/glx_api.c @@ -110,19 +110,6 @@ GetCurrentContext(void) /**********************************************************************/ -/*** Debug helper code ***/ -/**********************************************************************/ - -extern void _kw_ungrab_all( Display *dpy ); -void _kw_ungrab_all( Display *dpy ) -{ - XUngrabPointer( dpy, CurrentTime ); - XUngrabKeyboard( dpy, CurrentTime ); -} - - - -/**********************************************************************/ /*** GLX Visual Code ***/ /**********************************************************************/ @@ -1311,10 +1298,8 @@ void glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, unsigned long mask ) { - GLXContext fakeSrc = src; - GLXContext fakeDst = dst; - XMesaContext xm_src = fakeSrc->xmesaContext; - XMesaContext xm_dst = fakeDst->xmesaContext; + XMesaContext xm_src = src->xmesaContext; + XMesaContext xm_dst = dst->xmesaContext; (void) dpy; if (MakeCurrent_PrevContext == src) { _mesa_Flush(); diff --git a/src/gallium/state_trackers/python/retrace/parse.py b/src/gallium/state_trackers/python/retrace/parse.py index b0f3e8a432..b08d368671 100755 --- a/src/gallium/state_trackers/python/retrace/parse.py +++ b/src/gallium/state_trackers/python/retrace/parse.py @@ -371,7 +371,7 @@ class Main: stream = GzipFile(arg, 'rt') elif arg.endswith('.bz2'): from bz2 import BZ2File - stream = BZ2File(arg, 'rt') + stream = BZ2File(arg, 'rU') else: stream = open(arg, 'rt') self.process_arg(stream, options) diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c index f2dac73e90..8da113ec61 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa.c +++ b/src/gallium/state_trackers/xorg/xorg_exa.c @@ -491,7 +491,7 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0, PIPE_TRANSFER_WRITE, 0, 0, width, height); - pipe_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer), + util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer), &priv->tex->block, transfer->stride, 0, 0, width, height, pPixData, pPixmap->devKind, 0, 0); exa->scrn->transfer_unmap(exa->scrn, transfer); diff --git a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c index 775bda8308..07551e7cd1 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c @@ -134,18 +134,17 @@ static void *radeon_buffer_map(struct pipe_winsys *ws, (struct radeon_pipe_buffer*)buffer; int write = 0; - if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) { - /* XXX Remove this when radeon_bo_map supports DONTBLOCK */ - return NULL; + if (!(flags & PIPE_BUFFER_USAGE_DONTBLOCK)) { + radeon_bo_wait(radeon_buffer->bo); } if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) { write = 1; } - radeon_bo_wait(radeon_buffer->bo); - - if (radeon_bo_map(radeon_buffer->bo, write)) + if (radeon_bo_map(radeon_buffer->bo, write)) { return NULL; + } + return radeon_buffer->bo->ptr; } diff --git a/src/gallium/winsys/drm/radeon/core/radeon_r300.c b/src/gallium/winsys/drm/radeon/core/radeon_r300.c index 4e9a2ddd16..d723876221 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_r300.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_r300.c @@ -139,7 +139,17 @@ static void do_ioctls(struct r300_winsys* winsys, int fd) info.value = ⌖ - /* First, get PCI ID */ + /* First, get the number of pixel pipes */ + info.request = RADEON_INFO_NUM_GB_PIPES; + retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)); + if (retval) { + fprintf(stderr, "%s: Failed to get GB pipe count, " + "error number %d\n", __FUNCTION__, retval); + exit(1); + } + winsys->gb_pipes = target; + + /* Then, get PCI ID */ info.request = RADEON_INFO_DEVICE_ID; retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)); if (retval) { @@ -149,7 +159,7 @@ static void do_ioctls(struct r300_winsys* winsys, int fd) } winsys->pci_id = target; - /* Then, retrieve MM info */ + /* Finally, retrieve MM info */ retval = drmCommandWriteRead(fd, DRM_RADEON_GEM_INFO, &gem_info, sizeof(gem_info)); if (retval) { diff --git a/src/gallium/winsys/egl_xlib/egl_xlib.c b/src/gallium/winsys/egl_xlib/egl_xlib.c index f409a3fd6b..96f460f88a 100644 --- a/src/gallium/winsys/egl_xlib/egl_xlib.c +++ b/src/gallium/winsys/egl_xlib/egl_xlib.c @@ -62,6 +62,7 @@ struct xlib_egl_driver { _EGLDriver Base; /**< base class */ + EGLint apis; struct pipe_winsys *winsys; struct pipe_screen *screen; }; @@ -103,18 +104,16 @@ xlib_egl_driver(_EGLDriver *drv) static INLINE struct xlib_egl_surface * -lookup_surface(EGLSurface surf) +lookup_surface(_EGLSurface *surf) { - _EGLSurface *surface = _eglLookupSurface(surf); - return (struct xlib_egl_surface *) surface; + return (struct xlib_egl_surface *) surf; } static INLINE struct xlib_egl_context * -lookup_context(EGLContext ctx) +lookup_context(_EGLContext *ctx) { - _EGLContext *context = _eglLookupContext(ctx); - return (struct xlib_egl_context *) context; + return (struct xlib_egl_context *) ctx; } @@ -133,13 +132,12 @@ bitcount(unsigned int n) * Create the EGLConfigs. (one per X visual) */ static void -create_configs(_EGLDriver *drv, EGLDisplay dpy) +create_configs(_EGLDriver *drv, _EGLDisplay *disp) { static const EGLint all_apis = (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENVG_BIT | EGL_OPENGL_BIT); - _EGLDisplay *disp = _eglLookupDisplay(dpy); XVisualInfo *visInfo, visTemplate; int num_visuals, i; @@ -194,12 +192,18 @@ create_configs(_EGLDriver *drv, EGLDisplay dpy) * Called via eglInitialize(), drv->API.Initialize(). */ static EGLBoolean -xlib_eglInitialize(_EGLDriver *drv, EGLDisplay dpy, +xlib_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy, EGLint *minor, EGLint *major) { + struct xlib_egl_driver *xdrv = xlib_egl_driver(drv); + + if (!dpy->Xdpy) { + dpy->Xdpy = XOpenDisplay(NULL); + } + create_configs(drv, dpy); - drv->Initialized = EGL_TRUE; + dpy->ClientAPIsMask = xdrv->apis; /* we're supporting EGL 1.4 */ *minor = 1; @@ -213,8 +217,10 @@ xlib_eglInitialize(_EGLDriver *drv, EGLDisplay dpy, * Called via eglTerminate(), drv->API.Terminate(). */ static EGLBoolean -xlib_eglTerminate(_EGLDriver *drv, EGLDisplay dpy) +xlib_eglTerminate(_EGLDriver *drv, _EGLDisplay *dpy) { + _eglReleaseDisplayResources(drv, dpy); + _eglCleanupDisplay(dpy); return EGL_TRUE; } @@ -342,24 +348,23 @@ flush_frontbuffer(struct pipe_winsys *pws, /** * Called via eglCreateContext(), drv->API.CreateContext(). */ -static EGLContext -xlib_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, - EGLContext share_list, const EGLint *attrib_list) +static _EGLContext * +xlib_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, + _EGLContext *share_list, const EGLint *attrib_list) { struct xlib_egl_driver *xdrv = xlib_egl_driver(drv); - _EGLConfig *conf = _eglLookupConfig(drv, dpy, config); struct xlib_egl_context *ctx; struct st_context *share_ctx = NULL; /* XXX fix */ __GLcontextModes visual; ctx = CALLOC_STRUCT(xlib_egl_context); if (!ctx) - return EGL_NO_CONTEXT; + return NULL; /* let EGL lib init the common stuff */ if (!_eglInitContext(drv, &ctx->Base, conf, attrib_list)) { free(ctx); - return EGL_NO_CONTEXT; + return NULL; } /* API-dependent context creation */ @@ -379,41 +384,33 @@ xlib_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, default: _eglError(EGL_BAD_MATCH, "eglCreateContext(unsupported API)"); free(ctx); - return EGL_NO_CONTEXT; + return NULL; } - _eglLinkContext(&ctx->Base, _eglLookupDisplay(dpy)); - - return _eglGetContextHandle(&ctx->Base); + return &ctx->Base; } static EGLBoolean -xlib_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx) +xlib_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) { struct xlib_egl_context *context = lookup_context(ctx); - if (context) { - _eglUnlinkContext(&context->Base); - if (!_eglIsContextBound(&context->Base)) { - /* API-dependent clean-up */ - switch (context->Base.ClientAPI) { - case EGL_OPENGL_ES_API: - case EGL_OPENVG_API: - /* fall-through */ - case EGL_OPENGL_API: - st_destroy_context(context->Context); - break; - default: - assert(0); - } - free(context); + + if (!_eglIsContextBound(&context->Base)) { + /* API-dependent clean-up */ + switch (context->Base.ClientAPI) { + case EGL_OPENGL_ES_API: + case EGL_OPENVG_API: + /* fall-through */ + case EGL_OPENGL_API: + st_destroy_context(context->Context); + break; + default: + assert(0); } - return EGL_TRUE; - } - else { - _eglError(EGL_BAD_CONTEXT, "eglDestroyContext"); - return EGL_TRUE; + free(context); } + return EGL_TRUE; } @@ -421,20 +418,25 @@ xlib_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx) * Called via eglMakeCurrent(), drv->API.MakeCurrent(). */ static EGLBoolean -xlib_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, - EGLSurface draw, EGLSurface read, EGLContext ctx) +xlib_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx) { struct xlib_egl_context *context = lookup_context(ctx); struct xlib_egl_surface *draw_surf = lookup_surface(draw); struct xlib_egl_surface *read_surf = lookup_surface(read); - struct st_context *oldctx = st_get_current(); + struct st_context *oldcontext = NULL; + _EGLContext *oldctx; + + oldctx = _eglGetCurrentContext(); + if (oldctx && _eglIsContextLinked(oldctx)) + oldcontext = st_get_current(); - if (!_eglMakeCurrent(drv, dpy, draw, read, context)) + if (!_eglMakeCurrent(drv, dpy, draw, read, ctx)) return EGL_FALSE; /* Flush before switching context. Check client API? */ - if (oldctx) - st_flush(oldctx, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + if (oldcontext) + st_flush(oldcontext, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); st_make_current((context ? context->Context : NULL), (draw_surf ? draw_surf->Framebuffer : NULL), (read_surf ? read_surf->Framebuffer : NULL)); @@ -488,31 +490,26 @@ choose_stencil_format(const __GLcontextModes *visual) /** * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). */ -static EGLSurface -xlib_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, +static _EGLSurface * +xlib_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, NativeWindowType window, const EGLint *attrib_list) { struct xlib_egl_driver *xdrv = xlib_egl_driver(drv); - _EGLDisplay *disp = _eglLookupDisplay(dpy); - _EGLConfig *conf = _eglLookupConfig(drv, dpy, config); - struct xlib_egl_surface *surf; __GLcontextModes visual; uint width, height; surf = CALLOC_STRUCT(xlib_egl_surface); if (!surf) - return EGL_NO_SURFACE; + return NULL; /* Let EGL lib init the common stuff */ if (!_eglInitSurface(drv, &surf->Base, EGL_WINDOW_BIT, conf, attrib_list)) { free(surf); - return EGL_NO_SURFACE; + return NULL; } - _eglLinkSurface(&surf->Base, disp); - /* * Now init the Xlib and gallium stuff */ @@ -539,46 +536,35 @@ xlib_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, st_resize_framebuffer(surf->Framebuffer, width, height); - return _eglGetSurfaceHandle(&surf->Base); + return &surf->Base; } -static EGLSurface -xlib_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, +static _EGLSurface * +xlib_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, const EGLint *attrib_list) { struct xlib_egl_driver *xdrv = xlib_egl_driver(drv); - _EGLDisplay *disp = _eglLookupDisplay(dpy); - _EGLConfig *conf = _eglLookupConfig(drv, dpy, config); struct xlib_egl_surface *surf; __GLcontextModes visual; uint width, height; EGLBoolean bind_texture; - if (!disp) { - _eglError(EGL_BAD_DISPLAY, "eglCreatePbufferSurface"); - return EGL_NO_SURFACE; - } - if (!conf) { - _eglError(EGL_BAD_CONFIG, "eglCreatePbufferSurface"); - return EGL_NO_SURFACE; - } - surf = CALLOC_STRUCT(xlib_egl_surface); if (!surf) { _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface"); - return EGL_NO_SURFACE; + return NULL; } if (!_eglInitSurface(drv, &surf->Base, EGL_PBUFFER_BIT, conf, attrib_list)) { free(surf); - return EGL_NO_SURFACE; + return NULL; } if (surf->Base.Width < 0 || surf->Base.Height < 0) { _eglError(EGL_BAD_PARAMETER, "eglCreatePbufferSurface"); free(surf); - return EGL_NO_SURFACE; + return NULL; } bind_texture = (surf->Base.TextureFormat != EGL_NO_TEXTURE); @@ -588,19 +574,19 @@ xlib_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, (surf->Base.TextureTarget != EGL_NO_TEXTURE && !bind_texture)) { _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface"); free(surf); - return EGL_NO_SURFACE; + return NULL; } /* a framebuffer of zero width or height confuses st */ if (width == 0 || height == 0) { _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface"); free(surf); - return EGL_NO_SURFACE; + return NULL; } /* no mipmap generation */ if (surf->Base.MipmapTexture) { _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface"); free(surf); - return EGL_NO_SURFACE; + return NULL; } surf->winsys = xdrv->winsys; @@ -616,34 +602,27 @@ xlib_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, (void *) surf); st_resize_framebuffer(surf->Framebuffer, width, height); - return _eglLinkSurface(&surf->Base, disp); + return &surf->Base; } static EGLBoolean -xlib_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) +xlib_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface) { struct xlib_egl_surface *surf = lookup_surface(surface); - if (surf) { - _eglUnlinkSurface(&surf->Base); - if (!_eglIsSurfaceBound(&surf->Base)) { - if (surf->Base.Type != EGL_PBUFFER_BIT) - XFreeGC(surf->Dpy, surf->Gc); - st_unreference_framebuffer(surf->Framebuffer); - free(surf); - } - return EGL_TRUE; - } - else { - _eglError(EGL_BAD_SURFACE, "eglDestroySurface"); - return EGL_FALSE; + if (!_eglIsSurfaceBound(&surf->Base)) { + if (surf->Base.Type != EGL_PBUFFER_BIT) + XFreeGC(surf->Dpy, surf->Gc); + st_unreference_framebuffer(surf->Framebuffer); + free(surf); } + return EGL_TRUE; } static EGLBoolean -xlib_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, - EGLSurface surface, EGLint buffer) +xlib_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLSurface *surface, EGLint buffer) { struct xlib_egl_surface *xsurf = lookup_surface(surface); struct xlib_egl_context *xctx; @@ -680,12 +659,12 @@ xlib_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, /* flush properly */ if (eglGetCurrentSurface(EGL_DRAW) == surface) { - xctx = lookup_context(eglGetCurrentContext()); + xctx = lookup_context(_eglGetCurrentContext()); st_flush(xctx->Context, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); } else if (_eglIsSurfaceBound(&xsurf->Base)) { - xctx = lookup_context(_eglGetContextHandle(xsurf->Base.Binding)); + xctx = lookup_context(xsurf->Base.Binding); if (xctx) st_finish(xctx->Context); } @@ -700,7 +679,7 @@ xlib_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, static EGLBoolean -xlib_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, +xlib_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint buffer) { struct xlib_egl_surface *xsurf = lookup_surface(surface); @@ -722,7 +701,7 @@ xlib_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, static EGLBoolean -xlib_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) +xlib_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw) { /* error checking step: */ if (!_eglSwapBuffers(drv, dpy, draw)) @@ -779,12 +758,22 @@ find_supported_apis(void) } +static void +xlib_Unload(_EGLDriver *drv) +{ + struct xlib_egl_driver *xdrv = xlib_egl_driver(drv); + xdrv->screen->destroy(xdrv->screen); + free(xdrv->winsys); + free(xdrv); +} + + /** * This is the main entrypoint into the driver. * Called by libEGL to instantiate an _EGLDriver object. */ _EGLDriver * -_eglMain(_EGLDisplay *dpy, const char *args) +_eglMain(const char *args) { struct xlib_egl_driver *xdrv; @@ -794,10 +783,6 @@ _eglMain(_EGLDisplay *dpy, const char *args) if (!xdrv) return NULL; - if (!dpy->Xdpy) { - dpy->Xdpy = XOpenDisplay(NULL); - } - _eglInitDriverFallbacks(&xdrv->Base); xdrv->Base.API.Initialize = xlib_eglInitialize; xdrv->Base.API.Terminate = xlib_eglTerminate; @@ -812,16 +797,17 @@ _eglMain(_EGLDisplay *dpy, const char *args) xdrv->Base.API.MakeCurrent = xlib_eglMakeCurrent; xdrv->Base.API.SwapBuffers = xlib_eglSwapBuffers; - xdrv->Base.ClientAPIsMask = find_supported_apis(); - if (xdrv->Base.ClientAPIsMask == 0x0) { + xdrv->apis = find_supported_apis(); + if (xdrv->apis == 0x0) { /* the app isn't directly linked with any EGL-supprted APIs * (such as libGLESv2.so) so use an EGL utility to see what * APIs might be loaded dynamically on this system. */ - xdrv->Base.ClientAPIsMask = _eglFindAPIs(); - } + xdrv->apis = _eglFindAPIs(); + } xdrv->Base.Name = "Xlib/softpipe"; + xdrv->Base.Unload = xlib_Unload; /* create one winsys and use it for all contexts/surfaces */ xdrv->winsys = create_sw_winsys(); @@ -831,4 +817,3 @@ _eglMain(_EGLDisplay *dpy, const char *args) return &xdrv->Base; } - |
