diff options
Diffstat (limited to 'src/gallium')
198 files changed, 13198 insertions, 10039 deletions
diff --git a/src/gallium/Makefile b/src/gallium/Makefile index aa77021daf..291973c904 100644 --- a/src/gallium/Makefile +++ b/src/gallium/Makefile @@ -2,7 +2,7 @@ TOP = ../.. include $(TOP)/configs/current -SUBDIRS = auxiliary drivers +SUBDIRS = auxiliary drivers winsys/common default: subdirs diff --git a/src/gallium/auxiliary/draw/Makefile b/src/gallium/auxiliary/draw/Makefile index da7eded21f..f2e36a89e9 100644 --- a/src/gallium/auxiliary/draw/Makefile +++ b/src/gallium/auxiliary/draw/Makefile @@ -26,12 +26,18 @@ C_SOURCES = \ draw_pt_emit.c \ draw_pt_fetch.c \ draw_pt_fetch_emit.c \ + draw_pt_fetch_shade_emit.c \ draw_pt_fetch_shade_pipeline.c \ draw_pt_post_vs.c \ + draw_pt_util.c \ draw_pt_varray.c \ draw_pt_vcache.c \ draw_vertex.c \ draw_vs.c \ + draw_vs_varient.c \ + draw_vs_aos.c \ + draw_vs_aos_io.c \ + draw_vs_aos_machine.c \ draw_vs_exec.c \ draw_vs_llvm.c \ draw_vs_sse.c diff --git a/src/gallium/auxiliary/draw/SConscript b/src/gallium/auxiliary/draw/SConscript index 3b5d5ed492..544a04918b 100644 --- a/src/gallium/auxiliary/draw/SConscript +++ b/src/gallium/auxiliary/draw/SConscript @@ -15,7 +15,7 @@ draw = env.ConvenienceLibrary( 'draw_pipe_stipple.c', 'draw_pipe_twoside.c', 'draw_pipe_unfilled.c', - 'draw_pipe_util.c', + 'draw_pipe_util.c', 'draw_pipe_validate.c', 'draw_pipe_vbuf.c', 'draw_pipe_wide_line.c', @@ -25,15 +25,21 @@ draw = env.ConvenienceLibrary( 'draw_pt_emit.c', 'draw_pt_fetch.c', 'draw_pt_fetch_emit.c', + 'draw_pt_fetch_shade_emit.c', 'draw_pt_fetch_shade_pipeline.c', 'draw_pt_post_vs.c', + 'draw_pt_util.c', 'draw_pt_varray.c', 'draw_pt_vcache.c', 'draw_vertex.c', 'draw_vs.c', + 'draw_vs_aos.c', + 'draw_vs_aos_io.c', + 'draw_vs_aos_machine.c', 'draw_vs_exec.c', 'draw_vs_llvm.c', 'draw_vs_sse.c', + 'draw_vs_varient.c' ]) auxiliaries.insert(0, draw) diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c index 98e23fa830..2f263cf06a 100644 --- a/src/gallium/auxiliary/draw/draw_context.c +++ b/src/gallium/auxiliary/draw/draw_context.c @@ -56,12 +56,6 @@ struct draw_context *draw_create( void ) draw->reduced_prim = ~0; /* != any of PIPE_PRIM_x */ - tgsi_exec_machine_init(&draw->machine); - - /* FIXME: give this machine thing a proper constructor: - */ - draw->machine.Inputs = align_malloc(PIPE_MAX_ATTRIBS * sizeof(struct tgsi_exec_vector), 16); - draw->machine.Outputs = align_malloc(PIPE_MAX_ATTRIBS * sizeof(struct tgsi_exec_vector), 16); if (!draw_pipeline_init( draw )) goto fail; @@ -69,6 +63,9 @@ struct draw_context *draw_create( void ) if (!draw_pt_init( draw )) goto fail; + if (!draw_vs_init( draw )) + goto fail; + return draw; fail: @@ -83,13 +80,6 @@ void draw_destroy( struct draw_context *draw ) return; - if (draw->machine.Inputs) - align_free(draw->machine.Inputs); - - if (draw->machine.Outputs) - align_free(draw->machine.Outputs); - - tgsi_exec_machine_free_data(&draw->machine); /* Not so fast -- we're just borrowing this at the moment. * @@ -99,6 +89,7 @@ void draw_destroy( struct draw_context *draw ) draw_pipeline_destroy( draw ); draw_pt_destroy( draw ); + draw_vs_destroy( draw ); FREE( draw ); } @@ -183,6 +174,8 @@ void draw_set_viewport_state( struct draw_context *draw, viewport->translate[1] == 0.0f && viewport->translate[2] == 0.0f && viewport->translate[3] == 0.0f); + + draw_vs_set_viewport( draw, viewport ); } @@ -224,9 +217,11 @@ draw_set_mapped_vertex_buffer(struct draw_context *draw, void draw_set_mapped_constant_buffer(struct draw_context *draw, - const void *buffer) + const void *buffer, + unsigned size ) { draw->pt.user.constants = buffer; + draw_vs_set_constants( draw, (const float (*)[4])buffer, size ); } @@ -295,7 +290,7 @@ int draw_find_vs_output(struct draw_context *draw, uint semantic_name, uint semantic_index) { - const struct draw_vertex_shader *vs = draw->vertex_shader; + const struct draw_vertex_shader *vs = draw->vs.vertex_shader; uint i; for (i = 0; i < vs->info.num_outputs; i++) { if (vs->info.output_semantic_name[i] == semantic_name && @@ -320,7 +315,7 @@ draw_find_vs_output(struct draw_context *draw, uint draw_num_vs_outputs(struct draw_context *draw) { - uint count = draw->vertex_shader->info.num_outputs; + uint count = draw->vs.vertex_shader->info.num_outputs; if (draw->extra_vp_outputs.slot > 0) count++; return count; @@ -354,14 +349,30 @@ void draw_set_edgeflags( struct draw_context *draw, * \param elements the element buffer ptr */ void -draw_set_mapped_element_buffer( struct draw_context *draw, - unsigned eltSize, void *elements ) +draw_set_mapped_element_buffer_range( struct draw_context *draw, + unsigned eltSize, + unsigned min_index, + unsigned max_index, + void *elements ) { draw->pt.user.elts = elements; draw->pt.user.eltSize = eltSize; + draw->pt.user.min_index = min_index; + draw->pt.user.max_index = max_index; } +void +draw_set_mapped_element_buffer( struct draw_context *draw, + unsigned eltSize, + void *elements ) +{ + draw->pt.user.elts = elements; + draw->pt.user.eltSize = eltSize; + draw->pt.user.min_index = 0; + draw->pt.user.max_index = 0xffffffff; +} + /* Revamp me please: */ diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h index c5c3d3b09e..b8f2bfa332 100644 --- a/src/gallium/auxiliary/draw/draw_context.h +++ b/src/gallium/auxiliary/draw/draw_context.h @@ -118,14 +118,23 @@ void draw_set_vertex_elements(struct draw_context *draw, unsigned count, const struct pipe_vertex_element *elements); +void +draw_set_mapped_element_buffer_range( struct draw_context *draw, + unsigned eltSize, + unsigned min_index, + unsigned max_index, + void *elements ); + void draw_set_mapped_element_buffer( struct draw_context *draw, - unsigned eltSize, void *elements ); + unsigned eltSize, + void *elements ); void draw_set_mapped_vertex_buffer(struct draw_context *draw, unsigned attr, const void *buffer); void draw_set_mapped_constant_buffer(struct draw_context *draw, - const void *buffer); + const void *buffer, + unsigned size ); void draw_set_edgeflags( struct draw_context *draw, const unsigned *edgeflag ); diff --git a/src/gallium/auxiliary/draw/draw_pipe.c b/src/gallium/auxiliary/draw/draw_pipe.c index 46afb0f41f..3355c871ee 100644 --- a/src/gallium/auxiliary/draw/draw_pipe.c +++ b/src/gallium/auxiliary/draw/draw_pipe.c @@ -212,6 +212,72 @@ void draw_pipeline_run( struct draw_context *draw, draw->pipeline.vertex_count = 0; } +#define QUAD(i0,i1,i2,i3) \ + do_triangle( draw, \ + ( DRAW_PIPE_RESET_STIPPLE | \ + DRAW_PIPE_EDGE_FLAG_0 | \ + DRAW_PIPE_EDGE_FLAG_2 ), \ + verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \ + verts + stride * (i1), \ + verts + stride * (i3)); \ + do_triangle( draw, \ + ( DRAW_PIPE_EDGE_FLAG_0 | \ + DRAW_PIPE_EDGE_FLAG_1 ), \ + verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \ + verts + stride * (i2), \ + verts + stride * (i3)) + +#define TRIANGLE(flags,i0,i1,i2) \ + do_triangle( draw, \ + flags, /* flags */ \ + verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \ + verts + stride * (i1), \ + verts + stride * (i2)) + +#define LINE(flags,i0,i1) \ + do_line( draw, \ + flags, \ + verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \ + verts + stride * (i+1)) + +#define POINT(i0) \ + do_point( draw, \ + verts + stride * i0 ) + +#define FUNC pipe_run_linear +#define ARGS \ + struct draw_context *draw, \ + unsigned prim, \ + struct vertex_header *vertices, \ + unsigned stride + +#define LOCAL_VARS \ + char *verts = (char *)vertices; \ + boolean flatfirst = (draw->rasterizer->flatshade && \ + draw->rasterizer->flatshade_first); \ + unsigned i; \ + ushort flags + +#define FLUSH + +#include "draw_pt_decompose.h" + +void draw_pipeline_run_linear( struct draw_context *draw, + unsigned prim, + struct vertex_header *vertices, + unsigned count, + unsigned stride ) +{ + char *verts = (char *)vertices; + draw->pipeline.verts = verts; + draw->pipeline.vertex_stride = stride; + draw->pipeline.vertex_count = count; + + pipe_run_linear(draw, prim, vertices, stride, count); + + draw->pipeline.verts = NULL; + draw->pipeline.vertex_count = 0; +} void draw_pipeline_flush( struct draw_context *draw, diff --git a/src/gallium/auxiliary/draw/draw_pipe.h b/src/gallium/auxiliary/draw/draw_pipe.h index f1cb0891ca..dbad8f98ac 100644 --- a/src/gallium/auxiliary/draw/draw_pipe.h +++ b/src/gallium/auxiliary/draw/draw_pipe.h @@ -116,7 +116,7 @@ dup_vert( struct draw_stage *stage, { struct vertex_header *tmp = stage->tmp[idx]; const uint vsize = sizeof(struct vertex_header) - + stage->draw->num_vs_outputs * 4 * sizeof(float); + + stage->draw->vs.num_vs_outputs * 4 * sizeof(float); memcpy(tmp, vert, vsize); tmp->vertex_id = UNDEFINED_VERTEX_ID; return tmp; diff --git a/src/gallium/auxiliary/draw/draw_pipe_aaline.c b/src/gallium/auxiliary/draw/draw_pipe_aaline.c index b1ed8aa24e..ecdebca5f1 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_aaline.c +++ b/src/gallium/auxiliary/draw/draw_pipe_aaline.c @@ -78,6 +78,8 @@ struct aaline_stage /** For AA lines, this is the vertex attrib slot for the new texcoords */ uint tex_slot; + /** position, not necessarily output zero */ + uint pos_slot; void *sampler_cso; struct pipe_texture *texture; @@ -141,18 +143,18 @@ aa_transform_decl(struct tgsi_transform_context *ctx, if (decl->Declaration.File == TGSI_FILE_OUTPUT && decl->Semantic.SemanticName == TGSI_SEMANTIC_COLOR && decl->Semantic.SemanticIndex == 0) { - aactx->colorOutput = decl->u.DeclarationRange.First; + aactx->colorOutput = decl->DeclarationRange.First; } else if (decl->Declaration.File == TGSI_FILE_SAMPLER) { uint i; - for (i = decl->u.DeclarationRange.First; - i <= decl->u.DeclarationRange.Last; i++) { + for (i = decl->DeclarationRange.First; + i <= decl->DeclarationRange.Last; i++) { aactx->samplersUsed |= 1 << i; } } else if (decl->Declaration.File == TGSI_FILE_INPUT) { - if ((int) decl->u.DeclarationRange.Last > aactx->maxInput) - aactx->maxInput = decl->u.DeclarationRange.Last; + if ((int) decl->DeclarationRange.Last > aactx->maxInput) + aactx->maxInput = decl->DeclarationRange.Last; if (decl->Semantic.SemanticName == TGSI_SEMANTIC_GENERIC && (int) decl->Semantic.SemanticIndex > aactx->maxGeneric) { aactx->maxGeneric = decl->Semantic.SemanticIndex; @@ -160,8 +162,8 @@ aa_transform_decl(struct tgsi_transform_context *ctx, } else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) { uint i; - for (i = decl->u.DeclarationRange.First; - i <= decl->u.DeclarationRange.Last; i++) { + for (i = decl->DeclarationRange.First; + i <= decl->DeclarationRange.Last; i++) { aactx->tempsUsed |= (1 << i); } } @@ -225,34 +227,33 @@ aa_transform_inst(struct tgsi_transform_context *ctx, /* declare new generic input/texcoord */ decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_INPUT; + /* XXX this could be linear... */ + decl.Declaration.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE; decl.Declaration.Semantic = 1; decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC; decl.Semantic.SemanticIndex = aactx->maxGeneric + 1; - decl.Declaration.Interpolate = 1; - /* XXX this could be linear... */ - decl.Interpolation.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE; - decl.u.DeclarationRange.First = - decl.u.DeclarationRange.Last = aactx->maxInput + 1; + decl.DeclarationRange.First = + decl.DeclarationRange.Last = aactx->maxInput + 1; ctx->emit_declaration(ctx, &decl); /* declare new sampler */ decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_SAMPLER; - decl.u.DeclarationRange.First = - decl.u.DeclarationRange.Last = aactx->freeSampler; + decl.DeclarationRange.First = + decl.DeclarationRange.Last = aactx->freeSampler; ctx->emit_declaration(ctx, &decl); /* declare new temp regs */ decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_TEMPORARY; - decl.u.DeclarationRange.First = - decl.u.DeclarationRange.Last = aactx->texTemp; + decl.DeclarationRange.First = + decl.DeclarationRange.Last = aactx->texTemp; ctx->emit_declaration(ctx, &decl); decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_TEMPORARY; - decl.u.DeclarationRange.First = - decl.u.DeclarationRange.Last = aactx->colorTemp; + decl.DeclarationRange.First = + decl.DeclarationRange.Last = aactx->colorTemp; ctx->emit_declaration(ctx, &decl); aactx->firstInstruction = FALSE; @@ -521,9 +522,10 @@ aaline_line(struct draw_stage *stage, struct prim_header *header) struct prim_header tri; struct vertex_header *v[8]; uint texPos = aaline->tex_slot; + uint posPos = aaline->pos_slot; float *pos, *tex; - float dx = header->v[1]->data[0][0] - header->v[0]->data[0][0]; - float dy = header->v[1]->data[0][1] - header->v[0]->data[0][1]; + float dx = header->v[1]->data[posPos][0] - header->v[0]->data[posPos][0]; + float dy = header->v[1]->data[posPos][1] - header->v[0]->data[posPos][1]; double a = atan2(dy, dx); float c_a = (float) cos(a), s_a = (float) sin(a); uint i; @@ -550,35 +552,35 @@ aaline_line(struct draw_stage *stage, struct prim_header *header) */ /* new verts */ - pos = v[0]->data[0]; + pos = v[0]->data[posPos]; pos[0] += (-dx * c_a - dy * s_a); pos[1] += (-dx * s_a + dy * c_a); - pos = v[1]->data[0]; + pos = v[1]->data[posPos]; pos[0] += (-dx * c_a - -dy * s_a); pos[1] += (-dx * s_a + -dy * c_a); - pos = v[2]->data[0]; + pos = v[2]->data[posPos]; pos[0] += ( dx * c_a - dy * s_a); pos[1] += ( dx * s_a + dy * c_a); - pos = v[3]->data[0]; + pos = v[3]->data[posPos]; pos[0] += ( dx * c_a - -dy * s_a); pos[1] += ( dx * s_a + -dy * c_a); - pos = v[4]->data[0]; + pos = v[4]->data[posPos]; pos[0] += (-dx * c_a - dy * s_a); pos[1] += (-dx * s_a + dy * c_a); - pos = v[5]->data[0]; + pos = v[5]->data[posPos]; pos[0] += (-dx * c_a - -dy * s_a); pos[1] += (-dx * s_a + -dy * c_a); - pos = v[6]->data[0]; + pos = v[6]->data[posPos]; pos[0] += ( dx * c_a - dy * s_a); pos[1] += ( dx * s_a + dy * c_a); - pos = v[7]->data[0]; + pos = v[7]->data[posPos]; pos[0] += ( dx * c_a - -dy * s_a); pos[1] += ( dx * s_a + -dy * c_a); @@ -653,8 +655,8 @@ aaline_first_line(struct draw_stage *stage, struct prim_header *header) } /* update vertex attrib info */ - aaline->tex_slot = draw->num_vs_outputs; - assert(aaline->tex_slot > 0); /* output[0] is vertex pos */ + aaline->tex_slot = draw->vs.num_vs_outputs; + aaline->pos_slot = draw->vs.position_output; /* advertise the extra post-transformed vertex attribute */ draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC; diff --git a/src/gallium/auxiliary/draw/draw_pipe_aapoint.c b/src/gallium/auxiliary/draw/draw_pipe_aapoint.c index 122a48660a..87fd303649 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_aapoint.c +++ b/src/gallium/auxiliary/draw/draw_pipe_aapoint.c @@ -85,6 +85,7 @@ struct aapoint_stage /** this is the vertex attrib slot for the new texcoords */ uint tex_slot; + uint pos_slot; /* * Currently bound state @@ -131,11 +132,11 @@ aa_transform_decl(struct tgsi_transform_context *ctx, if (decl->Declaration.File == TGSI_FILE_OUTPUT && decl->Semantic.SemanticName == TGSI_SEMANTIC_COLOR && decl->Semantic.SemanticIndex == 0) { - aactx->colorOutput = decl->u.DeclarationRange.First; + aactx->colorOutput = decl->DeclarationRange.First; } else if (decl->Declaration.File == TGSI_FILE_INPUT) { - if ((int) decl->u.DeclarationRange.Last > aactx->maxInput) - aactx->maxInput = decl->u.DeclarationRange.Last; + if ((int) decl->DeclarationRange.Last > aactx->maxInput) + aactx->maxInput = decl->DeclarationRange.Last; if (decl->Semantic.SemanticName == TGSI_SEMANTIC_GENERIC && (int) decl->Semantic.SemanticIndex > aactx->maxGeneric) { aactx->maxGeneric = decl->Semantic.SemanticIndex; @@ -143,8 +144,8 @@ aa_transform_decl(struct tgsi_transform_context *ctx, } else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) { uint i; - for (i = decl->u.DeclarationRange.First; - i <= decl->u.DeclarationRange.Last; i++) { + for (i = decl->DeclarationRange.First; + i <= decl->DeclarationRange.Last; i++) { aactx->tempsUsed |= (1 << i); } } @@ -193,27 +194,26 @@ aa_transform_inst(struct tgsi_transform_context *ctx, /* declare new generic input/texcoord */ decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_INPUT; + /* XXX this could be linear... */ + decl.Declaration.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE; decl.Declaration.Semantic = 1; decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC; decl.Semantic.SemanticIndex = aactx->maxGeneric + 1; - decl.Declaration.Interpolate = 1; - /* XXX this could be linear... */ - decl.Interpolation.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE; - decl.u.DeclarationRange.First = - decl.u.DeclarationRange.Last = texInput; + decl.DeclarationRange.First = + decl.DeclarationRange.Last = texInput; ctx->emit_declaration(ctx, &decl); /* declare new temp regs */ decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_TEMPORARY; - decl.u.DeclarationRange.First = - decl.u.DeclarationRange.Last = tmp0; + decl.DeclarationRange.First = + decl.DeclarationRange.Last = tmp0; ctx->emit_declaration(ctx, &decl); decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_TEMPORARY; - decl.u.DeclarationRange.First = - decl.u.DeclarationRange.Last = aactx->colorTemp; + decl.DeclarationRange.First = + decl.DeclarationRange.Last = aactx->colorTemp; ctx->emit_declaration(ctx, &decl); aactx->firstInstruction = FALSE; @@ -571,6 +571,7 @@ aapoint_point(struct draw_stage *stage, struct prim_header *header) struct prim_header tri; struct vertex_header *v[4]; uint texPos = aapoint->tex_slot; + uint pos_slot = aapoint->pos_slot; float radius, *pos, *tex; uint i; float k; @@ -620,19 +621,19 @@ aapoint_point(struct draw_stage *stage, struct prim_header *header) } /* new verts */ - pos = v[0]->data[0]; + pos = v[0]->data[pos_slot]; pos[0] -= radius; pos[1] -= radius; - pos = v[1]->data[0]; + pos = v[1]->data[pos_slot]; pos[0] += radius; pos[1] -= radius; - pos = v[2]->data[0]; + pos = v[2]->data[pos_slot]; pos[0] += radius; pos[1] += radius; - pos = v[3]->data[0]; + pos = v[3]->data[pos_slot]; pos[0] -= radius; pos[1] += radius; @@ -681,9 +682,11 @@ aapoint_first_point(struct draw_stage *stage, struct prim_header *header) bind_aapoint_fragment_shader(aapoint); /* update vertex attrib info */ - aapoint->tex_slot = draw->num_vs_outputs; + aapoint->tex_slot = draw->vs.num_vs_outputs; assert(aapoint->tex_slot > 0); /* output[0] is vertex pos */ + aapoint->pos_slot = draw->vs.position_output; + draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC; draw->extra_vp_outputs.semantic_index = aapoint->fs->generic_attrib; draw->extra_vp_outputs.slot = aapoint->tex_slot; @@ -692,7 +695,7 @@ aapoint_first_point(struct draw_stage *stage, struct prim_header *header) aapoint->psize_slot = -1; if (draw->rasterizer->point_size_per_vertex) { /* find PSIZ vertex output */ - const struct draw_vertex_shader *vs = draw->vertex_shader; + const struct draw_vertex_shader *vs = draw->vs.vertex_shader; uint i; for (i = 0; i < vs->info.num_outputs; i++) { if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_PSIZE) { diff --git a/src/gallium/auxiliary/draw/draw_pipe_clip.c b/src/gallium/auxiliary/draw/draw_pipe_clip.c index ce80c94163..fa10f8efca 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_clip.c +++ b/src/gallium/auxiliary/draw/draw_pipe_clip.c @@ -112,7 +112,8 @@ static void interp( const struct clipper *clip, const struct vertex_header *out, const struct vertex_header *in ) { - const unsigned nr_attrs = clip->stage.draw->num_vs_outputs; + const unsigned nr_attrs = clip->stage.draw->vs.num_vs_outputs; + const unsigned pos_attr = clip->stage.draw->vs.position_output; unsigned j; /* Vertex header. @@ -138,18 +139,17 @@ static void interp( const struct clipper *clip, const float *trans = clip->stage.draw->viewport.translate; const float oow = 1.0f / pos[3]; - dst->data[0][0] = pos[0] * oow * scale[0] + trans[0]; - dst->data[0][1] = pos[1] * oow * scale[1] + trans[1]; - dst->data[0][2] = pos[2] * oow * scale[2] + trans[2]; - dst->data[0][3] = oow; + dst->data[pos_attr][0] = pos[0] * oow * scale[0] + trans[0]; + dst->data[pos_attr][1] = pos[1] * oow * scale[1] + trans[1]; + dst->data[pos_attr][2] = pos[2] * oow * scale[2] + trans[2]; + dst->data[pos_attr][3] = oow; } /* Other attributes - * Note: start at 1 to skip winpos (data[0]) since we just computed - * it above. */ - for (j = 1; j < nr_attrs; j++) { - interp_attr(dst->data[j], t, in->data[j], out->data[j]); + for (j = 0; j < nr_attrs; j++) { + if (j != pos_attr) + interp_attr(dst->data[j], t, in->data[j], out->data[j]); } } @@ -171,7 +171,7 @@ static void emit_poly( struct draw_stage *stage, header.flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle; header.pad = 0; - for (i = 2; i < n; i++, header.flags = 0) { + for (i = 2; i < n; i++, header.flags = edge_middle) { header.v[0] = inlist[i-1]; header.v[1] = inlist[i]; header.v[2] = inlist[0]; /* keep in v[2] for flatshading */ @@ -180,7 +180,7 @@ static void emit_poly( struct draw_stage *stage, header.flags |= edge_last; if (0) { - const struct draw_vertex_shader *vs = stage->draw->vertex_shader; + const struct draw_vertex_shader *vs = stage->draw->vs.vertex_shader; uint j, k; debug_printf("Clipped tri:\n"); for (j = 0; j < 3; j++) { @@ -425,7 +425,7 @@ clip_init_state( struct draw_stage *stage ) clipper->flat = stage->draw->rasterizer->flatshade ? TRUE : FALSE; if (clipper->flat) { - const struct draw_vertex_shader *vs = stage->draw->vertex_shader; + const struct draw_vertex_shader *vs = stage->draw->vs.vertex_shader; uint i; clipper->num_color_attribs = 0; diff --git a/src/gallium/auxiliary/draw/draw_pipe_cull.c b/src/gallium/auxiliary/draw/draw_pipe_cull.c index 87aaf1f85b..d0d22a38e0 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_cull.c +++ b/src/gallium/auxiliary/draw/draw_pipe_cull.c @@ -55,10 +55,12 @@ static INLINE struct cull_stage *cull_stage( struct draw_stage *stage ) static void cull_tri( struct draw_stage *stage, struct prim_header *header ) { + const unsigned pos = stage->draw->vs.position_output; + /* Window coords: */ - const float *v0 = header->v[0]->data[0]; - const float *v1 = header->v[1]->data[0]; - const float *v2 = header->v[2]->data[0]; + const float *v0 = header->v[0]->data[pos]; + const float *v1 = header->v[1]->data[pos]; + const float *v2 = header->v[2]->data[pos]; /* edge vectors e = v0 - v2, f = v1 - v2 */ const float ex = v0[0] - v2[0]; diff --git a/src/gallium/auxiliary/draw/draw_pipe_flatshade.c b/src/gallium/auxiliary/draw/draw_pipe_flatshade.c index 09b68c4559..4741b22d02 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_flatshade.c +++ b/src/gallium/auxiliary/draw/draw_pipe_flatshade.c @@ -40,9 +40,19 @@ struct flat_stage struct draw_stage stage; uint num_color_attribs; - uint color_attribs[4]; /* front/back primary/secondary colors */ + uint color_attribs[2]; /* front/back primary colors */ + + uint num_spec_attribs; + uint spec_attribs[2]; /* front/back secondary colors */ }; +#define COPY_3FV( DST, SRC ) \ +do { \ + (DST)[0] = (SRC)[0]; \ + (DST)[1] = (SRC)[1]; \ + (DST)[2] = (SRC)[2]; \ +} while (0) + static INLINE struct flat_stage * flat_stage(struct draw_stage *stage) @@ -58,10 +68,16 @@ static INLINE void copy_colors( struct draw_stage *stage, { const struct flat_stage *flat = flat_stage(stage); uint i; + for (i = 0; i < flat->num_color_attribs; i++) { const uint attr = flat->color_attribs[i]; COPY_4FV(dst->data[attr], src->data[attr]); } + + for (i = 0; i < flat->num_spec_attribs; i++) { + const uint attr = flat->spec_attribs[i]; + COPY_3FV(dst->data[attr], src->data[attr]); + } } @@ -78,6 +94,12 @@ static INLINE void copy_colors2( struct draw_stage *stage, COPY_4FV(dst0->data[attr], src->data[attr]); COPY_4FV(dst1->data[attr], src->data[attr]); } + + for (i = 0; i < flat->num_spec_attribs; i++) { + const uint attr = flat->spec_attribs[i]; + COPY_3FV(dst0->data[attr], src->data[attr]); + COPY_3FV(dst1->data[attr], src->data[attr]); + } } @@ -159,15 +181,19 @@ static void flatshade_line_1( struct draw_stage *stage, static void flatshade_init_state( struct draw_stage *stage ) { struct flat_stage *flat = flat_stage(stage); - const struct draw_vertex_shader *vs = stage->draw->vertex_shader; + const struct draw_vertex_shader *vs = stage->draw->vs.vertex_shader; uint i; /* Find which vertex shader outputs are colors, make a list */ flat->num_color_attribs = 0; + flat->num_spec_attribs = 0; for (i = 0; i < vs->info.num_outputs; i++) { if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_COLOR || vs->info.output_semantic_name[i] == TGSI_SEMANTIC_BCOLOR) { - flat->color_attribs[flat->num_color_attribs++] = i; + if (vs->info.output_semantic_index[i] == 0) + flat->color_attribs[flat->num_color_attribs++] = i; + else + flat->spec_attribs[flat->num_spec_attribs++] = i; } } diff --git a/src/gallium/auxiliary/draw/draw_pipe_offset.c b/src/gallium/auxiliary/draw/draw_pipe_offset.c index ea6de8c571..8f1650e55c 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_offset.c +++ b/src/gallium/auxiliary/draw/draw_pipe_offset.c @@ -62,14 +62,15 @@ static INLINE struct offset_stage *offset_stage( struct draw_stage *stage ) static void do_offset_tri( struct draw_stage *stage, struct prim_header *header ) { + const unsigned pos = stage->draw->vs.position_output; struct offset_stage *offset = offset_stage(stage); float inv_det = 1.0f / header->det; /* Window coords: */ - float *v0 = header->v[0]->data[0]; - float *v1 = header->v[1]->data[0]; - float *v2 = header->v[2]->data[0]; + float *v0 = header->v[0]->data[pos]; + float *v1 = header->v[1]->data[pos]; + float *v2 = header->v[2]->data[pos]; /* edge vectors e = v0 - v2, f = v1 - v2 */ float ex = v0[0] - v2[0]; diff --git a/src/gallium/auxiliary/draw/draw_pipe_pstipple.c b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c index 4c92416eb1..4087cf7a49 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_pstipple.c +++ b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c @@ -132,20 +132,20 @@ pstip_transform_decl(struct tgsi_transform_context *ctx, if (decl->Declaration.File == TGSI_FILE_SAMPLER) { uint i; - for (i = decl->u.DeclarationRange.First; - i <= decl->u.DeclarationRange.Last; i++) { + for (i = decl->DeclarationRange.First; + i <= decl->DeclarationRange.Last; i++) { pctx->samplersUsed |= 1 << i; } } else if (decl->Declaration.File == TGSI_FILE_INPUT) { - pctx->maxInput = MAX2(pctx->maxInput, (int) decl->u.DeclarationRange.Last); + pctx->maxInput = MAX2(pctx->maxInput, (int) decl->DeclarationRange.Last); if (decl->Semantic.SemanticName == TGSI_SEMANTIC_POSITION) - pctx->wincoordInput = (int) decl->u.DeclarationRange.First; + pctx->wincoordInput = (int) decl->DeclarationRange.First; } else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) { uint i; - for (i = decl->u.DeclarationRange.First; - i <= decl->u.DeclarationRange.Last; i++) { + for (i = decl->DeclarationRange.First; + i <= decl->DeclarationRange.Last; i++) { pctx->tempsUsed |= (1 << i); } } @@ -223,28 +223,27 @@ pstip_transform_inst(struct tgsi_transform_context *ctx, /* declare new position input reg */ decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_INPUT; + decl.Declaration.Interpolate = TGSI_INTERPOLATE_LINEAR; /* XXX? */ decl.Declaration.Semantic = 1; decl.Semantic.SemanticName = TGSI_SEMANTIC_POSITION; decl.Semantic.SemanticIndex = 0; - decl.Declaration.Interpolate = 1; - decl.Interpolation.Interpolate = TGSI_INTERPOLATE_LINEAR; /* XXX? */ - decl.u.DeclarationRange.First = - decl.u.DeclarationRange.Last = wincoordInput; + decl.DeclarationRange.First = + decl.DeclarationRange.Last = wincoordInput; ctx->emit_declaration(ctx, &decl); } /* declare new sampler */ decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_SAMPLER; - decl.u.DeclarationRange.First = - decl.u.DeclarationRange.Last = pctx->freeSampler; + decl.DeclarationRange.First = + decl.DeclarationRange.Last = pctx->freeSampler; ctx->emit_declaration(ctx, &decl); /* declare new temp regs */ decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_TEMPORARY; - decl.u.DeclarationRange.First = - decl.u.DeclarationRange.Last = pctx->texTemp; + decl.DeclarationRange.First = + decl.DeclarationRange.Last = pctx->texTemp; ctx->emit_declaration(ctx, &decl); /* emit immediate = {1/32, 1/32, 1, 1} diff --git a/src/gallium/auxiliary/draw/draw_pipe_stipple.c b/src/gallium/auxiliary/draw/draw_pipe_stipple.c index 3cbced362e..bf0db18a68 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_stipple.c +++ b/src/gallium/auxiliary/draw/draw_pipe_stipple.c @@ -71,7 +71,7 @@ screen_interp( struct draw_context *draw, const struct vertex_header *v1 ) { uint attr; - for (attr = 0; attr < draw->num_vs_outputs; attr++) { + for (attr = 0; attr < draw->vs.num_vs_outputs; attr++) { const float *val0 = v0->data[attr]; const float *val1 = v1->data[attr]; float *newv = dst->data[attr]; @@ -119,8 +119,9 @@ stipple_line(struct draw_stage *stage, struct prim_header *header) struct stipple_stage *stipple = stipple_stage(stage); struct vertex_header *v0 = header->v[0]; struct vertex_header *v1 = header->v[1]; - const float *pos0 = v0->data[0]; - const float *pos1 = v1->data[0]; + const unsigned pos = stage->draw->vs.position_output; + const float *pos0 = v0->data[pos]; + const float *pos1 = v1->data[pos]; float start = 0; int state = 0; @@ -175,6 +176,22 @@ reset_stipple_counter(struct draw_stage *stage) stage->next->reset_stipple_counter( stage->next ); } +static void +stipple_reset_point(struct draw_stage *stage, struct prim_header *header) +{ + struct stipple_stage *stipple = stipple_stage(stage); + stipple->counter = 0; + stage->next->point(stage->next, header); +} + +static void +stipple_reset_tri(struct draw_stage *stage, struct prim_header *header) +{ + struct stipple_stage *stipple = stipple_stage(stage); + stipple->counter = 0; + stage->next->tri(stage->next, header); +} + static void stipple_first_line(struct draw_stage *stage, @@ -220,9 +237,9 @@ struct draw_stage *draw_stipple_stage( struct draw_context *draw ) stipple->stage.draw = draw; stipple->stage.next = NULL; - stipple->stage.point = draw_pipe_passthrough_point; + stipple->stage.point = stipple_reset_point; stipple->stage.line = stipple_first_line; - stipple->stage.tri = draw_pipe_passthrough_tri; + stipple->stage.tri = stipple_reset_tri; stipple->stage.reset_stipple_counter = reset_stipple_counter; stipple->stage.flush = stipple_flush; stipple->stage.destroy = stipple_destroy; diff --git a/src/gallium/auxiliary/draw/draw_pipe_twoside.c b/src/gallium/auxiliary/draw/draw_pipe_twoside.c index 50872fdbe9..3ac825f565 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_twoside.c +++ b/src/gallium/auxiliary/draw/draw_pipe_twoside.c @@ -105,7 +105,7 @@ static void twoside_first_tri( struct draw_stage *stage, struct prim_header *header ) { struct twoside_stage *twoside = twoside_stage(stage); - const struct draw_vertex_shader *vs = stage->draw->vertex_shader; + const struct draw_vertex_shader *vs = stage->draw->vs.vertex_shader; uint i; twoside->attrib_front0 = 0; diff --git a/src/gallium/auxiliary/draw/draw_pipe_vbuf.c b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c index 67b9a9503d..a6fde77a0e 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_vbuf.c +++ b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c @@ -136,6 +136,8 @@ emit_vertex( struct vbuf_stage *vbuf, * set_buffer is efficient. Consider a special one-shot mode for * translate. */ + /* Note: we really do want data[0] here, not data[pos]: + */ vbuf->translate->set_buffer(vbuf->translate, 0, vertex->data[0], 0); vbuf->translate->run(vbuf->translate, 0, 1, vbuf->vertex_ptr); @@ -145,7 +147,7 @@ emit_vertex( struct vbuf_stage *vbuf, vertex->vertex_id = vbuf->nr_vertices++; } - return vertex->vertex_id; + return (ushort)vertex->vertex_id; } @@ -387,6 +389,15 @@ vbuf_alloc_vertices( struct vbuf_stage *vbuf ) /* Allocate a new vertex buffer */ vbuf->max_vertices = vbuf->render->max_vertex_buffer_bytes / vbuf->vertex_size; + + /* even number */ + vbuf->max_vertices = vbuf->max_vertices & ~1; + + /* Must always succeed -- driver gives us a + * 'max_vertex_buffer_bytes' which it guarantees it can allocate, + * and it will flush itself if necessary to do so. If this does + * fail, we are basically without usable hardware. + */ vbuf->vertices = (uint *) vbuf->render->allocate_vertices(vbuf->render, (ushort) vbuf->vertex_size, (ushort) vbuf->max_vertices); diff --git a/src/gallium/auxiliary/draw/draw_pipe_wide_line.c b/src/gallium/auxiliary/draw/draw_pipe_wide_line.c index 878c9c7169..29649f5787 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_wide_line.c +++ b/src/gallium/auxiliary/draw/draw_pipe_wide_line.c @@ -58,6 +58,7 @@ static void wideline_line( struct draw_stage *stage, struct prim_header *header ) { /*const struct wideline_stage *wide = wideline_stage(stage);*/ + const unsigned pos = stage->draw->vs.position_output; const float half_width = 0.5f * stage->draw->rasterizer->line_width; struct prim_header tri; @@ -67,10 +68,10 @@ static void wideline_line( struct draw_stage *stage, struct vertex_header *v2 = dup_vert(stage, header->v[1], 2); struct vertex_header *v3 = dup_vert(stage, header->v[1], 3); - float *pos0 = v0->data[0]; - float *pos1 = v1->data[0]; - float *pos2 = v2->data[0]; - float *pos3 = v3->data[0]; + float *pos0 = v0->data[pos]; + float *pos1 = v1->data[pos]; + float *pos2 = v2->data[pos]; + float *pos3 = v3->data[pos]; const float dx = FABSF(pos0[0] - pos2[0]); const float dy = FABSF(pos0[1] - pos2[1]); diff --git a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c index ed08573382..d40a07f4ae 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c +++ b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c @@ -96,6 +96,7 @@ static void widepoint_point( struct draw_stage *stage, struct prim_header *header ) { const struct widepoint_stage *wide = widepoint_stage(stage); + const unsigned pos = stage->draw->vs.position_output; const boolean sprite = (boolean) stage->draw->rasterizer->point_sprite; float half_size; float left_adj, right_adj, bot_adj, top_adj; @@ -108,10 +109,10 @@ static void widepoint_point( struct draw_stage *stage, struct vertex_header *v2 = dup_vert(stage, header->v[0], 2); struct vertex_header *v3 = dup_vert(stage, header->v[0], 3); - float *pos0 = v0->data[0]; - float *pos1 = v1->data[0]; - float *pos2 = v2->data[0]; - float *pos3 = v3->data[0]; + float *pos0 = v0->data[pos]; + float *pos1 = v1->data[pos]; + float *pos2 = v2->data[pos]; + float *pos3 = v3->data[pos]; /* point size is either per-vertex or fixed size */ if (wide->psize_slot >= 0) { @@ -197,7 +198,7 @@ static void widepoint_first_point( struct draw_stage *stage, if (draw->rasterizer->point_sprite) { /* find vertex shader texcoord outputs */ - const struct draw_vertex_shader *vs = draw->vertex_shader; + const struct draw_vertex_shader *vs = draw->vs.vertex_shader; uint i, j = 0; for (i = 0; i < vs->info.num_outputs; i++) { if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_GENERIC) { @@ -212,7 +213,7 @@ static void widepoint_first_point( struct draw_stage *stage, wide->psize_slot = -1; if (draw->rasterizer->point_size_per_vertex) { /* find PSIZ vertex output */ - const struct draw_vertex_shader *vs = draw->vertex_shader; + const struct draw_vertex_shader *vs = draw->vs.vertex_shader; uint i; for (i = 0; i < vs->info.num_outputs; i++) { if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_PSIZE) { diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h index cee58bbf73..7bd1e670b4 100644 --- a/src/gallium/auxiliary/draw/draw_private.h +++ b/src/gallium/auxiliary/draw/draw_private.h @@ -124,6 +124,7 @@ struct draw_context struct { struct { struct draw_pt_middle_end *fetch_emit; + struct draw_pt_middle_end *fetch_shade_emit; struct draw_pt_middle_end *general; } middle; @@ -146,6 +147,8 @@ struct draw_context const void *elts; /** bytes per index (0, 1, 2 or 4) */ unsigned eltSize; + unsigned min_index; + unsigned max_index; /** vertex arrays */ const void *vbuffer[PIPE_MAX_ATTRIBS]; @@ -154,6 +157,8 @@ struct draw_context const void *constants; } user; + boolean test_fse; /* enable FSE even though its not correct (eg for softpipe) */ + boolean no_fse; /* disable FSE even when it is correct */ } pt; struct { @@ -167,13 +172,36 @@ struct draw_context /* pipe state that we need: */ const struct pipe_rasterizer_state *rasterizer; struct pipe_viewport_state viewport; + boolean identity_viewport; + + struct { + struct draw_vertex_shader *vertex_shader; + uint num_vs_outputs; /**< convenience, from vertex_shader */ + uint position_output; - struct draw_vertex_shader *vertex_shader; + /** TGSI program interpreter runtime state */ + struct tgsi_exec_machine machine; + + /* This (and the tgsi_exec_machine struct) probably need to be moved somewhere private. + */ + struct gallivm_cpu_engine *engine; + + /* Here's another one: + */ + struct aos_machine *aos_machine; - boolean identity_viewport; - uint num_vs_outputs; /**< convenience, from vertex_shader */ + const float (*aligned_constants)[4]; + float (*aligned_constant_storage)[4]; + unsigned const_storage_size; + + + struct translate *fetch; + struct translate_cache *fetch_cache; + struct translate *emit; + struct translate_cache *emit_cache; + } vs; /* Clip derived state: */ @@ -190,17 +218,22 @@ struct draw_context unsigned reduced_prim; - /** TGSI program interpreter runtime state */ - struct tgsi_exec_machine machine; - - /* This (and the tgsi_exec_machine struct) probably need to be moved somewhere private. - */ - struct gallivm_cpu_engine *engine; void *driver_private; }; +/******************************************************************************* + * Vertex shader code: + */ +boolean draw_vs_init( struct draw_context *draw ); +void draw_vs_destroy( struct draw_context *draw ); +void draw_vs_set_viewport( struct draw_context *, + const struct pipe_viewport_state * ); + +void draw_vs_set_constants( struct draw_context *, + const float (*constants)[4], + unsigned size ); @@ -232,6 +265,7 @@ void draw_pipeline_destroy( struct draw_context *draw ); * These flags expected at first vertex of lines & triangles when * unfilled and/or line stipple modes are operational. */ +#define DRAW_PIPE_MAX_VERTICES (0x1<<12) #define DRAW_PIPE_EDGE_FLAG_0 (0x1<<12) #define DRAW_PIPE_EDGE_FLAG_1 (0x2<<12) #define DRAW_PIPE_EDGE_FLAG_2 (0x4<<12) @@ -247,6 +281,12 @@ void draw_pipeline_run( struct draw_context *draw, const ushort *elts, unsigned count ); +void draw_pipeline_run_linear( struct draw_context *draw, + unsigned prim, + struct vertex_header *vertices, + unsigned count, + unsigned stride ); + void draw_pipeline_flush( struct draw_context *draw, diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c index c9c5d18313..9140faeea9 100644 --- a/src/gallium/auxiliary/draw/draw_pt.c +++ b/src/gallium/auxiliary/draw/draw_pt.c @@ -35,6 +35,10 @@ #include "draw/draw_private.h" #include "draw/draw_pt.h" +static unsigned trim( unsigned count, unsigned first, unsigned incr ) +{ + return count - (count - first) % incr; +} @@ -54,6 +58,17 @@ draw_pt_arrays(struct draw_context *draw, struct draw_pt_middle_end *middle = NULL; unsigned opt = 0; + /* Sanitize primitive length: + */ + { + unsigned first, incr; + draw_pt_split_prim(prim, &first, &incr); + count = trim(count, first, incr); + if (count < first) + return TRUE; + } + + if (!draw->render) { opt |= PT_PIPELINE; } @@ -64,7 +79,7 @@ draw_pt_arrays(struct draw_context *draw, opt |= PT_PIPELINE; } - if (!draw->bypass_clipping) { + if (!draw->bypass_clipping && !draw->pt.test_fse) { opt |= PT_CLIPTEST; } @@ -72,16 +87,18 @@ draw_pt_arrays(struct draw_context *draw, opt |= PT_SHADE; } - if (opt) - middle = draw->pt.middle.general; - else + + if (opt == 0) middle = draw->pt.middle.fetch_emit; + else if (opt == PT_SHADE && !draw->pt.no_fse) + middle = draw->pt.middle.fetch_shade_emit; + else + middle = draw->pt.middle.general; /* Pick the right frontend */ - if (draw->pt.user.elts || - count >= 256) { + if (draw->pt.user.elts || (opt & PT_PIPELINE)) { frontend = draw->pt.front.vcache; } else { frontend = draw->pt.front.varray; @@ -102,6 +119,9 @@ draw_pt_arrays(struct draw_context *draw, boolean draw_pt_init( struct draw_context *draw ) { + draw->pt.test_fse = debug_get_bool_option("DRAW_FSE", FALSE); + draw->pt.no_fse = debug_get_bool_option("DRAW_NO_FSE", FALSE); + draw->pt.front.vcache = draw_pt_vcache( draw ); if (!draw->pt.front.vcache) return FALSE; @@ -114,6 +134,10 @@ boolean draw_pt_init( struct draw_context *draw ) if (!draw->pt.middle.fetch_emit) return FALSE; + draw->pt.middle.fetch_shade_emit = draw_pt_middle_fse( draw ); + if (!draw->pt.middle.fetch_shade_emit) + return FALSE; + draw->pt.middle.general = draw_pt_fetch_pipeline_or_emit( draw ); if (!draw->pt.middle.general) return FALSE; @@ -134,6 +158,11 @@ void draw_pt_destroy( struct draw_context *draw ) draw->pt.middle.fetch_emit = NULL; } + if (draw->pt.middle.fetch_shade_emit) { + draw->pt.middle.fetch_shade_emit->destroy( draw->pt.middle.fetch_shade_emit ); + draw->pt.middle.fetch_shade_emit = NULL; + } + if (draw->pt.front.vcache) { draw->pt.front.vcache->destroy( draw->pt.front.vcache ); draw->pt.front.vcache = NULL; @@ -147,19 +176,6 @@ void draw_pt_destroy( struct draw_context *draw ) -static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = { - PIPE_PRIM_POINTS, - PIPE_PRIM_LINES, - PIPE_PRIM_LINES, - PIPE_PRIM_LINES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES -}; - /** * Draw vertex arrays @@ -172,9 +188,10 @@ void draw_arrays(struct draw_context *draw, unsigned prim, unsigned start, unsigned count) { - if (reduced_prim[prim] != draw->reduced_prim) { + unsigned reduced_prim = draw_pt_reduced_prim(prim); + if (reduced_prim != draw->reduced_prim) { draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); - draw->reduced_prim = reduced_prim[prim]; + draw->reduced_prim = reduced_prim; } /* drawing done here: */ diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h index 2dec376cee..3d2a9c78b7 100644 --- a/src/gallium/auxiliary/draw/draw_pt.h +++ b/src/gallium/auxiliary/draw/draw_pt.h @@ -84,7 +84,8 @@ struct draw_pt_front_end { struct draw_pt_middle_end { void (*prepare)( struct draw_pt_middle_end *, unsigned prim, - unsigned opt ); + unsigned opt, + unsigned *max_vertices ); void (*run)( struct draw_pt_middle_end *, const unsigned *fetch_elts, @@ -92,6 +93,21 @@ struct draw_pt_middle_end { const ushort *draw_elts, unsigned draw_count ); + void (*run_linear)(struct draw_pt_middle_end *, + unsigned start, + unsigned count); + + /* Transform all vertices in a linear range and then draw them with + * the supplied element list. + */ + void (*run_linear_elts)( struct draw_pt_middle_end *, + unsigned fetch_start, + unsigned fetch_count, + const ushort *draw_elts, + unsigned draw_count ); + + int (*get_max_vertex_count)( struct draw_pt_middle_end * ); + void (*finish)( struct draw_pt_middle_end * ); void (*destroy)( struct draw_pt_middle_end * ); }; @@ -117,6 +133,7 @@ const void *draw_pt_elt_ptr( struct draw_context *draw, struct draw_pt_front_end *draw_pt_vcache( struct draw_context *draw ); struct draw_pt_front_end *draw_pt_varray(struct draw_context *draw); + /* Middle-ends: * * Currently one general-purpose case which can do all possibilities, @@ -128,6 +145,7 @@ struct draw_pt_front_end *draw_pt_varray(struct draw_context *draw); * vertex_elements. */ struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw ); +struct draw_pt_middle_end *draw_pt_middle_fse( struct draw_context *draw ); struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit(struct draw_context *draw); @@ -143,7 +161,8 @@ boolean draw_pt_get_edgeflag( struct draw_context *draw, struct pt_emit; void draw_pt_emit_prepare( struct pt_emit *emit, - unsigned prim ); + unsigned prim, + unsigned *max_vertices ); void draw_pt_emit( struct pt_emit *emit, const float (*vertex_data)[4], @@ -152,6 +171,13 @@ void draw_pt_emit( struct pt_emit *emit, const ushort *elts, unsigned count ); +void draw_pt_emit_linear( struct pt_emit *emit, + const float (*vertex_data)[4], + unsigned vertex_count, + unsigned stride, + unsigned start, + unsigned count ); + void draw_pt_emit_destroy( struct pt_emit *emit ); struct pt_emit *draw_pt_emit_create( struct draw_context *draw ); @@ -170,6 +196,11 @@ void draw_pt_fetch_run( struct pt_fetch *fetch, unsigned count, char *verts ); +void draw_pt_fetch_run_linear( struct pt_fetch *fetch, + unsigned start, + unsigned count, + char *verts ); + void draw_pt_fetch_destroy( struct pt_fetch *fetch ); struct pt_fetch *draw_pt_fetch_create( struct draw_context *draw ); @@ -194,4 +225,11 @@ struct pt_post_vs *draw_pt_post_vs_create( struct draw_context *draw ); void draw_pt_post_vs_destroy( struct pt_post_vs *pvs ); +/******************************************************************************* + * Utils: + */ +void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr); +unsigned draw_pt_reduced_prim(unsigned prim); + + #endif diff --git a/src/gallium/auxiliary/draw/draw_pt_decompose.h b/src/gallium/auxiliary/draw/draw_pt_decompose.h new file mode 100644 index 0000000000..3fb0695687 --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_pt_decompose.h @@ -0,0 +1,153 @@ + + +static void FUNC( ARGS, + unsigned count ) +{ + LOCAL_VARS; + + switch (prim) { + case PIPE_PRIM_POINTS: + for (i = 0; i < count; i ++) { + POINT( (i + 0) ); + } + break; + + case PIPE_PRIM_LINES: + for (i = 0; i+1 < count; i += 2) { + LINE( DRAW_PIPE_RESET_STIPPLE, + (i + 0), + (i + 1)); + } + break; + + case PIPE_PRIM_LINE_LOOP: + if (count >= 2) { + flags = DRAW_PIPE_RESET_STIPPLE; + + for (i = 1; i < count; i++, flags = 0) { + LINE( flags, + (i - 1), + (i )); + } + + LINE( flags, + (i - 1), + (0 )); + } + break; + + case PIPE_PRIM_LINE_STRIP: + flags = DRAW_PIPE_RESET_STIPPLE; + for (i = 1; i < count; i++, flags = 0) { + LINE( flags, + (i - 1), + (i )); + } + break; + + case PIPE_PRIM_TRIANGLES: + for (i = 0; i+2 < count; i += 3) { + TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + (i + 0), + (i + 1), + (i + 2 )); + } + break; + + case PIPE_PRIM_TRIANGLE_STRIP: + if (flatfirst) { + for (i = 0; i+2 < count; i++) { + TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + (i + 0), + (i + 1 + (i&1)), + (i + 2 - (i&1))); + } + } + else { + for (i = 0; i+2 < count; i++) { + TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + (i + 0 + (i&1)), + (i + 1 - (i&1)), + (i + 2 )); + } + } + break; + + case PIPE_PRIM_TRIANGLE_FAN: + if (count >= 3) { + if (flatfirst) { + for (i = 0; i+2 < count; i++) { + TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + (i + 1), + (i + 2), + (0 )); + } + } + else { + for (i = 0; i+2 < count; i++) { + TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + (0), + (i + 1), + (i + 2 )); + } + } + } + break; + + + case PIPE_PRIM_QUADS: + for (i = 0; i+3 < count; i += 4) { + QUAD( (i + 0), + (i + 1), + (i + 2), + (i + 3)); + } + break; + + case PIPE_PRIM_QUAD_STRIP: + for (i = 0; i+3 < count; i += 2) { + QUAD( (i + 2), + (i + 0), + (i + 1), + (i + 3)); + } + break; + + case PIPE_PRIM_POLYGON: + { + /* These bitflags look a little odd because we submit the + * vertices as (1,2,0) to satisfy flatshade requirements. + */ + const ushort edge_first = DRAW_PIPE_EDGE_FLAG_2; + const ushort edge_middle = DRAW_PIPE_EDGE_FLAG_0; + const ushort edge_last = DRAW_PIPE_EDGE_FLAG_1; + + flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle; + + for (i = 0; i+2 < count; i++, flags = edge_middle) { + + if (i + 3 == count) + flags |= edge_last; + + TRIANGLE( flags, + (i + 1), + (i + 2), + (0)); + } + } + break; + + default: + assert(0); + break; + } + + FLUSH; +} + + +#undef TRIANGLE +#undef QUAD +#undef POINT +#undef LINE +#undef FUNC diff --git a/src/gallium/auxiliary/draw/draw_pt_elts.c b/src/gallium/auxiliary/draw/draw_pt_elts.c index 2094c081ed..b7780fb507 100644 --- a/src/gallium/auxiliary/draw/draw_pt_elts.c +++ b/src/gallium/auxiliary/draw/draw_pt_elts.c @@ -60,10 +60,10 @@ static unsigned elt_vert( const void *elts, unsigned idx ) pt_elt_func draw_pt_elt_func( struct draw_context *draw ) { switch (draw->pt.user.eltSize) { - case 0: return elt_vert; - case 1: return elt_ubyte; - case 2: return elt_ushort; - case 4: return elt_uint; + case 0: return &elt_vert; + case 1: return &elt_ubyte; + case 2: return &elt_ushort; + case 4: return &elt_uint; default: return NULL; } } diff --git a/src/gallium/auxiliary/draw/draw_pt_emit.c b/src/gallium/auxiliary/draw/draw_pt_emit.c index ce3a153f64..40f05cb9e0 100644 --- a/src/gallium/auxiliary/draw/draw_pt_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_emit.c @@ -40,10 +40,14 @@ struct pt_emit { struct translate *translate; struct translate_cache *cache; + unsigned prim; + + const struct vertex_info *vinfo; }; void draw_pt_emit_prepare( struct pt_emit *emit, - unsigned prim ) + unsigned prim, + unsigned *max_vertices ) { struct draw_context *draw = emit->draw; const struct vertex_info *vinfo; @@ -51,8 +55,18 @@ void draw_pt_emit_prepare( struct pt_emit *emit, struct translate_key hw_key; unsigned i; boolean ok; + + /* XXX: need to flush to get prim_vbuf.c to release its allocation?? + */ + draw_do_flush( draw, DRAW_FLUSH_BACKEND ); + + + /* XXX: may need to defensively reset this later on as clipping can + * clobber this state in the render backend. + */ + emit->prim = prim; - ok = draw->render->set_primitive(draw->render, prim); + ok = draw->render->set_primitive(draw->render, emit->prim); if (!ok) { assert(0); return; @@ -60,7 +74,7 @@ void draw_pt_emit_prepare( struct pt_emit *emit, /* Must do this after set_primitive() above: */ - vinfo = draw->render->get_vertex_info(draw->render); + emit->vinfo = vinfo = draw->render->get_vertex_info(draw->render); /* Translate from pipeline vertices to hw vertices. @@ -100,6 +114,7 @@ void draw_pt_emit_prepare( struct pt_emit *emit, case EMIT_4UB: output_format = PIPE_FORMAT_B8G8R8A8_UNORM; emit_sz = 4 * sizeof(ubyte); + break; default: assert(0); output_format = PIPE_FORMAT_NONE; @@ -125,6 +140,12 @@ void draw_pt_emit_prepare( struct pt_emit *emit, translate_key_sanitize(&hw_key); emit->translate = translate_cache_find(emit->cache, &hw_key); } + + *max_vertices = (draw->render->max_vertex_buffer_bytes / + (vinfo->size * 4)); + + /* even number */ + *max_vertices = *max_vertices & ~1; } @@ -144,6 +165,14 @@ void draw_pt_emit( struct pt_emit *emit, */ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); + /* XXX: and work out some way to coordinate the render primitive + * between vbuf.c and here... + */ + if (!draw->render->set_primitive(draw->render, emit->prim)) { + assert(0); + return; + } + hw_verts = render->allocate_vertices(render, (ushort)translate->key.output_stride, (ushort)vertex_count); @@ -178,6 +207,72 @@ void draw_pt_emit( struct pt_emit *emit, } +void draw_pt_emit_linear(struct pt_emit *emit, + const float (*vertex_data)[4], + unsigned vertex_count, + unsigned stride, + unsigned start, + unsigned count) +{ + struct draw_context *draw = emit->draw; + struct translate *translate = emit->translate; + struct vbuf_render *render = draw->render; + void *hw_verts; + +#if 0 + debug_printf("Linear emit\n"); +#endif + /* XXX: need to flush to get prim_vbuf.c to release its allocation?? + */ + draw_do_flush( draw, DRAW_FLUSH_BACKEND ); + + /* XXX: and work out some way to coordinate the render primitive + * between vbuf.c and here... + */ + if (!draw->render->set_primitive(draw->render, emit->prim)) { + assert(0); + return; + } + + hw_verts = render->allocate_vertices(render, + (ushort)translate->key.output_stride, + (ushort)count); + if (!hw_verts) { + assert(0); + return; + } + + translate->set_buffer(translate, 0, + vertex_data, stride); + + translate->set_buffer(translate, 1, + &draw->rasterizer->point_size, + 0); + + translate->run(translate, + 0, + vertex_count, + hw_verts); + + if (0) { + unsigned i; + for (i = 0; i < vertex_count; i++) { + debug_printf("\n\n%s vertex %d:\n", __FUNCTION__, i); + draw_dump_emitted_vertex( emit->vinfo, + (const uint8_t *)hw_verts + + translate->key.output_stride * i ); + } + } + + + render->draw_arrays(render, start, count); + + render->release_vertices(render, + hw_verts, + translate->key.output_stride, + vertex_count); +} + struct pt_emit *draw_pt_emit_create( struct draw_context *draw ) { struct pt_emit *emit = CALLOC_STRUCT(pt_emit); diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch.c b/src/gallium/auxiliary/draw/draw_pt_fetch.c index b96335b789..07f4c99164 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch.c @@ -166,6 +166,42 @@ void draw_pt_fetch_run( struct pt_fetch *fetch, } +void draw_pt_fetch_run_linear( struct pt_fetch *fetch, + unsigned start, + unsigned count, + char *verts ) +{ + struct draw_context *draw = fetch->draw; + struct translate *translate = fetch->translate; + unsigned i; + + for (i = 0; i < draw->pt.nr_vertex_buffers; i++) { + translate->set_buffer(translate, + i, + ((char *)draw->pt.user.vbuffer[i] + + draw->pt.vertex_buffer[i].buffer_offset), + draw->pt.vertex_buffer[i].pitch ); + } + + translate->run( translate, + start, + count, + verts ); + + /* Edgeflags are hard to fit into a translate program, populate + * them separately if required. In the setup above they are + * defaulted to one, so only need this if there is reason to change + * that default: + */ + if (fetch->need_edgeflags) { + for (i = 0; i < count; i++) { + struct vertex_header *vh = (struct vertex_header *)(verts + i * fetch->vertex_size); + vh->edgeflag = draw_pt_get_edgeflag( draw, start + i ); + } + } +} + + struct pt_fetch *draw_pt_fetch_create( struct draw_context *draw ) { struct pt_fetch *fetch = CALLOC_STRUCT(pt_fetch); diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c index 4ea7d4359f..4a1f3b0953 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c @@ -90,7 +90,8 @@ struct fetch_emit_middle_end { static void fetch_emit_prepare( struct draw_pt_middle_end *middle, unsigned prim, - unsigned opt ) + unsigned opt, + unsigned *max_vertices ) { struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle; struct draw_context *draw = feme->draw; @@ -196,6 +197,18 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle, draw->pt.vertex_buffer[i].buffer_offset), draw->pt.vertex_buffer[i].pitch ); } + + *max_vertices = (draw->render->max_vertex_buffer_bytes / + (vinfo->size * 4)); + + /* Return an even number of verts. + * This prevents "parity" errors when splitting long triangle strips which + * can lead to front/back culling mix-ups. + * Every other triangle in a strip has an alternate front/back orientation + * so splitting at an odd position can cause the orientation of subsequent + * triangles to get reversed. + */ + *max_vertices = *max_vertices & ~1; } @@ -258,6 +271,106 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle, } +static void fetch_emit_run_linear( struct draw_pt_middle_end *middle, + unsigned start, + unsigned count ) +{ + struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle; + struct draw_context *draw = feme->draw; + void *hw_verts; + + /* XXX: need to flush to get prim_vbuf.c to release its allocation?? + */ + draw_do_flush( draw, DRAW_FLUSH_BACKEND ); + + hw_verts = draw->render->allocate_vertices( draw->render, + (ushort)feme->translate->key.output_stride, + (ushort)count ); + if (!hw_verts) { + assert(0); + return; + } + + /* Single routine to fetch vertices and emit HW verts. + */ + feme->translate->run( feme->translate, + start, + count, + hw_verts ); + + if (0) { + unsigned i; + for (i = 0; i < count; i++) { + debug_printf("\n\nvertex %d:\n", i); + draw_dump_emitted_vertex( feme->vinfo, + (const uint8_t *)hw_verts + feme->vinfo->size * 4 * i ); + } + } + + /* XXX: Draw arrays path to avoid re-emitting index list again and + * again. + */ + draw->render->draw_arrays( draw->render, + 0, /*start*/ + count ); + + /* Done -- that was easy, wasn't it: + */ + draw->render->release_vertices( draw->render, + hw_verts, + feme->translate->key.output_stride, + count ); + +} + + +static void fetch_emit_run_linear_elts( struct draw_pt_middle_end *middle, + unsigned start, + unsigned count, + const ushort *draw_elts, + unsigned draw_count ) +{ + struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle; + struct draw_context *draw = feme->draw; + void *hw_verts; + + /* XXX: need to flush to get prim_vbuf.c to release its allocation?? + */ + draw_do_flush( draw, DRAW_FLUSH_BACKEND ); + + hw_verts = draw->render->allocate_vertices( draw->render, + (ushort)feme->translate->key.output_stride, + (ushort)count ); + if (!hw_verts) { + assert(0); + return; + } + + /* Single routine to fetch vertices and emit HW verts. + */ + feme->translate->run( feme->translate, + start, + count, + hw_verts ); + + /* XXX: Draw arrays path to avoid re-emitting index list again and + * again. + */ + draw->render->draw( draw->render, + draw_elts, + draw_count ); + + /* Done -- that was easy, wasn't it: + */ + draw->render->release_vertices( draw->render, + hw_verts, + feme->translate->key.output_stride, + count ); + +} + + + static void fetch_emit_finish( struct draw_pt_middle_end *middle ) { @@ -287,10 +400,12 @@ struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw ) return NULL; } - fetch_emit->base.prepare = fetch_emit_prepare; - fetch_emit->base.run = fetch_emit_run; - fetch_emit->base.finish = fetch_emit_finish; - fetch_emit->base.destroy = fetch_emit_destroy; + fetch_emit->base.prepare = fetch_emit_prepare; + fetch_emit->base.run = fetch_emit_run; + fetch_emit->base.run_linear = fetch_emit_run_linear; + fetch_emit->base.run_linear_elts = fetch_emit_run_linear_elts; + fetch_emit->base.finish = fetch_emit_finish; + fetch_emit->base.destroy = fetch_emit_destroy; fetch_emit->draw = draw; diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c new file mode 100644 index 0000000000..fdf9b6fe6a --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c @@ -0,0 +1,406 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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: + * Keith Whitwell <keith@tungstengraphics.com> + */ + + +#include "pipe/p_util.h" +#include "draw/draw_context.h" +#include "draw/draw_private.h" +#include "draw/draw_vbuf.h" +#include "draw/draw_vertex.h" +#include "draw/draw_pt.h" +#include "draw/draw_vs.h" + +#include "translate/translate.h" + +struct fetch_shade_emit; + + +/* Prototype fetch, shade, emit-hw-verts all in one go. + */ +struct fetch_shade_emit { + struct draw_pt_middle_end base; + struct draw_context *draw; + + + /* Temporaries: + */ + const float *constants; + unsigned pitch[PIPE_MAX_ATTRIBS]; + const ubyte *src[PIPE_MAX_ATTRIBS]; + unsigned prim; + + struct draw_vs_varient_key key; + struct draw_vs_varient *active; + + + const struct vertex_info *vinfo; +}; + + + + +static void fse_prepare( struct draw_pt_middle_end *middle, + unsigned prim, + unsigned opt, + unsigned *max_vertices ) +{ + struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle; + struct draw_context *draw = fse->draw; + unsigned num_vs_inputs = draw->vs.vertex_shader->info.num_inputs; + const struct vertex_info *vinfo; + unsigned i; + + + if (!draw->render->set_primitive( draw->render, + prim )) { + assert(0); + return; + } + + /* Must do this after set_primitive() above: + */ + fse->vinfo = vinfo = draw->render->get_vertex_info(draw->render); + + + + fse->key.output_stride = vinfo->size * 4; + fse->key.nr_outputs = vinfo->num_attribs; + fse->key.nr_inputs = num_vs_inputs; + + fse->key.nr_elements = MAX2(fse->key.nr_outputs, /* outputs - translate to hw format */ + fse->key.nr_inputs); /* inputs - fetch from api format */ + + fse->key.viewport = !draw->identity_viewport; + fse->key.clip = !draw->bypass_clipping; + fse->key.pad = 0; + + memset(fse->key.element, 0, + fse->key.nr_elements * sizeof(fse->key.element[0])); + + for (i = 0; i < num_vs_inputs; i++) { + const struct pipe_vertex_element *src = &draw->pt.vertex_element[i]; + fse->key.element[i].in.format = src->src_format; + + /* Consider ignoring these, ie make generated programs + * independent of this state: + */ + fse->key.element[i].in.buffer = src->vertex_buffer_index; + fse->key.element[i].in.offset = src->src_offset; + } + + + { + unsigned dst_offset = 0; + + for (i = 0; i < vinfo->num_attribs; i++) { + unsigned emit_sz = 0; + + switch (vinfo->emit[i]) { + case EMIT_4F: + emit_sz = 4 * sizeof(float); + break; + case EMIT_3F: + emit_sz = 3 * sizeof(float); + break; + case EMIT_2F: + emit_sz = 2 * sizeof(float); + break; + case EMIT_1F: + emit_sz = 1 * sizeof(float); + break; + case EMIT_1F_PSIZE: + emit_sz = 1 * sizeof(float); + break; + case EMIT_4UB: + emit_sz = 4 * sizeof(ubyte); + break; + default: + assert(0); + break; + } + + /* The elements in the key correspond to vertex shader output + * numbers, not to positions in the hw vertex description -- + * that's handled by the output_offset field. + */ + fse->key.element[i].out.format = vinfo->emit[i]; + fse->key.element[i].out.vs_output = vinfo->src_index[i]; + fse->key.element[i].out.offset = dst_offset; + + dst_offset += emit_sz; + assert(fse->key.output_stride >= dst_offset); + } + } + + + /* Would normally look up a vertex shader and peruse its list of + * varients somehow. We omitted that step and put all the + * hardcoded "shaders" into an array. We're just making the + * assumption that this happens to be a matching shader... ie + * you're running isosurf, aren't you? + */ + fse->active = draw_vs_lookup_varient( draw->vs.vertex_shader, + &fse->key ); + + if (!fse->active) { + assert(0); + return ; + } + + /* Now set buffer pointers: + */ + for (i = 0; i < num_vs_inputs; i++) { + unsigned buf = draw->pt.vertex_element[i].vertex_buffer_index; + + fse->active->set_input( fse->active, + i, + + ((const ubyte *) draw->pt.user.vbuffer[buf] + + draw->pt.vertex_buffer[buf].buffer_offset), + + draw->pt.vertex_buffer[buf].pitch ); + } + + *max_vertices = (draw->render->max_vertex_buffer_bytes / + (vinfo->size * 4)); + + /* Return an even number of verts. + * This prevents "parity" errors when splitting long triangle strips which + * can lead to front/back culling mix-ups. + * Every other triangle in a strip has an alternate front/back orientation + * so splitting at an odd position can cause the orientation of subsequent + * triangles to get reversed. + */ + *max_vertices = *max_vertices & ~1; + + /* Probably need to do this somewhere (or fix exec shader not to + * need it): + */ + if (1) { + struct draw_vertex_shader *vs = draw->vs.vertex_shader; + vs->prepare(vs, draw); + } + + + //return TRUE; +} + + + + + + + +static void fse_run_linear( struct draw_pt_middle_end *middle, + unsigned start, + unsigned count ) +{ + struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle; + struct draw_context *draw = fse->draw; + char *hw_verts; + + /* XXX: need to flush to get prim_vbuf.c to release its allocation?? + */ + draw_do_flush( draw, DRAW_FLUSH_BACKEND ); + + hw_verts = draw->render->allocate_vertices( draw->render, + (ushort)fse->key.output_stride, + (ushort)count ); + + if (!hw_verts) { + assert(0); + return; + } + + /* Single routine to fetch vertices, run shader and emit HW verts. + * Clipping is done elsewhere -- either by the API or on hardware, + * or for some other reason not required... + */ + fse->active->run_linear( fse->active, + start, count, + hw_verts ); + + /* Draw arrays path to avoid re-emitting index list again and + * again. + */ + draw->render->draw_arrays( draw->render, + 0, + count ); + + if (0) { + unsigned i; + for (i = 0; i < count; i++) { + debug_printf("\n\n%s vertex %d: (stride %d, offset %d)\n", __FUNCTION__, i, + fse->key.output_stride, + fse->key.output_stride * i); + + draw_dump_emitted_vertex( fse->vinfo, + (const uint8_t *)hw_verts + fse->key.output_stride * i ); + } + } + + + draw->render->release_vertices( draw->render, + hw_verts, + fse->key.output_stride, + count ); +} + + +static void +fse_run(struct draw_pt_middle_end *middle, + const unsigned *fetch_elts, + unsigned fetch_count, + const ushort *draw_elts, + unsigned draw_count ) +{ + struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle; + struct draw_context *draw = fse->draw; + void *hw_verts; + + /* XXX: need to flush to get prim_vbuf.c to release its allocation?? + */ + draw_do_flush( draw, DRAW_FLUSH_BACKEND ); + + hw_verts = draw->render->allocate_vertices( draw->render, + (ushort)fse->key.output_stride, + (ushort)fetch_count ); + if (!hw_verts) { + assert(0); + return; + } + + + /* Single routine to fetch vertices, run shader and emit HW verts. + */ + fse->active->run_elts( fse->active, + fetch_elts, + fetch_count, + hw_verts ); + + draw->render->draw( draw->render, + draw_elts, + draw_count ); + + if (0) { + unsigned i; + for (i = 0; i < fetch_count; i++) { + debug_printf("\n\n%s vertex %d:\n", __FUNCTION__, i); + draw_dump_emitted_vertex( fse->vinfo, + (const uint8_t *)hw_verts + + fse->key.output_stride * i ); + } + } + + + draw->render->release_vertices( draw->render, + hw_verts, + fse->key.output_stride, + fetch_count ); + +} + + + +static void fse_run_linear_elts( struct draw_pt_middle_end *middle, + unsigned start, + unsigned count, + const ushort *draw_elts, + unsigned draw_count ) +{ + struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle; + struct draw_context *draw = fse->draw; + char *hw_verts; + + /* XXX: need to flush to get prim_vbuf.c to release its allocation?? + */ + draw_do_flush( draw, DRAW_FLUSH_BACKEND ); + + hw_verts = draw->render->allocate_vertices( draw->render, + (ushort)fse->key.output_stride, + (ushort)count ); + + if (!hw_verts) { + assert(0); + return; + } + + /* Single routine to fetch vertices, run shader and emit HW verts. + * Clipping is done elsewhere -- either by the API or on hardware, + * or for some other reason not required... + */ + fse->active->run_linear( fse->active, + start, count, + hw_verts ); + + + draw->render->draw( draw->render, + draw_elts, + draw_count ); + + + + draw->render->release_vertices( draw->render, + hw_verts, + fse->key.output_stride, + count ); +} + + + +static void fse_finish( struct draw_pt_middle_end *middle ) +{ +} + + +static void +fse_destroy( struct draw_pt_middle_end *middle ) +{ + FREE(middle); +} + +struct draw_pt_middle_end *draw_pt_middle_fse( struct draw_context *draw ) +{ + struct fetch_shade_emit *fse = CALLOC_STRUCT(fetch_shade_emit); + if (!fse) + return NULL; + + fse->base.prepare = fse_prepare; + fse->base.run = fse_run; + fse->base.run_linear = fse_run_linear; + fse->base.run_linear_elts = fse_run_linear_elts; + fse->base.finish = fse_finish; + fse->base.destroy = fse_destroy; + fse->draw = draw; + + return &fse->base; +} diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c index 4ec20493c4..0aec4b71ba 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c @@ -51,11 +51,12 @@ struct fetch_pipeline_middle_end { static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle, unsigned prim, - unsigned opt ) + unsigned opt, + unsigned *max_vertices ) { struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle; struct draw_context *draw = fpme->draw; - struct draw_vertex_shader *vs = draw->vertex_shader; + struct draw_vertex_shader *vs = draw->vs.vertex_shader; /* Add one to num_outputs because the pipeline occasionally tags on * an additional texcoord, eg for AA lines. @@ -81,24 +82,33 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle, * but gl vs dx9 clip spaces. */ draw_pt_post_vs_prepare( fpme->post_vs, - draw->bypass_clipping, - draw->identity_viewport, - draw->rasterizer->gl_rasterization_rules ); + (boolean)draw->bypass_clipping, + (boolean)draw->identity_viewport, + (boolean)draw->rasterizer->gl_rasterization_rules ); - if (!(opt & PT_PIPELINE)) + if (!(opt & PT_PIPELINE)) { draw_pt_emit_prepare( fpme->emit, - prim ); + prim, + max_vertices ); + + *max_vertices = MAX2( *max_vertices, + DRAW_PIPE_MAX_VERTICES ); + } + else { + *max_vertices = DRAW_PIPE_MAX_VERTICES; + } + + /* return even number */ + *max_vertices = *max_vertices & ~1; /* No need to prepare the shader. */ vs->prepare(vs, draw); - } - static void fetch_pipeline_run( struct draw_pt_middle_end *middle, const unsigned *fetch_elts, unsigned fetch_count, @@ -107,7 +117,7 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle, { struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle; struct draw_context *draw = fpme->draw; - struct draw_vertex_shader *shader = draw->vertex_shader; + struct draw_vertex_shader *shader = draw->vs.vertex_shader; unsigned opt = fpme->opt; unsigned alloc_count = align_int( fetch_count, 4 ); @@ -162,7 +172,7 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle, fpme->vertex_size, draw_elts, draw_count ); - } + } else { draw_pt_emit( fpme->emit, (const float (*)[4])pipeline_verts->data, @@ -177,6 +187,157 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle, } +static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle, + unsigned start, + unsigned count) +{ + struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle; + struct draw_context *draw = fpme->draw; + struct draw_vertex_shader *shader = draw->vs.vertex_shader; + unsigned opt = fpme->opt; + unsigned alloc_count = align_int( count, 4 ); + + struct vertex_header *pipeline_verts = + (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count); + + if (!pipeline_verts) { + /* Not much we can do here - just skip the rendering. + */ + assert(0); + return; + } + + /* Fetch into our vertex buffer + */ + draw_pt_fetch_run_linear( fpme->fetch, + start, + count, + (char *)pipeline_verts ); + + /* Run the shader, note that this overwrites the data[] parts of + * the pipeline verts. If there is no shader, ie a bypass shader, + * then the inputs == outputs, and are already in the correct + * place. + */ + if (opt & PT_SHADE) + { + shader->run_linear(shader, + (const float (*)[4])pipeline_verts->data, + ( float (*)[4])pipeline_verts->data, + (const float (*)[4])draw->pt.user.constants, + count, + fpme->vertex_size, + fpme->vertex_size); + } + + if (draw_pt_post_vs_run( fpme->post_vs, + pipeline_verts, + count, + fpme->vertex_size )) + { + opt |= PT_PIPELINE; + } + + /* Do we need to run the pipeline? + */ + if (opt & PT_PIPELINE) { + draw_pipeline_run_linear( fpme->draw, + fpme->prim, + pipeline_verts, + count, + fpme->vertex_size); + } + else { + draw_pt_emit_linear( fpme->emit, + (const float (*)[4])pipeline_verts->data, + count, + fpme->vertex_size, + 0, /*start*/ + count ); + } + + FREE(pipeline_verts); +} + + + +static void fetch_pipeline_linear_run_elts( struct draw_pt_middle_end *middle, + unsigned start, + unsigned count, + const ushort *draw_elts, + unsigned draw_count ) +{ + struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle; + struct draw_context *draw = fpme->draw; + struct draw_vertex_shader *shader = draw->vs.vertex_shader; + unsigned opt = fpme->opt; + unsigned alloc_count = align_int( count, 4 ); + + struct vertex_header *pipeline_verts = + (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count); + + if (!pipeline_verts) { + /* Not much we can do here - just skip the rendering. + */ + assert(0); + return; + } + + /* Fetch into our vertex buffer + */ + draw_pt_fetch_run_linear( fpme->fetch, + start, + count, + (char *)pipeline_verts ); + + /* Run the shader, note that this overwrites the data[] parts of + * the pipeline verts. If there is no shader, ie a bypass shader, + * then the inputs == outputs, and are already in the correct + * place. + */ + if (opt & PT_SHADE) + { + shader->run_linear(shader, + (const float (*)[4])pipeline_verts->data, + ( float (*)[4])pipeline_verts->data, + (const float (*)[4])draw->pt.user.constants, + count, + fpme->vertex_size, + fpme->vertex_size); + } + + if (draw_pt_post_vs_run( fpme->post_vs, + pipeline_verts, + count, + fpme->vertex_size )) + { + opt |= PT_PIPELINE; + } + + /* Do we need to run the pipeline? + */ + if (opt & PT_PIPELINE) { + draw_pipeline_run( fpme->draw, + fpme->prim, + pipeline_verts, + count, + fpme->vertex_size, + draw_elts, + draw_count ); + } + else { + draw_pt_emit( fpme->emit, + (const float (*)[4])pipeline_verts->data, + count, + fpme->vertex_size, + draw_elts, + draw_count ); + } + + FREE(pipeline_verts); +} + + static void fetch_pipeline_finish( struct draw_pt_middle_end *middle ) { @@ -206,10 +367,12 @@ struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit( struct draw_context * if (!fpme) goto fail; - fpme->base.prepare = fetch_pipeline_prepare; - fpme->base.run = fetch_pipeline_run; - fpme->base.finish = fetch_pipeline_finish; - fpme->base.destroy = fetch_pipeline_destroy; + fpme->base.prepare = fetch_pipeline_prepare; + fpme->base.run = fetch_pipeline_run; + fpme->base.run_linear = fetch_pipeline_linear_run; + fpme->base.run_linear_elts = fetch_pipeline_linear_run_elts; + fpme->base.finish = fetch_pipeline_finish; + fpme->base.destroy = fetch_pipeline_destroy; fpme->draw = draw; diff --git a/src/gallium/auxiliary/draw/draw_pt_post_vs.c b/src/gallium/auxiliary/draw/draw_pt_post_vs.c index c4a67c8289..af6306b1c6 100644 --- a/src/gallium/auxiliary/draw/draw_pt_post_vs.c +++ b/src/gallium/auxiliary/draw/draw_pt_post_vs.c @@ -100,16 +100,19 @@ static boolean post_vs_cliptest_viewport_gl( struct pt_post_vs *pvs, struct vertex_header *out = vertices; const float *scale = pvs->draw->viewport.scale; const float *trans = pvs->draw->viewport.translate; + const unsigned pos = pvs->draw->vs.position_output; unsigned clipped = 0; unsigned j; if (0) debug_printf("%s\n"); for (j = 0; j < count; j++) { - out->clip[0] = out->data[0][0]; - out->clip[1] = out->data[0][1]; - out->clip[2] = out->data[0][2]; - out->clip[3] = out->data[0][3]; + float *position = out->data[pos]; + + out->clip[0] = position[0]; + out->clip[1] = position[1]; + out->clip[2] = position[2]; + out->clip[3] = position[3]; out->vertex_id = 0xffff; out->clipmask = compute_clipmask_gl(out->clip, @@ -120,19 +123,19 @@ static boolean post_vs_cliptest_viewport_gl( struct pt_post_vs *pvs, if (out->clipmask == 0) { /* divide by w */ - float w = 1.0f / out->data[0][3]; + float w = 1.0f / position[3]; /* Viewport mapping */ - out->data[0][0] = out->data[0][0] * w * scale[0] + trans[0]; - out->data[0][1] = out->data[0][1] * w * scale[1] + trans[1]; - out->data[0][2] = out->data[0][2] * w * scale[2] + trans[2]; - out->data[0][3] = w; + position[0] = position[0] * w * scale[0] + trans[0]; + position[1] = position[1] * w * scale[1] + trans[1]; + position[2] = position[2] * w * scale[2] + trans[2]; + position[3] = w; #if 0 debug_printf("post viewport: %f %f %f %f\n", - out->data[0][0], - out->data[0][1], - out->data[0][2], - out->data[0][3]); + position[0], + position[1], + position[2], + position[3]); #endif } @@ -154,15 +157,18 @@ static boolean post_vs_viewport( struct pt_post_vs *pvs, struct vertex_header *out = vertices; const float *scale = pvs->draw->viewport.scale; const float *trans = pvs->draw->viewport.translate; + const unsigned pos = pvs->draw->vs.position_output; unsigned j; if (0) debug_printf("%s\n", __FUNCTION__); for (j = 0; j < count; j++) { + float *position = out->data[pos]; + /* Viewport mapping only, no cliptest/rhw divide */ - out->data[0][0] = out->data[0][0] * scale[0] + trans[0]; - out->data[0][1] = out->data[0][1] * scale[1] + trans[1]; - out->data[0][2] = out->data[0][2] * scale[2] + trans[2]; + position[0] = position[0] * scale[0] + trans[0]; + position[1] = position[1] * scale[1] + trans[1]; + position[2] = position[2] * scale[2] + trans[2]; out = (struct vertex_header *)((char *)out + stride); } diff --git a/src/gallium/auxiliary/draw/draw_pt_util.c b/src/gallium/auxiliary/draw/draw_pt_util.c new file mode 100644 index 0000000000..32c8a9632c --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_pt_util.c @@ -0,0 +1,103 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "pipe/p_util.h" +#include "draw/draw_context.h" +#include "draw/draw_private.h" +#include "draw/draw_pt.h" + +void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr) +{ + switch (prim) { + case PIPE_PRIM_POINTS: + *first = 1; + *incr = 1; + break; + case PIPE_PRIM_LINES: + *first = 2; + *incr = 2; + break; + case PIPE_PRIM_LINE_STRIP: + case PIPE_PRIM_LINE_LOOP: + *first = 2; + *incr = 1; + break; + case PIPE_PRIM_TRIANGLES: + *first = 3; + *incr = 3; + break; + case PIPE_PRIM_TRIANGLE_STRIP: + case PIPE_PRIM_TRIANGLE_FAN: + case PIPE_PRIM_POLYGON: + *first = 3; + *incr = 1; + break; + case PIPE_PRIM_QUADS: + *first = 4; + *incr = 4; + break; + case PIPE_PRIM_QUAD_STRIP: + *first = 4; + *incr = 2; + break; + default: + assert(0); + *first = 0; + *incr = 1; /* set to one so that count % incr works */ + break; + } +} + + +unsigned draw_pt_reduced_prim(unsigned prim) +{ + switch (prim) { + case PIPE_PRIM_POINTS: + return PIPE_PRIM_POINTS; + case PIPE_PRIM_LINES: + case PIPE_PRIM_LINE_STRIP: + case PIPE_PRIM_LINE_LOOP: + return PIPE_PRIM_LINES; + case PIPE_PRIM_TRIANGLES: + case PIPE_PRIM_TRIANGLE_STRIP: + case PIPE_PRIM_TRIANGLE_FAN: + case PIPE_PRIM_POLYGON: + case PIPE_PRIM_QUADS: + case PIPE_PRIM_QUAD_STRIP: + return PIPE_PRIM_TRIANGLES; + default: + assert(0); + return PIPE_PRIM_POINTS; + } +} + + diff --git a/src/gallium/auxiliary/draw/draw_pt_varray.c b/src/gallium/auxiliary/draw/draw_pt_varray.c index 355093f945..46e722a154 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray.c +++ b/src/gallium/auxiliary/draw/draw_pt_varray.c @@ -31,7 +31,7 @@ #include "draw/draw_pt.h" #define FETCH_MAX 256 -#define DRAW_MAX (16*FETCH_MAX) +#define DRAW_MAX (FETCH_MAX+8) struct varray_frontend { struct draw_pt_front_end base; @@ -40,8 +40,8 @@ struct varray_frontend { ushort draw_elts[DRAW_MAX]; unsigned fetch_elts[FETCH_MAX]; - unsigned draw_count; - unsigned fetch_count; + unsigned driver_fetch_max; + unsigned fetch_max; struct draw_pt_middle_end *middle; @@ -49,147 +49,86 @@ struct varray_frontend { unsigned output_prim; }; -static void varray_flush(struct varray_frontend *varray) -{ - if (varray->draw_count) { -#if 0 - debug_printf("FLUSH fc = %d, dc = %d\n", - varray->fetch_count, - varray->draw_count); -#endif - varray->middle->run(varray->middle, - varray->fetch_elts, - varray->fetch_count, - varray->draw_elts, - varray->draw_count); - } - - varray->fetch_count = 0; - varray->draw_count = 0; -} -#if 0 -static void varray_check_flush(struct varray_frontend *varray) +static void varray_flush_linear(struct varray_frontend *varray, + unsigned start, unsigned count) { - if (varray->draw_count + 6 >= DRAW_MAX/* || - varray->fetch_count + 4 >= FETCH_MAX*/) { - varray_flush(varray); + if (count) { + assert(varray->middle->run_linear); + varray->middle->run_linear(varray->middle, start, count); } } -#endif -static INLINE void add_draw_el(struct varray_frontend *varray, - int idx, ushort flags) +static void varray_line_loop_segment(struct varray_frontend *varray, + unsigned start, + unsigned segment_start, + unsigned segment_count, + boolean end ) { - varray->draw_elts[varray->draw_count++] = idx | flags; -} + assert(segment_count+1 < varray->fetch_max); + if (segment_count >= 1) { + unsigned nr = 0, i; + for (i = 0; i < segment_count; i++) + varray->fetch_elts[nr++] = start + segment_start + i; -static INLINE void varray_triangle( struct varray_frontend *varray, - unsigned i0, - unsigned i1, - unsigned i2 ) -{ - add_draw_el(varray, i0, 0); - add_draw_el(varray, i1, 0); - add_draw_el(varray, i2, 0); -} + if (end) + varray->fetch_elts[nr++] = start; -static INLINE void varray_triangle_flags( struct varray_frontend *varray, - ushort flags, - unsigned i0, - unsigned i1, - unsigned i2 ) -{ - add_draw_el(varray, i0, flags); - add_draw_el(varray, i1, 0); - add_draw_el(varray, i2, 0); -} + assert(nr < FETCH_MAX); -static INLINE void varray_line( struct varray_frontend *varray, - unsigned i0, - unsigned i1 ) -{ - add_draw_el(varray, i0, 0); - add_draw_el(varray, i1, 0); + varray->middle->run(varray->middle, + varray->fetch_elts, + nr, + varray->draw_elts, /* ie. linear */ + nr); + } } -static INLINE void varray_line_flags( struct varray_frontend *varray, - ushort flags, - unsigned i0, - unsigned i1 ) -{ - add_draw_el(varray, i0, flags); - add_draw_el(varray, i1, 0); -} - -static INLINE void varray_point( struct varray_frontend *varray, - unsigned i0 ) +static void varray_fan_segment(struct varray_frontend *varray, + unsigned start, + unsigned segment_start, + unsigned segment_count ) { - add_draw_el(varray, i0, 0); -} + assert(segment_count+1 < varray->fetch_max); + if (segment_count >= 2) { + unsigned nr = 0, i; -static INLINE void varray_quad( struct varray_frontend *varray, - unsigned i0, - unsigned i1, - unsigned i2, - unsigned i3 ) -{ - varray_triangle( varray, i0, i1, i3 ); - varray_triangle( varray, i1, i2, i3 ); -} + if (segment_start != 0) + varray->fetch_elts[nr++] = start; -static INLINE void varray_ef_quad( struct varray_frontend *varray, - unsigned i0, - unsigned i1, - unsigned i2, - unsigned i3 ) -{ - const unsigned omitEdge1 = DRAW_PIPE_EDGE_FLAG_0 | DRAW_PIPE_EDGE_FLAG_2; - const unsigned omitEdge2 = DRAW_PIPE_EDGE_FLAG_0 | DRAW_PIPE_EDGE_FLAG_1; + for (i = 0 ; i < segment_count; i++) + varray->fetch_elts[nr++] = start + segment_start + i; - varray_triangle_flags( varray, - DRAW_PIPE_RESET_STIPPLE | omitEdge1, - i0, i1, i3 ); + assert(nr < FETCH_MAX); - varray_triangle_flags( varray, - omitEdge2, - i1, i2, i3 ); + varray->middle->run(varray->middle, + varray->fetch_elts, + nr, + varray->draw_elts, /* ie. linear */ + nr); + } } -/* At least for now, we're back to using a template include file for - * this. The two paths aren't too different though - it may be - * possible to reunify them. - */ -#define TRIANGLE(vc,flags,i0,i1,i2) varray_triangle_flags(vc,flags,i0,i1,i2) -#define QUAD(vc,i0,i1,i2,i3) varray_ef_quad(vc,i0,i1,i2,i3) -#define LINE(vc,flags,i0,i1) varray_line_flags(vc,flags,i0,i1) -#define POINT(vc,i0) varray_point(vc,i0) -#define FUNC varray_run_extras -#include "draw_pt_varray_tmp.h" - -#define TRIANGLE(vc,flags,i0,i1,i2) varray_triangle(vc,i0,i1,i2) -#define QUAD(vc,i0,i1,i2,i3) varray_quad(vc,i0,i1,i2,i3) -#define LINE(vc,flags,i0,i1) varray_line(vc,i0,i1) -#define POINT(vc,i0) varray_point(vc,i0) -#define FUNC varray_run -#include "draw_pt_varray_tmp.h" -static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = { +#define FUNC varray_run +#include "draw_pt_varray_tmp_linear.h" + +static unsigned decompose_prim[PIPE_PRIM_POLYGON + 1] = { PIPE_PRIM_POINTS, PIPE_PRIM_LINES, - PIPE_PRIM_LINES, - PIPE_PRIM_LINES, + PIPE_PRIM_LINE_STRIP, /* decomposed LINELOOP */ + PIPE_PRIM_LINE_STRIP, PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES + PIPE_PRIM_TRIANGLE_STRIP, + PIPE_PRIM_TRIANGLE_FAN, + PIPE_PRIM_QUADS, + PIPE_PRIM_QUAD_STRIP, + PIPE_PRIM_POLYGON }; @@ -201,20 +140,18 @@ static void varray_prepare(struct draw_pt_front_end *frontend, { struct varray_frontend *varray = (struct varray_frontend *)frontend; - if (opt & PT_PIPELINE) - { - varray->base.run = varray_run_extras; - } - else - { - varray->base.run = varray_run; - } + varray->base.run = varray_run; varray->input_prim = prim; - varray->output_prim = reduced_prim[prim]; + varray->output_prim = decompose_prim[prim]; varray->middle = middle; - middle->prepare(middle, varray->output_prim, opt); + middle->prepare(middle, varray->output_prim, opt, &varray->driver_fetch_max ); + + /* check that the max is even */ + assert((varray->driver_fetch_max & 1) == 0); + + varray->fetch_max = MIN2(FETCH_MAX, varray->driver_fetch_max); } @@ -235,6 +172,7 @@ static void varray_destroy(struct draw_pt_front_end *frontend) struct draw_pt_front_end *draw_pt_varray(struct draw_context *draw) { + ushort i; struct varray_frontend *varray = CALLOC_STRUCT(varray_frontend); if (varray == NULL) return NULL; @@ -245,5 +183,9 @@ struct draw_pt_front_end *draw_pt_varray(struct draw_context *draw) varray->base.destroy = varray_destroy; varray->draw = draw; + for (i = 0; i < DRAW_MAX; i++) { + varray->draw_elts[i] = i; + } + return &varray->base; } diff --git a/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h b/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h index b9a319b253..7c722457c3 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h +++ b/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h @@ -10,32 +10,45 @@ static void FUNC(struct draw_pt_front_end *frontend, boolean flatfirst = (draw->rasterizer->flatshade && draw->rasterizer->flatshade_first); - unsigned i, flags; + unsigned i, j; + ushort flags; + unsigned first, incr; + + varray->fetch_start = start; + + draw_pt_split_prim(varray->input_prim, &first, &incr); #if 0 - debug_printf("%s (%d) %d/%d\n", __FUNCTION__, draw->prim, start, count); -#endif -#if 0 - debug_printf("INPUT PRIM = %d (start = %d, count = %d)\n", varray->input_prim, + debug_printf("%s (%d) %d/%d\n", __FUNCTION__, + varray->input_prim, start, count); #endif - for (i = 0; i < count; ++i) { - varray->fetch_elts[i] = start + i; - } - varray->fetch_count = count; - switch (varray->input_prim) { case PIPE_PRIM_POINTS: - for (i = 0; i < count; i ++) { - POINT(varray, i + 0); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i < end; i++) { + POINT(varray, i + 0); + } + i = end; + fetch_init(varray, end); + varray_flush(varray); } break; case PIPE_PRIM_LINES: - for (i = 0; i+1 < count; i += 2) { - LINE(varray, DRAW_PIPE_RESET_STIPPLE, - i + 0, i + 1); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+1 < end; i += 2) { + LINE(varray, DRAW_PIPE_RESET_STIPPLE, + i + 0, i + 1); + } + i = end; + fetch_init(varray, end); + varray_flush(varray); } break; @@ -43,38 +56,81 @@ static void FUNC(struct draw_pt_front_end *frontend, if (count >= 2) { flags = DRAW_PIPE_RESET_STIPPLE; - for (i = 1; i < count; i++, flags = 0) { - LINE(varray, flags, i - 1, i); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 1; i < end; i++, flags = 0) { + LINE(varray, flags, i - 1, i); + } + LINE(varray, flags, i - 1, 0); + i = end; + fetch_init(varray, end); + varray_flush(varray); } - LINE(varray, flags, i - 1, 0); } break; case PIPE_PRIM_LINE_STRIP: flags = DRAW_PIPE_RESET_STIPPLE; - for (i = 1; i < count; i++, flags = 0) { - LINE(varray, flags, i - 1, i); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 1; i < end; i++, flags = 0) { + LINE(varray, flags, i - 1, i); + } + i = end; + fetch_init(varray, end); + varray_flush(varray); } break; case PIPE_PRIM_TRIANGLES: - for (i = 0; i+2 < count; i += 3) { - TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, - i + 0, i + 1, i + 2); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+2 < end; i += 3) { + TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + i + 0, i + 1, i + 2); + } + i = end; + fetch_init(varray, end); + varray_flush(varray); } break; case PIPE_PRIM_TRIANGLE_STRIP: if (flatfirst) { - for (i = 0; i+2 < count; i++) { - TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, - i + 0, i + 1 + (i&1), i + 2 - (i&1)); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+2 < end; i++) { + TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + i + 0, i + 1 + (i&1), i + 2 - (i&1)); + } + i = end; + fetch_init(varray, end); + varray_flush(varray); + if (j + first + i <= count) { + varray->fetch_start -= 2; + i -= 2; + } } } else { - for (i = 0; i+2 < count; i++) { - TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, - i + 0 + (i&1), i + 1 - (i&1), i + 2); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i + 2 < end; i++) { + TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + i + 0 + (i&1), i + 1 - (i&1), i + 2); + } + i = end; + fetch_init(varray, end); + varray_flush(varray); + if (j + first + i <= count) { + varray->fetch_start -= 2; + i -= 2; + } } } break; @@ -83,51 +139,89 @@ static void FUNC(struct draw_pt_front_end *frontend, if (count >= 3) { if (flatfirst) { flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL; - for (i = 0; i+2 < count; i++) { - TRIANGLE(varray, flags, i + 1, i + 2, 0); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+2 < end; i++) { + TRIANGLE(varray, flags, i + 1, i + 2, 0); + } + i = end; + fetch_init(varray, end); + varray_flush(varray); } } else { flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL; - for (i = 0; i+2 < count; i++) { - TRIANGLE(varray, flags, 0, i + 1, i + 2); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+2 < end; i++) { + TRIANGLE(varray, flags, 0, i + 1, i + 2); + } + i = end; + fetch_init(varray, end); + varray_flush(varray); } } } break; case PIPE_PRIM_QUADS: - for (i = 0; i+3 < count; i += 4) { - QUAD(varray, i + 0, i + 1, i + 2, i + 3); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+3 < end; i += 4) { + QUAD(varray, i + 0, i + 1, i + 2, i + 3); + } + i = end; + fetch_init(varray, end); + varray_flush(varray); } break; case PIPE_PRIM_QUAD_STRIP: - for (i = 0; i+3 < count; i += 2) { - QUAD(varray, i + 2, i + 0, i + 1, i + 3); + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+3 < end; i += 2) { + QUAD(varray, i + 2, i + 0, i + 1, i + 3); + } + i = end; + fetch_init(varray, end); + varray_flush(varray); + if (j + first + i <= count) { + varray->fetch_start -= 2; + i -= 2; + } } break; case PIPE_PRIM_POLYGON: { - /* These bitflags look a little odd because we submit the - * vertices as (1,2,0) to satisfy flatshade requirements. - */ - const unsigned edge_first = DRAW_PIPE_EDGE_FLAG_2; - const unsigned edge_middle = DRAW_PIPE_EDGE_FLAG_0; - const unsigned edge_last = DRAW_PIPE_EDGE_FLAG_1; - - flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle; - - for (i = 0; i+2 < count; i++, flags = edge_middle) { + /* These bitflags look a little odd because we submit the + * vertices as (1,2,0) to satisfy flatshade requirements. + */ + const ushort edge_first = DRAW_PIPE_EDGE_FLAG_2; + const ushort edge_middle = DRAW_PIPE_EDGE_FLAG_0; + const ushort edge_last = DRAW_PIPE_EDGE_FLAG_1; + + flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle; + for (j = 0; j + first <= count; j += i) { + unsigned end = MIN2(FETCH_MAX, count - j); + end -= (end % incr); + for (i = 0; i+2 < end; i++, flags = edge_middle) { if (i + 3 == count) flags |= edge_last; - TRIANGLE(varray, flags, i + 1, i + 2, 0); - } + TRIANGLE(varray, flags, i + 1, i + 2, 0); + } + i = end; + fetch_init(varray, end); + varray_flush(varray); } - break; + } + break; default: assert(0); diff --git a/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h b/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h new file mode 100644 index 0000000000..55a8e6521d --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h @@ -0,0 +1,91 @@ +static unsigned trim( unsigned count, unsigned first, unsigned incr ) +{ + return count - (count - first) % incr; +} + +static void FUNC(struct draw_pt_front_end *frontend, + pt_elt_func get_elt, + const void *elts, + unsigned count) +{ + struct varray_frontend *varray = (struct varray_frontend *)frontend; + unsigned start = (unsigned)elts; + + unsigned j; + unsigned first, incr; + + draw_pt_split_prim(varray->input_prim, &first, &incr); + + /* Sanitize primitive length: + */ + count = trim(count, first, incr); + if (count < first) + return; + +#if 0 + debug_printf("%s (%d) %d/%d\n", __FUNCTION__, + varray->input_prim, + start, count); +#endif + + switch (varray->input_prim) { + case PIPE_PRIM_POINTS: + case PIPE_PRIM_LINES: + case PIPE_PRIM_TRIANGLES: + case PIPE_PRIM_LINE_STRIP: + case PIPE_PRIM_TRIANGLE_STRIP: + case PIPE_PRIM_QUADS: + case PIPE_PRIM_QUAD_STRIP: + for (j = 0; j < count;) { + unsigned remaining = count - j; + unsigned nr = trim( MIN2(varray->driver_fetch_max, remaining), first, incr ); + varray_flush_linear(varray, start + j, nr); + j += nr; + if (nr != remaining) + j -= (first - incr); + } + break; + + case PIPE_PRIM_LINE_LOOP: + /* Always have to decompose as we've stated that this will be + * emitted as a line-strip. + */ + for (j = 0; j < count;) { + unsigned remaining = count - j; + unsigned nr = trim( MIN2(varray->fetch_max-1, remaining), first, incr ); + varray_line_loop_segment(varray, start, j, nr, nr == remaining); + j += nr; + if (nr != remaining) + j -= (first - incr); + } + break; + + + case PIPE_PRIM_POLYGON: + case PIPE_PRIM_TRIANGLE_FAN: + if (count < varray->driver_fetch_max) { + varray_flush_linear(varray, start, count); + } + else { + for ( j = 0; j < count;) { + unsigned remaining = count - j; + unsigned nr = trim( MIN2(varray->fetch_max-1, remaining), first, incr ); + varray_fan_segment(varray, start, j, nr); + j += nr; + if (nr != remaining) + j -= (first - incr); + } + } + break; + + default: + assert(0); + break; + } +} + +#undef TRIANGLE +#undef QUAD +#undef POINT +#undef LINE +#undef FUNC diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache.c b/src/gallium/auxiliary/draw/draw_pt_vcache.c index 6b3fb1406b..cda2987c9e 100644 --- a/src/gallium/auxiliary/draw/draw_pt_vcache.c +++ b/src/gallium/auxiliary/draw/draw_pt_vcache.c @@ -36,8 +36,8 @@ #include "draw/draw_pt.h" -#define CACHE_MAX 32 -#define FETCH_MAX 128 +#define CACHE_MAX 256 +#define FETCH_MAX 256 #define DRAW_MAX (16*1024) struct vcache_frontend { @@ -52,15 +52,27 @@ struct vcache_frontend { unsigned draw_count; unsigned fetch_count; + unsigned fetch_max; struct draw_pt_middle_end *middle; unsigned input_prim; unsigned output_prim; + + unsigned middle_prim; + unsigned opt; }; static void vcache_flush( struct vcache_frontend *vcache ) { + if (vcache->middle_prim != vcache->output_prim) { + vcache->middle_prim = vcache->output_prim; + vcache->middle->prepare( vcache->middle, + vcache->middle_prim, + vcache->opt, + &vcache->fetch_max ); + } + if (vcache->draw_count) { vcache->middle->run( vcache->middle, vcache->fetch_elts, @@ -171,15 +183,15 @@ static void vcache_ef_quad( struct vcache_frontend *vcache, unsigned i2, unsigned i3 ) { - const unsigned omitEdge1 = DRAW_PIPE_EDGE_FLAG_0 | DRAW_PIPE_EDGE_FLAG_2; - const unsigned omitEdge2 = DRAW_PIPE_EDGE_FLAG_0 | DRAW_PIPE_EDGE_FLAG_1; - - vcache_triangle_flags( vcache, - DRAW_PIPE_RESET_STIPPLE | omitEdge1, + vcache_triangle_flags( vcache, + ( DRAW_PIPE_RESET_STIPPLE | + DRAW_PIPE_EDGE_FLAG_0 | + DRAW_PIPE_EDGE_FLAG_2 ), i0, i1, i3 ); - vcache_triangle_flags( vcache, - omitEdge2, + vcache_triangle_flags( vcache, + ( DRAW_PIPE_EDGE_FLAG_0 | + DRAW_PIPE_EDGE_FLAG_1 ), i1, i2, i3 ); } @@ -201,21 +213,201 @@ static void vcache_ef_quad( struct vcache_frontend *vcache, #define FUNC vcache_run #include "draw_pt_vcache_tmp.h" +static void rebase_uint_elts( const unsigned *src, + unsigned count, + int delta, + ushort *dest ) +{ + unsigned i; + for (i = 0; i < count; i++) + dest[i] = (ushort)(src[i] + delta); +} +static void rebase_ushort_elts( const ushort *src, + unsigned count, + int delta, + ushort *dest ) +{ + unsigned i; + + for (i = 0; i < count; i++) + dest[i] = (ushort)(src[i] + delta); +} + +static void rebase_ubyte_elts( const ubyte *src, + unsigned count, + int delta, + ushort *dest ) +{ + unsigned i; + + for (i = 0; i < count; i++) + dest[i] = (ushort)(src[i] + delta); +} + + + +static void translate_uint_elts( const unsigned *src, + unsigned count, + ushort *dest ) +{ + unsigned i; + + for (i = 0; i < count; i++) + dest[i] = (ushort)(src[i]); +} + +static void translate_ushort_elts( const ushort *src, + unsigned count, + ushort *dest ) +{ + unsigned i; + + for (i = 0; i < count; i++) + dest[i] = (ushort)(src[i]); +} + +static void translate_ubyte_elts( const ubyte *src, + unsigned count, + ushort *dest ) +{ + unsigned i; + + for (i = 0; i < count; i++) + dest[i] = (ushort)(src[i]); +} + + + + +#if 0 +static enum pipe_format format_from_get_elt( pt_elt_func get_elt ) +{ + switch (draw->pt.user.eltSize) { + case 1: return PIPE_FORMAT_R8_UNORM; + case 2: return PIPE_FORMAT_R16_UNORM; + case 4: return PIPE_FORMAT_R32_UNORM; + default: return PIPE_FORMAT_NONE; + } +} +#endif + +static void vcache_check_run( struct draw_pt_front_end *frontend, + pt_elt_func get_elt, + const void *elts, + unsigned draw_count ) +{ + struct vcache_frontend *vcache = (struct vcache_frontend *)frontend; + struct draw_context *draw = vcache->draw; + unsigned min_index = draw->pt.user.min_index; + unsigned max_index = draw->pt.user.max_index; + unsigned index_size = draw->pt.user.eltSize; + unsigned fetch_count = max_index + 1 - min_index; + const ushort *transformed_elts; + ushort *storage = NULL; + + + if (0) debug_printf("fetch_count %d fetch_max %d draw_count %d\n", fetch_count, + vcache->fetch_max, + draw_count); + + if (max_index == 0xffffffff || + fetch_count >= vcache->fetch_max || + fetch_count > draw_count) { + if (0) debug_printf("fail\n"); + goto fail; + } + + if (vcache->middle_prim != vcache->input_prim) { + vcache->middle_prim = vcache->input_prim; + vcache->middle->prepare( vcache->middle, + vcache->middle_prim, + vcache->opt, + &vcache->fetch_max ); + } + + + if (min_index == 0 && + index_size == 2) + { + transformed_elts = (const ushort *)elts; + } + else + { + storage = MALLOC( draw_count * sizeof(ushort) ); + if (!storage) + goto fail; + + if (min_index == 0) { + switch(index_size) { + case 1: + translate_ubyte_elts( (const ubyte *)elts, + draw_count, + storage ); + break; + + case 2: + translate_ushort_elts( (const ushort *)elts, + draw_count, + storage ); + break; + + case 4: + translate_uint_elts( (const uint *)elts, + draw_count, + storage ); + break; + + default: + assert(0); + return; + } + } + else { + switch(index_size) { + case 1: + rebase_ubyte_elts( (const ubyte *)elts, + draw_count, + 0 - (int)min_index, + storage ); + break; + + case 2: + rebase_ushort_elts( (const ushort *)elts, + draw_count, + 0 - (int)min_index, + storage ); + break; + + case 4: + rebase_uint_elts( (const uint *)elts, + draw_count, + 0 - (int)min_index, + storage ); + break; + + default: + assert(0); + return; + } + } + transformed_elts = storage; + } + + vcache->middle->run_linear_elts( vcache->middle, + min_index, /* start */ + fetch_count, + transformed_elts, + draw_count ); + + FREE(storage); + return; + + fail: + vcache_run( frontend, get_elt, elts, draw_count ); +} -static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = { - PIPE_PRIM_POINTS, - PIPE_PRIM_LINES, - PIPE_PRIM_LINES, - PIPE_PRIM_LINES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES -}; @@ -232,14 +424,20 @@ static void vcache_prepare( struct draw_pt_front_end *frontend, } else { - vcache->base.run = vcache_run; + vcache->base.run = vcache_check_run; } vcache->input_prim = prim; - vcache->output_prim = reduced_prim[prim]; + vcache->output_prim = draw_pt_reduced_prim(prim); vcache->middle = middle; - middle->prepare( middle, vcache->output_prim, opt ); + vcache->opt = opt; + + /* Have to run prepare here, but try and guess a good prim for + * doing so: + */ + vcache->middle_prim = (opt & PT_PIPELINE) ? vcache->output_prim : vcache->input_prim; + middle->prepare( middle, vcache->middle_prim, opt, &vcache->fetch_max ); } diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h b/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h index cf9f394aa3..ec05bbeab4 100644 --- a/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h +++ b/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h @@ -10,7 +10,10 @@ static void FUNC( struct draw_pt_front_end *frontend, boolean flatfirst = (draw->rasterizer->flatshade && draw->rasterizer->flatshade_first); - unsigned i, flags; + unsigned i; + ushort flags; + + if (0) debug_printf("%s %d\n", __FUNCTION__, count); switch (vcache->input_prim) { @@ -138,9 +141,9 @@ static void FUNC( struct draw_pt_front_end *frontend, /* These bitflags look a little odd because we submit the * vertices as (1,2,0) to satisfy flatshade requirements. */ - const unsigned edge_first = DRAW_PIPE_EDGE_FLAG_2; - const unsigned edge_middle = DRAW_PIPE_EDGE_FLAG_0; - const unsigned edge_last = DRAW_PIPE_EDGE_FLAG_1; + const ushort edge_first = DRAW_PIPE_EDGE_FLAG_2; + const ushort edge_middle = DRAW_PIPE_EDGE_FLAG_0; + const ushort edge_last = DRAW_PIPE_EDGE_FLAG_1; flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle; diff --git a/src/gallium/auxiliary/draw/draw_vertex.h b/src/gallium/auxiliary/draw/draw_vertex.h index 6d8bac5138..16c65c4317 100644 --- a/src/gallium/auxiliary/draw/draw_vertex.h +++ b/src/gallium/auxiliary/draw/draw_vertex.h @@ -109,4 +109,25 @@ extern void draw_compute_vertex_size(struct vertex_info *vinfo); void draw_dump_emitted_vertex(const struct vertex_info *vinfo, const uint8_t *data); + +static INLINE unsigned draw_translate_vinfo_format(unsigned format ) +{ + switch (format) { + case EMIT_1F: + case EMIT_1F_PSIZE: + return PIPE_FORMAT_R32_FLOAT; + case EMIT_2F: + return PIPE_FORMAT_R32G32_FLOAT; + case EMIT_3F: + return PIPE_FORMAT_R32G32B32_FLOAT; + case EMIT_4F: + return PIPE_FORMAT_R32G32B32A32_FLOAT; + case EMIT_4UB: + return PIPE_FORMAT_R8G8B8A8_UNORM; + default: + return PIPE_FORMAT_NONE; + } +} + + #endif /* DRAW_VERTEX_H */ diff --git a/src/gallium/auxiliary/draw/draw_vs.c b/src/gallium/auxiliary/draw/draw_vs.c index 03fe00a951..978954e91c 100644 --- a/src/gallium/auxiliary/draw/draw_vs.c +++ b/src/gallium/auxiliary/draw/draw_vs.c @@ -36,6 +36,38 @@ #include "draw_private.h" #include "draw_context.h" #include "draw_vs.h" +#include "translate/translate.h" +#include "translate/translate_cache.h" + + + + +void draw_vs_set_constants( struct draw_context *draw, + const float (*constants)[4], + unsigned size ) +{ + if (((unsigned)constants) & 0xf) { + if (size > draw->vs.const_storage_size) { + if (draw->vs.aligned_constant_storage) + align_free((void *)draw->vs.aligned_constant_storage); + draw->vs.aligned_constant_storage = align_malloc( size, 16 ); + } + memcpy( (void*)draw->vs.aligned_constant_storage, + constants, + size ); + constants = draw->vs.aligned_constant_storage; + } + + draw->vs.aligned_constants = constants; + draw_vs_aos_machine_constants( draw->vs.aos_machine, constants ); +} + + +void draw_vs_set_viewport( struct draw_context *draw, + const struct pipe_viewport_state *viewport ) +{ + draw_vs_aos_machine_viewport( draw->vs.aos_machine, viewport ); +} @@ -53,6 +85,16 @@ draw_create_vertex_shader(struct draw_context *draw, } } + if (vs) + { + uint i; + for (i = 0; i < vs->info.num_outputs; i++) { + if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION && + vs->info.output_semantic_index[i] == 0) + vs->position_output = i; + } + } + assert(vs); return vs; } @@ -66,13 +108,14 @@ draw_bind_vertex_shader(struct draw_context *draw, if (dvs) { - draw->vertex_shader = dvs; - draw->num_vs_outputs = dvs->info.num_outputs; + draw->vs.vertex_shader = dvs; + draw->vs.num_vs_outputs = dvs->info.num_outputs; + draw->vs.position_output = dvs->position_output; dvs->prepare( dvs, draw ); } else { - draw->vertex_shader = NULL; - draw->num_vs_outputs = 0; + draw->vs.vertex_shader = NULL; + draw->vs.num_vs_outputs = 0; } } @@ -81,5 +124,135 @@ void draw_delete_vertex_shader(struct draw_context *draw, struct draw_vertex_shader *dvs) { + unsigned i; + + for (i = 0; i < dvs->nr_varients; i++) + dvs->varient[i]->destroy( dvs->varient[i] ); + + dvs->nr_varients = 0; + dvs->delete( dvs ); } + + + +boolean +draw_vs_init( struct draw_context *draw ) +{ + tgsi_exec_machine_init(&draw->vs.machine); + + /* FIXME: give this machine thing a proper constructor: + */ + draw->vs.machine.Inputs = align_malloc(PIPE_MAX_ATTRIBS * sizeof(struct tgsi_exec_vector), 16); + if (!draw->vs.machine.Inputs) + return FALSE; + + draw->vs.machine.Outputs = align_malloc(PIPE_MAX_ATTRIBS * sizeof(struct tgsi_exec_vector), 16); + if (!draw->vs.machine.Outputs) + return FALSE; + + draw->vs.emit_cache = translate_cache_create(); + if (!draw->vs.emit_cache) + return FALSE; + + draw->vs.fetch_cache = translate_cache_create(); + if (!draw->vs.fetch_cache) + return FALSE; + + draw->vs.aos_machine = draw_vs_aos_machine(); + if (!draw->vs.aos_machine) + return FALSE; + + return TRUE; +} + +void +draw_vs_destroy( struct draw_context *draw ) +{ + if (draw->vs.machine.Inputs) + align_free(draw->vs.machine.Inputs); + + if (draw->vs.machine.Outputs) + align_free(draw->vs.machine.Outputs); + + if (draw->vs.fetch_cache) + translate_cache_destroy(draw->vs.fetch_cache); + + if (draw->vs.emit_cache) + translate_cache_destroy(draw->vs.emit_cache); + + if (draw->vs.aos_machine) + draw_vs_aos_machine_destroy(draw->vs.aos_machine); + + if (draw->vs.aligned_constant_storage) + align_free((void*)draw->vs.aligned_constant_storage); + + tgsi_exec_machine_free_data(&draw->vs.machine); + +} + + +struct draw_vs_varient * +draw_vs_lookup_varient( struct draw_vertex_shader *vs, + const struct draw_vs_varient_key *key ) +{ + struct draw_vs_varient *varient; + unsigned i; + + /* Lookup existing varient: + */ + for (i = 0; i < vs->nr_varients; i++) + if (draw_vs_varient_key_compare(key, &vs->varient[i]->key) == 0) + return vs->varient[i]; + + /* Else have to create a new one: + */ + varient = vs->create_varient( vs, key ); + if (varient == NULL) + return NULL; + + /* Add it to our list, could be smarter: + */ + if (vs->nr_varients < Elements(vs->varient)) { + vs->varient[vs->nr_varients++] = varient; + } + else { + vs->last_varient++; + vs->last_varient %= Elements(vs->varient); + vs->varient[vs->last_varient]->destroy(vs->varient[vs->last_varient]); + vs->varient[vs->last_varient] = varient; + } + + /* Done + */ + return varient; +} + + +struct translate * +draw_vs_get_fetch( struct draw_context *draw, + struct translate_key *key ) +{ + if (!draw->vs.fetch || + translate_key_compare(&draw->vs.fetch->key, key) != 0) + { + translate_key_sanitize(key); + draw->vs.fetch = translate_cache_find(draw->vs.fetch_cache, key); + } + + return draw->vs.fetch; +} + +struct translate * +draw_vs_get_emit( struct draw_context *draw, + struct translate_key *key ) +{ + if (!draw->vs.emit || + translate_key_compare(&draw->vs.emit->key, key) != 0) + { + translate_key_sanitize(key); + draw->vs.emit = translate_cache_find(draw->vs.emit_cache, key); + } + + return draw->vs.emit; +} diff --git a/src/gallium/auxiliary/draw/draw_vs.h b/src/gallium/auxiliary/draw/draw_vs.h index f9772b83b8..45992d1986 100644 --- a/src/gallium/auxiliary/draw/draw_vs.h +++ b/src/gallium/auxiliary/draw/draw_vs.h @@ -38,16 +38,88 @@ struct draw_context; struct pipe_shader_state; +struct draw_varient_input +{ + enum pipe_format format; + unsigned buffer; + unsigned offset; +}; + +struct draw_varient_output +{ + enum pipe_format format; /* output format */ + unsigned vs_output:8; /* which vertex shader output is this? */ + unsigned offset:24; /* offset into output vertex */ +}; + +struct draw_varient_element { + struct draw_varient_input in; + struct draw_varient_output out; +}; + +struct draw_vs_varient_key { + unsigned output_stride; + unsigned nr_elements:8; /* max2(nr_inputs, nr_outputs) */ + unsigned nr_inputs:8; + unsigned nr_outputs:8; + unsigned viewport:1; + unsigned clip:1; + unsigned pad:5; + struct draw_varient_element element[PIPE_MAX_ATTRIBS]; +}; + +struct draw_vs_varient; + + +struct draw_vs_varient { + struct draw_vs_varient_key key; + + struct draw_vertex_shader *vs; + + void (*set_input)( struct draw_vs_varient *, + unsigned i, + const void *ptr, + unsigned stride ); + + void (PIPE_CDECL *run_linear)( struct draw_vs_varient *shader, + unsigned start, + unsigned count, + void *output_buffer ); + + void (PIPE_CDECL *run_elts)( struct draw_vs_varient *shader, + const unsigned *elts, + unsigned count, + void *output_buffer ); + + void (*destroy)( struct draw_vs_varient * ); +}; + + /** * Private version of the compiled vertex_shader */ struct draw_vertex_shader { + struct draw_context *draw; /* This member will disappear shortly: */ struct pipe_shader_state state; struct tgsi_shader_info info; + unsigned position_output; + + /* Extracted from shader: + */ + const float (*immediates)[4]; + + /* + */ + struct draw_vs_varient *varient[16]; + unsigned nr_varients; + unsigned last_varient; + struct draw_vs_varient *(*create_varient)( struct draw_vertex_shader *shader, + const struct draw_vs_varient_key *key ); + void (*prepare)( struct draw_vertex_shader *shader, struct draw_context *draw ); @@ -68,6 +140,15 @@ struct draw_vertex_shader { }; +struct draw_vs_varient * +draw_vs_lookup_varient( struct draw_vertex_shader *base, + const struct draw_vs_varient_key *key ); + + +/******************************************************************************** + * Internal functions: + */ + struct draw_vertex_shader * draw_create_vs_exec(struct draw_context *draw, const struct pipe_shader_state *templ); @@ -81,7 +162,59 @@ draw_create_vs_llvm(struct draw_context *draw, const struct pipe_shader_state *templ); + +struct draw_vs_varient_key; +struct draw_vertex_shader; + +struct draw_vs_varient *draw_vs_varient_aos_sse( struct draw_vertex_shader *vs, + const struct draw_vs_varient_key *key ); + + + +/******************************************************************************** + * Helpers for vs implementations that don't do their own fetch/emit varients. + * Means these can be shared between shaders. + */ +struct translate; +struct translate_key; + +struct translate *draw_vs_get_fetch( struct draw_context *draw, + struct translate_key *key ); + + +struct translate *draw_vs_get_emit( struct draw_context *draw, + struct translate_key *key ); + +struct draw_vs_varient *draw_vs_varient_generic( struct draw_vertex_shader *vs, + const struct draw_vs_varient_key *key ); + + + +static INLINE int draw_vs_varient_keysize( const struct draw_vs_varient_key *key ) +{ + return 2 * sizeof(int) + key->nr_elements * sizeof(struct draw_varient_element); +} + +static INLINE int draw_vs_varient_key_compare( const struct draw_vs_varient_key *a, + const struct draw_vs_varient_key *b ) +{ + int keysize = draw_vs_varient_keysize(a); + return memcmp(a, b, keysize); +} + + +struct aos_machine *draw_vs_aos_machine( void ); +void draw_vs_aos_machine_destroy( struct aos_machine *machine ); + +void draw_vs_aos_machine_constants( struct aos_machine *machine, + const float (*constants)[4] ); + +void draw_vs_aos_machine_viewport( struct aos_machine *machine, + const struct pipe_viewport_state *viewport ); + + #define MAX_TGSI_VERTICES 4 + #endif diff --git a/src/gallium/auxiliary/draw/draw_vs_aos.c b/src/gallium/auxiliary/draw/draw_vs_aos.c new file mode 100644 index 0000000000..1f926b3e85 --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_vs_aos.c @@ -0,0 +1,2138 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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. + */ + +/** + * Translate tgsi vertex programs to x86/x87/SSE/SSE2 machine code + * using the rtasm runtime assembler. Based on the old + * t_vb_arb_program_sse.c + */ + + +#include "pipe/p_util.h" +#include "pipe/p_shader_tokens.h" +#include "tgsi/util/tgsi_parse.h" +#include "tgsi/util/tgsi_util.h" +#include "tgsi/exec/tgsi_exec.h" +#include "tgsi/util/tgsi_dump.h" + +#include "draw_vs.h" +#include "draw_vs_aos.h" + +#include "rtasm/rtasm_x86sse.h" + +#ifdef PIPE_ARCH_X86 +#define DISASSEM 0 + +static const char *files[] = +{ + "NULL", + "CONST", + "IN", + "OUT", + "TEMP", + "SAMP", + "ADDR", + "IMM", + "INTERNAL", +}; + +static INLINE boolean eq( struct x86_reg a, + struct x86_reg b ) +{ + return (a.file == b.file && + a.idx == b.idx && + a.mod == b.mod && + a.disp == b.disp); +} + +struct x86_reg aos_get_x86( struct aos_compilation *cp, + unsigned which_reg, /* quick hack */ + unsigned value ) +{ + struct x86_reg reg; + + if (which_reg == 0) + reg = cp->temp_EBP; + else + reg = cp->tmp_EAX; + + if (cp->x86_reg[which_reg] != value) { + unsigned offset; + + switch (value) { + case X86_IMMEDIATES: + assert(which_reg == 0); + offset = Offset(struct aos_machine, immediates); + break; + case X86_CONSTANTS: + assert(which_reg == 1); + offset = Offset(struct aos_machine, constants); + break; + case X86_ATTRIBS: + assert(which_reg == 0); + offset = Offset(struct aos_machine, attrib); + break; + default: + assert(0); + offset = 0; + } + + + x86_mov(cp->func, reg, + x86_make_disp(cp->machine_EDX, offset)); + + cp->x86_reg[which_reg] = value; + } + + return reg; +} + + +static struct x86_reg get_reg_ptr(struct aos_compilation *cp, + unsigned file, + unsigned idx ) +{ + struct x86_reg ptr = cp->machine_EDX; + + switch (file) { + case TGSI_FILE_INPUT: + return x86_make_disp(ptr, Offset(struct aos_machine, input[idx])); + + case TGSI_FILE_OUTPUT: + return x86_make_disp(ptr, Offset(struct aos_machine, output[idx])); + + case TGSI_FILE_TEMPORARY: + return x86_make_disp(ptr, Offset(struct aos_machine, temp[idx])); + + case AOS_FILE_INTERNAL: + return x86_make_disp(ptr, Offset(struct aos_machine, internal[idx])); + + case TGSI_FILE_IMMEDIATE: + return x86_make_disp(aos_get_x86(cp, 0, X86_IMMEDIATES), idx * 4 * sizeof(float)); + + case TGSI_FILE_CONSTANT: + return x86_make_disp(aos_get_x86(cp, 1, X86_CONSTANTS), idx * 4 * sizeof(float)); + + default: + ERROR(cp, "unknown reg file"); + return x86_make_reg(0,0); + } +} + + + +#define X87_CW_EXCEPTION_INV_OP (1<<0) +#define X87_CW_EXCEPTION_DENORM_OP (1<<1) +#define X87_CW_EXCEPTION_ZERO_DIVIDE (1<<2) +#define X87_CW_EXCEPTION_OVERFLOW (1<<3) +#define X87_CW_EXCEPTION_UNDERFLOW (1<<4) +#define X87_CW_EXCEPTION_PRECISION (1<<5) +#define X87_CW_PRECISION_SINGLE (0<<8) +#define X87_CW_PRECISION_RESERVED (1<<8) +#define X87_CW_PRECISION_DOUBLE (2<<8) +#define X87_CW_PRECISION_DOUBLE_EXT (3<<8) +#define X87_CW_PRECISION_MASK (3<<8) +#define X87_CW_ROUND_NEAREST (0<<10) +#define X87_CW_ROUND_DOWN (1<<10) +#define X87_CW_ROUND_UP (2<<10) +#define X87_CW_ROUND_ZERO (3<<10) +#define X87_CW_ROUND_MASK (3<<10) +#define X87_CW_INFINITY (1<<12) + + + + +static void spill( struct aos_compilation *cp, unsigned idx ) +{ + if (!cp->xmm[idx].dirty || + (cp->xmm[idx].file != TGSI_FILE_INPUT && /* inputs are fetched into xmm & set dirty */ + cp->xmm[idx].file != TGSI_FILE_OUTPUT && + cp->xmm[idx].file != TGSI_FILE_TEMPORARY)) { + ERROR(cp, "invalid spill"); + return; + } + else { + struct x86_reg oldval = get_reg_ptr(cp, + cp->xmm[idx].file, + cp->xmm[idx].idx); + + if (0) debug_printf("\nspill %s[%d]", + files[cp->xmm[idx].file], + cp->xmm[idx].idx); + + assert(cp->xmm[idx].dirty); + sse_movaps(cp->func, oldval, x86_make_reg(file_XMM, idx)); + cp->xmm[idx].dirty = 0; + } +} + + +static struct x86_reg get_xmm_writable( struct aos_compilation *cp, + struct x86_reg reg ) +{ + if (reg.file != file_XMM || + cp->xmm[reg.idx].file != TGSI_FILE_NULL) + { + struct x86_reg tmp = aos_get_xmm_reg(cp); + sse_movaps(cp->func, tmp, reg); + reg = tmp; + } + + cp->xmm[reg.idx].last_used = cp->insn_counter; + return reg; +} + +static struct x86_reg get_xmm( struct aos_compilation *cp, + struct x86_reg reg ) +{ + if (reg.file != file_XMM) + { + struct x86_reg tmp = aos_get_xmm_reg(cp); + sse_movaps(cp->func, tmp, reg); + reg = tmp; + } + + cp->xmm[reg.idx].last_used = cp->insn_counter; + return reg; +} + + +/* Allocate an empty xmm register, either as a temporary or later to + * "adopt" as a shader reg. + */ +struct x86_reg aos_get_xmm_reg( struct aos_compilation *cp ) +{ + unsigned i; + unsigned oldest = 0; + boolean found = FALSE; + + for (i = 0; i < 8; i++) + if (cp->xmm[i].last_used != cp->insn_counter && + cp->xmm[i].file == TGSI_FILE_NULL) { + oldest = i; + found = TRUE; + } + + if (!found) { + for (i = 0; i < 8; i++) + if (cp->xmm[i].last_used < cp->xmm[oldest].last_used) + oldest = i; + } + + /* Need to write out the old value? + */ + if (cp->xmm[oldest].dirty) + spill(cp, oldest); + + assert(cp->xmm[oldest].last_used != cp->insn_counter); + + cp->xmm[oldest].file = TGSI_FILE_NULL; + cp->xmm[oldest].idx = 0; + cp->xmm[oldest].dirty = 0; + cp->xmm[oldest].last_used = cp->insn_counter; + return x86_make_reg(file_XMM, oldest); +} + +void aos_release_xmm_reg( struct aos_compilation *cp, + unsigned idx ) +{ + cp->xmm[idx].file = TGSI_FILE_NULL; + cp->xmm[idx].idx = 0; + cp->xmm[idx].dirty = 0; + cp->xmm[idx].last_used = 0; +} + + + + +/* Mark an xmm reg as holding the current copy of a shader reg. + */ +void aos_adopt_xmm_reg( struct aos_compilation *cp, + struct x86_reg reg, + unsigned file, + unsigned idx, + unsigned dirty ) +{ + unsigned i; + + if (reg.file != file_XMM) { + assert(0); + return; + } + + + /* If any xmm reg thinks it holds this shader reg, break the + * illusion. + */ + for (i = 0; i < 8; i++) { + if (cp->xmm[i].file == file && + cp->xmm[i].idx == idx) + { + /* If an xmm reg is already holding this shader reg, take into account its + * dirty flag... + */ + dirty |= cp->xmm[i].dirty; + aos_release_xmm_reg(cp, i); + } + } + + cp->xmm[reg.idx].file = file; + cp->xmm[reg.idx].idx = idx; + cp->xmm[reg.idx].dirty = dirty; + cp->xmm[reg.idx].last_used = cp->insn_counter; +} + + +/* Return a pointer to the in-memory copy of the reg, making sure it is uptodate. + */ +static struct x86_reg aos_get_shader_reg_ptr( struct aos_compilation *cp, + unsigned file, + unsigned idx ) +{ + unsigned i; + + /* Ensure the in-memory copy of this reg is up-to-date + */ + for (i = 0; i < 8; i++) { + if (cp->xmm[i].file == file && + cp->xmm[i].idx == idx && + cp->xmm[i].dirty) { + spill(cp, i); + } + } + + return get_reg_ptr( cp, file, idx ); +} + + +/* As above, but return a pointer. Note - this pointer may alias + * those returned by get_arg_ptr(). + */ +static struct x86_reg get_dst_ptr( struct aos_compilation *cp, + const struct tgsi_full_dst_register *dst ) +{ + unsigned file = dst->DstRegister.File; + unsigned idx = dst->DstRegister.Index; + unsigned i; + + + /* Ensure in-memory copy of this reg is up-to-date and invalidate + * any xmm copies. + */ + for (i = 0; i < 8; i++) { + if (cp->xmm[i].file == file && + cp->xmm[i].idx == idx) + { + if (cp->xmm[i].dirty) + spill(cp, i); + + aos_release_xmm_reg(cp, i); + } + } + + return get_reg_ptr( cp, file, idx ); +} + + + + + +/* Return an XMM reg if the argument is resident, otherwise return a + * base+offset pointer to the saved value. + */ +struct x86_reg aos_get_shader_reg( struct aos_compilation *cp, + unsigned file, + unsigned idx ) +{ + unsigned i; + + for (i = 0; i < 8; i++) { + if (cp->xmm[i].file == file && + cp->xmm[i].idx == idx) + { + cp->xmm[i].last_used = cp->insn_counter; + return x86_make_reg(file_XMM, i); + } + } + + /* If not found in the XMM register file, return an indirect + * reference to the in-memory copy: + */ + return get_reg_ptr( cp, file, idx ); +} + + + +static struct x86_reg aos_get_shader_reg_xmm( struct aos_compilation *cp, + unsigned file, + unsigned idx ) +{ + struct x86_reg reg = get_xmm( cp, + aos_get_shader_reg( cp, file, idx ) ); + + aos_adopt_xmm_reg( cp, + reg, + file, + idx, + FALSE ); + + return reg; +} + + + +struct x86_reg aos_get_internal_xmm( struct aos_compilation *cp, + unsigned imm ) +{ + return aos_get_shader_reg_xmm( cp, AOS_FILE_INTERNAL, imm ); +} + + +struct x86_reg aos_get_internal( struct aos_compilation *cp, + unsigned imm ) +{ + return aos_get_shader_reg( cp, AOS_FILE_INTERNAL, imm ); +} + + + + + +/* Emulate pshufd insn in regular SSE, if necessary: + */ +static void emit_pshufd( struct aos_compilation *cp, + struct x86_reg dst, + struct x86_reg arg0, + ubyte shuf ) +{ + if (cp->have_sse2) { + sse2_pshufd(cp->func, dst, arg0, shuf); + } + else { + if (!eq(dst, arg0)) + sse_movaps(cp->func, dst, arg0); + + sse_shufps(cp->func, dst, dst, shuf); + } +} + +/* load masks (pack into negs??) + * pshufd - shuffle according to writemask + * and - result, mask + * nand - dest, mask + * or - dest, result + */ +static boolean mask_write( struct aos_compilation *cp, + struct x86_reg dst, + struct x86_reg result, + unsigned mask ) +{ + struct x86_reg imm_swz = aos_get_internal_xmm(cp, IMM_SWZ); + struct x86_reg tmp = aos_get_xmm_reg(cp); + + emit_pshufd(cp, tmp, imm_swz, + SHUF((mask & 1) ? 2 : 3, + (mask & 2) ? 2 : 3, + (mask & 4) ? 2 : 3, + (mask & 8) ? 2 : 3)); + + sse_andps(cp->func, dst, tmp); + sse_andnps(cp->func, tmp, result); + sse_orps(cp->func, dst, tmp); + + aos_release_xmm_reg(cp, tmp.idx); + return TRUE; +} + + + + +/* Helper for writemask: + */ +static boolean emit_shuf_copy2( struct aos_compilation *cp, + struct x86_reg dst, + struct x86_reg arg0, + struct x86_reg arg1, + ubyte shuf ) +{ + struct x86_reg tmp = aos_get_xmm_reg(cp); + + emit_pshufd(cp, dst, arg1, shuf); + emit_pshufd(cp, tmp, arg0, shuf); + sse_shufps(cp->func, dst, tmp, SHUF(X, Y, Z, W)); + emit_pshufd(cp, dst, dst, shuf); + + aos_release_xmm_reg(cp, tmp.idx); + return TRUE; +} + + + +#define SSE_SWIZZLE_NOOP ((0<<0) | (1<<2) | (2<<4) | (3<<6)) + + +/* Locate a source register and perform any required (simple) swizzle. + * + * Just fail on complex swizzles at this point. + */ +static struct x86_reg fetch_src( struct aos_compilation *cp, + const struct tgsi_full_src_register *src ) +{ + struct x86_reg arg0 = aos_get_shader_reg(cp, + src->SrcRegister.File, + src->SrcRegister.Index); + unsigned i; + ubyte swz = 0; + unsigned negs = 0; + unsigned abs = 0; + + for (i = 0; i < 4; i++) { + unsigned swizzle = tgsi_util_get_full_src_register_extswizzle( src, i ); + unsigned neg = tgsi_util_get_full_src_register_sign_mode( src, i ); + + switch (swizzle) { + case TGSI_EXTSWIZZLE_ZERO: + case TGSI_EXTSWIZZLE_ONE: + ERROR(cp, "not supporting full swizzles yet in tgsi_aos_sse2"); + break; + + default: + swz |= (swizzle & 0x3) << (i * 2); + break; + } + + switch (neg) { + case TGSI_UTIL_SIGN_TOGGLE: + negs |= (1<<i); + break; + + case TGSI_UTIL_SIGN_KEEP: + break; + + case TGSI_UTIL_SIGN_CLEAR: + abs |= (1<<i); + break; + + default: + ERROR(cp, "unsupported sign-mode"); + break; + } + } + + if (swz != SSE_SWIZZLE_NOOP || negs != 0 || abs != 0) { + struct x86_reg dst = aos_get_xmm_reg(cp); + + if (swz != SSE_SWIZZLE_NOOP) + emit_pshufd(cp, dst, arg0, swz); + else + sse_movaps(cp->func, dst, arg0); + + if (negs && negs != 0xf) { + struct x86_reg imm_swz = aos_get_internal_xmm(cp, IMM_SWZ); + struct x86_reg tmp = aos_get_xmm_reg(cp); + + /* Load 1,-1,0,0 + * Use neg as arg to pshufd + * Multiply + */ + emit_pshufd(cp, tmp, imm_swz, + SHUF((negs & 1) ? 1 : 0, + (negs & 2) ? 1 : 0, + (negs & 4) ? 1 : 0, + (negs & 8) ? 1 : 0)); + sse_mulps(cp->func, dst, tmp); + + aos_release_xmm_reg(cp, tmp.idx); + } + else if (negs) { + struct x86_reg imm_negs = aos_get_internal_xmm(cp, IMM_NEGS); + sse_mulps(cp->func, dst, imm_negs); + } + + + if (abs && abs != 0xf) { + ERROR(cp, "unsupported partial abs"); + } + else if (abs) { + struct x86_reg neg = aos_get_internal(cp, IMM_NEGS); + struct x86_reg tmp = aos_get_xmm_reg(cp); + + sse_movaps(cp->func, tmp, dst); + sse_mulps(cp->func, tmp, neg); + sse_maxps(cp->func, dst, tmp); + + aos_release_xmm_reg(cp, tmp.idx); + } + + return dst; + } + + return arg0; +} + +static void x87_fld_src( struct aos_compilation *cp, + const struct tgsi_full_src_register *src, + unsigned channel ) +{ + struct x86_reg arg0 = aos_get_shader_reg_ptr(cp, + src->SrcRegister.File, + src->SrcRegister.Index); + + unsigned swizzle = tgsi_util_get_full_src_register_extswizzle( src, channel ); + unsigned neg = tgsi_util_get_full_src_register_sign_mode( src, channel ); + + switch (swizzle) { + case TGSI_EXTSWIZZLE_ZERO: + x87_fldz( cp->func ); + break; + + case TGSI_EXTSWIZZLE_ONE: + x87_fld1( cp->func ); + break; + + default: + x87_fld( cp->func, x86_make_disp(arg0, (swizzle & 3) * sizeof(float)) ); + break; + } + + + switch (neg) { + case TGSI_UTIL_SIGN_TOGGLE: + /* Flip the sign: + */ + x87_fchs( cp->func ); + break; + + case TGSI_UTIL_SIGN_KEEP: + break; + + case TGSI_UTIL_SIGN_CLEAR: + x87_fabs( cp->func ); + break; + + case TGSI_UTIL_SIGN_SET: + x87_fabs( cp->func ); + x87_fchs( cp->func ); + break; + + default: + ERROR(cp, "unsupported sign-mode"); + break; + } +} + + + + + + +/* Used to implement write masking. This and most of the other instructions + * here would be easier to implement if there had been a translation + * to a 2 argument format (dst/arg0, arg1) at the shader level before + * attempting to translate to x86/sse code. + */ +static void store_dest( struct aos_compilation *cp, + const struct tgsi_full_dst_register *reg, + struct x86_reg result ) +{ + struct x86_reg dst; + + switch (reg->DstRegister.WriteMask) { + case 0: + return; + + case TGSI_WRITEMASK_XYZW: + aos_adopt_xmm_reg(cp, + get_xmm_writable(cp, result), + reg->DstRegister.File, + reg->DstRegister.Index, + TRUE); + return; + default: + break; + } + + dst = aos_get_shader_reg_xmm(cp, + reg->DstRegister.File, + reg->DstRegister.Index); + + switch (reg->DstRegister.WriteMask) { + case TGSI_WRITEMASK_X: + sse_movss(cp->func, dst, get_xmm(cp, result)); + break; + + case TGSI_WRITEMASK_ZW: + sse_shufps(cp->func, dst, get_xmm(cp, result), SHUF(X, Y, Z, W)); + break; + + case TGSI_WRITEMASK_XY: + result = get_xmm_writable(cp, result); + sse_shufps(cp->func, result, dst, SHUF(X, Y, Z, W)); + dst = result; + break; + + case TGSI_WRITEMASK_YZW: + result = get_xmm_writable(cp, result); + sse_movss(cp->func, result, dst); + dst = result; + break; + + default: + mask_write(cp, dst, result, reg->DstRegister.WriteMask); + break; + } + + aos_adopt_xmm_reg(cp, + dst, + reg->DstRegister.File, + reg->DstRegister.Index, + TRUE); + +} + +static void inject_scalar( struct aos_compilation *cp, + struct x86_reg dst, + struct x86_reg result, + ubyte swizzle ) +{ + sse_shufps(cp->func, dst, dst, swizzle); + sse_movss(cp->func, dst, result); + sse_shufps(cp->func, dst, dst, swizzle); +} + + +static void store_scalar_dest( struct aos_compilation *cp, + const struct tgsi_full_dst_register *reg, + struct x86_reg result ) +{ + unsigned writemask = reg->DstRegister.WriteMask; + struct x86_reg dst; + + if (writemask != TGSI_WRITEMASK_X && + writemask != TGSI_WRITEMASK_Y && + writemask != TGSI_WRITEMASK_Z && + writemask != TGSI_WRITEMASK_W && + writemask != 0) + { + result = get_xmm_writable(cp, result); /* already true, right? */ + sse_shufps(cp->func, result, result, SHUF(X,X,X,X)); + store_dest(cp, reg, result); + return; + } + + result = get_xmm(cp, result); + dst = aos_get_shader_reg_xmm(cp, + reg->DstRegister.File, + reg->DstRegister.Index); + + + + switch (reg->DstRegister.WriteMask) { + case TGSI_WRITEMASK_X: + sse_movss(cp->func, dst, result); + break; + + case TGSI_WRITEMASK_Y: + inject_scalar(cp, dst, result, SHUF(Y, X, Z, W)); + break; + + case TGSI_WRITEMASK_Z: + inject_scalar(cp, dst, result, SHUF(Z, Y, X, W)); + break; + + case TGSI_WRITEMASK_W: + inject_scalar(cp, dst, result, SHUF(W, Y, Z, X)); + break; + + default: + break; + } + + aos_adopt_xmm_reg(cp, + dst, + reg->DstRegister.File, + reg->DstRegister.Index, + TRUE); +} + + + +static void x87_fst_or_nop( struct x86_function *func, + unsigned writemask, + unsigned channel, + struct x86_reg ptr ) +{ + assert(ptr.file == file_REG32); + if (writemask & (1<<channel)) + x87_fst( func, x86_make_disp(ptr, channel * sizeof(float)) ); +} + +static void x87_fstp_or_pop( struct x86_function *func, + unsigned writemask, + unsigned channel, + struct x86_reg ptr ) +{ + assert(ptr.file == file_REG32); + if (writemask & (1<<channel)) + x87_fstp( func, x86_make_disp(ptr, channel * sizeof(float)) ); + else + x87_fstp( func, x86_make_reg( file_x87, 0 )); +} + + + +/* + */ +static void x87_fstp_dest4( struct aos_compilation *cp, + const struct tgsi_full_dst_register *dst ) +{ + struct x86_reg ptr = get_dst_ptr(cp, dst); + unsigned writemask = dst->DstRegister.WriteMask; + + x87_fst_or_nop(cp->func, writemask, 0, ptr); + x87_fst_or_nop(cp->func, writemask, 1, ptr); + x87_fst_or_nop(cp->func, writemask, 2, ptr); + x87_fstp_or_pop(cp->func, writemask, 3, ptr); +} + +/* Save current x87 state and put it into single precision mode. + */ +static void save_fpu_state( struct aos_compilation *cp ) +{ + x87_fnstcw( cp->func, x86_make_disp(cp->machine_EDX, + Offset(struct aos_machine, fpu_restore))); +} + +static void restore_fpu_state( struct aos_compilation *cp ) +{ + x87_fnclex(cp->func); + x87_fldcw( cp->func, x86_make_disp(cp->machine_EDX, + Offset(struct aos_machine, fpu_restore))); +} + +static void set_fpu_round_neg_inf( struct aos_compilation *cp ) +{ + if (cp->fpucntl != FPU_RND_NEG) { + cp->fpucntl = FPU_RND_NEG; + x87_fnclex(cp->func); + x87_fldcw( cp->func, x86_make_disp(cp->machine_EDX, + Offset(struct aos_machine, fpu_rnd_neg_inf))); + } +} + +static void set_fpu_round_nearest( struct aos_compilation *cp ) +{ + if (cp->fpucntl != FPU_RND_NEAREST) { + cp->fpucntl = FPU_RND_NEAREST; + x87_fnclex(cp->func); + x87_fldcw( cp->func, x86_make_disp(cp->machine_EDX, + Offset(struct aos_machine, fpu_rnd_nearest))); + } +} + + +static void x87_emit_ex2( struct aos_compilation *cp ) +{ + struct x86_reg st0 = x86_make_reg(file_x87, 0); + struct x86_reg st1 = x86_make_reg(file_x87, 1); + int stack = cp->func->x87_stack; + +// set_fpu_round_neg_inf( cp ); + + x87_fld(cp->func, st0); /* a a */ + x87_fprndint( cp->func ); /* int(a) a*/ + x87_fsubr(cp->func, st1, st0); /* int(a) frc(a) */ + x87_fxch(cp->func, st1); /* frc(a) int(a) */ + x87_f2xm1(cp->func); /* (2^frc(a))-1 int(a) */ + x87_fld1(cp->func); /* 1 (2^frc(a))-1 int(a) */ + x87_faddp(cp->func, st1); /* 2^frac(a) int(a) */ + x87_fscale(cp->func); /* (2^frac(a)*2^int(int(a))) int(a) */ + /* 2^a int(a) */ + x87_fstp(cp->func, st1); /* 2^a */ + + assert( stack == cp->func->x87_stack); + +} + +static void PIPE_CDECL print_reg( const char *msg, + const float *reg ) +{ + debug_printf("%s: %f %f %f %f\n", msg, reg[0], reg[1], reg[2], reg[3]); +} + +static void emit_print( struct aos_compilation *cp, + const char *message, /* must point to a static string! */ + unsigned file, + unsigned idx ) +{ + struct x86_reg ecx = x86_make_reg( file_REG32, reg_CX ); + struct x86_reg arg = aos_get_shader_reg_ptr( cp, file, idx ); + unsigned i; + + /* There shouldn't be anything on the x87 stack. Can add this + * capacity later if need be. + */ + assert(cp->func->x87_stack == 0); + + /* For absolute correctness, need to spill/invalidate all XMM regs + * too. We're obviously not concerned about performance on this + * debug path, so here goes: + */ + for (i = 0; i < 8; i++) { + if (cp->xmm[i].dirty) + spill(cp, i); + + aos_release_xmm_reg(cp, i); + } + + /* Push caller-save (ie scratch) regs. + */ + x86_cdecl_caller_push_regs( cp->func ); + + + /* Push the arguments: + */ + x86_lea( cp->func, ecx, arg ); + x86_push( cp->func, ecx ); + x86_push_imm32( cp->func, (int)message ); + + /* Call the helper. Could call debug_printf directly, but + * print_reg is a nice place to put a breakpoint if need be. + */ + x86_mov_reg_imm( cp->func, ecx, (int)print_reg ); + x86_call( cp->func, ecx ); + x86_pop( cp->func, ecx ); + x86_pop( cp->func, ecx ); + + /* Pop caller-save regs + */ + x86_cdecl_caller_pop_regs( cp->func ); + + /* Done... + */ +} + +/** + * The traditional instructions. All operate on internal registers + * and ignore write masks and swizzling issues. + */ + +static boolean emit_ABS( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); + struct x86_reg neg = aos_get_internal(cp, IMM_NEGS); + struct x86_reg tmp = aos_get_xmm_reg(cp); + + sse_movaps(cp->func, tmp, arg0); + sse_mulps(cp->func, tmp, neg); + sse_maxps(cp->func, tmp, arg0); + + store_dest(cp, &op->FullDstRegisters[0], tmp); + return TRUE; +} + +static boolean emit_ADD( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); + struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]); + struct x86_reg dst = get_xmm_writable(cp, arg0); + + sse_addps(cp->func, dst, arg1); + + store_dest(cp, &op->FullDstRegisters[0], dst); + return TRUE; +} + +static boolean emit_COS( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + x87_fld_src(cp, &op->FullSrcRegisters[0], 0); + x87_fcos(cp->func); + x87_fstp_dest4(cp, &op->FullDstRegisters[0]); + return TRUE; +} + +/* The dotproduct instructions don't really do that well in sse: + * XXX: produces wrong results -- disabled. + */ +static boolean emit_DP3( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); + struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]); + struct x86_reg tmp = aos_get_xmm_reg(cp); + struct x86_reg dst = get_xmm_writable(cp, arg0); + + sse_mulps(cp->func, dst, arg1); + /* Now the hard bit: sum the first 3 values: + */ + sse_movhlps(cp->func, tmp, dst); + sse_addss(cp->func, dst, tmp); /* a*x+c*z, b*y, ?, ? */ + emit_pshufd(cp, tmp, dst, SHUF(Y,X,W,Z)); + sse_addss(cp->func, dst, tmp); + + aos_release_xmm_reg(cp, tmp.idx); + store_scalar_dest(cp, &op->FullDstRegisters[0], dst); + return TRUE; +} + +static boolean emit_DP4( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); + struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]); + struct x86_reg tmp = aos_get_xmm_reg(cp); + struct x86_reg dst = get_xmm_writable(cp, arg0); + + sse_mulps(cp->func, dst, arg1); + + /* Now the hard bit: sum the values: + */ + sse_movhlps(cp->func, tmp, dst); + sse_addps(cp->func, dst, tmp); /* a*x+c*z, b*y+d*w, a*x+c*z, b*y+d*w */ + emit_pshufd(cp, tmp, dst, SHUF(Y,X,W,Z)); + sse_addss(cp->func, dst, tmp); + + aos_release_xmm_reg(cp, tmp.idx); + store_scalar_dest(cp, &op->FullDstRegisters[0], dst); + return TRUE; +} + +static boolean emit_DPH( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); + struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]); + struct x86_reg tmp = aos_get_xmm_reg(cp); + struct x86_reg dst = get_xmm_writable(cp, arg0); + + sse_mulps(cp->func, dst, arg1); + + /* Now the hard bit: sum the values (from DP3): + */ + sse_movhlps(cp->func, tmp, dst); + sse_addss(cp->func, dst, tmp); /* a*x+c*z, b*y, ?, ? */ + emit_pshufd(cp, tmp, dst, SHUF(Y,X,W,Z)); + sse_addss(cp->func, dst, tmp); + emit_pshufd(cp, tmp, arg1, SHUF(W,W,W,W)); + sse_addss(cp->func, dst, tmp); + + aos_release_xmm_reg(cp, tmp.idx); + store_scalar_dest(cp, &op->FullDstRegisters[0], dst); + return TRUE; +} + +static boolean emit_DST( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); + struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]); + struct x86_reg dst = aos_get_xmm_reg(cp); + struct x86_reg tmp = aos_get_xmm_reg(cp); + struct x86_reg ones = aos_get_internal(cp, IMM_ONES); + +/* dst[0] = 1.0 * 1.0F; */ +/* dst[1] = arg0[1] * arg1[1]; */ +/* dst[2] = arg0[2] * 1.0; */ +/* dst[3] = 1.0 * arg1[3]; */ + + emit_shuf_copy2(cp, dst, arg0, ones, SHUF(X,W,Z,Y)); + emit_shuf_copy2(cp, tmp, arg1, ones, SHUF(X,Z,Y,W)); + sse_mulps(cp->func, dst, tmp); + + aos_release_xmm_reg(cp, tmp.idx); + store_dest(cp, &op->FullDstRegisters[0], dst); + return TRUE; +} + +static boolean emit_LG2( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + x87_fld1(cp->func); /* 1 */ + x87_fld_src(cp, &op->FullSrcRegisters[0], 0); /* a0 1 */ + x87_fyl2x(cp->func); /* log2(a0) */ + x87_fstp_dest4(cp, &op->FullDstRegisters[0]); + return TRUE; +} + + +static boolean emit_EX2( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + x87_fld_src(cp, &op->FullSrcRegisters[0], 0); + x87_emit_ex2(cp); + x87_fstp_dest4(cp, &op->FullDstRegisters[0]); + return TRUE; +} + + +static boolean emit_FLR( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg dst = get_dst_ptr(cp, &op->FullDstRegisters[0]); + unsigned writemask = op->FullDstRegisters[0].DstRegister.WriteMask; + int i; + + set_fpu_round_neg_inf( cp ); + + /* Load all sources first to avoid aliasing + */ + for (i = 3; i >= 0; i--) { + if (writemask & (1<<i)) { + x87_fld_src(cp, &op->FullSrcRegisters[0], i); + } + } + + for (i = 0; i < 4; i++) { + if (writemask & (1<<i)) { + x87_fprndint( cp->func ); + x87_fstp(cp->func, x86_make_disp(dst, i*4)); + } + } + + return TRUE; +} + + +static boolean emit_RND( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg dst = get_dst_ptr(cp, &op->FullDstRegisters[0]); + unsigned writemask = op->FullDstRegisters[0].DstRegister.WriteMask; + int i; + + set_fpu_round_nearest( cp ); + + /* Load all sources first to avoid aliasing + */ + for (i = 3; i >= 0; i--) { + if (writemask & (1<<i)) { + x87_fld_src(cp, &op->FullSrcRegisters[0], i); + } + } + + for (i = 0; i < 4; i++) { + if (writemask & (1<<i)) { + x87_fprndint( cp->func ); + x87_fstp(cp->func, x86_make_disp(dst, i*4)); + } + } + + return TRUE; +} + + +static boolean emit_FRC( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg dst = get_dst_ptr(cp, &op->FullDstRegisters[0]); + struct x86_reg st0 = x86_make_reg(file_x87, 0); + struct x86_reg st1 = x86_make_reg(file_x87, 1); + unsigned writemask = op->FullDstRegisters[0].DstRegister.WriteMask; + int i; + + set_fpu_round_neg_inf( cp ); + + /* suck all the source values onto the stack before writing out any + * dst, which may alias... + */ + for (i = 3; i >= 0; i--) { + if (writemask & (1<<i)) { + x87_fld_src(cp, &op->FullSrcRegisters[0], i); + } + } + + for (i = 0; i < 4; i++) { + if (writemask & (1<<i)) { + x87_fld(cp->func, st0); /* a a */ + x87_fprndint( cp->func ); /* flr(a) a */ + x87_fsubp(cp->func, st1); /* frc(a) */ + x87_fstp(cp->func, x86_make_disp(dst, i*4)); + } + } + + return TRUE; +} + + + + + + +static boolean emit_LIT( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg ecx = x86_make_reg( file_REG32, reg_CX ); + unsigned writemask = op->FullDstRegisters[0].DstRegister.WriteMask; + unsigned lit_count = cp->lit_count++; + struct x86_reg result, arg0; + unsigned i; + +#if 1 + /* For absolute correctness, need to spill/invalidate all XMM regs + * too. + */ + for (i = 0; i < 8; i++) { + if (cp->xmm[i].dirty) + spill(cp, i); + aos_release_xmm_reg(cp, i); + } +#endif + + if (writemask != TGSI_WRITEMASK_XYZW) + result = x86_make_disp(cp->machine_EDX, Offset(struct aos_machine, tmp[0])); + else + result = get_dst_ptr(cp, &op->FullDstRegisters[0]); + + + arg0 = fetch_src( cp, &op->FullSrcRegisters[0] ); + if (arg0.file == file_XMM) { + struct x86_reg tmp = x86_make_disp(cp->machine_EDX, + Offset(struct aos_machine, tmp[1])); + sse_movaps( cp->func, tmp, arg0 ); + arg0 = tmp; + } + + + + /* Push caller-save (ie scratch) regs. + */ + x86_cdecl_caller_push_regs( cp->func ); + + /* Push the arguments: + */ + x86_push_imm32( cp->func, lit_count ); + + x86_lea( cp->func, ecx, arg0 ); + x86_push( cp->func, ecx ); + + x86_lea( cp->func, ecx, result ); + x86_push( cp->func, ecx ); + + x86_push( cp->func, cp->machine_EDX ); + + if (lit_count < MAX_LIT_INFO) { + x86_mov( cp->func, ecx, x86_make_disp( cp->machine_EDX, + Offset(struct aos_machine, lit_info) + + lit_count * sizeof(struct lit_info) + + Offset(struct lit_info, func))); + } + else { + x86_mov_reg_imm( cp->func, ecx, (int)aos_do_lit ); + } + + x86_call( cp->func, ecx ); + + x86_pop( cp->func, ecx ); /* fixme... */ + x86_pop( cp->func, ecx ); + x86_pop( cp->func, ecx ); + x86_pop( cp->func, ecx ); + + x86_cdecl_caller_pop_regs( cp->func ); + + if (writemask != TGSI_WRITEMASK_XYZW) { + store_dest( cp, + &op->FullDstRegisters[0], + get_xmm_writable( cp, result ) ); + } + + return TRUE; +} + +#if 0 +static boolean emit_inline_LIT( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg dst = get_dst_ptr(cp, &op->FullDstRegisters[0]); + unsigned writemask = op->FullDstRegisters[0].DstRegister.WriteMask; + + if (writemask & TGSI_WRITEMASK_YZ) { + struct x86_reg st1 = x86_make_reg(file_x87, 1); + struct x86_reg st2 = x86_make_reg(file_x87, 2); + + /* a1' = a1 <= 0 ? 1 : a1; + */ + x87_fldz(cp->func); /* 1 0 */ +#if 1 + x87_fld1(cp->func); /* 1 0 */ +#else + /* Correct but slow due to fp exceptions generated in fyl2x - fix me. + */ + x87_fldz(cp->func); /* 1 0 */ +#endif + x87_fld_src(cp, &op->FullSrcRegisters[0], 1); /* a1 1 0 */ + x87_fcomi(cp->func, st2); /* a1 1 0 */ + x87_fcmovb(cp->func, st1); /* a1' 1 0 */ + x87_fstp(cp->func, st1); /* a1' 0 */ + x87_fstp(cp->func, st1); /* a1' */ + + x87_fld_src(cp, &op->FullSrcRegisters[0], 3); /* a3 a1' */ + x87_fxch(cp->func, st1); /* a1' a3 */ + + + /* Compute pow(a1, a3) + */ + x87_fyl2x(cp->func); /* a3*log2(a1) */ + x87_emit_ex2( cp ); /* 2^(a3*log2(a1)) */ + + + /* a0' = max2(a0, 0): + */ + x87_fldz(cp->func); /* 0 r2 */ + x87_fld_src(cp, &op->FullSrcRegisters[0], 0); /* a0 0 r2 */ + x87_fcomi(cp->func, st1); + x87_fcmovb(cp->func, st1); /* a0' 0 r2 */ + + x87_fst_or_nop(cp->func, writemask, 1, dst); /* result[1] = a0' */ + + x87_fcomi(cp->func, st1); /* a0' 0 r2 */ + x87_fcmovnbe(cp->func, st2); /* r2' 0' r2 */ + + x87_fstp_or_pop(cp->func, writemask, 2, dst); /* 0 r2 */ + x87_fpop(cp->func); /* r2 */ + x87_fpop(cp->func); + } + + if (writemask & TGSI_WRITEMASK_XW) { + x87_fld1(cp->func); + x87_fst_or_nop(cp->func, writemask, 0, dst); + x87_fstp_or_pop(cp->func, writemask, 3, dst); + } + + return TRUE; +} +#endif + + + +static boolean emit_MAX( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); + struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]); + struct x86_reg dst = get_xmm_writable(cp, arg0); + + sse_maxps(cp->func, dst, arg1); + + store_dest(cp, &op->FullDstRegisters[0], dst); + return TRUE; +} + + +static boolean emit_MIN( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); + struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]); + struct x86_reg dst = get_xmm_writable(cp, arg0); + + sse_minps(cp->func, dst, arg1); + + store_dest(cp, &op->FullDstRegisters[0], dst); + return TRUE; +} + +static boolean emit_MOV( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); + struct x86_reg dst = get_xmm_writable(cp, arg0); + + /* potentially nothing to do */ + + store_dest(cp, &op->FullDstRegisters[0], dst); + return TRUE; +} + +static boolean emit_MUL( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); + struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]); + struct x86_reg dst = get_xmm_writable(cp, arg0); + + sse_mulps(cp->func, dst, arg1); + + store_dest(cp, &op->FullDstRegisters[0], dst); + return TRUE; +} + + +static boolean emit_MAD( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); + struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]); + struct x86_reg arg2 = fetch_src(cp, &op->FullSrcRegisters[2]); + + /* If we can't clobber old contents of arg0, get a temporary & copy + * it there, then clobber it... + */ + arg0 = get_xmm_writable(cp, arg0); + + sse_mulps(cp->func, arg0, arg1); + sse_addps(cp->func, arg0, arg2); + store_dest(cp, &op->FullDstRegisters[0], arg0); + return TRUE; +} + +/* A wrapper for powf(). + * Makes sure it is cdecl and operates on floats. + */ +static float PIPE_CDECL _powerf( float x, float y ) +{ + return powf( x, y ); +} + +/* Really not sufficient -- need to check for conditions that could + * generate inf/nan values, which will slow things down hugely. + */ +static boolean emit_POW( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ +#if 0 + x87_fld_src(cp, &op->FullSrcRegisters[1], 0); /* a1.x */ + x87_fld_src(cp, &op->FullSrcRegisters[0], 0); /* a0.x a1.x */ + x87_fyl2x(cp->func); /* a1*log2(a0) */ + + x87_emit_ex2( cp ); /* 2^(a1*log2(a0)) */ + + x87_fstp_dest4(cp, &op->FullDstRegisters[0]); +#else + uint i; + + /* For absolute correctness, need to spill/invalidate all XMM regs + * too. + */ + for (i = 0; i < 8; i++) { + if (cp->xmm[i].dirty) + spill(cp, i); + aos_release_xmm_reg(cp, i); + } + + /* Push caller-save (ie scratch) regs. + */ + x86_cdecl_caller_push_regs( cp->func ); + + x86_lea( cp->func, cp->stack_ESP, x86_make_disp(cp->stack_ESP, -8) ); + + x87_fld_src( cp, &op->FullSrcRegisters[1], 0 ); + x87_fstp( cp->func, x86_make_disp( cp->stack_ESP, 4 ) ); + x87_fld_src( cp, &op->FullSrcRegisters[0], 0 ); + x87_fstp( cp->func, x86_make_disp( cp->stack_ESP, 0 ) ); + + /* tmp_EAX has been pushed & will be restored below */ + x86_mov_reg_imm( cp->func, cp->tmp_EAX, (unsigned long) _powerf ); + x86_call( cp->func, cp->tmp_EAX ); + + x86_lea( cp->func, cp->stack_ESP, x86_make_disp(cp->stack_ESP, 8) ); + + x86_cdecl_caller_pop_regs( cp->func ); + + /* Note retval on x87 stack: + */ + cp->func->x87_stack++; + + x87_fstp_dest4( cp, &op->FullDstRegisters[0] ); +#endif + return TRUE; +} + + +static boolean emit_RCP( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); + struct x86_reg dst = aos_get_xmm_reg(cp); + + if (cp->have_sse2) { + sse2_rcpss(cp->func, dst, arg0); + /* extend precision here... + */ + } + else { + struct x86_reg ones = aos_get_internal(cp, IMM_ONES); + sse_movss(cp->func, dst, ones); + sse_divss(cp->func, dst, arg0); + } + + store_scalar_dest(cp, &op->FullDstRegisters[0], dst); + return TRUE; +} + + +/* Although rsqrtps() and rcpps() are low precision on some/all SSE + * implementations, it is possible to improve its precision at + * fairly low cost, using a newton/raphson step, as below: + * + * x1 = 2 * rcpps(a) - a * rcpps(a) * rcpps(a) + * x1 = 0.5 * rsqrtps(a) * [3.0 - (a * rsqrtps(a))* rsqrtps(a)] + * or: + * x1 = rsqrtps(a) * [1.5 - .5 * a * rsqrtps(a) * rsqrtps(a)] + * + * + * See: http://softwarecommunity.intel.com/articles/eng/1818.htm + */ +static boolean emit_RSQ( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + + if (0) { + struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); + struct x86_reg r = aos_get_xmm_reg(cp); + sse_rsqrtss(cp->func, r, arg0); + store_scalar_dest(cp, &op->FullDstRegisters[0], r); + return TRUE; + } + else { + struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); + struct x86_reg r = aos_get_xmm_reg(cp); + + struct x86_reg neg_half = get_reg_ptr( cp, AOS_FILE_INTERNAL, IMM_RSQ ); + struct x86_reg one_point_five = x86_make_disp( neg_half, 4 ); + struct x86_reg src = get_xmm_writable( cp, arg0 ); + + sse_rsqrtss( cp->func, r, src ); /* rsqrtss(a) */ + sse_mulss( cp->func, src, neg_half ); /* -.5 * a */ + sse_mulss( cp->func, src, r ); /* -.5 * a * r */ + sse_mulss( cp->func, src, r ); /* -.5 * a * r * r */ + sse_addss( cp->func, src, one_point_five ); /* 1.5 - .5 * a * r * r */ + sse_mulss( cp->func, r, src ); /* r * (1.5 - .5 * a * r * r) */ + + store_scalar_dest(cp, &op->FullDstRegisters[0], r); + return TRUE; + } +} + + +static boolean emit_SGE( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); + struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]); + struct x86_reg ones = aos_get_internal(cp, IMM_ONES); + struct x86_reg dst = get_xmm_writable(cp, arg0); + + sse_cmpps(cp->func, dst, arg1, cc_NotLessThan); + sse_andps(cp->func, dst, ones); + + store_dest(cp, &op->FullDstRegisters[0], dst); + return TRUE; +} + +static boolean emit_SIN( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + x87_fld_src(cp, &op->FullSrcRegisters[0], 0); + x87_fsin(cp->func); + x87_fstp_dest4(cp, &op->FullDstRegisters[0]); + return TRUE; +} + + + +static boolean emit_SLT( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); + struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]); + struct x86_reg ones = aos_get_internal(cp, IMM_ONES); + struct x86_reg dst = get_xmm_writable(cp, arg0); + + sse_cmpps(cp->func, dst, arg1, cc_LessThan); + sse_andps(cp->func, dst, ones); + + store_dest(cp, &op->FullDstRegisters[0], dst); + return TRUE; +} + +static boolean emit_SUB( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); + struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]); + struct x86_reg dst = get_xmm_writable(cp, arg0); + + sse_subps(cp->func, dst, arg1); + + store_dest(cp, &op->FullDstRegisters[0], dst); + return TRUE; +} + + +static boolean emit_XPD( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) +{ + struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); + struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]); + struct x86_reg tmp0 = aos_get_xmm_reg(cp); + struct x86_reg tmp1 = aos_get_xmm_reg(cp); + + emit_pshufd(cp, tmp1, arg1, SHUF(Y, Z, X, W)); + sse_mulps(cp->func, tmp1, arg0); + emit_pshufd(cp, tmp0, arg0, SHUF(Y, Z, X, W)); + sse_mulps(cp->func, tmp0, arg1); + sse_subps(cp->func, tmp1, tmp0); + sse_shufps(cp->func, tmp1, tmp1, SHUF(Y, Z, X, W)); + +/* dst[2] = arg0[0] * arg1[1] - arg0[1] * arg1[0]; */ +/* dst[0] = arg0[1] * arg1[2] - arg0[2] * arg1[1]; */ +/* dst[1] = arg0[2] * arg1[0] - arg0[0] * arg1[2]; */ +/* dst[3] is undef */ + + + aos_release_xmm_reg(cp, tmp0.idx); + store_dest(cp, &op->FullDstRegisters[0], tmp1); + return TRUE; +} + + + +static boolean +emit_instruction( struct aos_compilation *cp, + struct tgsi_full_instruction *inst ) +{ + x87_assert_stack_empty(cp->func); + + switch( inst->Instruction.Opcode ) { + case TGSI_OPCODE_MOV: + return emit_MOV( cp, inst ); + + case TGSI_OPCODE_LIT: + return emit_LIT(cp, inst); + + case TGSI_OPCODE_RCP: + return emit_RCP(cp, inst); + + case TGSI_OPCODE_RSQ: + return emit_RSQ(cp, inst); + + case TGSI_OPCODE_EXP: + /*return emit_EXP(cp, inst);*/ + return FALSE; + + case TGSI_OPCODE_LOG: + /*return emit_LOG(cp, inst);*/ + return FALSE; + + case TGSI_OPCODE_MUL: + return emit_MUL(cp, inst); + + case TGSI_OPCODE_ADD: + return emit_ADD(cp, inst); + + case TGSI_OPCODE_DP3: + return emit_DP3(cp, inst); + + case TGSI_OPCODE_DP4: + return emit_DP4(cp, inst); + + case TGSI_OPCODE_DST: + return emit_DST(cp, inst); + + case TGSI_OPCODE_MIN: + return emit_MIN(cp, inst); + + case TGSI_OPCODE_MAX: + return emit_MAX(cp, inst); + + case TGSI_OPCODE_SLT: + return emit_SLT(cp, inst); + + case TGSI_OPCODE_SGE: + return emit_SGE(cp, inst); + + case TGSI_OPCODE_MAD: + return emit_MAD(cp, inst); + + case TGSI_OPCODE_SUB: + return emit_SUB(cp, inst); + + case TGSI_OPCODE_LERP: +// return emit_LERP(cp, inst); + return FALSE; + + case TGSI_OPCODE_FRAC: + return emit_FRC(cp, inst); + + case TGSI_OPCODE_CLAMP: +// return emit_CLAMP(cp, inst); + return FALSE; + + case TGSI_OPCODE_FLOOR: + return emit_FLR(cp, inst); + + case TGSI_OPCODE_ROUND: + return emit_RND(cp, inst); + + case TGSI_OPCODE_EXPBASE2: +#if 0 + /* this seems to fail for "larger" exponents. + * See glean tvertProg1's EX2 test. + */ + return emit_EX2(cp, inst); +#else + return FALSE; +#endif + + case TGSI_OPCODE_LOGBASE2: + return emit_LG2(cp, inst); + + case TGSI_OPCODE_POWER: + return emit_POW(cp, inst); + + case TGSI_OPCODE_CROSSPRODUCT: + return emit_XPD(cp, inst); + + case TGSI_OPCODE_ABS: + return emit_ABS(cp, inst); + + case TGSI_OPCODE_DPH: + return emit_DPH(cp, inst); + + case TGSI_OPCODE_COS: + return emit_COS(cp, inst); + + case TGSI_OPCODE_SIN: + return emit_SIN(cp, inst); + + case TGSI_OPCODE_END: + return TRUE; + + default: + return FALSE; + } +} + + +static boolean emit_viewport( struct aos_compilation *cp ) +{ + struct x86_reg pos = aos_get_shader_reg_xmm(cp, + TGSI_FILE_OUTPUT, + cp->vaos->draw->vs.position_output ); + + struct x86_reg scale = x86_make_disp(cp->machine_EDX, + Offset(struct aos_machine, scale)); + + struct x86_reg translate = x86_make_disp(cp->machine_EDX, + Offset(struct aos_machine, translate)); + + sse_mulps(cp->func, pos, scale); + sse_addps(cp->func, pos, translate); + + aos_adopt_xmm_reg( cp, + pos, + TGSI_FILE_OUTPUT, + cp->vaos->draw->vs.position_output, + TRUE ); + return TRUE; +} + + +/* This is useful to be able to see the results on softpipe. Doesn't + * do proper clipping, just assumes the backend can do it during + * rasterization -- for debug only... + */ +static boolean emit_rhw_viewport( struct aos_compilation *cp ) +{ + struct x86_reg tmp = aos_get_xmm_reg(cp); + struct x86_reg pos = aos_get_shader_reg_xmm(cp, + TGSI_FILE_OUTPUT, + cp->vaos->draw->vs.position_output); + + struct x86_reg scale = x86_make_disp(cp->machine_EDX, + Offset(struct aos_machine, scale)); + + struct x86_reg translate = x86_make_disp(cp->machine_EDX, + Offset(struct aos_machine, translate)); + + + + emit_pshufd(cp, tmp, pos, SHUF(W, W, W, W)); + sse2_rcpss(cp->func, tmp, tmp); + sse_shufps(cp->func, tmp, tmp, SHUF(X, X, X, X)); + + sse_mulps(cp->func, pos, scale); + sse_mulps(cp->func, pos, tmp); + sse_addps(cp->func, pos, translate); + + /* Set pos[3] = w + */ + mask_write(cp, pos, tmp, TGSI_WRITEMASK_W); + + aos_adopt_xmm_reg( cp, + pos, + TGSI_FILE_OUTPUT, + cp->vaos->draw->vs.position_output, + TRUE ); + return TRUE; +} + + +#if 0 +static boolean note_immediate( struct aos_compilation *cp, + struct tgsi_full_immediate *imm ) +{ + unsigned pos = cp->num_immediates++; + unsigned j; + + for (j = 0; j < imm->Immediate.Size; j++) { + cp->vaos->machine->immediate[pos][j] = imm->u.ImmediateFloat32[j].Float; + } + + return TRUE; +} +#endif + + + + +static void find_last_write_outputs( struct aos_compilation *cp ) +{ + struct tgsi_parse_context parse; + unsigned this_instruction = 0; + unsigned i; + + tgsi_parse_init( &parse, cp->vaos->base.vs->state.tokens ); + + while (!tgsi_parse_end_of_tokens( &parse )) { + + tgsi_parse_token( &parse ); + + if (parse.FullToken.Token.Type != TGSI_TOKEN_TYPE_INSTRUCTION) + continue; + + for (i = 0; i < TGSI_FULL_MAX_DST_REGISTERS; i++) { + if (parse.FullToken.FullInstruction.FullDstRegisters[i].DstRegister.File == + TGSI_FILE_OUTPUT) + { + unsigned idx = parse.FullToken.FullInstruction.FullDstRegisters[i].DstRegister.Index; + cp->output_last_write[idx] = this_instruction; + } + } + + this_instruction++; + } + + tgsi_parse_free( &parse ); +} + + +#define ARG_MACHINE 1 +#define ARG_START_ELTS 2 +#define ARG_COUNT 3 +#define ARG_OUTBUF 4 + + +static boolean build_vertex_program( struct draw_vs_varient_aos_sse *varient, + boolean linear ) +{ + struct tgsi_parse_context parse; + struct aos_compilation cp; + unsigned fixup, label; + + tgsi_parse_init( &parse, varient->base.vs->state.tokens ); + + memset(&cp, 0, sizeof(cp)); + + cp.insn_counter = 1; + cp.vaos = varient; + cp.have_sse2 = 1; + cp.func = &varient->func[ linear ? 0 : 1 ]; + + cp.tmp_EAX = x86_make_reg(file_REG32, reg_AX); + cp.idx_EBX = x86_make_reg(file_REG32, reg_BX); + cp.outbuf_ECX = x86_make_reg(file_REG32, reg_CX); + cp.machine_EDX = x86_make_reg(file_REG32, reg_DX); + cp.count_ESI = x86_make_reg(file_REG32, reg_SI); + cp.temp_EBP = x86_make_reg(file_REG32, reg_BP); + cp.stack_ESP = x86_make_reg( file_REG32, reg_SP ); + + x86_init_func(cp.func); + + find_last_write_outputs(&cp); + + x86_push(cp.func, cp.idx_EBX); + x86_push(cp.func, cp.count_ESI); + x86_push(cp.func, cp.temp_EBP); + + + /* Load arguments into regs: + */ + x86_mov(cp.func, cp.machine_EDX, x86_fn_arg(cp.func, ARG_MACHINE)); + x86_mov(cp.func, cp.idx_EBX, x86_fn_arg(cp.func, ARG_START_ELTS)); + x86_mov(cp.func, cp.count_ESI, x86_fn_arg(cp.func, ARG_COUNT)); + x86_mov(cp.func, cp.outbuf_ECX, x86_fn_arg(cp.func, ARG_OUTBUF)); + + + /* Compare count to zero and possibly bail. + */ + x86_xor(cp.func, cp.tmp_EAX, cp.tmp_EAX); + x86_cmp(cp.func, cp.count_ESI, cp.tmp_EAX); + fixup = x86_jcc_forward(cp.func, cc_E); + + + save_fpu_state( &cp ); + set_fpu_round_nearest( &cp ); + + /* Note address for loop jump + */ + label = x86_get_label(cp.func); + { + /* Fetch inputs... TODO: fetch lazily... + */ + if (!aos_fetch_inputs( &cp, linear )) + goto fail; + + /* Emit the shader: + */ + while( !tgsi_parse_end_of_tokens( &parse ) && !cp.error ) + { + tgsi_parse_token( &parse ); + + switch (parse.FullToken.Token.Type) { + case TGSI_TOKEN_TYPE_IMMEDIATE: +#if 0 + if (!note_immediate( &cp, &parse.FullToken.FullImmediate )) + goto fail; +#endif + break; + + case TGSI_TOKEN_TYPE_INSTRUCTION: + if (DISASSEM) + tgsi_dump_instruction( &parse.FullToken.FullInstruction, cp.insn_counter ); + + if (!emit_instruction( &cp, &parse.FullToken.FullInstruction )) + goto fail; + break; + } + + x87_assert_stack_empty(cp.func); + cp.insn_counter++; + + if (DISASSEM) + debug_printf("\n"); + } + + + { + unsigned i; + for (i = 0; i < 8; i++) { + if (cp.xmm[i].file != TGSI_FILE_OUTPUT) { + cp.xmm[i].file = TGSI_FILE_NULL; + cp.xmm[i].dirty = 0; + } + } + } + + if (cp.error) + goto fail; + + if (cp.vaos->base.key.clip) { + /* not really handling clipping, just do the rhw so we can + * see the results... + */ + emit_rhw_viewport(&cp); + } + else if (cp.vaos->base.key.viewport) { + emit_viewport(&cp); + } + + /* Emit output... TODO: do this eagerly after the last write to a + * given output. + */ + if (!aos_emit_outputs( &cp )) + goto fail; + + + /* Next vertex: + */ + x86_lea(cp.func, + cp.outbuf_ECX, + x86_make_disp(cp.outbuf_ECX, + cp.vaos->base.key.output_stride)); + + /* Incr index + */ + if (linear) { + x86_inc(cp.func, cp.idx_EBX); + } + else { + x86_lea(cp.func, cp.idx_EBX, x86_make_disp(cp.idx_EBX, 4)); + } + + } + /* decr count, loop if not zero + */ + x86_dec(cp.func, cp.count_ESI); + x86_jcc(cp.func, cc_NZ, label); + + restore_fpu_state(&cp); + + /* Land forward jump here: + */ + x86_fixup_fwd_jump(cp.func, fixup); + + /* Exit mmx state? + */ + if (cp.func->need_emms) + mmx_emms(cp.func); + + x86_pop(cp.func, cp.temp_EBP); + x86_pop(cp.func, cp.count_ESI); + x86_pop(cp.func, cp.idx_EBX); + + x87_assert_stack_empty(cp.func); + x86_ret(cp.func); + + tgsi_parse_free( &parse ); + return !cp.error; + + fail: + tgsi_parse_free( &parse ); + return FALSE; +} + + + +static void vaos_set_buffer( struct draw_vs_varient *varient, + unsigned buf, + const void *ptr, + unsigned stride ) +{ + struct draw_vs_varient_aos_sse *vaos = (struct draw_vs_varient_aos_sse *)varient; + unsigned i; + + for (i = 0; i < vaos->base.key.nr_inputs; i++) { + if (vaos->base.key.element[i].in.buffer == buf) { + vaos->attrib[i].input_ptr = ((char *)ptr + + vaos->base.key.element[i].in.offset); + vaos->attrib[i].input_stride = stride; + } + } +} + + + +static void PIPE_CDECL vaos_run_elts( struct draw_vs_varient *varient, + const unsigned *elts, + unsigned count, + void *output_buffer ) +{ + struct draw_vs_varient_aos_sse *vaos = (struct draw_vs_varient_aos_sse *)varient; + struct aos_machine *machine = vaos->draw->vs.aos_machine; + + machine->internal[IMM_PSIZE][0] = vaos->draw->rasterizer->point_size; + machine->constants = vaos->draw->vs.aligned_constants; + machine->immediates = vaos->base.vs->immediates; + machine->attrib = vaos->attrib; + + vaos->gen_run_elts( machine, + elts, + count, + output_buffer ); +} + +static void PIPE_CDECL vaos_run_linear( struct draw_vs_varient *varient, + unsigned start, + unsigned count, + void *output_buffer ) +{ + struct draw_vs_varient_aos_sse *vaos = (struct draw_vs_varient_aos_sse *)varient; + struct aos_machine *machine = vaos->draw->vs.aos_machine; + + machine->internal[IMM_PSIZE][0] = vaos->draw->rasterizer->point_size; + machine->constants = vaos->draw->vs.aligned_constants; + machine->immediates = vaos->base.vs->immediates; + machine->attrib = vaos->attrib; + + vaos->gen_run_linear( machine, + start, + count, + output_buffer ); +} + + + +static void vaos_destroy( struct draw_vs_varient *varient ) +{ + struct draw_vs_varient_aos_sse *vaos = (struct draw_vs_varient_aos_sse *)varient; + + FREE( vaos->attrib ); + + x86_release_func( &vaos->func[0] ); + x86_release_func( &vaos->func[1] ); + + FREE(vaos); +} + + + +static struct draw_vs_varient *varient_aos_sse( struct draw_vertex_shader *vs, + const struct draw_vs_varient_key *key ) +{ + struct draw_vs_varient_aos_sse *vaos = CALLOC_STRUCT(draw_vs_varient_aos_sse); + + if (!vaos) + goto fail; + + vaos->base.key = *key; + vaos->base.vs = vs; + vaos->base.set_input = vaos_set_buffer; + vaos->base.destroy = vaos_destroy; + vaos->base.run_linear = vaos_run_linear; + vaos->base.run_elts = vaos_run_elts; + + vaos->draw = vs->draw; + + vaos->attrib = MALLOC( key->nr_inputs * sizeof(vaos->attrib[0]) ); + if (!vaos->attrib) + goto fail; + +#if 0 + tgsi_dump(vs->state.tokens, 0); +#endif + + if (!build_vertex_program( vaos, TRUE )) + goto fail; + + if (!build_vertex_program( vaos, FALSE )) + goto fail; + + vaos->gen_run_linear = (vaos_run_linear_func)x86_get_func(&vaos->func[0]); + if (!vaos->gen_run_linear) + goto fail; + + vaos->gen_run_elts = (vaos_run_elts_func)x86_get_func(&vaos->func[1]); + if (!vaos->gen_run_elts) + goto fail; + + return &vaos->base; + + fail: + if (vaos && vaos->attrib) + FREE(vaos->attrib); + + if (vaos) + x86_release_func( &vaos->func[0] ); + + if (vaos) + x86_release_func( &vaos->func[1] ); + + FREE(vaos); + + return NULL; +} + + +struct draw_vs_varient *draw_vs_varient_aos_sse( struct draw_vertex_shader *vs, + const struct draw_vs_varient_key *key ) +{ + struct draw_vs_varient *varient = varient_aos_sse( vs, key ); + + if (varient == NULL) { + varient = draw_vs_varient_generic( vs, key ); + } + + return varient; +} + + + +#endif diff --git a/src/gallium/auxiliary/draw/draw_vs_aos.h b/src/gallium/auxiliary/draw/draw_vs_aos.h new file mode 100644 index 0000000000..64e021ff6b --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_vs_aos.h @@ -0,0 +1,248 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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: Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef DRAW_VS_AOS_H +#define DRAW_VS_AOS_H + +#include "pipe/p_config.h" + +#ifdef PIPE_ARCH_X86 + +struct tgsi_token; +struct x86_function; + +#include "pipe/p_state.h" +#include "rtasm/rtasm_x86sse.h" + + + + + +#define X 0 +#define Y 1 +#define Z 2 +#define W 3 + +#define MAX_INPUTS PIPE_MAX_ATTRIBS +#define MAX_OUTPUTS PIPE_MAX_ATTRIBS +#define MAX_TEMPS PIPE_MAX_ATTRIBS /* say */ +#define MAX_CONSTANTS PIPE_MAX_ATTRIBS /* say */ +#define MAX_IMMEDIATES PIPE_MAX_ATTRIBS /* say */ +#define MAX_INTERNALS 8 + +#define AOS_FILE_INTERNAL TGSI_FILE_COUNT + +#define FPU_RND_NEG 1 +#define FPU_RND_NEAREST 2 + +struct aos_machine; +typedef void (PIPE_CDECL *lit_func)( struct aos_machine *, + float *result, + const float *in, + unsigned count ); + +void PIPE_CDECL aos_do_lit( struct aos_machine *machine, + float *result, + const float *in, + unsigned count ); + +struct shine_tab { + float exponent; + float values[258]; + unsigned last_used; +}; + +struct lit_info { + lit_func func; + struct shine_tab *shine_tab; +}; + +#define MAX_SHINE_TAB 4 +#define MAX_LIT_INFO 16 + +struct aos_attrib { + const void *input_ptr; + unsigned input_stride; +}; + + + + +/* This is the temporary storage used by all the aos_sse vs varients. + * Create one per context and reuse by passing a pointer in at + * vs_varient creation?? + */ +struct aos_machine { + float input [MAX_INPUTS ][4]; + float output [MAX_OUTPUTS ][4]; + float temp [MAX_TEMPS ][4]; + float internal [MAX_INTERNALS ][4]; + + float scale[4]; /* viewport */ + float translate[4]; /* viewport */ + + float tmp[2][4]; /* scratch space for LIT */ + + struct shine_tab shine_tab[MAX_SHINE_TAB]; + struct lit_info lit_info[MAX_LIT_INFO]; + unsigned now; + + + ushort fpu_rnd_nearest; + ushort fpu_rnd_neg_inf; + ushort fpu_restore; + ushort fpucntl; /* one of FPU_* above */ + + const float (*immediates)[4]; /* points to shader data */ + const float (*constants)[4]; /* points to draw data */ + + const struct aos_attrib *attrib; /* points to ? */ +}; + + + + +struct aos_compilation { + struct x86_function *func; + struct draw_vs_varient_aos_sse *vaos; + + unsigned insn_counter; + unsigned num_immediates; + unsigned count; + unsigned lit_count; + + struct { + unsigned idx:16; + unsigned file:8; + unsigned dirty:8; + unsigned last_used; + } xmm[8]; + + unsigned x86_reg[2]; /* one of X86_* */ + + boolean input_fetched[PIPE_MAX_ATTRIBS]; + unsigned output_last_write[PIPE_MAX_ATTRIBS]; + + boolean have_sse2; + boolean error; + short fpucntl; + + /* these are actually known values, but putting them in a struct + * like this is helpful to keep them in sync across the file. + */ + struct x86_reg tmp_EAX; + struct x86_reg idx_EBX; /* either start+i or &elt[i] */ + struct x86_reg outbuf_ECX; + struct x86_reg machine_EDX; + struct x86_reg count_ESI; /* decrements to zero */ + struct x86_reg temp_EBP; + struct x86_reg stack_ESP; +}; + +struct x86_reg aos_get_xmm_reg( struct aos_compilation *cp ); +void aos_release_xmm_reg( struct aos_compilation *cp, unsigned idx ); + +void aos_adopt_xmm_reg( struct aos_compilation *cp, + struct x86_reg reg, + unsigned file, + unsigned idx, + unsigned dirty ); + +struct x86_reg aos_get_shader_reg( struct aos_compilation *cp, + unsigned file, + unsigned idx ); + +boolean aos_fetch_inputs( struct aos_compilation *cp, + boolean linear ); + +boolean aos_emit_outputs( struct aos_compilation *cp ); + + +#define IMM_ONES 0 /* 1, 1,1,1 */ +#define IMM_SWZ 1 /* 1,-1,0, 0xffffffff */ +#define IMM_IDENTITY 2 /* 0, 0,0,1 */ +#define IMM_INV_255 3 /* 1/255, 1/255, 1/255, 1/255 */ +#define IMM_255 4 /* 255, 255, 255, 255 */ +#define IMM_NEGS 5 /* -1,-1,-1,-1 */ +#define IMM_RSQ 6 /* -.5,1.5,_,_ */ +#define IMM_PSIZE 7 /* not really an immediate - updated each run */ + +struct x86_reg aos_get_internal( struct aos_compilation *cp, + unsigned imm ); +struct x86_reg aos_get_internal_xmm( struct aos_compilation *cp, + unsigned imm ); + + +#define ERROR(cp, msg) \ +do { \ + if (0) debug_printf("%s: x86 translation failed: %s\n", __FUNCTION__, msg); \ + cp->error = 1; \ +} while (0) + + +#define X86_NULL 0 +#define X86_IMMEDIATES 1 +#define X86_CONSTANTS 2 +#define X86_ATTRIBS 3 + +struct x86_reg aos_get_x86( struct aos_compilation *cp, + unsigned which_reg, + unsigned value ); + + +typedef void (PIPE_CDECL *vaos_run_elts_func)( struct aos_machine *, + const unsigned *elts, + unsigned count, + void *output_buffer); + +typedef void (PIPE_CDECL *vaos_run_linear_func)( struct aos_machine *, + unsigned start, + unsigned count, + void *output_buffer); + + +struct draw_vs_varient_aos_sse { + struct draw_vs_varient base; + struct draw_context *draw; + + struct aos_attrib *attrib; + + vaos_run_linear_func gen_run_linear; + vaos_run_elts_func gen_run_elts; + + + struct x86_function func[2]; +}; + + +#endif + +#endif + diff --git a/src/gallium/auxiliary/draw/draw_vs_aos_io.c b/src/gallium/auxiliary/draw/draw_vs_aos_io.c new file mode 100644 index 0000000000..6b92811870 --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_vs_aos_io.c @@ -0,0 +1,325 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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. + * + **************************************************************************/ + + +#include "pipe/p_util.h" +#include "pipe/p_shader_tokens.h" +#include "tgsi/util/tgsi_parse.h" +#include "tgsi/util/tgsi_util.h" +#include "tgsi/exec/tgsi_exec.h" +#include "draw_vs.h" +#include "draw_vs_aos.h" +#include "draw_vertex.h" + +#include "rtasm/rtasm_x86sse.h" + +#ifdef PIPE_ARCH_X86 + +/* Note - don't yet have to worry about interacting with the code in + * draw_vs_aos.c as there is no intermingling of generated code... + * That may have to change, we'll see. + */ +static void emit_load_R32G32B32A32( struct aos_compilation *cp, + struct x86_reg data, + struct x86_reg src_ptr ) +{ + sse_movups(cp->func, data, src_ptr); +} + +static void emit_load_R32G32B32( struct aos_compilation *cp, + struct x86_reg data, + struct x86_reg src_ptr ) +{ + sse_movss(cp->func, data, x86_make_disp(src_ptr, 8)); + sse_shufps(cp->func, data, aos_get_internal_xmm( cp, IMM_IDENTITY ), SHUF(X,Y,Z,W) ); + sse_shufps(cp->func, data, data, SHUF(Y,Z,X,W) ); + sse_movlps(cp->func, data, src_ptr); +} + +static void emit_load_R32G32( struct aos_compilation *cp, + struct x86_reg data, + struct x86_reg src_ptr ) +{ + sse_movups(cp->func, data, aos_get_internal_xmm( cp, IMM_IDENTITY ) ); + sse_movlps(cp->func, data, src_ptr); +} + + +static void emit_load_R32( struct aos_compilation *cp, + struct x86_reg data, + struct x86_reg src_ptr ) +{ + sse_movss(cp->func, data, src_ptr); + sse_orps(cp->func, data, aos_get_internal_xmm( cp, IMM_IDENTITY ) ); +} + + +static void emit_load_R8G8B8A8_UNORM( struct aos_compilation *cp, + struct x86_reg data, + struct x86_reg src_ptr ) +{ + sse_movss(cp->func, data, src_ptr); + sse2_punpcklbw(cp->func, data, aos_get_internal_xmm( cp, IMM_IDENTITY )); + sse2_punpcklbw(cp->func, data, aos_get_internal_xmm( cp, IMM_IDENTITY )); + sse2_cvtdq2ps(cp->func, data, data); + sse_mulps(cp->func, data, aos_get_internal(cp, IMM_INV_255)); +} + + + +static void get_src_ptr( struct aos_compilation *cp, + struct x86_reg src, + struct x86_reg elt, + unsigned a ) +{ + struct x86_reg attrib = x86_make_disp(aos_get_x86( cp, 0, X86_ATTRIBS ), + a * sizeof(struct aos_attrib)); + + struct x86_reg input_ptr = x86_make_disp(attrib, + Offset(struct aos_attrib, input_ptr)); + + struct x86_reg input_stride = x86_make_disp(attrib, + Offset(struct aos_attrib, input_stride)); + + /* Calculate pointer to current attrib: + */ + x86_mov(cp->func, src, input_stride); + x86_imul(cp->func, src, elt); + x86_add(cp->func, src, input_ptr); +} + + +/* Extended swizzles? Maybe later. + */ +static void emit_swizzle( struct aos_compilation *cp, + struct x86_reg dest, + struct x86_reg src, + ubyte shuffle ) +{ + sse_shufps(cp->func, dest, src, shuffle); +} + + +static boolean load_input( struct aos_compilation *cp, + unsigned idx, + boolean linear ) +{ + unsigned format = cp->vaos->base.key.element[idx].in.format; + struct x86_reg src = cp->tmp_EAX; + struct x86_reg dataXMM = aos_get_xmm_reg(cp); + + /* Figure out source pointer address: + */ + get_src_ptr(cp, + src, + linear ? cp->idx_EBX : x86_deref(cp->idx_EBX), + idx); + + src = x86_deref(src); + + aos_adopt_xmm_reg( cp, + dataXMM, + TGSI_FILE_INPUT, + idx, + TRUE ); + + switch (format) { + case PIPE_FORMAT_R32_FLOAT: + emit_load_R32(cp, dataXMM, src); + break; + case PIPE_FORMAT_R32G32_FLOAT: + emit_load_R32G32(cp, dataXMM, src); + break; + case PIPE_FORMAT_R32G32B32_FLOAT: + emit_load_R32G32B32(cp, dataXMM, src); + break; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + emit_load_R32G32B32A32(cp, dataXMM, src); + break; + case PIPE_FORMAT_B8G8R8A8_UNORM: + emit_load_R8G8B8A8_UNORM(cp, dataXMM, src); + emit_swizzle(cp, dataXMM, dataXMM, SHUF(Z,Y,X,W)); + break; + case PIPE_FORMAT_R8G8B8A8_UNORM: + emit_load_R8G8B8A8_UNORM(cp, dataXMM, src); + break; + default: + ERROR(cp, "unhandled input format"); + return FALSE; + } + + return TRUE; +} + + +boolean aos_fetch_inputs( struct aos_compilation *cp, boolean linear ) +{ + unsigned i; + + for (i = 0; i < cp->vaos->base.key.nr_inputs; i++) { + if (!load_input( cp, i, linear )) + return FALSE; + cp->insn_counter++; + debug_printf("\n"); + } + + return TRUE; +} + + + + + + + +static void emit_store_R32G32B32A32( struct aos_compilation *cp, + struct x86_reg dst_ptr, + struct x86_reg dataXMM ) +{ + sse_movups(cp->func, dst_ptr, dataXMM); +} + +static void emit_store_R32G32B32( struct aos_compilation *cp, + struct x86_reg dst_ptr, + struct x86_reg dataXMM ) +{ + sse_movlps(cp->func, dst_ptr, dataXMM); + sse_shufps(cp->func, dataXMM, dataXMM, SHUF(Z,Z,Z,Z) ); /* NOTE! destructive */ + sse_movss(cp->func, x86_make_disp(dst_ptr,8), dataXMM); +} + +static void emit_store_R32G32( struct aos_compilation *cp, + struct x86_reg dst_ptr, + struct x86_reg dataXMM ) +{ + sse_movlps(cp->func, dst_ptr, dataXMM); +} + +static void emit_store_R32( struct aos_compilation *cp, + struct x86_reg dst_ptr, + struct x86_reg dataXMM ) +{ + sse_movss(cp->func, dst_ptr, dataXMM); +} + + + +static void emit_store_R8G8B8A8_UNORM( struct aos_compilation *cp, + struct x86_reg dst_ptr, + struct x86_reg dataXMM ) +{ + sse_mulps(cp->func, dataXMM, aos_get_internal(cp, IMM_255)); + sse2_cvtps2dq(cp->func, dataXMM, dataXMM); + sse2_packssdw(cp->func, dataXMM, dataXMM); + sse2_packuswb(cp->func, dataXMM, dataXMM); + sse_movss(cp->func, dst_ptr, dataXMM); +} + + + + + +static boolean emit_output( struct aos_compilation *cp, + struct x86_reg ptr, + struct x86_reg dataXMM, + unsigned format ) +{ + switch (format) { + case EMIT_1F: + case EMIT_1F_PSIZE: + emit_store_R32(cp, ptr, dataXMM); + break; + case EMIT_2F: + emit_store_R32G32(cp, ptr, dataXMM); + break; + case EMIT_3F: + emit_store_R32G32B32(cp, ptr, dataXMM); + break; + case EMIT_4F: + emit_store_R32G32B32A32(cp, ptr, dataXMM); + break; + case EMIT_4UB: + if (1) { + emit_swizzle(cp, dataXMM, dataXMM, SHUF(Z,Y,X,W)); + emit_store_R8G8B8A8_UNORM(cp, ptr, dataXMM); + } + else { + emit_store_R8G8B8A8_UNORM(cp, ptr, dataXMM); + } + break; + default: + ERROR(cp, "unhandled output format"); + return FALSE; + } + + return TRUE; +} + + + +boolean aos_emit_outputs( struct aos_compilation *cp ) +{ + unsigned i; + + for (i = 0; i < cp->vaos->base.key.nr_outputs; i++) { + unsigned format = cp->vaos->base.key.element[i].out.format; + unsigned offset = cp->vaos->base.key.element[i].out.offset; + unsigned vs_output = cp->vaos->base.key.element[i].out.vs_output; + + struct x86_reg data; + + if (format == EMIT_1F_PSIZE) { + data = aos_get_internal_xmm( cp, IMM_PSIZE ); + } + else { + data = aos_get_shader_reg( cp, + TGSI_FILE_OUTPUT, + vs_output ); + } + + if (data.file != file_XMM) { + struct x86_reg tmp = aos_get_xmm_reg( cp ); + sse_movups(cp->func, tmp, data); + data = tmp; + } + + if (!emit_output( cp, + x86_make_disp( cp->outbuf_ECX, offset ), + data, + format )) + return FALSE; + + aos_release_xmm_reg( cp, data.idx ); + + cp->insn_counter++; + debug_printf("\n"); + } + + return TRUE; +} + +#endif diff --git a/src/gallium/auxiliary/draw/draw_vs_aos_machine.c b/src/gallium/auxiliary/draw/draw_vs_aos_machine.c new file mode 100644 index 0000000000..6a54917ae3 --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_vs_aos_machine.c @@ -0,0 +1,323 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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. + * + **************************************************************************/ + + +#include "pipe/p_config.h" + + +#include "pipe/p_util.h" +#include "pipe/p_shader_tokens.h" +#include "tgsi/util/tgsi_parse.h" +#include "tgsi/util/tgsi_util.h" +#include "tgsi/exec/tgsi_exec.h" +#include "draw_vs.h" +#include "draw_vs_aos.h" +#include "draw_vertex.h" + +#ifdef PIPE_ARCH_X86 + +#include "rtasm/rtasm_x86sse.h" + + +#define X87_CW_EXCEPTION_INV_OP (1<<0) +#define X87_CW_EXCEPTION_DENORM_OP (1<<1) +#define X87_CW_EXCEPTION_ZERO_DIVIDE (1<<2) +#define X87_CW_EXCEPTION_OVERFLOW (1<<3) +#define X87_CW_EXCEPTION_UNDERFLOW (1<<4) +#define X87_CW_EXCEPTION_PRECISION (1<<5) +#define X87_CW_PRECISION_SINGLE (0<<8) +#define X87_CW_PRECISION_RESERVED (1<<8) +#define X87_CW_PRECISION_DOUBLE (2<<8) +#define X87_CW_PRECISION_DOUBLE_EXT (3<<8) +#define X87_CW_PRECISION_MASK (3<<8) +#define X87_CW_ROUND_NEAREST (0<<10) +#define X87_CW_ROUND_DOWN (1<<10) +#define X87_CW_ROUND_UP (2<<10) +#define X87_CW_ROUND_ZERO (3<<10) +#define X87_CW_ROUND_MASK (3<<10) +#define X87_CW_INFINITY (1<<12) + + +void PIPE_CDECL aos_do_lit( struct aos_machine *machine, + float *result, + const float *in, + unsigned count ) +{ + if (in[0] > 0) + { + if (in[1] <= 0.0) + { + result[0] = 1.0F; + result[1] = in[0]; + result[2] = 1.0; + result[3] = 1.0F; + } + else + { + const float epsilon = 1.0F / 256.0F; + float exponent = CLAMP(in[3], -(128.0F - epsilon), (128.0F - epsilon)); + result[0] = 1.0F; + result[1] = in[0]; + result[2] = powf(in[1], exponent); + result[3] = 1.0; + } + } + else + { + result[0] = 1.0F; + result[1] = 0.0; + result[2] = 0.0; + result[3] = 1.0F; + } +} + + +static void PIPE_CDECL do_lit_lut( struct aos_machine *machine, + float *result, + const float *in, + unsigned count ) +{ + if (in[0] > 0) + { + if (in[1] <= 0.0) + { + result[0] = 1.0F; + result[1] = in[0]; + result[2] = 1.0; + result[3] = 1.0F; + return; + } + + if (machine->lit_info[count].shine_tab->exponent != in[3]) { + machine->lit_info[count].func = aos_do_lit; + goto no_luck; + } + + if (in[1] <= 1.0) + { + const float *tab = machine->lit_info[count].shine_tab->values; + float f = in[1] * 256; + int k = (int)f; + float frac = f - (float)k; + + result[0] = 1.0F; + result[1] = in[0]; + result[2] = tab[k] + frac*(tab[k+1]-tab[k]); + result[3] = 1.0; + return; + } + + no_luck: + { + const float epsilon = 1.0F / 256.0F; + float exponent = CLAMP(in[3], -(128.0F - epsilon), (128.0F - epsilon)); + result[0] = 1.0F; + result[1] = in[0]; + result[2] = powf(in[1], exponent); + result[3] = 1.0; + } + } + else + { + result[0] = 1.0F; + result[1] = 0.0; + result[2] = 0.0; + result[3] = 1.0F; + } +} + + +static void do_populate_lut( struct shine_tab *tab, + float unclamped_exponent ) +{ + const float epsilon = 1.0F / 256.0F; + float exponent = CLAMP(unclamped_exponent, -(128.0F - epsilon), (128.0F - epsilon)); + unsigned i; + + tab->exponent = unclamped_exponent; /* for later comparison */ + + tab->values[0] = 0; + if (exponent == 0) { + for (i = 1; i < 258; i++) { + tab->values[i] = 1.0; + } + } + else { + for (i = 1; i < 258; i++) { + tab->values[i] = powf((float)i * epsilon, exponent); + } + } +} + + + + +static void PIPE_CDECL populate_lut( struct aos_machine *machine, + float *result, + const float *in, + unsigned count ) +{ + unsigned i, tab; + + /* Search for an existing table for this value. Note that without + * static analysis we don't really know if in[3] will be constant, + * but it usually is... + */ + for (tab = 0; tab < 4; tab++) { + if (machine->shine_tab[tab].exponent == in[3]) { + goto found; + } + } + + for (tab = 0, i = 1; i < 4; i++) { + if (machine->shine_tab[i].last_used < machine->shine_tab[tab].last_used) + tab = i; + } + + if (machine->shine_tab[tab].last_used == machine->now) { + /* No unused tables (this is not a ffvertex program...). Just + * call pow each time: + */ + machine->lit_info[count].func = aos_do_lit; + machine->lit_info[count].func( machine, result, in, count ); + return; + } + else { + do_populate_lut( &machine->shine_tab[tab], in[3] ); + } + + found: + machine->shine_tab[tab].last_used = machine->now; + machine->lit_info[count].shine_tab = &machine->shine_tab[tab]; + machine->lit_info[count].func = do_lit_lut; + machine->lit_info[count].func( machine, result, in, count ); +} + + +void draw_vs_aos_machine_constants( struct aos_machine *machine, + const float (*constants)[4] ) +{ + machine->constants = constants; + + { + unsigned i; + for (i = 0; i < MAX_LIT_INFO; i++) { + machine->lit_info[i].func = populate_lut; + machine->now++; + } + } +} + + +void draw_vs_aos_machine_viewport( struct aos_machine *machine, + const struct pipe_viewport_state *viewport ) +{ + memcpy(machine->scale, viewport->scale, 4 * sizeof(float)); + memcpy(machine->translate, viewport->translate, 4 * sizeof(float)); +} + + + +void draw_vs_aos_machine_destroy( struct aos_machine *machine ) +{ + align_free(machine); +} + +struct aos_machine *draw_vs_aos_machine( void ) +{ + struct aos_machine *machine; + unsigned i; + float inv = 1.0f/255.0f; + float f255 = 255.0f; + + machine = align_malloc(sizeof(struct aos_machine), 16); + if (!machine) + return NULL; + + memset(machine, 0, sizeof(*machine)); + + ASSIGN_4V(machine->internal[IMM_SWZ], 1.0f, -1.0f, 0.0f, 1.0f); + *(unsigned *)&machine->internal[IMM_SWZ][3] = 0xffffffff; + + ASSIGN_4V(machine->internal[IMM_ONES], 1.0f, 1.0f, 1.0f, 1.0f); + ASSIGN_4V(machine->internal[IMM_NEGS], -1.0f, -1.0f, -1.0f, -1.0f); + ASSIGN_4V(machine->internal[IMM_IDENTITY], 0.0f, 0.0f, 0.0f, 1.0f); + ASSIGN_4V(machine->internal[IMM_INV_255], inv, inv, inv, inv); + ASSIGN_4V(machine->internal[IMM_255], f255, f255, f255, f255); + ASSIGN_4V(machine->internal[IMM_RSQ], -.5f, 1.5f, 0.0f, 0.0f); + + + machine->fpu_rnd_nearest = (X87_CW_EXCEPTION_INV_OP | + X87_CW_EXCEPTION_DENORM_OP | + X87_CW_EXCEPTION_ZERO_DIVIDE | + X87_CW_EXCEPTION_OVERFLOW | + X87_CW_EXCEPTION_UNDERFLOW | + X87_CW_EXCEPTION_PRECISION | + (1<<6) | + X87_CW_ROUND_NEAREST | + X87_CW_PRECISION_DOUBLE_EXT); + + assert(machine->fpu_rnd_nearest == 0x37f); + + machine->fpu_rnd_neg_inf = (X87_CW_EXCEPTION_INV_OP | + X87_CW_EXCEPTION_DENORM_OP | + X87_CW_EXCEPTION_ZERO_DIVIDE | + X87_CW_EXCEPTION_OVERFLOW | + X87_CW_EXCEPTION_UNDERFLOW | + X87_CW_EXCEPTION_PRECISION | + (1<<6) | + X87_CW_ROUND_DOWN | + X87_CW_PRECISION_DOUBLE_EXT); + + for (i = 0; i < MAX_SHINE_TAB; i++) + do_populate_lut( &machine->shine_tab[i], 1.0f ); + + return machine; +} + +#else + +void draw_vs_aos_machine_viewport( struct aos_machine *machine, + const struct pipe_viewport_state *viewport ) +{ +} + +void draw_vs_aos_machine_constants( struct aos_machine *machine, + const float (*constants)[4] ) +{ +} + +void draw_vs_aos_machine_destroy( struct aos_machine *machine ) +{ +} + +struct aos_machine *draw_vs_aos_machine( void ) +{ + return NULL; +} +#endif + diff --git a/src/gallium/auxiliary/draw/draw_vs_exec.c b/src/gallium/auxiliary/draw/draw_vs_exec.c index 7a02f6334b..4501877efc 100644 --- a/src/gallium/auxiliary/draw/draw_vs_exec.c +++ b/src/gallium/auxiliary/draw/draw_vs_exec.c @@ -179,10 +179,12 @@ draw_create_vs_exec(struct draw_context *draw, tgsi_scan_shader(state->tokens, &vs->base.info); + vs->base.draw = draw; vs->base.prepare = vs_exec_prepare; vs->base.run_linear = vs_exec_run_linear; vs->base.delete = vs_exec_delete; - vs->machine = &draw->machine; + vs->base.create_varient = draw_vs_varient_generic; + vs->machine = &draw->vs.machine; return &vs->base; } diff --git a/src/gallium/auxiliary/draw/draw_vs_llvm.c b/src/gallium/auxiliary/draw/draw_vs_llvm.c index 171da51dd5..621472ec7c 100644 --- a/src/gallium/auxiliary/draw/draw_vs_llvm.c +++ b/src/gallium/auxiliary/draw/draw_vs_llvm.c @@ -114,7 +114,9 @@ draw_create_vs_llvm(struct draw_context *draw, tgsi_scan_shader(vs->base.state.tokens, &vs->base.info); + vs->base.draw = draw; vs->base.prepare = vs_llvm_prepare; + vs->base.create_varient = draw_vs_varient_generic; vs->base.run_linear = vs_llvm_run_linear; vs->base.delete = vs_llvm_delete; vs->machine = &draw->machine; diff --git a/src/gallium/auxiliary/draw/draw_vs_sse.c b/src/gallium/auxiliary/draw/draw_vs_sse.c index e3f4e67472..c3189c707d 100644 --- a/src/gallium/auxiliary/draw/draw_vs_sse.c +++ b/src/gallium/auxiliary/draw/draw_vs_sse.c @@ -31,9 +31,11 @@ * Brian Paul */ +#include "pipe/p_config.h" + #include "draw_vs.h" -#if defined(__i386__) || defined(__386__) +#if defined(PIPE_ARCH_X86) #include "pipe/p_util.h" #include "pipe/p_shader_tokens.h" @@ -47,10 +49,8 @@ #include "tgsi/util/tgsi_parse.h" #define SSE_MAX_VERTICES 4 -#define SSE_SWIZZLES 1 -#if SSE_SWIZZLES -typedef void (XSTDCALL *codegen_function) ( +typedef void (PIPE_CDECL *codegen_function) ( const struct tgsi_exec_vector *input, /* 1 */ struct tgsi_exec_vector *output, /* 2 */ float (*constant)[4], /* 3 */ @@ -62,14 +62,6 @@ typedef void (XSTDCALL *codegen_function) ( float (*aos_output)[4], /* 9 */ uint num_outputs, /* 10 */ uint output_stride ); /* 11 */ -#else -typedef void (XSTDCALL *codegen_function) ( - const struct tgsi_exec_vector *input, - struct tgsi_exec_vector *output, - float (*constant)[4], - struct tgsi_exec_vector *temporary, - float (*immediates)[4] ); -#endif struct draw_sse_vertex_shader { struct draw_vertex_shader base; @@ -78,8 +70,6 @@ struct draw_sse_vertex_shader { codegen_function func; struct tgsi_exec_machine *machine; - - float immediates[TGSI_EXEC_NUM_IMMEDIATES][4]; }; @@ -111,14 +101,13 @@ vs_sse_run_linear( struct draw_vertex_shader *base, for (i = 0; i < count; i += MAX_TGSI_VERTICES) { unsigned int max_vertices = MIN2(MAX_TGSI_VERTICES, count - i); -#if SSE_SWIZZLES /* run compiled shader */ shader->func(machine->Inputs, machine->Outputs, (float (*)[4])constants, machine->Temps, - shader->immediates, + (float (*)[4])shader->base.immediates, input, base->info.num_inputs, input_stride, @@ -128,43 +117,6 @@ vs_sse_run_linear( struct draw_vertex_shader *base, input = (const float (*)[4])((const char *)input + input_stride * max_vertices); output = (float (*)[4])((char *)output + output_stride * max_vertices); -#else - unsigned int j, slot; - - /* Swizzle inputs. - */ - for (j = 0; j < max_vertices; j++) { - for (slot = 0; slot < base->info.num_inputs; slot++) { - machine->Inputs[slot].xyzw[0].f[j] = input[slot][0]; - machine->Inputs[slot].xyzw[1].f[j] = input[slot][1]; - machine->Inputs[slot].xyzw[2].f[j] = input[slot][2]; - machine->Inputs[slot].xyzw[3].f[j] = input[slot][3]; - } - - input = (const float (*)[4])((const char *)input + input_stride); - } - - /* run compiled shader - */ - shader->func(machine->Inputs, - machine->Outputs, - (float (*)[4])constants, - machine->Temps, - shader->immediates); - - /* Unswizzle all output results. - */ - for (j = 0; j < max_vertices; j++) { - for (slot = 0; slot < base->info.num_outputs; slot++) { - output[slot][0] = machine->Outputs[slot].xyzw[0].f[j]; - output[slot][1] = machine->Outputs[slot].xyzw[1].f[j]; - output[slot][2] = machine->Outputs[slot].xyzw[2].f[j]; - output[slot][3] = machine->Outputs[slot].xyzw[3].f[j]; - } - - output = (float (*)[4])((char *)output + output_stride); - } -#endif } } @@ -178,6 +130,8 @@ vs_sse_delete( struct draw_vertex_shader *base ) x86_release_func( &shader->sse2_program ); + align_free( (void *) shader->base.immediates ); + FREE( (void*) shader->base.state.tokens ); FREE( shader ); } @@ -203,15 +157,26 @@ draw_create_vs_sse(struct draw_context *draw, tgsi_scan_shader(templ->tokens, &vs->base.info); + vs->base.draw = draw; + if (1) + vs->base.create_varient = draw_vs_varient_aos_sse; + else + vs->base.create_varient = draw_vs_varient_generic; vs->base.prepare = vs_sse_prepare; vs->base.run_linear = vs_sse_run_linear; vs->base.delete = vs_sse_delete; - vs->machine = &draw->machine; + + vs->base.immediates = align_malloc(TGSI_EXEC_NUM_IMMEDIATES * 4 * + sizeof(float), 16); + + vs->machine = &draw->vs.machine; x86_init_func( &vs->sse2_program ); if (!tgsi_emit_sse2( (struct tgsi_token *) vs->base.state.tokens, - &vs->sse2_program, vs->immediates, SSE_SWIZZLES )) + &vs->sse2_program, + (float (*)[4])vs->base.immediates, + TRUE )) goto fail; vs->func = (codegen_function) x86_get_func( &vs->sse2_program ); @@ -222,7 +187,7 @@ draw_create_vs_sse(struct draw_context *draw, return &vs->base; fail: - fprintf(stderr, "tgsi_emit_sse2() failed, falling back to interpreter\n"); + debug_error("tgsi_emit_sse2() failed, falling back to interpreter\n"); x86_release_func( &vs->sse2_program ); diff --git a/src/gallium/auxiliary/draw/draw_vs_varient.c b/src/gallium/auxiliary/draw/draw_vs_varient.c new file mode 100644 index 0000000000..ad0b829afa --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_vs_varient.c @@ -0,0 +1,321 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "pipe/p_util.h" +#include "draw/draw_context.h" +#include "draw/draw_private.h" +#include "draw/draw_vbuf.h" +#include "draw/draw_vertex.h" +#include "draw/draw_vs.h" +#include "translate/translate.h" +#include "translate/translate_cache.h" + +/* A first pass at incorporating vertex fetch/emit functionality into + */ +struct draw_vs_varient_generic { + struct draw_vs_varient base; + + struct draw_vertex_shader *shader; + struct draw_context *draw; + + /* Basic plan is to run these two translate functions before/after + * the vertex shader's existing run_linear() routine to simulate + * the inclusion of this functionality into the shader... + * + * Next will look at actually including it. + */ + struct translate *fetch; + struct translate *emit; + + unsigned temp_vertex_stride; +}; + + + + + +static void vsvg_set_input( struct draw_vs_varient *varient, + unsigned buffer, + const void *ptr, + unsigned stride ) +{ + struct draw_vs_varient_generic *vsvg = (struct draw_vs_varient_generic *)varient; + + vsvg->fetch->set_buffer(vsvg->fetch, + buffer, + ptr, + stride); +} + + +/* Mainly for debug at this stage: + */ +static void do_rhw_viewport( struct draw_vs_varient_generic *vsvg, + unsigned count, + void *output_buffer ) +{ + char *ptr = (char *)output_buffer; + const float *scale = vsvg->base.vs->draw->viewport.scale; + const float *trans = vsvg->base.vs->draw->viewport.translate; + unsigned stride = vsvg->temp_vertex_stride; + unsigned j; + + ptr += vsvg->base.vs->position_output * 4 * sizeof(float); + + for (j = 0; j < count; j++, ptr += stride) { + float *data = (float *)ptr; + float w = 1.0f / data[3]; + + data[0] = data[0] * w * scale[0] + trans[0]; + data[1] = data[1] * w * scale[1] + trans[1]; + data[2] = data[2] * w * scale[2] + trans[2]; + data[3] = w; + } +} + +static void do_viewport( struct draw_vs_varient_generic *vsvg, + unsigned count, + void *output_buffer ) +{ + char *ptr = (char *)output_buffer; + const float *scale = vsvg->base.vs->draw->viewport.scale; + const float *trans = vsvg->base.vs->draw->viewport.translate; + unsigned stride = vsvg->temp_vertex_stride; + unsigned j; + + ptr += vsvg->base.vs->position_output * 4 * sizeof(float); + + for (j = 0; j < count; j++, ptr += stride) { + float *data = (float *)ptr; + + data[0] = data[0] * scale[0] + trans[0]; + data[1] = data[1] * scale[1] + trans[1]; + data[2] = data[2] * scale[2] + trans[2]; + } +} + + +static void PIPE_CDECL vsvg_run_elts( struct draw_vs_varient *varient, + const unsigned *elts, + unsigned count, + void *output_buffer) +{ + struct draw_vs_varient_generic *vsvg = (struct draw_vs_varient_generic *)varient; + unsigned temp_vertex_stride = vsvg->temp_vertex_stride; + void *temp_buffer = MALLOC( align(count,4) * temp_vertex_stride ); + + if (0) debug_printf("%s %d \n", __FUNCTION__, count); + + /* Want to do this in small batches for cache locality? + */ + + vsvg->fetch->run_elts( vsvg->fetch, + elts, + count, + temp_buffer ); + + vsvg->base.vs->run_linear( vsvg->base.vs, + temp_buffer, + temp_buffer, + (const float (*)[4])vsvg->base.vs->draw->pt.user.constants, + count, + temp_vertex_stride, + temp_vertex_stride); + + + if (vsvg->base.key.clip) { + /* not really handling clipping, just do the rhw so we can + * see the results... + */ + do_rhw_viewport( vsvg, + count, + temp_buffer ); + } + else if (vsvg->base.key.viewport) { + do_viewport( vsvg, + count, + temp_buffer ); + } + + + vsvg->emit->set_buffer( vsvg->emit, + 0, + temp_buffer, + temp_vertex_stride ); + + vsvg->emit->set_buffer( vsvg->emit, + 1, + &vsvg->draw->rasterizer->point_size, + 0); + + vsvg->emit->run( vsvg->emit, + 0, count, + output_buffer ); + + FREE(temp_buffer); +} + + +static void PIPE_CDECL vsvg_run_linear( struct draw_vs_varient *varient, + unsigned start, + unsigned count, + void *output_buffer ) +{ + struct draw_vs_varient_generic *vsvg = (struct draw_vs_varient_generic *)varient; + unsigned temp_vertex_stride = vsvg->temp_vertex_stride; + void *temp_buffer = MALLOC( align(count,4) * temp_vertex_stride ); + + if (0) debug_printf("%s %d %d (sz %d, %d)\n", __FUNCTION__, start, count, + vsvg->base.key.output_stride, + temp_vertex_stride); + + vsvg->fetch->run( vsvg->fetch, + start, + count, + temp_buffer ); + + vsvg->base.vs->run_linear( vsvg->base.vs, + temp_buffer, + temp_buffer, + (const float (*)[4])vsvg->base.vs->draw->pt.user.constants, + count, + temp_vertex_stride, + temp_vertex_stride); + + if (vsvg->base.key.clip) { + /* not really handling clipping, just do the rhw so we can + * see the results... + */ + do_rhw_viewport( vsvg, + count, + temp_buffer ); + } + else if (vsvg->base.key.viewport) { + do_viewport( vsvg, + count, + temp_buffer ); + } + + vsvg->emit->set_buffer( vsvg->emit, + 0, + temp_buffer, + temp_vertex_stride ); + + vsvg->emit->set_buffer( vsvg->emit, + 1, + &vsvg->draw->rasterizer->point_size, + 0); + + vsvg->emit->run( vsvg->emit, + 0, count, + output_buffer ); + + FREE(temp_buffer); +} + + + + + +static void vsvg_destroy( struct draw_vs_varient *varient ) +{ + FREE(varient); +} + + +struct draw_vs_varient *draw_vs_varient_generic( struct draw_vertex_shader *vs, + const struct draw_vs_varient_key *key ) +{ + unsigned i; + struct translate_key fetch, emit; + + struct draw_vs_varient_generic *vsvg = CALLOC_STRUCT( draw_vs_varient_generic ); + if (vsvg == NULL) + return NULL; + + vsvg->base.key = *key; + vsvg->base.vs = vs; + vsvg->base.set_input = vsvg_set_input; + vsvg->base.run_elts = vsvg_run_elts; + vsvg->base.run_linear = vsvg_run_linear; + vsvg->base.destroy = vsvg_destroy; + + vsvg->draw = vs->draw; + + vsvg->temp_vertex_stride = MAX2(key->nr_inputs, + vsvg->base.vs->info.num_outputs) * 4 * sizeof(float); + + /* Build free-standing fetch and emit functions: + */ + fetch.nr_elements = key->nr_inputs; + fetch.output_stride = vsvg->temp_vertex_stride; + for (i = 0; i < key->nr_inputs; i++) { + fetch.element[i].input_format = key->element[i].in.format; + fetch.element[i].input_buffer = key->element[i].in.buffer; + fetch.element[i].input_offset = key->element[i].in.offset; + fetch.element[i].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + fetch.element[i].output_offset = i * 4 * sizeof(float); + assert(fetch.element[i].output_offset < fetch.output_stride); + } + + + emit.nr_elements = key->nr_outputs; + emit.output_stride = key->output_stride; + for (i = 0; i < key->nr_outputs; i++) { + if (key->element[i].out.format != EMIT_1F_PSIZE) + { + emit.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + emit.element[i].input_buffer = 0; + emit.element[i].input_offset = key->element[i].out.vs_output * 4 * sizeof(float); + emit.element[i].output_format = draw_translate_vinfo_format(key->element[i].out.format); + emit.element[i].output_offset = key->element[i].out.offset; + assert(emit.element[i].input_offset < fetch.output_stride); + } + else { + emit.element[i].input_format = PIPE_FORMAT_R32_FLOAT; + emit.element[i].input_buffer = 1; + emit.element[i].input_offset = 0; + emit.element[i].output_format = PIPE_FORMAT_R32_FLOAT; + emit.element[i].output_offset = key->element[i].out.offset; + } + } + + vsvg->fetch = draw_vs_get_fetch( vs->draw, &fetch ); + vsvg->emit = draw_vs_get_emit( vs->draw, &emit ); + + return &vsvg->base; +} + + + + + diff --git a/src/gallium/auxiliary/gallivm/tgsitollvm.cpp b/src/gallium/auxiliary/gallivm/tgsitollvm.cpp index 9695358ab8..98014bdaa1 100644 --- a/src/gallium/auxiliary/gallivm/tgsitollvm.cpp +++ b/src/gallium/auxiliary/gallivm/tgsitollvm.cpp @@ -96,10 +96,8 @@ translate_declaration(struct gallivm_ir *prog, unsigned first, last, mask; uint interp_method; - assert(decl->Declaration.Declare == TGSI_DECLARE_RANGE); - - first = decl->u.DeclarationRange.First; - last = decl->u.DeclarationRange.Last; + first = decl->DeclarationRange.First; + last = decl->DeclarationRange.Last; mask = decl->Declaration.UsageMask; /* Do not touch WPOS.xy */ @@ -113,7 +111,7 @@ translate_declaration(struct gallivm_ir *prog, } } - interp_method = decl->Interpolation.Interpolate; + interp_method = decl->Declaration.Interpolate; if (mask == TGSI_WRITEMASK_XYZW) { unsigned i, j; @@ -153,7 +151,7 @@ translate_declarationir(struct gallivm_ir *, struct tgsi_full_declaration *) { if (decl->Declaration.File == TGSI_FILE_ADDRESS) { - int idx = decl->u.DeclarationRange.First; + int idx = decl->DeclarationRange.First; storage->addAddress(idx); } } diff --git a/src/gallium/auxiliary/pipebuffer/Makefile b/src/gallium/auxiliary/pipebuffer/Makefile index ff09011b66..1d9b036c07 100644 --- a/src/gallium/auxiliary/pipebuffer/Makefile +++ b/src/gallium/auxiliary/pipebuffer/Makefile @@ -6,6 +6,7 @@ LIBNAME = pipebuffer C_SOURCES = \ pb_buffer_fenced.c \ pb_buffer_malloc.c \ + pb_bufmgr_alt.c \ pb_bufmgr_cache.c \ pb_bufmgr_fenced.c \ pb_bufmgr_mm.c \ diff --git a/src/gallium/auxiliary/pipebuffer/SConscript b/src/gallium/auxiliary/pipebuffer/SConscript index 9db0c0eae3..e52177bc79 100644 --- a/src/gallium/auxiliary/pipebuffer/SConscript +++ b/src/gallium/auxiliary/pipebuffer/SConscript @@ -5,6 +5,7 @@ pipebuffer = env.ConvenienceLibrary( source = [ 'pb_buffer_fenced.c', 'pb_buffer_malloc.c', + 'pb_bufmgr_alt.c', 'pb_bufmgr_cache.c', 'pb_bufmgr_fenced.c', 'pb_bufmgr_mm.c', diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c index 9e8244f909..e90d2e5623 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c @@ -30,13 +30,14 @@ * Implementation of malloc-based buffers to store data that can't be processed * by the hardware. * - * \author José Fonseca <jrfonseca@tungstengraphics.com> + * \author Jose Fonseca <jrfonseca@tungstengraphics.com> */ #include "pipe/p_debug.h" #include "pipe/p_util.h" #include "pb_buffer.h" +#include "pb_bufmgr.h" struct malloc_buffer @@ -119,9 +120,39 @@ pb_malloc_buffer_create(size_t size, buf->data = align_malloc(size, desc->alignment < sizeof(void*) ? sizeof(void*) : desc->alignment); if(!buf->data) { - align_free(buf); + FREE(buf); return NULL; } return &buf->base; } + + +static struct pb_buffer * +pb_malloc_buffer_create_buffer(struct pb_manager *mgr, + size_t size, + const struct pb_desc *desc) +{ + return pb_malloc_buffer_create(size, desc); +} + + +static void +pb_malloc_bufmgr_destroy(struct pb_manager *mgr) +{ + /* No-op */ +} + + +static struct pb_manager +pb_malloc_bufmgr = { + pb_malloc_buffer_create_buffer, + pb_malloc_bufmgr_destroy +}; + + +struct pb_manager * +pb_malloc_bufmgr_create(void) +{ + return &pb_malloc_bufmgr; +} diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h index f6cc7a525b..00279f7010 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h @@ -79,6 +79,15 @@ struct pb_manager }; +/** + * Malloc buffer provider. + * + * Simple wrapper around pb_malloc_buffer_create for convenience. + */ +struct pb_manager * +pb_malloc_bufmgr_create(void); + + /** * Static buffer pool sub-allocator. * @@ -162,6 +171,11 @@ fenced_bufmgr_create(struct pb_manager *provider, struct pipe_winsys *winsys); +struct pb_manager * +pb_alt_manager_create(struct pb_manager *provider1, + struct pb_manager *provider2); + + #ifdef __cplusplus } #endif diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_alt.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_alt.c new file mode 100644 index 0000000000..702bef1c04 --- /dev/null +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_alt.c @@ -0,0 +1,101 @@ +/************************************************************************** + * + * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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 + * Allocate buffers from two alternative buffer providers. + * + * \author Jose Fonseca <jrfonseca@tungstengraphics.com> + */ + + +#include "pipe/p_compiler.h" +#include "pipe/p_debug.h" +#include "pipe/p_util.h" + +#include "pb_buffer.h" +#include "pb_bufmgr.h" + + +struct pb_alt_manager +{ + struct pb_manager base; + + struct pb_manager *provider1; + struct pb_manager *provider2; +}; + + +static INLINE struct pb_alt_manager * +pb_alt_manager(struct pb_manager *mgr) +{ + assert(mgr); + return (struct pb_alt_manager *)mgr; +} + + +static struct pb_buffer * +pb_alt_manager_create_buffer(struct pb_manager *_mgr, + size_t size, + const struct pb_desc *desc) +{ + struct pb_alt_manager *mgr = pb_alt_manager(_mgr); + struct pb_buffer *buf; + + buf = mgr->provider1->create_buffer(mgr->provider1, size, desc); + if(buf) + return buf; + + buf = mgr->provider2->create_buffer(mgr->provider2, size, desc); + return buf; +} + + +static void +pb_alt_manager_destroy(struct pb_manager *mgr) +{ + FREE(mgr); +} + + +struct pb_manager * +pb_alt_manager_create(struct pb_manager *provider1, + struct pb_manager *provider2) +{ + struct pb_alt_manager *mgr; + + mgr = CALLOC_STRUCT(pb_alt_manager); + if (!mgr) + return NULL; + + mgr->base.destroy = pb_alt_manager_destroy; + mgr->base.create_buffer = pb_alt_manager_create_buffer; + mgr->provider1 = provider1; + mgr->provider2 = provider2; + + return &mgr->base; +} diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c index 4bd3f94a6c..f1a457dde4 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c @@ -207,8 +207,11 @@ pb_cache_is_buffer_compat(struct pb_cache_buffer *buf, size_t size, const struct pb_desc *desc) { - /* TODO: be more lenient with size */ - if(buf->base.base.size != size) + if(buf->base.base.size < size) + return FALSE; + + /* be lenient with size */ + if(buf->base.base.size >= 2*size) return FALSE; if(!pb_check_alignment(desc->alignment, buf->base.base.alignment)) diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c index 66256f3fa7..0a1e8c83b1 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c @@ -184,7 +184,6 @@ mm_bufmgr_create_buffer(struct pb_manager *mgr, mm_buf->block = mmAllocMem(mm->heap, size, mm->align2, 0); if(!mm_buf->block) { - assert(0); FREE(mm_buf); _glthread_UNLOCK_MUTEX(mm->mutex); return NULL; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c index 45ba158a4d..b9dff09804 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c @@ -312,8 +312,8 @@ pb_slab_manager_create_buffer(struct pb_manager *_mgr, struct list_head *list; /* check size */ - assert(size == mgr->bufSize); - if(size != mgr->bufSize) + assert(size <= mgr->bufSize); + if(size > mgr->bufSize) return NULL; /* check if we can provide the requested alignment */ diff --git a/src/gallium/auxiliary/rtasm/rtasm_cpu.c b/src/gallium/auxiliary/rtasm/rtasm_cpu.c index f01e12faa0..5499018b21 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_cpu.c +++ b/src/gallium/auxiliary/rtasm/rtasm_cpu.c @@ -47,7 +47,7 @@ static boolean rtasm_sse_enabled(void) int rtasm_cpu_has_sse(void) { /* FIXME: actually detect this at run-time */ -#if defined(__i386__) || defined(__386__) || defined(i386) +#if defined(PIPE_ARCH_X86) return rtasm_sse_enabled(); #else return 0; @@ -57,7 +57,7 @@ int rtasm_cpu_has_sse(void) int rtasm_cpu_has_sse2(void) { /* FIXME: actually detect this at run-time */ -#if defined(__i386__) || defined(__386__) || defined(i386) +#if defined(PIPE_ARCH_X86) return rtasm_sse_enabled(); #else return 0; diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c index 4e036d9032..f4ca282dd9 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c +++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c @@ -21,7 +21,9 @@ * **************************************************************************/ -#if defined(__i386__) || defined(__386__) || defined(i386) +#include "pipe/p_config.h" + +#if defined(PIPE_ARCH_X86) #include "pipe/p_compiler.h" #include "pipe/p_debug.h" @@ -36,11 +38,8 @@ #define DUMP_SSE 0 -#if DUMP_SSE -static void -_print_reg( - struct x86_reg reg ) +void x86_print_reg( struct x86_reg reg ) { if (reg.mod != mod_REG) debug_printf( "[" ); @@ -77,6 +76,7 @@ _print_reg( debug_printf( "]" ); } +#if DUMP_SSE #define DUMP_START() debug_printf( "\n" ) #define DUMP_END() debug_printf( "\n" ) @@ -87,7 +87,7 @@ _print_reg( foo++; \ if (*foo) \ foo++; \ - debug_printf( "\n% 15s ", foo ); \ + debug_printf( "\n% 4x% 15s ", p->csr - p->store, foo ); \ } while (0) #define DUMP_I( I ) do { \ @@ -97,27 +97,27 @@ _print_reg( #define DUMP_R( R0 ) do { \ DUMP(); \ - _print_reg( R0 ); \ + x86_print_reg( R0 ); \ } while( 0 ) #define DUMP_RR( R0, R1 ) do { \ DUMP(); \ - _print_reg( R0 ); \ + x86_print_reg( R0 ); \ debug_printf( ", " ); \ - _print_reg( R1 ); \ + x86_print_reg( R1 ); \ } while( 0 ) #define DUMP_RI( R0, I ) do { \ DUMP(); \ - _print_reg( R0 ); \ + x86_print_reg( R0 ); \ debug_printf( ", %u", I ); \ } while( 0 ) #define DUMP_RRI( R0, R1, I ) do { \ DUMP(); \ - _print_reg( R0 ); \ + x86_print_reg( R0 ); \ debug_printf( ", " ); \ - _print_reg( R1 ); \ + x86_print_reg( R1 ); \ debug_printf( ", %u", I ); \ } while( 0 ) @@ -220,6 +220,8 @@ static void emit_3ub( struct x86_function *p, unsigned char b0, unsigned char b1 /* Build a modRM byte + possible displacement. No treatment of SIB * indexing. BZZT - no way to encode an absolute address. + * + * This is the "/r" field in the x86 manuals... */ static void emit_modrm( struct x86_function *p, struct x86_reg reg, @@ -258,7 +260,8 @@ static void emit_modrm( struct x86_function *p, } } - +/* Emits the "/0".."/7" specialized versions of the modrm ("/r") bytes. + */ static void emit_modrm_noreg( struct x86_function *p, unsigned op, struct x86_reg regmem ) @@ -327,7 +330,7 @@ struct x86_reg x86_make_disp( struct x86_reg reg, else reg.disp += disp; - if (reg.disp == 0) + if (reg.disp == 0 && reg.idx != reg_BP) reg.mod = mod_INDIRECT; else if (reg.disp <= 127 && reg.disp >= -128) reg.mod = mod_DISP8; @@ -367,8 +370,7 @@ void x86_jcc( struct x86_function *p, DUMP_I(cc); if (offset < 0) { - int amt = p->csr - p->store; - assert(amt > -offset); + assert(p->csr - p->store > -offset); } if (offset <= 127 && offset >= -128) { @@ -445,6 +447,16 @@ void x86_mov_reg_imm( struct x86_function *p, struct x86_reg dst, int imm ) emit_1i(p, imm); } +void x86_add_reg_imm8( struct x86_function *p, struct x86_reg dst, ubyte imm ) +{ + DUMP_RI( dst, imm ); + assert(dst.mod == mod_REG); + emit_1ub(p, 0x80); + emit_modrm_noreg(p, 0, dst); + emit_1ub(p, imm); +} + + void x86_push( struct x86_function *p, struct x86_reg reg ) { @@ -461,6 +473,17 @@ void x86_push( struct x86_function *p, p->stack_offset += 4; } +void x86_push_imm32( struct x86_function *p, + int imm32 ) +{ + DUMP_I( imm32 ); + emit_1ub(p, 0x68); + emit_1i(p, imm32); + + p->stack_offset += 4; +} + + void x86_pop( struct x86_function *p, struct x86_reg reg ) { @@ -865,7 +888,7 @@ void sse_unpcklps( struct x86_function *p, struct x86_reg dst, struct x86_reg sr void sse_cmpps( struct x86_function *p, struct x86_reg dst, struct x86_reg src, - unsigned char cc) + enum sse_cc cc) { DUMP_RRI( dst, src, cc ); emit_2ub(p, X86_TWOB, 0xC2); @@ -988,6 +1011,24 @@ void sse2_movd( struct x86_function *p, /*********************************************************************** * x87 instructions */ +static void note_x87_pop( struct x86_function *p ) +{ + p->x87_stack--; + assert(p->x87_stack >= 0); +} + +static void note_x87_push( struct x86_function *p ) +{ + p->x87_stack++; + assert(p->x87_stack <= 7); +} + +void x87_assert_stack_empty( struct x86_function *p ) +{ + assert (p->x87_stack == 0); +} + + void x87_fist( struct x86_function *p, struct x86_reg dst ) { DUMP_R( dst ); @@ -1000,6 +1041,7 @@ void x87_fistp( struct x86_function *p, struct x86_reg dst ) DUMP_R( dst ); emit_1ub(p, 0xdb); emit_modrm_noreg(p, 3, dst); + note_x87_pop(p); } void x87_fild( struct x86_function *p, struct x86_reg arg ) @@ -1007,12 +1049,14 @@ void x87_fild( struct x86_function *p, struct x86_reg arg ) DUMP_R( arg ); emit_1ub(p, 0xdf); emit_modrm_noreg(p, 0, arg); + note_x87_push(p); } void x87_fldz( struct x86_function *p ) { DUMP(); emit_2ub(p, 0xd9, 0xee); + note_x87_push(p); } @@ -1029,18 +1073,21 @@ void x87_fld1( struct x86_function *p ) { DUMP(); emit_2ub(p, 0xd9, 0xe8); + note_x87_push(p); } void x87_fldl2e( struct x86_function *p ) { DUMP(); emit_2ub(p, 0xd9, 0xea); + note_x87_push(p); } void x87_fldln2( struct x86_function *p ) { DUMP(); emit_2ub(p, 0xd9, 0xed); + note_x87_push(p); } void x87_fwait( struct x86_function *p ) @@ -1061,6 +1108,49 @@ void x87_fclex( struct x86_function *p ) x87_fnclex(p); } +void x87_fcmovb( struct x86_function *p, struct x86_reg arg ) +{ + DUMP_R( arg ); + assert(arg.file == file_x87); + emit_2ub(p, 0xda, 0xc0+arg.idx); +} + +void x87_fcmove( struct x86_function *p, struct x86_reg arg ) +{ + DUMP_R( arg ); + assert(arg.file == file_x87); + emit_2ub(p, 0xda, 0xc8+arg.idx); +} + +void x87_fcmovbe( struct x86_function *p, struct x86_reg arg ) +{ + DUMP_R( arg ); + assert(arg.file == file_x87); + emit_2ub(p, 0xda, 0xd0+arg.idx); +} + +void x87_fcmovnb( struct x86_function *p, struct x86_reg arg ) +{ + DUMP_R( arg ); + assert(arg.file == file_x87); + emit_2ub(p, 0xdb, 0xc0+arg.idx); +} + +void x87_fcmovne( struct x86_function *p, struct x86_reg arg ) +{ + DUMP_R( arg ); + assert(arg.file == file_x87); + emit_2ub(p, 0xdb, 0xc8+arg.idx); +} + +void x87_fcmovnbe( struct x86_function *p, struct x86_reg arg ) +{ + DUMP_R( arg ); + assert(arg.file == file_x87); + emit_2ub(p, 0xdb, 0xd0+arg.idx); +} + + static void x87_arith_op( struct x86_function *p, struct x86_reg dst, struct x86_reg arg, unsigned char dst0ub0, @@ -1148,6 +1238,7 @@ void x87_fmulp( struct x86_function *p, struct x86_reg dst ) assert(dst.file == file_x87); assert(dst.idx >= 1); emit_2ub(p, 0xde, 0xc8+dst.idx); + note_x87_pop(p); } void x87_fsubp( struct x86_function *p, struct x86_reg dst ) @@ -1156,6 +1247,7 @@ void x87_fsubp( struct x86_function *p, struct x86_reg dst ) assert(dst.file == file_x87); assert(dst.idx >= 1); emit_2ub(p, 0xde, 0xe8+dst.idx); + note_x87_pop(p); } void x87_fsubrp( struct x86_function *p, struct x86_reg dst ) @@ -1164,6 +1256,7 @@ void x87_fsubrp( struct x86_function *p, struct x86_reg dst ) assert(dst.file == file_x87); assert(dst.idx >= 1); emit_2ub(p, 0xde, 0xe0+dst.idx); + note_x87_pop(p); } void x87_faddp( struct x86_function *p, struct x86_reg dst ) @@ -1172,6 +1265,7 @@ void x87_faddp( struct x86_function *p, struct x86_reg dst ) assert(dst.file == file_x87); assert(dst.idx >= 1); emit_2ub(p, 0xde, 0xc0+dst.idx); + note_x87_pop(p); } void x87_fdivp( struct x86_function *p, struct x86_reg dst ) @@ -1180,6 +1274,7 @@ void x87_fdivp( struct x86_function *p, struct x86_reg dst ) assert(dst.file == file_x87); assert(dst.idx >= 1); emit_2ub(p, 0xde, 0xf8+dst.idx); + note_x87_pop(p); } void x87_fdivrp( struct x86_function *p, struct x86_reg dst ) @@ -1188,6 +1283,13 @@ void x87_fdivrp( struct x86_function *p, struct x86_reg dst ) assert(dst.file == file_x87); assert(dst.idx >= 1); emit_2ub(p, 0xde, 0xf0+dst.idx); + note_x87_pop(p); +} + +void x87_ftst( struct x86_function *p ) +{ + DUMP(); + emit_2ub(p, 0xd9, 0xe4); } void x87_fucom( struct x86_function *p, struct x86_reg arg ) @@ -1202,12 +1304,15 @@ void x87_fucomp( struct x86_function *p, struct x86_reg arg ) DUMP_R( arg ); assert(arg.file == file_x87); emit_2ub(p, 0xdd, 0xe8+arg.idx); + note_x87_pop(p); } void x87_fucompp( struct x86_function *p ) { DUMP(); emit_2ub(p, 0xda, 0xe9); + note_x87_pop(p); /* pop twice */ + note_x87_pop(p); /* pop twice */ } void x87_fxch( struct x86_function *p, struct x86_reg arg ) @@ -1289,6 +1394,7 @@ void x87_fyl2x( struct x86_function *p ) { DUMP(); emit_2ub(p, 0xd9, 0xf1); + note_x87_pop(p); } /* st1 = st1 * log2(st0 + 1.0); @@ -1300,6 +1406,7 @@ void x87_fyl2xp1( struct x86_function *p ) { DUMP(); emit_2ub(p, 0xd9, 0xf9); + note_x87_pop(p); } @@ -1312,6 +1419,7 @@ void x87_fld( struct x86_function *p, struct x86_reg arg ) emit_1ub(p, 0xd9); emit_modrm_noreg(p, 0, arg); } + note_x87_push(p); } void x87_fst( struct x86_function *p, struct x86_reg dst ) @@ -1334,8 +1442,15 @@ void x87_fstp( struct x86_function *p, struct x86_reg dst ) emit_1ub(p, 0xd9); emit_modrm_noreg(p, 3, dst); } + note_x87_pop(p); } +void x87_fpop( struct x86_function *p ) +{ + x87_fstp( p, x86_make_reg( file_x87, 0 )); +} + + void x87_fcom( struct x86_function *p, struct x86_reg dst ) { DUMP_R( dst ); @@ -1347,6 +1462,7 @@ void x87_fcom( struct x86_function *p, struct x86_reg dst ) } } + void x87_fcomp( struct x86_function *p, struct x86_reg dst ) { DUMP_R( dst ); @@ -1356,6 +1472,20 @@ void x87_fcomp( struct x86_function *p, struct x86_reg dst ) emit_1ub(p, 0xd8); emit_modrm_noreg(p, 3, dst); } + note_x87_pop(p); +} + +void x87_fcomi( struct x86_function *p, struct x86_reg arg ) +{ + DUMP_R( arg ); + emit_2ub(p, 0xdb, 0xf0+arg.idx); +} + +void x87_fcomip( struct x86_function *p, struct x86_reg arg ) +{ + DUMP_R( arg ); + emit_2ub(p, 0xdb, 0xf0+arg.idx); + note_x87_pop(p); } @@ -1374,6 +1504,17 @@ void x87_fnstsw( struct x86_function *p, struct x86_reg dst ) } +void x87_fnstcw( struct x86_function *p, struct x86_reg dst ) +{ + DUMP_R( dst ); + assert(dst.file == file_REG32); + + emit_1ub(p, 0x9b); /* WAIT -- needed? */ + emit_1ub(p, 0xd9); + emit_modrm_noreg(p, 7, dst); +} + + /*********************************************************************** @@ -1442,6 +1583,21 @@ void mmx_movq( struct x86_function *p, */ +void x86_cdecl_caller_push_regs( struct x86_function *p ) +{ + x86_push(p, x86_make_reg(file_REG32, reg_AX)); + x86_push(p, x86_make_reg(file_REG32, reg_CX)); + x86_push(p, x86_make_reg(file_REG32, reg_DX)); +} + +void x86_cdecl_caller_pop_regs( struct x86_function *p ) +{ + x86_pop(p, x86_make_reg(file_REG32, reg_DX)); + x86_pop(p, x86_make_reg(file_REG32, reg_CX)); + x86_pop(p, x86_make_reg(file_REG32, reg_AX)); +} + + /* Retreive a reference to one of the function arguments, taking into * account any push/pop activity: */ diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.h b/src/gallium/auxiliary/rtasm/rtasm_x86sse.h index eacaeeaf6f..af94577aab 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_x86sse.h +++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.h @@ -24,7 +24,9 @@ #ifndef _RTASM_X86SSE_H_ #define _RTASM_X86SSE_H_ -#if defined(__i386__) || defined(__386__) || defined(i386) +#include "pipe/p_config.h" + +#if defined(PIPE_ARCH_X86) /* It is up to the caller to ensure that instructions issued are * suitable for the host cpu. There are no checks made in this module @@ -41,10 +43,12 @@ struct x86_function { unsigned size; unsigned char *store; unsigned char *csr; - unsigned stack_offset; - int need_emms; + + unsigned stack_offset:16; + unsigned need_emms:8; + int x87_stack:8; + unsigned char error_overflow[4]; - const char *fn; }; enum x86_reg_file { @@ -107,6 +111,9 @@ void x86_init_func_size( struct x86_function *p, unsigned code_size ); void x86_release_func( struct x86_function *p ); void (*x86_get_func( struct x86_function *p ))( void ); +/* Debugging: + */ +void x86_print_reg( struct x86_reg reg ); /* Create and manipulate registers and regmem values: @@ -150,6 +157,7 @@ void x86_call( struct x86_function *p, struct x86_reg reg); * I load the immediate into general purpose register and use it. */ void x86_mov_reg_imm( struct x86_function *p, struct x86_reg dst, int imm ); +void x86_add_reg_imm8( struct x86_function *p, struct x86_reg dst, ubyte imm ); /* Macro for sse_shufps() and sse2_pshufd(): @@ -183,7 +191,7 @@ void sse_divss( struct x86_function *p, struct x86_reg dst, struct x86_reg src ) void sse_andnps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); void sse_andps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); void sse_cmpps( struct x86_function *p, struct x86_reg dst, struct x86_reg src, - unsigned char cc ); + enum sse_cc cc ); void sse_maxps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); void sse_maxss( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); void sse_minps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); @@ -220,6 +228,7 @@ void x86_imul( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); void x86_or( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); void x86_pop( struct x86_function *p, struct x86_reg reg ); void x86_push( struct x86_function *p, struct x86_reg reg ); +void x86_push_imm32( struct x86_function *p, int imm ); void x86_ret( struct x86_function *p ); void x86_retw( struct x86_function *p, unsigned short imm ); void x86_sub( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); @@ -227,13 +236,27 @@ void x86_test( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); void x86_xor( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); void x86_sahf( struct x86_function *p ); + +void x86_cdecl_caller_push_regs( struct x86_function *p ); +void x86_cdecl_caller_pop_regs( struct x86_function *p ); + +void x87_assert_stack_empty( struct x86_function *p ); + void x87_f2xm1( struct x86_function *p ); void x87_fabs( struct x86_function *p ); void x87_fadd( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ); void x87_faddp( struct x86_function *p, struct x86_reg dst ); void x87_fchs( struct x86_function *p ); void x87_fclex( struct x86_function *p ); +void x87_fcmovb( struct x86_function *p, struct x86_reg src ); +void x87_fcmovbe( struct x86_function *p, struct x86_reg src ); +void x87_fcmove( struct x86_function *p, struct x86_reg src ); +void x87_fcmovnb( struct x86_function *p, struct x86_reg src ); +void x87_fcmovnbe( struct x86_function *p, struct x86_reg src ); +void x87_fcmovne( struct x86_function *p, struct x86_reg src ); void x87_fcom( struct x86_function *p, struct x86_reg dst ); +void x87_fcomi( struct x86_function *p, struct x86_reg dst ); +void x87_fcomip( struct x86_function *p, struct x86_reg dst ); void x87_fcomp( struct x86_function *p, struct x86_reg dst ); void x87_fcos( struct x86_function *p ); void x87_fdiv( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ); @@ -253,6 +276,7 @@ void x87_fmul( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ); void x87_fmulp( struct x86_function *p, struct x86_reg dst ); void x87_fnclex( struct x86_function *p ); void x87_fprndint( struct x86_function *p ); +void x87_fpop( struct x86_function *p ); void x87_fscale( struct x86_function *p ); void x87_fsin( struct x86_function *p ); void x87_fsincos( struct x86_function *p ); @@ -263,11 +287,13 @@ void x87_fsub( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ); void x87_fsubp( struct x86_function *p, struct x86_reg dst ); void x87_fsubr( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ); void x87_fsubrp( struct x86_function *p, struct x86_reg dst ); +void x87_ftst( struct x86_function *p ); void x87_fxch( struct x86_function *p, struct x86_reg dst ); void x87_fxtract( struct x86_function *p ); void x87_fyl2x( struct x86_function *p ); void x87_fyl2xp1( struct x86_function *p ); void x87_fwait( struct x86_function *p ); +void x87_fnstcw( struct x86_function *p, struct x86_reg dst ); void x87_fnstsw( struct x86_function *p, struct x86_reg dst ); void x87_fucompp( struct x86_function *p ); void x87_fucomp( struct x86_function *p, struct x86_reg arg ); diff --git a/src/gallium/auxiliary/tgsi/exec/tgsi_exec.c b/src/gallium/auxiliary/tgsi/exec/tgsi_exec.c index 826b432f09..13b8c2e5bf 100644 --- a/src/gallium/auxiliary/tgsi/exec/tgsi_exec.c +++ b/src/gallium/auxiliary/tgsi/exec/tgsi_exec.c @@ -165,9 +165,17 @@ tgsi_exec_machine_bind_shader( declarations = (struct tgsi_full_declaration *) MALLOC( maxDeclarations * sizeof(struct tgsi_full_declaration) ); + if (!declarations) { + return; + } + instructions = (struct tgsi_full_instruction *) MALLOC( maxInstructions * sizeof(struct tgsi_full_instruction) ); + if (!instructions) { + FREE( declarations ); + return; + } while( !tgsi_parse_end_of_tokens( &parse ) ) { uint pointer = parse.Position; @@ -1411,13 +1419,11 @@ exec_declaration( unsigned first, last, mask; eval_coef_func eval; - assert( decl->Declaration.Declare == TGSI_DECLARE_RANGE ); - - first = decl->u.DeclarationRange.First; - last = decl->u.DeclarationRange.Last; + first = decl->DeclarationRange.First; + last = decl->DeclarationRange.Last; mask = decl->Declaration.UsageMask; - switch( decl->Interpolation.Interpolate ) { + switch( decl->Declaration.Interpolate ) { case TGSI_INTERPOLATE_CONSTANT: eval = eval_constant_coef; break; @@ -1479,7 +1485,7 @@ exec_instruction( break; case TGSI_OPCODE_MOV: - /* TGSI_OPCODE_SWZ */ + case TGSI_OPCODE_SWZ: FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { FETCH( &r[0], 0, chan_index ); STORE( &r[0], 0, chan_index ); diff --git a/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.c b/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.c index 8018bd7fa4..cdbdf5c882 100755 --- a/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.c +++ b/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.c @@ -194,22 +194,12 @@ get_coef( } -#ifdef WIN32 -static void -emit_retw( - struct x86_function *func, - unsigned size ) -{ - x86_retw( func, size ); -} -#else static void emit_ret( struct x86_function *func ) { x86_ret( func ); } -#endif /** @@ -475,7 +465,7 @@ static void emit_func_call_dst( struct x86_function *func, unsigned xmm_dst, - void (*code)() ) + void (PIPE_CDECL *code)() ) { sse_movaps( func, @@ -496,9 +486,7 @@ emit_func_call_dst( x86_push( func, ecx ); x86_mov_reg_imm( func, ecx, (unsigned long) code ); x86_call( func, ecx ); -#ifndef WIN32 x86_pop(func, ecx ); -#endif } @@ -516,7 +504,7 @@ emit_func_call_dst_src( struct x86_function *func, unsigned xmm_dst, unsigned xmm_src, - void (*code)() ) + void (PIPE_CDECL *code)() ) { sse_movaps( func, @@ -558,7 +546,7 @@ emit_add( make_xmm( xmm_src ) ); } -static void XSTDCALL +static void PIPE_CDECL cos4f( float *store ) { @@ -581,7 +569,7 @@ emit_cos( cos4f ); } -static void XSTDCALL +static void PIPE_CDECL ex24f( float *store ) { @@ -615,7 +603,7 @@ emit_f2it( make_xmm( xmm ) ); } -static void XSTDCALL +static void PIPE_CDECL flr4f( float *store ) { @@ -638,7 +626,7 @@ emit_flr( flr4f ); } -static void XSTDCALL +static void PIPE_CDECL frc4f( float *store ) { @@ -661,7 +649,7 @@ emit_frc( frc4f ); } -static void XSTDCALL +static void PIPE_CDECL lg24f( float *store ) { @@ -720,7 +708,7 @@ emit_neg( TGSI_EXEC_TEMP_80000000_C ) ); } -static void XSTDCALL +static void PIPE_CDECL pow4f( float *store ) { @@ -820,7 +808,7 @@ emit_setsign( TGSI_EXEC_TEMP_80000000_C ) ); } -static void XSTDCALL +static void PIPE_CDECL sin4f( float *store ) { @@ -1190,7 +1178,7 @@ emit_instruction( break; case TGSI_OPCODE_MOV: - /* TGSI_OPCODE_SWZ */ + case TGSI_OPCODE_SWZ: FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) { FETCH( func, *inst, 0, 0, chan_index ); STORE( func, *inst, 0, 0, chan_index ); @@ -1736,11 +1724,7 @@ emit_instruction( break; case TGSI_OPCODE_RET: -#ifdef WIN32 - emit_retw( func, 16 ); -#else emit_ret( func ); -#endif break; case TGSI_OPCODE_END: @@ -1923,16 +1907,14 @@ emit_declaration( unsigned first, last, mask; unsigned i, j; - assert( decl->Declaration.Declare == TGSI_DECLARE_RANGE ); - - first = decl->u.DeclarationRange.First; - last = decl->u.DeclarationRange.Last; + first = decl->DeclarationRange.First; + last = decl->DeclarationRange.Last; mask = decl->Declaration.UsageMask; for( i = first; i <= last; i++ ) { for( j = 0; j < NUM_CHANNELS; j++ ) { if( mask & (1 << j) ) { - switch( decl->Interpolation.Interpolate ) { + switch( decl->Declaration.Interpolate ) { case TGSI_INTERPOLATE_CONSTANT: emit_coef_a0( func, 0, i, j ); emit_inputs( func, 0, i, j ); @@ -2283,11 +2265,7 @@ tgsi_emit_sse2( func, get_immediate_base() ); -#ifdef WIN32 - emit_retw( func, 16 ); -#else emit_ret( func ); -#endif tgsi_parse_free( &parse ); diff --git a/src/gallium/auxiliary/tgsi/util/tgsi_build.c b/src/gallium/auxiliary/tgsi/util/tgsi_build.c index 9c883ab704..18e44b38c2 100644 --- a/src/gallium/auxiliary/tgsi/util/tgsi_build.c +++ b/src/gallium/auxiliary/tgsi/util/tgsi_build.c @@ -90,9 +90,8 @@ tgsi_default_declaration( void ) declaration.Type = TGSI_TOKEN_TYPE_DECLARATION; declaration.Size = 1; declaration.File = TGSI_FILE_NULL; - declaration.Declare = TGSI_DECLARE_RANGE; declaration.UsageMask = TGSI_WRITEMASK_XYZW; - declaration.Interpolate = 0; + declaration.Interpolate = TGSI_INTERPOLATE_CONSTANT; declaration.Semantic = 0; declaration.Padding = 0; declaration.Extended = 0; @@ -103,7 +102,6 @@ tgsi_default_declaration( void ) struct tgsi_declaration tgsi_build_declaration( unsigned file, - unsigned declare, unsigned usage_mask, unsigned interpolate, unsigned semantic, @@ -112,11 +110,10 @@ tgsi_build_declaration( struct tgsi_declaration declaration; assert( file <= TGSI_FILE_IMMEDIATE ); - assert( declare <= TGSI_DECLARE_MASK ); + assert( interpolate <= TGSI_INTERPOLATE_PERSPECTIVE ); declaration = tgsi_default_declaration(); declaration.File = file; - declaration.Declare = declare; declaration.UsageMask = usage_mask; declaration.Interpolate = interpolate; declaration.Semantic = semantic; @@ -144,7 +141,7 @@ tgsi_default_full_declaration( void ) struct tgsi_full_declaration full_declaration; full_declaration.Declaration = tgsi_default_declaration(); - full_declaration.Interpolation = tgsi_default_declaration_interpolation(); + full_declaration.DeclarationRange = tgsi_default_declaration_range(); full_declaration.Semantic = tgsi_default_declaration_semantic(); return full_declaration; @@ -159,6 +156,7 @@ tgsi_build_full_declaration( { unsigned size = 0; struct tgsi_declaration *declaration; + struct tgsi_declaration_range *dr; if( maxsize <= size ) return 0; @@ -167,63 +165,21 @@ tgsi_build_full_declaration( *declaration = tgsi_build_declaration( full_decl->Declaration.File, - full_decl->Declaration.Declare, full_decl->Declaration.UsageMask, full_decl->Declaration.Interpolate, full_decl->Declaration.Semantic, header ); - switch( full_decl->Declaration.Declare ) { - case TGSI_DECLARE_RANGE: - { - struct tgsi_declaration_range *dr; - - if( maxsize <= size ) - return 0; - dr = (struct tgsi_declaration_range *) &tokens[size]; - size++; - - *dr = tgsi_build_declaration_range( - full_decl->u.DeclarationRange.First, - full_decl->u.DeclarationRange.Last, - declaration, - header ); - break; - } - - case TGSI_DECLARE_MASK: - { - struct tgsi_declaration_mask *dm; - - if( maxsize <= size ) - return 0; - dm = (struct tgsi_declaration_mask *) &tokens[size]; - size++; - - *dm = tgsi_build_declaration_mask( - full_decl->u.DeclarationMask.Mask, - declaration, - header ); - break; - } - - default: - assert( 0 ); - } - - if( full_decl->Declaration.Interpolate ) { - struct tgsi_declaration_interpolation *di; - - if( maxsize <= size ) - return 0; - di = (struct tgsi_declaration_interpolation *) &tokens[size]; - size++; + if (maxsize <= size) + return 0; + dr = (struct tgsi_declaration_range *) &tokens[size]; + size++; - *di = tgsi_build_declaration_interpolation( - full_decl->Interpolation.Interpolate, - declaration, - header ); - } + *dr = tgsi_build_declaration_range( + full_decl->DeclarationRange.First, + full_decl->DeclarationRange.Last, + declaration, + header ); if( full_decl->Declaration.Semantic ) { struct tgsi_declaration_semantic *ds; @@ -244,6 +200,17 @@ tgsi_build_full_declaration( } struct tgsi_declaration_range +tgsi_default_declaration_range( void ) +{ + struct tgsi_declaration_range dr; + + dr.First = 0; + dr.Last = 0; + + return dr; +} + +struct tgsi_declaration_range tgsi_build_declaration_range( unsigned first, unsigned last, @@ -255,6 +222,7 @@ tgsi_build_declaration_range( assert( last >= first ); assert( last <= 0xFFFF ); + declaration_range = tgsi_default_declaration_range(); declaration_range.First = first; declaration_range.Last = last; @@ -263,50 +231,6 @@ tgsi_build_declaration_range( return declaration_range; } -struct tgsi_declaration_mask -tgsi_build_declaration_mask( - unsigned mask, - struct tgsi_declaration *declaration, - struct tgsi_header *header ) -{ - struct tgsi_declaration_mask declaration_mask; - - declaration_mask.Mask = mask; - - declaration_grow( declaration, header ); - - return declaration_mask; -} - -struct tgsi_declaration_interpolation -tgsi_default_declaration_interpolation( void ) -{ - struct tgsi_declaration_interpolation di; - - di.Interpolate = TGSI_INTERPOLATE_CONSTANT; - di.Padding = 0; - - return di; -} - -struct tgsi_declaration_interpolation -tgsi_build_declaration_interpolation( - unsigned interpolate, - struct tgsi_declaration *declaration, - struct tgsi_header *header ) -{ - struct tgsi_declaration_interpolation di; - - assert( interpolate <= TGSI_INTERPOLATE_PERSPECTIVE ); - - di = tgsi_default_declaration_interpolation(); - di.Interpolate = interpolate; - - declaration_grow( declaration, header ); - - return di; -} - struct tgsi_declaration_semantic tgsi_default_declaration_semantic( void ) { @@ -704,6 +628,14 @@ tgsi_build_full_instruction( tgsi_default_src_register_ext_swz() ) ) { struct tgsi_src_register_ext_swz *src_register_ext_swz; + /* Use of the extended swizzle requires the simple swizzle to be identity. + */ + assert( reg->SrcRegister.SwizzleX == TGSI_SWIZZLE_X ); + assert( reg->SrcRegister.SwizzleY == TGSI_SWIZZLE_Y ); + assert( reg->SrcRegister.SwizzleZ == TGSI_SWIZZLE_Z ); + assert( reg->SrcRegister.SwizzleW == TGSI_SWIZZLE_W ); + assert( reg->SrcRegister.Negate == FALSE ); + if( maxsize <= size ) return 0; src_register_ext_swz = diff --git a/src/gallium/auxiliary/tgsi/util/tgsi_build.h b/src/gallium/auxiliary/tgsi/util/tgsi_build.h index 80bffc4ae7..423cf141f5 100644 --- a/src/gallium/auxiliary/tgsi/util/tgsi_build.h +++ b/src/gallium/auxiliary/tgsi/util/tgsi_build.h @@ -37,7 +37,6 @@ tgsi_default_declaration( void ); struct tgsi_declaration tgsi_build_declaration( unsigned file, - unsigned declare, unsigned usage_mask, unsigned interpolate, unsigned semantic, @@ -54,27 +53,15 @@ tgsi_build_full_declaration( unsigned maxsize ); struct tgsi_declaration_range +tgsi_default_declaration_range( void ); + +struct tgsi_declaration_range tgsi_build_declaration_range( unsigned first, unsigned last, struct tgsi_declaration *declaration, struct tgsi_header *header ); -struct tgsi_declaration_mask -tgsi_build_declaration_mask( - unsigned mask, - struct tgsi_declaration *declaration, - struct tgsi_header *header ); - -struct tgsi_declaration_interpolation -tgsi_default_declaration_interpolation( void ); - -struct tgsi_declaration_interpolation -tgsi_build_declaration_interpolation( - unsigned interpolate, - struct tgsi_declaration *declaration, - struct tgsi_header *header ); - struct tgsi_declaration_semantic tgsi_default_declaration_semantic( void ); diff --git a/src/gallium/auxiliary/tgsi/util/tgsi_dump.c b/src/gallium/auxiliary/tgsi/util/tgsi_dump.c index 4c65ffd780..92aff88925 100644 --- a/src/gallium/auxiliary/tgsi/util/tgsi_dump.c +++ b/src/gallium/auxiliary/tgsi/util/tgsi_dump.c @@ -539,26 +539,20 @@ static const char *TGSI_MODULATES[] = "MODULATE_EIGHTH" }; -static void -dump_declaration_short( - struct tgsi_full_declaration *decl ) +void +tgsi_dump_declaration( + const struct tgsi_full_declaration *decl ) { TXT( "\nDCL " ); ENM( decl->Declaration.File, TGSI_FILES_SHORT ); - switch( decl->Declaration.Declare ) { - case TGSI_DECLARE_RANGE: - CHR( '[' ); - UID( decl->u.DeclarationRange.First ); - if( decl->u.DeclarationRange.First != decl->u.DeclarationRange.Last ) { - TXT( ".." ); - UID( decl->u.DeclarationRange.Last ); - } - CHR( ']' ); - break; - default: - assert( 0 ); + CHR( '[' ); + UID( decl->DeclarationRange.First ); + if (decl->DeclarationRange.First != decl->DeclarationRange.Last) { + TXT( ".." ); + UID( decl->DeclarationRange.Last ); } + CHR( ']' ); if( decl->Declaration.UsageMask != TGSI_WRITEMASK_XYZW ) { CHR( '.' ); @@ -586,10 +580,8 @@ dump_declaration_short( } } - if (decl->Declaration.Interpolate) { - TXT( ", " ); - ENM( decl->Interpolation.Interpolate, TGSI_INTERPOLATES_SHORT ); - } + TXT( ", " ); + ENM( decl->Declaration.Interpolate, TGSI_INTERPOLATES_SHORT ); } static void @@ -601,8 +593,6 @@ dump_declaration_verbose( { TXT( "\nFile : " ); ENM( decl->Declaration.File, TGSI_FILES ); - TXT( "\nDeclare : " ); - ENM( decl->Declaration.Declare, TGSI_DECLARES ); if( deflt || fd->Declaration.UsageMask != decl->Declaration.UsageMask ) { TXT( "\nUsageMask : " ); if( decl->Declaration.UsageMask & TGSI_WRITEMASK_X ) { @@ -620,7 +610,7 @@ dump_declaration_verbose( } if( deflt || fd->Declaration.Interpolate != decl->Declaration.Interpolate ) { TXT( "\nInterpolate: " ); - UID( decl->Declaration.Interpolate ); + ENM( decl->Declaration.Interpolate, TGSI_INTERPOLATES ); } if( deflt || fd->Declaration.Semantic != decl->Declaration.Semantic ) { TXT( "\nSemantic : " ); @@ -632,32 +622,10 @@ dump_declaration_verbose( } EOL(); - switch( decl->Declaration.Declare ) { - case TGSI_DECLARE_RANGE: - TXT( "\nFirst: " ); - UID( decl->u.DeclarationRange.First ); - TXT( "\nLast : " ); - UID( decl->u.DeclarationRange.Last ); - break; - - case TGSI_DECLARE_MASK: - TXT( "\nMask: " ); - UIX( decl->u.DeclarationMask.Mask ); - break; - - default: - assert( 0 ); - } - - if( decl->Declaration.Interpolate ) { - EOL(); - TXT( "\nInterpolate: " ); - ENM( decl->Interpolation.Interpolate, TGSI_INTERPOLATES ); - if( ignored ) { - TXT( "\nPadding : " ); - UIX( decl->Interpolation.Padding ); - } - } + TXT( "\nFirst: " ); + UID( decl->DeclarationRange.First ); + TXT( "\nLast : " ); + UID( decl->DeclarationRange.Last ); if( decl->Declaration.Semantic ) { EOL(); @@ -672,9 +640,9 @@ dump_declaration_verbose( } } -static void -dump_immediate_short( - struct tgsi_full_immediate *imm ) +void +tgsi_dump_immediate( + const struct tgsi_full_immediate *imm ) { unsigned i; @@ -727,9 +695,9 @@ dump_immediate_verbose( } } -static void -dump_instruction_short( - struct tgsi_full_instruction *inst, +void +tgsi_dump_instruction( + const struct tgsi_full_instruction *inst, unsigned instno ) { unsigned i; @@ -754,7 +722,7 @@ dump_instruction_short( } for( i = 0; i < inst->Instruction.NumDstRegs; i++ ) { - struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i]; + const struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i]; if( !first_reg ) { CHR( ',' ); @@ -812,7 +780,7 @@ dump_instruction_short( } for( i = 0; i < inst->Instruction.NumSrcRegs; i++ ) { - struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i]; + const struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i]; if( !first_reg ) { CHR( ',' ); @@ -835,7 +803,14 @@ dump_instruction_short( ENM( src->SrcRegister.File, TGSI_FILES_SHORT ); CHR( '[' ); - SID( src->SrcRegister.Index ); + if (src->SrcRegister.Indirect) { + TXT( "addr" ); + if (src->SrcRegister.Index > 0) + CHR( '+' ); + SID( src->SrcRegister.Index ); + } + else + SID( src->SrcRegister.Index ); CHR( ']' ); if (src->SrcRegister.SwizzleX != TGSI_SWIZZLE_X || @@ -1281,17 +1256,17 @@ tgsi_dump( switch( parse.FullToken.Token.Type ) { case TGSI_TOKEN_TYPE_DECLARATION: - dump_declaration_short( + tgsi_dump_declaration( &parse.FullToken.FullDeclaration ); break; case TGSI_TOKEN_TYPE_IMMEDIATE: - dump_immediate_short( + tgsi_dump_immediate( &parse.FullToken.FullImmediate ); break; case TGSI_TOKEN_TYPE_INSTRUCTION: - dump_instruction_short( + tgsi_dump_instruction( &parse.FullToken.FullInstruction, instno ); instno++; diff --git a/src/gallium/auxiliary/tgsi/util/tgsi_dump.h b/src/gallium/auxiliary/tgsi/util/tgsi_dump.h index beb0155d56..ca83bdef20 100644 --- a/src/gallium/auxiliary/tgsi/util/tgsi_dump.h +++ b/src/gallium/auxiliary/tgsi/util/tgsi_dump.h @@ -14,6 +14,24 @@ tgsi_dump( const struct tgsi_token *tokens, unsigned flags ); +struct tgsi_full_immediate; +struct tgsi_full_instruction; +struct tgsi_full_declaration; + +void +tgsi_dump_immediate( + const struct tgsi_full_immediate *imm ); + +void +tgsi_dump_instruction( + const struct tgsi_full_instruction *inst, + unsigned instno ); + +void +tgsi_dump_declaration( + const struct tgsi_full_declaration *decl ); + + #if defined __cplusplus } #endif diff --git a/src/gallium/auxiliary/tgsi/util/tgsi_parse.c b/src/gallium/auxiliary/tgsi/util/tgsi_parse.c index 5c0b0bfd61..d16f0cdcad 100644 --- a/src/gallium/auxiliary/tgsi/util/tgsi_parse.c +++ b/src/gallium/auxiliary/tgsi/util/tgsi_parse.c @@ -118,22 +118,7 @@ tgsi_parse_token( *decl = tgsi_default_full_declaration(); decl->Declaration = *(struct tgsi_declaration *) &token; - switch( decl->Declaration.Type ) { - case TGSI_DECLARE_RANGE: - next_token( ctx, &decl->u.DeclarationRange ); - break; - - case TGSI_DECLARE_MASK: - next_token( ctx, &decl->u.DeclarationMask ); - break; - - default: - assert (0); - } - - if( decl->Declaration.Interpolate ) { - next_token( ctx, &decl->Interpolation ); - } + next_token( ctx, &decl->DeclarationRange ); if( decl->Declaration.Semantic ) { next_token( ctx, &decl->Semantic ); diff --git a/src/gallium/auxiliary/tgsi/util/tgsi_parse.h b/src/gallium/auxiliary/tgsi/util/tgsi_parse.h index 4102101093..054350712d 100644 --- a/src/gallium/auxiliary/tgsi/util/tgsi_parse.h +++ b/src/gallium/auxiliary/tgsi/util/tgsi_parse.h @@ -65,13 +65,8 @@ struct tgsi_full_src_register struct tgsi_full_declaration { struct tgsi_declaration Declaration; - union - { - struct tgsi_declaration_range DeclarationRange; - struct tgsi_declaration_mask DeclarationMask; - } u; - struct tgsi_declaration_interpolation Interpolation; - struct tgsi_declaration_semantic Semantic; + struct tgsi_declaration_range DeclarationRange; + struct tgsi_declaration_semantic Semantic; }; struct tgsi_full_immediate diff --git a/src/gallium/auxiliary/tgsi/util/tgsi_scan.c b/src/gallium/auxiliary/tgsi/util/tgsi_scan.c index 65650ed22a..240aaaf362 100644 --- a/src/gallium/auxiliary/tgsi/util/tgsi_scan.c +++ b/src/gallium/auxiliary/tgsi/util/tgsi_scan.c @@ -93,8 +93,8 @@ tgsi_scan_shader(const struct tgsi_token *tokens, = &parse.FullToken.FullDeclaration; uint file = fulldecl->Declaration.File; uint i; - for (i = fulldecl->u.DeclarationRange.First; - i <= fulldecl->u.DeclarationRange.Last; + for (i = fulldecl->DeclarationRange.First; + i <= fulldecl->DeclarationRange.Last; i++) { /* only first 32 regs will appear in this bitfield */ @@ -141,3 +141,86 @@ tgsi_scan_shader(const struct tgsi_token *tokens, tgsi_parse_free (&parse); } + + + +/** + * Check if the given shader is a "passthrough" shader consisting of only + * MOV instructions of the form: MOV OUT[n], IN[n] + * + */ +boolean +tgsi_is_passthrough_shader(const struct tgsi_token *tokens) +{ + struct tgsi_parse_context parse; + + /** + ** Setup to begin parsing input shader + **/ + if (tgsi_parse_init(&parse, tokens) != TGSI_PARSE_OK) { + debug_printf("tgsi_parse_init() failed in tgsi_is_passthrough_shader()!\n"); + return FALSE; + } + + /** + ** Loop over incoming program tokens/instructions + */ + while (!tgsi_parse_end_of_tokens(&parse)) { + + tgsi_parse_token(&parse); + + switch (parse.FullToken.Token.Type) { + case TGSI_TOKEN_TYPE_INSTRUCTION: + { + struct tgsi_full_instruction *fullinst = + &parse.FullToken.FullInstruction; + const struct tgsi_full_src_register *src = + &fullinst->FullSrcRegisters[0]; + const struct tgsi_full_dst_register *dst = + &fullinst->FullDstRegisters[0]; + + /* Do a whole bunch of checks for a simple move */ + if (fullinst->Instruction.Opcode != TGSI_OPCODE_MOV || + src->SrcRegister.File != TGSI_FILE_INPUT || + dst->DstRegister.File != TGSI_FILE_OUTPUT || + src->SrcRegister.Index != dst->DstRegister.Index || + + src->SrcRegister.Negate || + src->SrcRegisterExtMod.Negate || + src->SrcRegisterExtMod.Absolute || + src->SrcRegisterExtMod.Scale2X || + src->SrcRegisterExtMod.Bias || + src->SrcRegisterExtMod.Complement || + + src->SrcRegister.SwizzleX != TGSI_SWIZZLE_X || + src->SrcRegister.SwizzleY != TGSI_SWIZZLE_Y || + src->SrcRegister.SwizzleZ != TGSI_SWIZZLE_Z || + src->SrcRegister.SwizzleW != TGSI_SWIZZLE_W || + + src->SrcRegisterExtSwz.ExtSwizzleX != TGSI_EXTSWIZZLE_X || + src->SrcRegisterExtSwz.ExtSwizzleY != TGSI_EXTSWIZZLE_Y || + src->SrcRegisterExtSwz.ExtSwizzleZ != TGSI_EXTSWIZZLE_Z || + src->SrcRegisterExtSwz.ExtSwizzleW != TGSI_EXTSWIZZLE_W || + + dst->DstRegister.WriteMask != TGSI_WRITEMASK_XYZW) + { + tgsi_parse_free(&parse); + return FALSE; + } + } + break; + + case TGSI_TOKEN_TYPE_DECLARATION: + /* fall-through */ + case TGSI_TOKEN_TYPE_IMMEDIATE: + /* fall-through */ + default: + ; /* no-op */ + } + } + + tgsi_parse_free(&parse); + + /* if we get here, it's a pass-through shader */ + return TRUE; +} diff --git a/src/gallium/auxiliary/tgsi/util/tgsi_scan.h b/src/gallium/auxiliary/tgsi/util/tgsi_scan.h index 0530bc6b51..5cb6efb343 100644 --- a/src/gallium/auxiliary/tgsi/util/tgsi_scan.h +++ b/src/gallium/auxiliary/tgsi/util/tgsi_scan.h @@ -67,4 +67,8 @@ tgsi_scan_shader(const struct tgsi_token *tokens, struct tgsi_shader_info *info); +extern boolean +tgsi_is_passthrough_shader(const struct tgsi_token *tokens); + + #endif /* TGSI_SCAN_H */ diff --git a/src/gallium/auxiliary/tgsi/util/tgsi_util.c b/src/gallium/auxiliary/tgsi/util/tgsi_util.c index 4cdd89182a..56a50d3b21 100644 --- a/src/gallium/auxiliary/tgsi/util/tgsi_util.c +++ b/src/gallium/auxiliary/tgsi/util/tgsi_util.c @@ -8,7 +8,7 @@ union pointer_hack { void *pointer; - unsigned long long uint64; + uint64_t uint64; }; void * diff --git a/src/gallium/auxiliary/translate/translate.c b/src/gallium/auxiliary/translate/translate.c index b04bc6eefd..b93fbf9033 100644 --- a/src/gallium/auxiliary/translate/translate.c +++ b/src/gallium/auxiliary/translate/translate.c @@ -30,6 +30,7 @@ * Keith Whitwell <keith@tungstengraphics.com> */ +#include "pipe/p_config.h" #include "pipe/p_util.h" #include "pipe/p_state.h" #include "translate.h" @@ -38,7 +39,7 @@ struct translate *translate_create( const struct translate_key *key ) { struct translate *translate = NULL; -#if defined(__i386__) || defined(__386__) || defined(i386) +#if defined(PIPE_ARCH_X86) translate = translate_sse2_create( key ); if (translate) return translate; diff --git a/src/gallium/auxiliary/translate/translate.h b/src/gallium/auxiliary/translate/translate.h index b8210af50c..c3b754a902 100644 --- a/src/gallium/auxiliary/translate/translate.h +++ b/src/gallium/auxiliary/translate/translate.h @@ -71,15 +71,15 @@ struct translate { const void *ptr, unsigned stride ); - void (*run_elts)( struct translate *, - const unsigned *elts, - unsigned count, - void *output_buffer); - - void (*run)( struct translate *, - unsigned start, - unsigned count, - void *output_buffer); + void (PIPE_CDECL *run_elts)( struct translate *, + const unsigned *elts, + unsigned count, + void *output_buffer); + + void (PIPE_CDECL *run)( struct translate *, + unsigned start, + unsigned count, + void *output_buffer); }; diff --git a/src/gallium/auxiliary/translate/translate_generic.c b/src/gallium/auxiliary/translate/translate_generic.c index 402780ee53..3fec89b36e 100644 --- a/src/gallium/auxiliary/translate/translate_generic.c +++ b/src/gallium/auxiliary/translate/translate_generic.c @@ -255,140 +255,140 @@ static fetch_func get_fetch_func( enum pipe_format format ) { switch (format) { case PIPE_FORMAT_R64_FLOAT: - return fetch_R64_FLOAT; + return &fetch_R64_FLOAT; case PIPE_FORMAT_R64G64_FLOAT: - return fetch_R64G64_FLOAT; + return &fetch_R64G64_FLOAT; case PIPE_FORMAT_R64G64B64_FLOAT: - return fetch_R64G64B64_FLOAT; + return &fetch_R64G64B64_FLOAT; case PIPE_FORMAT_R64G64B64A64_FLOAT: - return fetch_R64G64B64A64_FLOAT; + return &fetch_R64G64B64A64_FLOAT; case PIPE_FORMAT_R32_FLOAT: - return fetch_R32_FLOAT; + return &fetch_R32_FLOAT; case PIPE_FORMAT_R32G32_FLOAT: - return fetch_R32G32_FLOAT; + return &fetch_R32G32_FLOAT; case PIPE_FORMAT_R32G32B32_FLOAT: - return fetch_R32G32B32_FLOAT; + return &fetch_R32G32B32_FLOAT; case PIPE_FORMAT_R32G32B32A32_FLOAT: - return fetch_R32G32B32A32_FLOAT; + return &fetch_R32G32B32A32_FLOAT; case PIPE_FORMAT_R32_UNORM: - return fetch_R32_UNORM; + return &fetch_R32_UNORM; case PIPE_FORMAT_R32G32_UNORM: - return fetch_R32G32_UNORM; + return &fetch_R32G32_UNORM; case PIPE_FORMAT_R32G32B32_UNORM: - return fetch_R32G32B32_UNORM; + return &fetch_R32G32B32_UNORM; case PIPE_FORMAT_R32G32B32A32_UNORM: - return fetch_R32G32B32A32_UNORM; + return &fetch_R32G32B32A32_UNORM; case PIPE_FORMAT_R32_USCALED: - return fetch_R32_USCALED; + return &fetch_R32_USCALED; case PIPE_FORMAT_R32G32_USCALED: - return fetch_R32G32_USCALED; + return &fetch_R32G32_USCALED; case PIPE_FORMAT_R32G32B32_USCALED: - return fetch_R32G32B32_USCALED; + return &fetch_R32G32B32_USCALED; case PIPE_FORMAT_R32G32B32A32_USCALED: - return fetch_R32G32B32A32_USCALED; + return &fetch_R32G32B32A32_USCALED; case PIPE_FORMAT_R32_SNORM: - return fetch_R32_SNORM; + return &fetch_R32_SNORM; case PIPE_FORMAT_R32G32_SNORM: - return fetch_R32G32_SNORM; + return &fetch_R32G32_SNORM; case PIPE_FORMAT_R32G32B32_SNORM: - return fetch_R32G32B32_SNORM; + return &fetch_R32G32B32_SNORM; case PIPE_FORMAT_R32G32B32A32_SNORM: - return fetch_R32G32B32A32_SNORM; + return &fetch_R32G32B32A32_SNORM; case PIPE_FORMAT_R32_SSCALED: - return fetch_R32_SSCALED; + return &fetch_R32_SSCALED; case PIPE_FORMAT_R32G32_SSCALED: - return fetch_R32G32_SSCALED; + return &fetch_R32G32_SSCALED; case PIPE_FORMAT_R32G32B32_SSCALED: - return fetch_R32G32B32_SSCALED; + return &fetch_R32G32B32_SSCALED; case PIPE_FORMAT_R32G32B32A32_SSCALED: - return fetch_R32G32B32A32_SSCALED; + return &fetch_R32G32B32A32_SSCALED; case PIPE_FORMAT_R16_UNORM: - return fetch_R16_UNORM; + return &fetch_R16_UNORM; case PIPE_FORMAT_R16G16_UNORM: - return fetch_R16G16_UNORM; + return &fetch_R16G16_UNORM; case PIPE_FORMAT_R16G16B16_UNORM: - return fetch_R16G16B16_UNORM; + return &fetch_R16G16B16_UNORM; case PIPE_FORMAT_R16G16B16A16_UNORM: - return fetch_R16G16B16A16_UNORM; + return &fetch_R16G16B16A16_UNORM; case PIPE_FORMAT_R16_USCALED: - return fetch_R16_USCALED; + return &fetch_R16_USCALED; case PIPE_FORMAT_R16G16_USCALED: - return fetch_R16G16_USCALED; + return &fetch_R16G16_USCALED; case PIPE_FORMAT_R16G16B16_USCALED: - return fetch_R16G16B16_USCALED; + return &fetch_R16G16B16_USCALED; case PIPE_FORMAT_R16G16B16A16_USCALED: - return fetch_R16G16B16A16_USCALED; + return &fetch_R16G16B16A16_USCALED; case PIPE_FORMAT_R16_SNORM: - return fetch_R16_SNORM; + return &fetch_R16_SNORM; case PIPE_FORMAT_R16G16_SNORM: - return fetch_R16G16_SNORM; + return &fetch_R16G16_SNORM; case PIPE_FORMAT_R16G16B16_SNORM: - return fetch_R16G16B16_SNORM; + return &fetch_R16G16B16_SNORM; case PIPE_FORMAT_R16G16B16A16_SNORM: - return fetch_R16G16B16A16_SNORM; + return &fetch_R16G16B16A16_SNORM; case PIPE_FORMAT_R16_SSCALED: - return fetch_R16_SSCALED; + return &fetch_R16_SSCALED; case PIPE_FORMAT_R16G16_SSCALED: - return fetch_R16G16_SSCALED; + return &fetch_R16G16_SSCALED; case PIPE_FORMAT_R16G16B16_SSCALED: - return fetch_R16G16B16_SSCALED; + return &fetch_R16G16B16_SSCALED; case PIPE_FORMAT_R16G16B16A16_SSCALED: - return fetch_R16G16B16A16_SSCALED; + return &fetch_R16G16B16A16_SSCALED; case PIPE_FORMAT_R8_UNORM: - return fetch_R8_UNORM; + return &fetch_R8_UNORM; case PIPE_FORMAT_R8G8_UNORM: - return fetch_R8G8_UNORM; + return &fetch_R8G8_UNORM; case PIPE_FORMAT_R8G8B8_UNORM: - return fetch_R8G8B8_UNORM; + return &fetch_R8G8B8_UNORM; case PIPE_FORMAT_R8G8B8A8_UNORM: - return fetch_R8G8B8A8_UNORM; + return &fetch_R8G8B8A8_UNORM; case PIPE_FORMAT_R8_USCALED: - return fetch_R8_USCALED; + return &fetch_R8_USCALED; case PIPE_FORMAT_R8G8_USCALED: - return fetch_R8G8_USCALED; + return &fetch_R8G8_USCALED; case PIPE_FORMAT_R8G8B8_USCALED: - return fetch_R8G8B8_USCALED; + return &fetch_R8G8B8_USCALED; case PIPE_FORMAT_R8G8B8A8_USCALED: - return fetch_R8G8B8A8_USCALED; + return &fetch_R8G8B8A8_USCALED; case PIPE_FORMAT_R8_SNORM: - return fetch_R8_SNORM; + return &fetch_R8_SNORM; case PIPE_FORMAT_R8G8_SNORM: - return fetch_R8G8_SNORM; + return &fetch_R8G8_SNORM; case PIPE_FORMAT_R8G8B8_SNORM: - return fetch_R8G8B8_SNORM; + return &fetch_R8G8B8_SNORM; case PIPE_FORMAT_R8G8B8A8_SNORM: - return fetch_R8G8B8A8_SNORM; + return &fetch_R8G8B8A8_SNORM; case PIPE_FORMAT_R8_SSCALED: - return fetch_R8_SSCALED; + return &fetch_R8_SSCALED; case PIPE_FORMAT_R8G8_SSCALED: - return fetch_R8G8_SSCALED; + return &fetch_R8G8_SSCALED; case PIPE_FORMAT_R8G8B8_SSCALED: - return fetch_R8G8B8_SSCALED; + return &fetch_R8G8B8_SSCALED; case PIPE_FORMAT_R8G8B8A8_SSCALED: - return fetch_R8G8B8A8_SSCALED; + return &fetch_R8G8B8A8_SSCALED; case PIPE_FORMAT_A8R8G8B8_UNORM: - return fetch_A8R8G8B8_UNORM; + return &fetch_A8R8G8B8_UNORM; case PIPE_FORMAT_B8G8R8A8_UNORM: - return fetch_B8G8R8A8_UNORM; + return &fetch_B8G8R8A8_UNORM; default: assert(0); - return fetch_NULL; + return &fetch_NULL; } } @@ -399,140 +399,140 @@ static emit_func get_emit_func( enum pipe_format format ) { switch (format) { case PIPE_FORMAT_R64_FLOAT: - return emit_R64_FLOAT; + return &emit_R64_FLOAT; case PIPE_FORMAT_R64G64_FLOAT: - return emit_R64G64_FLOAT; + return &emit_R64G64_FLOAT; case PIPE_FORMAT_R64G64B64_FLOAT: - return emit_R64G64B64_FLOAT; + return &emit_R64G64B64_FLOAT; case PIPE_FORMAT_R64G64B64A64_FLOAT: - return emit_R64G64B64A64_FLOAT; + return &emit_R64G64B64A64_FLOAT; case PIPE_FORMAT_R32_FLOAT: - return emit_R32_FLOAT; + return &emit_R32_FLOAT; case PIPE_FORMAT_R32G32_FLOAT: - return emit_R32G32_FLOAT; + return &emit_R32G32_FLOAT; case PIPE_FORMAT_R32G32B32_FLOAT: - return emit_R32G32B32_FLOAT; + return &emit_R32G32B32_FLOAT; case PIPE_FORMAT_R32G32B32A32_FLOAT: - return emit_R32G32B32A32_FLOAT; + return &emit_R32G32B32A32_FLOAT; case PIPE_FORMAT_R32_UNORM: - return emit_R32_UNORM; + return &emit_R32_UNORM; case PIPE_FORMAT_R32G32_UNORM: - return emit_R32G32_UNORM; + return &emit_R32G32_UNORM; case PIPE_FORMAT_R32G32B32_UNORM: - return emit_R32G32B32_UNORM; + return &emit_R32G32B32_UNORM; case PIPE_FORMAT_R32G32B32A32_UNORM: - return emit_R32G32B32A32_UNORM; + return &emit_R32G32B32A32_UNORM; case PIPE_FORMAT_R32_USCALED: - return emit_R32_USCALED; + return &emit_R32_USCALED; case PIPE_FORMAT_R32G32_USCALED: - return emit_R32G32_USCALED; + return &emit_R32G32_USCALED; case PIPE_FORMAT_R32G32B32_USCALED: - return emit_R32G32B32_USCALED; + return &emit_R32G32B32_USCALED; case PIPE_FORMAT_R32G32B32A32_USCALED: - return emit_R32G32B32A32_USCALED; + return &emit_R32G32B32A32_USCALED; case PIPE_FORMAT_R32_SNORM: - return emit_R32_SNORM; + return &emit_R32_SNORM; case PIPE_FORMAT_R32G32_SNORM: - return emit_R32G32_SNORM; + return &emit_R32G32_SNORM; case PIPE_FORMAT_R32G32B32_SNORM: - return emit_R32G32B32_SNORM; + return &emit_R32G32B32_SNORM; case PIPE_FORMAT_R32G32B32A32_SNORM: - return emit_R32G32B32A32_SNORM; + return &emit_R32G32B32A32_SNORM; case PIPE_FORMAT_R32_SSCALED: - return emit_R32_SSCALED; + return &emit_R32_SSCALED; case PIPE_FORMAT_R32G32_SSCALED: - return emit_R32G32_SSCALED; + return &emit_R32G32_SSCALED; case PIPE_FORMAT_R32G32B32_SSCALED: - return emit_R32G32B32_SSCALED; + return &emit_R32G32B32_SSCALED; case PIPE_FORMAT_R32G32B32A32_SSCALED: - return emit_R32G32B32A32_SSCALED; + return &emit_R32G32B32A32_SSCALED; case PIPE_FORMAT_R16_UNORM: - return emit_R16_UNORM; + return &emit_R16_UNORM; case PIPE_FORMAT_R16G16_UNORM: - return emit_R16G16_UNORM; + return &emit_R16G16_UNORM; case PIPE_FORMAT_R16G16B16_UNORM: - return emit_R16G16B16_UNORM; + return &emit_R16G16B16_UNORM; case PIPE_FORMAT_R16G16B16A16_UNORM: - return emit_R16G16B16A16_UNORM; + return &emit_R16G16B16A16_UNORM; case PIPE_FORMAT_R16_USCALED: - return emit_R16_USCALED; + return &emit_R16_USCALED; case PIPE_FORMAT_R16G16_USCALED: - return emit_R16G16_USCALED; + return &emit_R16G16_USCALED; case PIPE_FORMAT_R16G16B16_USCALED: - return emit_R16G16B16_USCALED; + return &emit_R16G16B16_USCALED; case PIPE_FORMAT_R16G16B16A16_USCALED: - return emit_R16G16B16A16_USCALED; + return &emit_R16G16B16A16_USCALED; case PIPE_FORMAT_R16_SNORM: - return emit_R16_SNORM; + return &emit_R16_SNORM; case PIPE_FORMAT_R16G16_SNORM: - return emit_R16G16_SNORM; + return &emit_R16G16_SNORM; case PIPE_FORMAT_R16G16B16_SNORM: - return emit_R16G16B16_SNORM; + return &emit_R16G16B16_SNORM; case PIPE_FORMAT_R16G16B16A16_SNORM: - return emit_R16G16B16A16_SNORM; + return &emit_R16G16B16A16_SNORM; case PIPE_FORMAT_R16_SSCALED: - return emit_R16_SSCALED; + return &emit_R16_SSCALED; case PIPE_FORMAT_R16G16_SSCALED: - return emit_R16G16_SSCALED; + return &emit_R16G16_SSCALED; case PIPE_FORMAT_R16G16B16_SSCALED: - return emit_R16G16B16_SSCALED; + return &emit_R16G16B16_SSCALED; case PIPE_FORMAT_R16G16B16A16_SSCALED: - return emit_R16G16B16A16_SSCALED; + return &emit_R16G16B16A16_SSCALED; case PIPE_FORMAT_R8_UNORM: - return emit_R8_UNORM; + return &emit_R8_UNORM; case PIPE_FORMAT_R8G8_UNORM: - return emit_R8G8_UNORM; + return &emit_R8G8_UNORM; case PIPE_FORMAT_R8G8B8_UNORM: - return emit_R8G8B8_UNORM; + return &emit_R8G8B8_UNORM; case PIPE_FORMAT_R8G8B8A8_UNORM: - return emit_R8G8B8A8_UNORM; + return &emit_R8G8B8A8_UNORM; case PIPE_FORMAT_R8_USCALED: - return emit_R8_USCALED; + return &emit_R8_USCALED; case PIPE_FORMAT_R8G8_USCALED: - return emit_R8G8_USCALED; + return &emit_R8G8_USCALED; case PIPE_FORMAT_R8G8B8_USCALED: - return emit_R8G8B8_USCALED; + return &emit_R8G8B8_USCALED; case PIPE_FORMAT_R8G8B8A8_USCALED: - return emit_R8G8B8A8_USCALED; + return &emit_R8G8B8A8_USCALED; case PIPE_FORMAT_R8_SNORM: - return emit_R8_SNORM; + return &emit_R8_SNORM; case PIPE_FORMAT_R8G8_SNORM: - return emit_R8G8_SNORM; + return &emit_R8G8_SNORM; case PIPE_FORMAT_R8G8B8_SNORM: - return emit_R8G8B8_SNORM; + return &emit_R8G8B8_SNORM; case PIPE_FORMAT_R8G8B8A8_SNORM: - return emit_R8G8B8A8_SNORM; + return &emit_R8G8B8A8_SNORM; case PIPE_FORMAT_R8_SSCALED: - return emit_R8_SSCALED; + return &emit_R8_SSCALED; case PIPE_FORMAT_R8G8_SSCALED: - return emit_R8G8_SSCALED; + return &emit_R8G8_SSCALED; case PIPE_FORMAT_R8G8B8_SSCALED: - return emit_R8G8B8_SSCALED; + return &emit_R8G8B8_SSCALED; case PIPE_FORMAT_R8G8B8A8_SSCALED: - return emit_R8G8B8A8_SSCALED; + return &emit_R8G8B8A8_SSCALED; case PIPE_FORMAT_A8R8G8B8_UNORM: - return emit_A8R8G8B8_UNORM; + return &emit_A8R8G8B8_UNORM; case PIPE_FORMAT_B8G8R8A8_UNORM: - return emit_B8G8R8A8_UNORM; + return &emit_B8G8R8A8_UNORM; default: assert(0); - return emit_NULL; + return &emit_NULL; } } @@ -541,10 +541,10 @@ static emit_func get_emit_func( enum pipe_format format ) /** * Fetch vertex attributes for 'count' vertices. */ -static void generic_run_elts( struct translate *translate, - const unsigned *elts, - unsigned count, - void *output_buffer ) +static void PIPE_CDECL generic_run_elts( struct translate *translate, + const unsigned *elts, + unsigned count, + void *output_buffer ) { struct translate_generic *tg = translate_generic(translate); char *vert = output_buffer; @@ -580,10 +580,10 @@ static void generic_run_elts( struct translate *translate, -static void generic_run( struct translate *translate, - unsigned start, - unsigned count, - void *output_buffer ) +static void PIPE_CDECL generic_run( struct translate *translate, + unsigned start, + unsigned count, + void *output_buffer ) { struct translate_generic *tg = translate_generic(translate); char *vert = output_buffer; diff --git a/src/gallium/auxiliary/translate/translate_sse.c b/src/gallium/auxiliary/translate/translate_sse.c index a54ac5a82f..18a212ac1c 100644 --- a/src/gallium/auxiliary/translate/translate_sse.c +++ b/src/gallium/auxiliary/translate/translate_sse.c @@ -26,6 +26,7 @@ */ +#include "pipe/p_config.h" #include "pipe/p_compiler.h" #include "pipe/p_util.h" #include "util/u_simple_list.h" @@ -33,7 +34,7 @@ #include "translate.h" -#if defined(__i386__) || defined(__386__) || defined(i386) +#if defined(PIPE_ARCH_X86) #include "rtasm/rtasm_cpu.h" #include "rtasm/rtasm_x86sse.h" @@ -45,22 +46,16 @@ #define W 3 -#ifdef WIN32 -#define RTASM __cdecl -#else -#define RTASM -#endif - -typedef void (RTASM *run_func)( struct translate *translate, - unsigned start, - unsigned count, - void *output_buffer ); - -typedef void (RTASM *run_elts_func)( struct translate *translate, - const unsigned *elts, +typedef void (PIPE_CDECL *run_func)( struct translate *translate, + unsigned start, unsigned count, void *output_buffer ); +typedef void (PIPE_CDECL *run_elts_func)( struct translate *translate, + const unsigned *elts, + unsigned count, + void *output_buffer ); + struct translate_sse { @@ -315,7 +310,7 @@ static void get_src_ptr( struct translate_sse *p, static void emit_swizzle( struct translate_sse *p, struct x86_reg dest, struct x86_reg src, - unsigned shuffle ) + unsigned char shuffle ) { sse_shufps(p->func, dest, src, shuffle); } @@ -472,13 +467,7 @@ static boolean build_vertex_emit( struct translate_sse *p, x86_lea(p->func, vertexECX, x86_make_disp(vertexECX, p->translate.key.output_stride)); /* Incr index - */ /* Emit code for each of the attributes. Currently routes - * everything through SSE registers, even when it might be more - * efficient to stick with regular old x86. No optimization or - * other tricks - enough new ground to cover here just getting - * things working. - */ - + */ if (linear) { x86_inc(p->func, idxEBX); } @@ -546,7 +535,7 @@ static void translate_sse_release( struct translate *translate ) FREE(p); } -static void translate_sse_run_elts( struct translate *translate, +static void PIPE_CDECL translate_sse_run_elts( struct translate *translate, const unsigned *elts, unsigned count, void *output_buffer ) @@ -559,7 +548,7 @@ static void translate_sse_run_elts( struct translate *translate, output_buffer ); } -static void translate_sse_run( struct translate *translate, +static void PIPE_CDECL translate_sse_run( struct translate *translate, unsigned start, unsigned count, void *output_buffer ) @@ -617,7 +606,7 @@ struct translate *translate_sse2_create( const struct translate_key *key ) #else -void translate_create_sse( const struct translate_key *key ) +struct translate *translate_sse2_create( const struct translate_key *key ) { return NULL; } diff --git a/src/gallium/auxiliary/util/Makefile b/src/gallium/auxiliary/util/Makefile index 05bc43131a..db3d810a2e 100644 --- a/src/gallium/auxiliary/util/Makefile +++ b/src/gallium/auxiliary/util/Makefile @@ -15,8 +15,7 @@ C_SOURCES = \ u_mm.c \ u_simple_shaders.c \ u_snprintf.c \ - u_time.c \ - u_mm.c + u_time.c include ../../Makefile.template diff --git a/src/gallium/auxiliary/util/p_debug.c b/src/gallium/auxiliary/util/p_debug.c index ce7fb58956..9d56f8bfab 100644 --- a/src/gallium/auxiliary/util/p_debug.c +++ b/src/gallium/auxiliary/util/p_debug.c @@ -153,7 +153,9 @@ const char * debug_get_option(const char *name, const char *dfault) { const char *result; -#ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY +#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) + /* EngMapFile creates the file if it does not exists, so it must either be + * disabled on release versions (or put in a less conspicuous place). */ #ifdef DEBUG ULONG_PTR iFile = 0; const void *pMap = NULL; @@ -161,9 +163,6 @@ debug_get_option(const char *name, const char *dfault) static char output[1024]; result = dfault; - /* XXX: this creates the file if it does not exists, so it must either be - * disabled on release versions, or put in a less conspicuous place. - */ pMap = EngMapFile(L"\\??\\c:\\gallium.cfg", 0, &iFile); if(pMap) { sol = (const char *)pMap; @@ -187,13 +186,15 @@ debug_get_option(const char *name, const char *dfault) #else result = dfault; #endif +#elif defined(PIPE_SUBSYSTEM_WINDOWS_CE) + /* TODO: implement */ + result = dfault; #else - result = getenv(name); if(!result) result = dfault; #endif - + debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? result : "(null)"); return result; @@ -229,8 +230,34 @@ debug_get_bool_option(const char *name, boolean dfault) long debug_get_num_option(const char *name, long dfault) { - /* FIXME */ - return dfault; + long result; + const char *str; + + str = debug_get_option(name, NULL); + if(!str) + result = dfault; + else { + long sign; + char c; + c = *str++; + if(c == '-') { + sign = -1; + c = *str++; + } + else { + sign = 1; + } + result = 0; + while('0' <= c && c <= '9') { + result = result*10 + (c - '0'); + c = *str++; + } + result *= sign; + } + + debug_printf("%s: %s = %li\n", __FUNCTION__, name, result); + + return result; } @@ -339,10 +366,12 @@ static const struct debug_named_value pipe_format_names[] = { DEBUG_NAMED_VALUE(PIPE_FORMAT_A1R5G5B5_UNORM), DEBUG_NAMED_VALUE(PIPE_FORMAT_A4R4G4B4_UNORM), DEBUG_NAMED_VALUE(PIPE_FORMAT_R5G6B5_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_A2B10G10R10_UNORM), DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_UNORM), DEBUG_NAMED_VALUE(PIPE_FORMAT_A8_UNORM), DEBUG_NAMED_VALUE(PIPE_FORMAT_I8_UNORM), DEBUG_NAMED_VALUE(PIPE_FORMAT_A8L8_UNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_L16_UNORM), DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR), DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR_REV), DEBUG_NAMED_VALUE(PIPE_FORMAT_Z16_UNORM), @@ -408,6 +437,9 @@ static const struct debug_named_value pipe_format_names[] = { DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SNORM), DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SNORM), DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_B6G5R5_SNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_A8B8G8R8_SNORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_X8B8G8R8_SNORM), DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SSCALED), DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SSCALED), DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SSCALED), @@ -418,6 +450,8 @@ static const struct debug_named_value pipe_format_names[] = { DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SRGB), DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SRGB), DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SRGB), + DEBUG_NAMED_VALUE(PIPE_FORMAT_X8UB8UG8SR8S_NORM), + DEBUG_NAMED_VALUE(PIPE_FORMAT_B6UG5SR5S_NORM), DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGB), DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGBA), DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT3_RGBA), diff --git a/src/gallium/auxiliary/util/p_debug_mem.c b/src/gallium/auxiliary/util/p_debug_mem.c index 78497c5f6a..ed18c6540e 100644 --- a/src/gallium/auxiliary/util/p_debug_mem.c +++ b/src/gallium/auxiliary/util/p_debug_mem.c @@ -75,6 +75,12 @@ struct debug_memory_header unsigned magic; }; +struct debug_memory_footer +{ + unsigned magic; +}; + + static struct list_head list = { &list, &list }; static unsigned long last_no = 0; @@ -98,14 +104,24 @@ data_from_header(struct debug_memory_header *hdr) return NULL; } +static INLINE struct debug_memory_footer * +footer_from_header(struct debug_memory_header *hdr) +{ + if(hdr) + return (struct debug_memory_footer *)((char *)hdr + sizeof(struct debug_memory_header) + hdr->size); + else + return NULL; +} + void * debug_malloc(const char *file, unsigned line, const char *function, size_t size) { struct debug_memory_header *hdr; + struct debug_memory_footer *ftr; - hdr = real_malloc(sizeof(*hdr) + size); + hdr = real_malloc(sizeof(*hdr) + size + sizeof(*ftr)); if(!hdr) return NULL; @@ -116,6 +132,9 @@ debug_malloc(const char *file, unsigned line, const char *function, hdr->size = size; hdr->magic = DEBUG_MEMORY_MAGIC; + ftr = footer_from_header(hdr); + ftr->magic = DEBUG_MEMORY_MAGIC; + LIST_ADDTAIL(&hdr->head, &list); return data_from_header(hdr); @@ -126,6 +145,7 @@ debug_free(const char *file, unsigned line, const char *function, void *ptr) { struct debug_memory_header *hdr; + struct debug_memory_footer *ftr; if(!ptr) return; @@ -139,8 +159,17 @@ debug_free(const char *file, unsigned line, const char *function, return; } + ftr = footer_from_header(hdr); + if(ftr->magic != DEBUG_MEMORY_MAGIC) { + debug_printf("%s:%u:%s: buffer overflow %p\n", + hdr->file, hdr->line, hdr->function, + ptr); + debug_assert(0); + } + LIST_DEL(&hdr->head); hdr->magic = 0; + ftr->magic = 0; real_free(hdr); } @@ -160,6 +189,7 @@ debug_realloc(const char *file, unsigned line, const char *function, void *old_ptr, size_t old_size, size_t new_size ) { struct debug_memory_header *old_hdr, *new_hdr; + struct debug_memory_footer *old_ftr, *new_ftr; void *new_ptr; if(!old_ptr) @@ -179,8 +209,16 @@ debug_realloc(const char *file, unsigned line, const char *function, return NULL; } + old_ftr = footer_from_header(old_hdr); + if(old_ftr->magic != DEBUG_MEMORY_MAGIC) { + debug_printf("%s:%u:%s: buffer overflow %p\n", + old_hdr->file, old_hdr->line, old_hdr->function, + old_ptr); + debug_assert(0); + } + /* alloc new */ - new_hdr = real_malloc(sizeof(*new_hdr) + new_size); + new_hdr = real_malloc(sizeof(*new_hdr) + new_size + sizeof(*new_ftr)); if(!new_hdr) return NULL; new_hdr->no = old_hdr->no; @@ -189,14 +227,19 @@ debug_realloc(const char *file, unsigned line, const char *function, new_hdr->function = old_hdr->function; new_hdr->size = new_size; new_hdr->magic = DEBUG_MEMORY_MAGIC; - LIST_REPLACE(&old_hdr->head, &new_hdr->head); + new_ftr = footer_from_header(new_hdr); + new_ftr->magic = DEBUG_MEMORY_MAGIC; + + LIST_REPLACE(&old_hdr->head, &new_hdr->head); + /* copy data */ new_ptr = data_from_header(new_hdr); memcpy( new_ptr, old_ptr, old_size < new_size ? old_size : new_size ); /* free old */ old_hdr->magic = 0; + old_ftr->magic = 0; real_free(old_hdr); return new_ptr; @@ -220,8 +263,8 @@ debug_memory_end(unsigned long start_no) void *ptr; hdr = LIST_ENTRY(struct debug_memory_header, entry, head); ptr = data_from_header(hdr); - if(start_no <= hdr->no && hdr->no < last_no || - last_no < start_no && (hdr->no < last_no || start_no <= hdr->no)) { + if((start_no <= hdr->no && hdr->no < last_no) || + (last_no < start_no && (hdr->no < last_no || start_no <= hdr->no))) { debug_printf("%s:%u:%s: %u bytes at %p not freed\n", hdr->file, hdr->line, hdr->function, hdr->size, ptr); diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c index 999a3e5099..7b9415d49a 100644 --- a/src/gallium/auxiliary/util/u_blit.c +++ b/src/gallium/auxiliary/util/u_blit.c @@ -281,7 +281,7 @@ util_blit_pixels(struct blit_state *ctx, texTemp.height[0] = srcH; texTemp.depth[0] = 1; texTemp.compressed = 0; - texTemp.cpp = pf_get_bits(src->format) / 8; + texTemp.cpp = pf_get_size(src->format); tex = screen->texture_create(screen, &texTemp); if (!tex) diff --git a/src/gallium/auxiliary/util/u_pack_color.h b/src/gallium/auxiliary/util/u_pack_color.h index 655e2c8259..06abb34d5a 100644 --- a/src/gallium/auxiliary/util/u_pack_color.h +++ b/src/gallium/auxiliary/util/u_pack_color.h @@ -255,20 +255,28 @@ util_pack_color(const float rgba[4], enum pipe_format format, void *dest) static INLINE uint util_pack_z(enum pipe_format format, double z) { + if (z == 0.0) + return 0; + switch (format) { case PIPE_FORMAT_Z16_UNORM: + if (z == 1.0) + return 0xffff; return (uint) (z * 0xffff); case PIPE_FORMAT_Z32_UNORM: /* special-case to avoid overflow */ if (z == 1.0) return 0xffffffff; - else - return (uint) (z * 0xffffffff); + return (uint) (z * 0xffffffff); case PIPE_FORMAT_S8Z24_UNORM: case PIPE_FORMAT_X8Z24_UNORM: + if (z == 1.0) + return 0xffffff; return (uint) (z * 0xffffff); case PIPE_FORMAT_Z24S8_UNORM: case PIPE_FORMAT_Z24X8_UNORM: + if (z == 1.0) + return 0xffffff00; return ((uint) (z * 0xffffff)) << 8; default: debug_print_format("gallium: unhandled format in util_pack_z()", format); diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c index 5f8d12191d..505d93d727 100644 --- a/src/gallium/auxiliary/util/u_simple_shaders.c +++ b/src/gallium/auxiliary/util/u_simple_shaders.c @@ -92,8 +92,8 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe, decl.Semantic.SemanticName = semantic_names[i]; decl.Semantic.SemanticIndex = semantic_indexes[i]; - decl.u.DeclarationRange.First = - decl.u.DeclarationRange.Last = i; + decl.DeclarationRange.First = + decl.DeclarationRange.Last = i; ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, @@ -107,8 +107,8 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe, decl.Declaration.Semantic = 1; decl.Semantic.SemanticName = semantic_names[i]; decl.Semantic.SemanticIndex = semantic_indexes[i]; - decl.u.DeclarationRange.First = - decl.u.DeclarationRange.Last = i; + decl.DeclarationRange.First = + decl.DeclarationRange.Last = i; ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, @@ -190,14 +190,13 @@ util_make_fragment_tex_shader(struct pipe_context *pipe, /* declare TEX[0] input */ decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_INPUT; + /* XXX this could be linear... */ + decl.Declaration.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE; decl.Declaration.Semantic = 1; decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC; decl.Semantic.SemanticIndex = 0; - /* XXX this could be linear... */ - decl.Declaration.Interpolate = 1; - decl.Interpolation.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE; - decl.u.DeclarationRange.First = - decl.u.DeclarationRange.Last = 0; + decl.DeclarationRange.First = + decl.DeclarationRange.Last = 0; ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, @@ -209,8 +208,8 @@ util_make_fragment_tex_shader(struct pipe_context *pipe, decl.Declaration.Semantic = 1; decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR; decl.Semantic.SemanticIndex = 0; - decl.u.DeclarationRange.First = - decl.u.DeclarationRange.Last = 0; + decl.DeclarationRange.First = + decl.DeclarationRange.Last = 0; ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, @@ -219,8 +218,8 @@ util_make_fragment_tex_shader(struct pipe_context *pipe, /* declare sampler */ decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_SAMPLER; - decl.u.DeclarationRange.First = - decl.u.DeclarationRange.Last = 0; + decl.DeclarationRange.First = + decl.DeclarationRange.Last = 0; ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, @@ -303,8 +302,8 @@ util_make_fragment_passthrough_shader(struct pipe_context *pipe, decl.Declaration.Semantic = 1; decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR; decl.Semantic.SemanticIndex = 0; - decl.u.DeclarationRange.First = - decl.u.DeclarationRange.Last = 0; + decl.DeclarationRange.First = + decl.DeclarationRange.Last = 0; ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, @@ -316,8 +315,8 @@ util_make_fragment_passthrough_shader(struct pipe_context *pipe, decl.Declaration.Semantic = 1; decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR; decl.Semantic.SemanticIndex = 0; - decl.u.DeclarationRange.First = - decl.u.DeclarationRange.Last = 0; + decl.DeclarationRange.First = + decl.DeclarationRange.Last = 0; ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, diff --git a/src/gallium/auxiliary/util/u_time.c b/src/gallium/auxiliary/util/u_time.c index 9b97050d51..49dce75289 100644 --- a/src/gallium/auxiliary/util/u_time.c +++ b/src/gallium/auxiliary/util/u_time.c @@ -33,26 +33,44 @@ */ -#include "util/u_time.h" +#include "pipe/p_config.h" #if defined(PIPE_OS_LINUX) #include <sys/time.h> #elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) #include <windows.h> #include <winddi.h> -#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) +#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT) +#include <windows.h> +extern VOID KeQuerySystemTime(PLARGE_INTEGER); +#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE) #include <windows.h> #else #error Unsupported OS #endif +#include "util/u_time.h" + -#if defined(PIPE_OS_WINDOWS) -static LONGLONG frequency = 0; -#if !defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) -#define EngQueryPerformanceFrequency(p) QueryPerformanceFrequency((LARGE_INTEGER*)(p)) -#define EngQueryPerformanceCounter(p) QueryPerformanceCounter((LARGE_INTEGER*)(p)) +#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE) + +static int64_t frequency = 0; + +static INLINE void +util_time_get_frequency(void) +{ + if(!frequency) { +#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) + LONGLONG temp; + EngQueryPerformanceFrequency(&temp); + frequency = temp; +#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE) + LARGE_INTEGER temp; + QueryPerformanceFrequency(&temp); + frequency = temp.QuadPart; #endif + } +} #endif @@ -61,8 +79,20 @@ util_time_get(struct util_time *t) { #if defined(PIPE_OS_LINUX) gettimeofday(&t->tv, NULL); -#elif defined(PIPE_OS_WINDOWS) - EngQueryPerformanceCounter(&t->counter); +#elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) + LONGLONG temp; + EngQueryPerformanceCounter(&temp); + t->counter = temp; +#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT) + /* Updated every 10 miliseconds, measured in units of 100 nanoseconds. + * http://msdn.microsoft.com/en-us/library/ms801642.aspx */ + LARGE_INTEGER temp; + KeQuerySystemTime(&temp); + t->counter = temp.QuadPart; +#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE) + LARGE_INTEGER temp; + QueryPerformanceCounter(&temp); + t->counter = temp.QuadPart; #endif } @@ -75,10 +105,17 @@ util_time_add(const struct util_time *t1, #if defined(PIPE_OS_LINUX) t2->tv.tv_sec = t1->tv.tv_sec + usecs / 1000000; t2->tv.tv_usec = t1->tv.tv_usec + usecs % 1000000; -#elif defined(PIPE_OS_WINDOWS) - if(!frequency) - EngQueryPerformanceFrequency(&frequency); - t2->counter = t1->counter + (usecs * frequency + 999999LL)/1000000LL; +#elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE) + util_time_get_frequency(); + t2->counter = t1->counter + (usecs * frequency + INT64_C(999999))/INT64_C(1000000); +#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT) + /* 1 tick = 100 nano seconds. */ + t2->counter = t1->counter + usecs * 10; +#elif + LARGE_INTEGER temp; + LONGLONG freq; + freq = temp.QuadPart; + t2->counter = t1->counter + (usecs * freq)/1000000L; #endif } @@ -90,10 +127,11 @@ util_time_diff(const struct util_time *t1, #if defined(PIPE_OS_LINUX) return (t2->tv.tv_usec - t1->tv.tv_usec) + (t2->tv.tv_sec - t1->tv.tv_sec)*1000000; -#elif defined(PIPE_OS_WINDOWS) - if(!frequency) - EngQueryPerformanceFrequency(&frequency); - return (t2->counter - t1->counter)*1000000LL/frequency; +#elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE) + util_time_get_frequency(); + return (t2->counter - t1->counter)*INT64_C(1000000)/frequency; +#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT) + return (t2->counter - t1->counter)/10; #endif } @@ -142,7 +180,7 @@ util_time_timeout(const struct util_time *start, } -#if defined(PIPE_OS_WINDOWS) +#if defined(PIPE_SUBSYSYEM_WINDOWS_DISPLAY) void util_time_sleep(unsigned usecs) { LONGLONG start, curr, end; diff --git a/src/gallium/auxiliary/util/u_time.h b/src/gallium/auxiliary/util/u_time.h index 48ec7a4a96..f9963ce0e2 100644 --- a/src/gallium/auxiliary/util/u_time.h +++ b/src/gallium/auxiliary/util/u_time.h @@ -61,7 +61,7 @@ struct util_time #if defined(PIPE_OS_LINUX) struct timeval tv; #else - long long counter; + int64_t counter; #endif }; diff --git a/src/gallium/drivers/cell/spu/spu_exec.c b/src/gallium/drivers/cell/spu/spu_exec.c index 48edc62f49..3a80df427d 100644 --- a/src/gallium/drivers/cell/spu/spu_exec.c +++ b/src/gallium/drivers/cell/spu/spu_exec.c @@ -830,13 +830,11 @@ exec_declaration(struct spu_exec_machine *mach, unsigned first, last, mask; interpolation_func interp; - assert( decl->Declaration.Declare == TGSI_DECLARE_RANGE ); - - first = decl->u.DeclarationRange.First; - last = decl->u.DeclarationRange.Last; + first = decl->DeclarationRange.First; + last = decl->DeclarationRange.Last; mask = decl->Declaration.UsageMask; - switch( decl->Interpolation.Interpolate ) { + switch( decl->Declaration.Interpolate ) { case TGSI_INTERPOLATE_CONSTANT: interp = constant_interpolation; break; @@ -898,7 +896,7 @@ exec_instruction( break; case TGSI_OPCODE_MOV: - /* TGSI_OPCODE_SWZ */ + case TGSI_OPCODE_SWZ: FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { FETCH( &r[0], 0, chan_index ); STORE( &r[0], 0, chan_index ); diff --git a/src/gallium/drivers/i915simple/i915_batch.h b/src/gallium/drivers/i915simple/i915_batch.h index 4ea06ce02b..45bf4f4028 100644 --- a/src/gallium/drivers/i915simple/i915_batch.h +++ b/src/gallium/drivers/i915simple/i915_batch.h @@ -29,26 +29,88 @@ #define I915_BATCH_H #include "i915_winsys.h" -#include "i915_debug.h" -#define BATCH_LOCALS +struct i915_batchbuffer +{ + struct pipe_buffer *buffer; + struct i915_winsys *winsys; + + unsigned char *map; + unsigned char *ptr; + + size_t size; + size_t actual_size; + + size_t relocs; + size_t max_relocs; +}; + +static INLINE boolean +i915_batchbuffer_check( struct i915_batchbuffer *batch, + size_t dwords, + size_t relocs ) +{ + /** TODO JB: Check relocs */ + return dwords * 4 <= batch->size - (batch->ptr - batch->map); +} + +static INLINE size_t +i915_batchbuffer_space( struct i915_batchbuffer *batch ) +{ + return batch->size - (batch->ptr - batch->map); +} + +static INLINE void +i915_batchbuffer_dword( struct i915_batchbuffer *batch, + unsigned dword ) +{ + if (i915_batchbuffer_space(batch) < 4) + return; + + *(unsigned *)batch->ptr = dword; + batch->ptr += 4; +} + +static INLINE void +i915_batchbuffer_write( struct i915_batchbuffer *batch, + void *data, + size_t size ) +{ + if (i915_batchbuffer_space(batch) < size) + return; + + memcpy(data, batch->ptr, size); + batch->ptr += size; +} + +static INLINE void +i915_batchbuffer_reloc( struct i915_batchbuffer *batch, + struct pipe_buffer *buffer, + size_t flags, + size_t offset ) +{ + batch->winsys->batch_reloc( batch->winsys, buffer, flags, offset ); +} + +static INLINE void +i915_batchbuffer_flush( struct i915_batchbuffer *batch, + struct pipe_fence_handle **fence ) +{ + batch->winsys->batch_flush( batch->winsys, fence ); +} #define BEGIN_BATCH( dwords, relocs ) \ - (i915->batch_start = i915->winsys->batch_start( i915->winsys, dwords, relocs )) + (i915_batchbuffer_check( i915->batch, dwords, relocs )) #define OUT_BATCH( dword ) \ - i915->winsys->batch_dword( i915->winsys, dword ) + i915_batchbuffer_dword( i915->batch, dword ) #define OUT_RELOC( buf, flags, delta ) \ - i915->winsys->batch_reloc( i915->winsys, buf, flags, delta ) - -#define ADVANCE_BATCH() + i915_batchbuffer_reloc( i915->batch, buf, flags, delta ) #define FLUSH_BATCH(fence) do { \ - if (0) i915_dump_batchbuffer( i915 ); \ i915->winsys->batch_flush( i915->winsys, fence ); \ - i915->batch_start = NULL; \ i915->hardware_dirty = ~0; \ } while (0) -#endif +#endif diff --git a/src/gallium/drivers/i915simple/i915_blit.c b/src/gallium/drivers/i915simple/i915_blit.c index 24449e3fb3..22f91fab92 100644 --- a/src/gallium/drivers/i915simple/i915_blit.c +++ b/src/gallium/drivers/i915simple/i915_blit.c @@ -31,6 +31,7 @@ #include "i915_blit.h" #include "i915_reg.h" #include "i915_batch.h" +#include "i915_debug.h" #define FILE_DEBUG_FLAG DEBUG_BLIT @@ -45,7 +46,6 @@ i915_fill_blit(struct i915_context *i915, unsigned color) { unsigned BR13, CMD; - BATCH_LOCALS; dst_pitch *= (short) cpp; @@ -79,7 +79,6 @@ i915_fill_blit(struct i915_context *i915, OUT_BATCH(((y + h) << 16) | (x + w)); OUT_RELOC( dst_buffer, I915_BUFFER_ACCESS_WRITE, dst_offset); OUT_BATCH(color); - ADVANCE_BATCH(); } @@ -100,7 +99,6 @@ i915_copy_blit( struct i915_context *i915, unsigned CMD, BR13; int dst_y2 = dst_y + h; int dst_x2 = dst_x + w; - BATCH_LOCALS; I915_DBG(i915, @@ -156,7 +154,6 @@ i915_copy_blit( struct i915_context *i915, OUT_BATCH((src_y << 16) | src_x); OUT_BATCH(((int) src_pitch & 0xffff)); OUT_RELOC(src_buffer, I915_BUFFER_ACCESS_READ, src_offset); - ADVANCE_BATCH(); } diff --git a/src/gallium/drivers/i915simple/i915_clear.c b/src/gallium/drivers/i915simple/i915_clear.c index cde69daacc..8a2d3ca43f 100644 --- a/src/gallium/drivers/i915simple/i915_clear.c +++ b/src/gallium/drivers/i915simple/i915_clear.c @@ -44,4 +44,5 @@ i915_clear(struct pipe_context *pipe, struct pipe_surface *ps, unsigned clearValue) { pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue); + ps->status = PIPE_SURFACE_STATUS_DEFINED; } diff --git a/src/gallium/drivers/i915simple/i915_context.c b/src/gallium/drivers/i915simple/i915_context.c index 4bef21619c..4c01b8d5b1 100644 --- a/src/gallium/drivers/i915simple/i915_context.c +++ b/src/gallium/drivers/i915simple/i915_context.c @@ -50,10 +50,12 @@ static void i915_destroy( struct pipe_context *pipe ) static boolean -i915_draw_elements( struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, - unsigned indexSize, - unsigned prim, unsigned start, unsigned count) +i915_draw_range_elements(struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, + unsigned indexSize, + unsigned min_index, + unsigned max_index, + unsigned prim, unsigned start, unsigned count) { struct i915_context *i915 = i915_context( pipe ); struct draw_context *draw = i915->draw; @@ -77,7 +79,10 @@ i915_draw_elements( struct pipe_context *pipe, void *mapped_indexes = pipe->winsys->buffer_map(pipe->winsys, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ); - draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes); + draw_set_mapped_element_buffer_range(draw, indexSize, + min_index, + max_index, + mapped_indexes); } else { /* no index/element buffer */ @@ -86,7 +91,9 @@ i915_draw_elements( struct pipe_context *pipe, draw_set_mapped_constant_buffer(draw, - i915->current.constants[PIPE_SHADER_VERTEX]); + i915->current.constants[PIPE_SHADER_VERTEX], + ( i915->current.num_user_constants[PIPE_SHADER_VERTEX] * + 4 * sizeof(float) )); /* draw! */ draw_arrays(i915->draw, prim, start, count); @@ -100,12 +107,23 @@ i915_draw_elements( struct pipe_context *pipe, } if (indexBuffer) { pipe->winsys->buffer_unmap(pipe->winsys, indexBuffer); - draw_set_mapped_element_buffer(draw, 0, NULL); + draw_set_mapped_element_buffer_range(draw, 0, start, start + count - 1, NULL); } return TRUE; } +static boolean +i915_draw_elements( struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, + unsigned indexSize, + unsigned prim, unsigned start, unsigned count) +{ + return i915_draw_range_elements( pipe, indexBuffer, + indexSize, + 0, 0xffffffff, + prim, start, count ); +} static boolean i915_draw_arrays( struct pipe_context *pipe, unsigned prim, unsigned start, unsigned count) @@ -136,13 +154,14 @@ struct pipe_context *i915_create_context( struct pipe_screen *screen, i915->pipe.draw_arrays = i915_draw_arrays; i915->pipe.draw_elements = i915_draw_elements; + i915->pipe.draw_range_elements = i915_draw_range_elements; /* * Create drawing context and plug our rendering stage into it. */ i915->draw = draw_create(); assert(i915->draw); - if (!GETENV("I915_NO_VBUF")) { + if (!debug_get_bool_option("I915_NO_VBUF", FALSE)) { draw_set_rasterize_stage(i915->draw, i915_draw_vbuf_stage(i915)); } else { @@ -162,7 +181,8 @@ struct pipe_context *i915_create_context( struct pipe_screen *screen, /* Batch stream debugging is a bit hacked up at the moment: */ - i915->batch_start = NULL; + i915->batch = i915_winsys->batch_get(i915_winsys); + i915->batch->winsys = i915_winsys; return &i915->pipe; } diff --git a/src/gallium/drivers/i915simple/i915_context.h b/src/gallium/drivers/i915simple/i915_context.h index 53fc5ed079..892a88fd2c 100644 --- a/src/gallium/drivers/i915simple/i915_context.h +++ b/src/gallium/drivers/i915simple/i915_context.h @@ -178,6 +178,8 @@ struct i915_rasterizer_state { struct i915_sampler_state { unsigned state[3]; const struct pipe_sampler_state *templ; + unsigned minlod; + unsigned maxlod; }; @@ -209,6 +211,8 @@ struct i915_texture { struct pipe_buffer *buffer; }; +struct i915_batchbuffer; + struct i915_context { struct pipe_context pipe; @@ -241,10 +245,12 @@ struct i915_context unsigned num_vertex_elements; unsigned num_vertex_buffers; - unsigned *batch_start; + struct i915_batchbuffer *batch; /** Vertex buffer */ struct pipe_buffer *vbo; + size_t vbo_offset; + unsigned vbo_flushed; struct i915_state current; unsigned hardware_dirty; diff --git a/src/gallium/drivers/i915simple/i915_debug.c b/src/gallium/drivers/i915simple/i915_debug.c index 9b9111167f..5e26d1b905 100644 --- a/src/gallium/drivers/i915simple/i915_debug.c +++ b/src/gallium/drivers/i915simple/i915_debug.c @@ -861,8 +861,9 @@ void i915_dump_batchbuffer( struct i915_context *i915 ) { struct debug_stream stream; - unsigned *start = i915->batch_start; - unsigned *end = i915->winsys->batch_start( i915->winsys, 0, 0 ); + /* TODO fix me */ + unsigned *start = 0;/*i915->batch_start;*/ + unsigned *end = 0;/*i915->winsys->batch_start( i915->winsys, 0, 0 );*/ unsigned long bytes = (unsigned long) (end - start) * 4; boolean done = FALSE; diff --git a/src/gallium/drivers/i915simple/i915_flush.c b/src/gallium/drivers/i915simple/i915_flush.c index 7d23e6b6b9..472e0ab774 100644 --- a/src/gallium/drivers/i915simple/i915_flush.c +++ b/src/gallium/drivers/i915simple/i915_flush.c @@ -62,12 +62,12 @@ static void i915_flush( struct pipe_context *pipe, assert(BEGIN_BATCH(1, 0)); } OUT_BATCH( flush ); - ADVANCE_BATCH(); } /* If there are no flags, just flush pending commands to hardware: */ FLUSH_BATCH(fence); + i915->vbo_flushed = 1; } diff --git a/src/gallium/drivers/i915simple/i915_fpc_translate.c b/src/gallium/drivers/i915simple/i915_fpc_translate.c index 3ccf74c72c..23cd909337 100644 --- a/src/gallium/drivers/i915simple/i915_fpc_translate.c +++ b/src/gallium/drivers/i915simple/i915_fpc_translate.c @@ -676,7 +676,7 @@ i915_translate_instruction(struct i915_fp_compile *p, break; case TGSI_OPCODE_MOV: - /* aka TGSI_OPCODE_SWZ */ + case TGSI_OPCODE_SWZ: emit_simple_arith(p, inst, A0_MOV, 1); break; @@ -943,8 +943,8 @@ i915_translate_instructions(struct i915_fp_compile *p, if (parse.FullToken.FullDeclaration.Declaration.File == TGSI_FILE_CONSTANT) { uint i; - for (i = parse.FullToken.FullDeclaration.u.DeclarationRange.First; - i <= parse.FullToken.FullDeclaration.u.DeclarationRange.Last; + for (i = parse.FullToken.FullDeclaration.DeclarationRange.First; + i <= parse.FullToken.FullDeclaration.DeclarationRange.Last; i++) { assert(ifs->constant_flags[i] == 0x0); ifs->constant_flags[i] = I915_CONSTFLAG_USER; @@ -954,8 +954,8 @@ i915_translate_instructions(struct i915_fp_compile *p, else if (parse.FullToken.FullDeclaration.Declaration.File == TGSI_FILE_TEMPORARY) { uint i; - for (i = parse.FullToken.FullDeclaration.u.DeclarationRange.First; - i <= parse.FullToken.FullDeclaration.u.DeclarationRange.Last; + for (i = parse.FullToken.FullDeclaration.DeclarationRange.First; + i <= parse.FullToken.FullDeclaration.DeclarationRange.Last; i++) { assert(i < I915_MAX_TEMPORARY); /* XXX just use shader->info->file_mask[TGSI_FILE_TEMPORARY] */ diff --git a/src/gallium/drivers/i915simple/i915_prim_vbuf.c b/src/gallium/drivers/i915simple/i915_prim_vbuf.c index 7fb2adbb53..aef3682bbf 100644 --- a/src/gallium/drivers/i915simple/i915_prim_vbuf.c +++ b/src/gallium/drivers/i915simple/i915_prim_vbuf.c @@ -38,6 +38,7 @@ */ +#include "draw/draw_context.h" #include "draw/draw_vbuf.h" #include "pipe/p_debug.h" #include "pipe/p_util.h" @@ -62,8 +63,21 @@ struct i915_vbuf_render { /** Vertex size in bytes */ unsigned vertex_size; + /** Software primitive */ + unsigned prim; + /** Hardware primitive */ unsigned hwprim; + + /** Genereate a vertex list */ + unsigned fallback; + + /* Stuff for the vbo */ + struct pipe_buffer *vbo; + size_t vbo_size; + size_t vbo_offset; + void *vbo_ptr; + size_t vbo_alloc_size; }; @@ -95,8 +109,8 @@ i915_vbuf_render_get_vertex_info( struct vbuf_render *render ) static void * i915_vbuf_render_allocate_vertices( struct vbuf_render *render, - ushort vertex_size, - ushort nr_vertices ) + ushort vertex_size, + ushort nr_vertices ) { struct i915_vbuf_render *i915_render = i915_vbuf_render(render); struct i915_context *i915 = i915_render->i915; @@ -105,14 +119,31 @@ i915_vbuf_render_allocate_vertices( struct vbuf_render *render, /* FIXME: handle failure */ assert(!i915->vbo); - i915->vbo = winsys->buffer_create(winsys, 64, I915_BUFFER_USAGE_LIT_VERTEX, - size); - + + if (i915_render->vbo_size > size + i915_render->vbo_offset && !i915->vbo_flushed) { + } else { + i915->vbo_flushed = 0; + pipe_buffer_reference(winsys, &i915_render->vbo, NULL); + } + + if (!i915_render->vbo) { + i915_render->vbo_size = MAX2(size, i915_render->vbo_alloc_size); + i915_render->vbo_offset = 0; + i915_render->vbo = winsys->buffer_create(winsys, + 64, + I915_BUFFER_USAGE_LIT_VERTEX, + i915_render->vbo_size); + i915_render->vbo_ptr = winsys->buffer_map(winsys, + i915_render->vbo, + PIPE_BUFFER_USAGE_CPU_WRITE); + winsys->buffer_unmap(winsys, i915_render->vbo); + } + + i915->vbo = i915_render->vbo; + i915->vbo_offset = i915_render->vbo_offset; i915->dirty |= I915_NEW_VBO; - - return winsys->buffer_map(winsys, - i915->vbo, - PIPE_BUFFER_USAGE_CPU_WRITE); + + return (unsigned char *)i915_render->vbo_ptr + i915->vbo_offset; } @@ -121,18 +152,51 @@ i915_vbuf_render_set_primitive( struct vbuf_render *render, unsigned prim ) { struct i915_vbuf_render *i915_render = i915_vbuf_render(render); - + i915_render->prim = prim; + switch(prim) { case PIPE_PRIM_POINTS: i915_render->hwprim = PRIM3D_POINTLIST; + i915_render->fallback = 0; return TRUE; case PIPE_PRIM_LINES: i915_render->hwprim = PRIM3D_LINELIST; + i915_render->fallback = 0; + return TRUE; + case PIPE_PRIM_LINE_LOOP: + i915_render->hwprim = PRIM3D_LINELIST; + i915_render->fallback = PIPE_PRIM_LINE_LOOP; + return TRUE; + case PIPE_PRIM_LINE_STRIP: + i915_render->hwprim = PRIM3D_LINESTRIP; + i915_render->fallback = 0; return TRUE; case PIPE_PRIM_TRIANGLES: i915_render->hwprim = PRIM3D_TRILIST; + i915_render->fallback = 0; + return TRUE; + case PIPE_PRIM_TRIANGLE_STRIP: + i915_render->hwprim = PRIM3D_TRISTRIP; + i915_render->fallback = 0; + return TRUE; + case PIPE_PRIM_TRIANGLE_FAN: + i915_render->hwprim = PRIM3D_TRIFAN; + i915_render->fallback = 0; + return TRUE; + case PIPE_PRIM_QUADS: + i915_render->hwprim = PRIM3D_TRILIST; + i915_render->fallback = PIPE_PRIM_QUADS; + return TRUE; + case PIPE_PRIM_QUAD_STRIP: + i915_render->hwprim = PRIM3D_TRILIST; + i915_render->fallback = PIPE_PRIM_QUAD_STRIP; + return TRUE; + case PIPE_PRIM_POLYGON: + i915_render->hwprim = PRIM3D_POLY; + i915_render->fallback = 0; return TRUE; default: + assert((int)"Error unkown primtive type" & 0); /* Actually, can handle a lot more just fine... Fixme. */ return FALSE; @@ -140,6 +204,205 @@ i915_vbuf_render_set_primitive( struct vbuf_render *render, } + +/** + * Used for fallbacks in draw_arrays + */ +static void +draw_arrays_generate_indices( struct vbuf_render *render, + unsigned start, uint nr, + unsigned type ) +{ + struct i915_vbuf_render *i915_render = i915_vbuf_render(render); + struct i915_context *i915 = i915_render->i915; + unsigned i; + unsigned end = start + nr; + switch(type) { + case 0: + for (i = start; i+1 < end; i += 2) + OUT_BATCH( (i+0) | (i+1) << 16 ); + if (i < end) + OUT_BATCH( i ); + break; + case PIPE_PRIM_LINE_LOOP: + if (nr >= 2) { + for (i = start + 1; i < end; i++) + OUT_BATCH( (i-0) | (i+0) << 16 ); + OUT_BATCH( (i-0) | ( start) << 16 ); + } + break; + case PIPE_PRIM_QUADS: + for (i = start; i + 3 < end; i += 4) { + OUT_BATCH( (i+0) | (i+1) << 16 ); + OUT_BATCH( (i+3) | (i+1) << 16 ); + OUT_BATCH( (i+2) | (i+3) << 16 ); + } + break; + case PIPE_PRIM_QUAD_STRIP: + for (i = start; i + 3 < end; i += 2) { + OUT_BATCH( (i+0) | (i+1) << 16 ); + OUT_BATCH( (i+3) | (i+2) << 16 ); + OUT_BATCH( (i+0) | (i+3) << 16 ); + } + break; + default: + assert(0); + } +} + +static unsigned +draw_arrays_calc_nr_indices( uint nr, unsigned type ) +{ + switch (type) { + case 0: + return nr; + case PIPE_PRIM_LINE_LOOP: + if (nr >= 2) + return nr * 2; + else + return 0; + case PIPE_PRIM_QUADS: + return (nr / 4) * 6; + case PIPE_PRIM_QUAD_STRIP: + return ((nr - 2) / 2) * 6; + default: + assert(0); + return 0; + } +} + +static void +draw_arrays_fallback( struct vbuf_render *render, + unsigned start, + uint nr ) +{ + struct i915_vbuf_render *i915_render = i915_vbuf_render(render); + struct i915_context *i915 = i915_render->i915; + unsigned nr_indices; + + if (i915->dirty) + i915_update_derived( i915 ); + + if (i915->hardware_dirty) + i915_emit_hardware_state( i915 ); + + nr_indices = draw_arrays_calc_nr_indices( nr, i915_render->fallback ); + if (!nr_indices) + return; + + if (!BEGIN_BATCH( 1 + (nr_indices + 1)/2, 1 )) { + FLUSH_BATCH(NULL); + + /* Make sure state is re-emitted after a flush: + */ + i915_update_derived( i915 ); + i915_emit_hardware_state( i915 ); + i915->vbo_flushed = 1; + + if (!BEGIN_BATCH( 1 + (nr_indices + 1)/2, 1 )) { + assert(0); + goto out; + } + } + OUT_BATCH( _3DPRIMITIVE | + PRIM_INDIRECT | + i915_render->hwprim | + PRIM_INDIRECT_ELTS | + nr_indices ); + + draw_arrays_generate_indices( render, start, nr, i915_render->fallback ); + +out: + return; +} + +static void +i915_vbuf_render_draw_arrays( struct vbuf_render *render, + unsigned start, + uint nr ) +{ + struct i915_vbuf_render *i915_render = i915_vbuf_render(render); + + if (i915_render->fallback) { + draw_arrays_fallback( render, start, nr ); + return; + } + + /* JB: TODO submit direct cmds */ + draw_arrays_fallback( render, start, nr ); +} + +/** + * Used for normal and fallback emitting of indices + * If type is zero normal operation assumed. + */ +static void +draw_generate_indices( struct vbuf_render *render, + const ushort *indices, + uint nr_indices, + unsigned type ) +{ + struct i915_vbuf_render *i915_render = i915_vbuf_render(render); + struct i915_context *i915 = i915_render->i915; + unsigned i; + + switch(type) { + case 0: + for (i = 0; i + 1 < nr_indices; i += 2) { + OUT_BATCH( indices[i] | indices[i+1] << 16 ); + } + if (i < nr_indices) { + OUT_BATCH( indices[i] ); + } + break; + case PIPE_PRIM_LINE_LOOP: + if (nr_indices >= 2) { + for (i = 1; i < nr_indices; i++) + OUT_BATCH( indices[i-1] | indices[i] << 16 ); + OUT_BATCH( indices[i-1] | indices[0] << 16 ); + } + break; + case PIPE_PRIM_QUADS: + for (i = 0; i + 3 < nr_indices; i += 4) { + OUT_BATCH( indices[i+0] | indices[i+1] << 16 ); + OUT_BATCH( indices[i+3] | indices[i+1] << 16 ); + OUT_BATCH( indices[i+2] | indices[i+3] << 16 ); + } + break; + case PIPE_PRIM_QUAD_STRIP: + for (i = 0; i + 3 < nr_indices; i += 2) { + OUT_BATCH( indices[i+0] | indices[i+1] << 16 ); + OUT_BATCH( indices[i+3] | indices[i+2] << 16 ); + OUT_BATCH( indices[i+0] | indices[i+3] << 16 ); + } + break; + default: + assert(0); + break; + } +} + +static unsigned +draw_calc_nr_indices( uint nr_indices, unsigned type ) +{ + switch (type) { + case 0: + return nr_indices; + case PIPE_PRIM_LINE_LOOP: + if (nr_indices >= 2) + return nr_indices * 2; + else + return 0; + case PIPE_PRIM_QUADS: + return (nr_indices / 4) * 6; + case PIPE_PRIM_QUAD_STRIP: + return ((nr_indices - 2) / 2) * 6; + default: + assert(0); + return 0; + } +} + static void i915_vbuf_render_draw( struct vbuf_render *render, const ushort *indices, @@ -147,13 +410,14 @@ i915_vbuf_render_draw( struct vbuf_render *render, { struct i915_vbuf_render *i915_render = i915_vbuf_render(render); struct i915_context *i915 = i915_render->i915; - unsigned i; + unsigned save_nr_indices; - assert(nr_indices); + save_nr_indices = nr_indices; + + nr_indices = draw_calc_nr_indices( nr_indices, i915_render->fallback ); + if (!nr_indices) + return; - /* this seems to be bogus, since we validate state right after this */ - /*assert((i915->dirty & ~I915_NEW_VBO) == 0);*/ - if (i915->dirty) i915_update_derived( i915 ); @@ -167,25 +431,26 @@ i915_vbuf_render_draw( struct vbuf_render *render, */ i915_update_derived( i915 ); i915_emit_hardware_state( i915 ); + i915->vbo_flushed = 1; if (!BEGIN_BATCH( 1 + (nr_indices + 1)/2, 1 )) { assert(0); - return; + goto out; } } OUT_BATCH( _3DPRIMITIVE | - PRIM_INDIRECT | - i915_render->hwprim | - PRIM_INDIRECT_ELTS | - nr_indices ); - for (i = 0; i + 1 < nr_indices; i += 2) { - OUT_BATCH( indices[i] | - (indices[i + 1] << 16) ); - } - if (i < nr_indices) { - OUT_BATCH( indices[i] ); - } + PRIM_INDIRECT | + i915_render->hwprim | + PRIM_INDIRECT_ELTS | + nr_indices ); + draw_generate_indices( render, + indices, + save_nr_indices, + i915_render->fallback ); + +out: + return; } @@ -197,11 +462,13 @@ i915_vbuf_render_release_vertices( struct vbuf_render *render, { struct i915_vbuf_render *i915_render = i915_vbuf_render(render); struct i915_context *i915 = i915_render->i915; - struct pipe_winsys *winsys = i915->pipe.winsys; + size_t size = (size_t)vertex_size * (size_t)vertices_used; assert(i915->vbo); - winsys->buffer_unmap(winsys, i915->vbo); - pipe_buffer_reference(winsys, &i915->vbo, NULL); + + i915_render->vbo_offset += size; + i915->vbo = NULL; + i915->dirty |= I915_NEW_VBO; } @@ -220,6 +487,7 @@ static struct vbuf_render * i915_vbuf_render_create( struct i915_context *i915 ) { struct i915_vbuf_render *i915_render = CALLOC_STRUCT(i915_vbuf_render); + struct pipe_winsys *winsys = i915->pipe.winsys; i915_render->i915 = i915; @@ -229,14 +497,27 @@ i915_vbuf_render_create( struct i915_context *i915 ) * batch buffer. */ i915_render->base.max_indices = 16*1024; - + i915_render->base.get_vertex_info = i915_vbuf_render_get_vertex_info; i915_render->base.allocate_vertices = i915_vbuf_render_allocate_vertices; i915_render->base.set_primitive = i915_vbuf_render_set_primitive; i915_render->base.draw = i915_vbuf_render_draw; + i915_render->base.draw_arrays = i915_vbuf_render_draw_arrays; i915_render->base.release_vertices = i915_vbuf_render_release_vertices; i915_render->base.destroy = i915_vbuf_render_destroy; - + + i915_render->vbo_alloc_size = 128 * 4096; + i915_render->vbo_size = i915_render->vbo_alloc_size; + i915_render->vbo_offset = 0; + i915_render->vbo = winsys->buffer_create(winsys, + 64, + I915_BUFFER_USAGE_LIT_VERTEX, + i915_render->vbo_size); + i915_render->vbo_ptr = winsys->buffer_map(winsys, + i915_render->vbo, + PIPE_BUFFER_USAGE_CPU_WRITE); + winsys->buffer_unmap(winsys, i915_render->vbo); + return &i915_render->base; } @@ -258,6 +539,8 @@ struct draw_stage *i915_draw_vbuf_stage( struct i915_context *i915 ) render->destroy(render); return NULL; } - + /** TODO JB: this shouldn't be here */ + draw_set_render(i915->draw, render); + return stage; } diff --git a/src/gallium/drivers/i915simple/i915_state.c b/src/gallium/drivers/i915simple/i915_state.c index e6c4671700..dbb33f2695 100644 --- a/src/gallium/drivers/i915simple/i915_state.c +++ b/src/gallium/drivers/i915simple/i915_state.c @@ -41,7 +41,6 @@ #include "i915_state_inlines.h" #include "i915_fpc.h" - /* The i915 (and related graphics cores) do not support GL_CLAMP. The * Intel drivers for "other operating systems" implement GL_CLAMP as * GL_CLAMP_TO_EDGE, so the same is done here. @@ -178,6 +177,7 @@ static void i915_bind_blend_state(struct pipe_context *pipe, void *blend) { struct i915_context *i915 = i915_context(pipe); + draw_flush(i915->draw); i915->blend = (struct i915_blend_state*)blend; @@ -194,6 +194,7 @@ static void i915_set_blend_color( struct pipe_context *pipe, const struct pipe_blend_color *blend_color ) { struct i915_context *i915 = i915_context(pipe); + draw_flush(i915->draw); i915->blend_color = *blend_color; @@ -250,11 +251,17 @@ i915_create_sampler_state(struct pipe_context *pipe, if (sampler->normalized_coords) cso->state[1] |= SS3_NORMALIZED_COORDS; - if (0) /* XXX not tested yet */ { int minlod = (int) (16.0 * sampler->min_lod); + int maxlod = (int) (16.0 * sampler->max_lod); minlod = CLAMP(minlod, 0, 16 * 11); - cso->state[1] |= (minlod << SS3_MIN_LOD_SHIFT); + maxlod = CLAMP(maxlod, 0, 16 * 11); + + if (minlod > maxlod) + maxlod = minlod; + + cso->minlod = minlod; + cso->maxlod = maxlod; } { @@ -280,6 +287,8 @@ static void i915_bind_sampler_states(struct pipe_context *pipe, !memcmp(i915->sampler, sampler, num * sizeof(void *))) return; + draw_flush(i915->draw); + for (i = 0; i < num; ++i) i915->sampler[i] = sampler[i]; for (i = num; i < PIPE_MAX_SAMPLERS; ++i) @@ -398,6 +407,7 @@ static void i915_bind_depth_stencil_state(struct pipe_context *pipe, void *depth_stencil) { struct i915_context *i915 = i915_context(pipe); + draw_flush(i915->draw); i915->depth_stencil = (const struct i915_depth_stencil_state *)depth_stencil; @@ -415,6 +425,7 @@ static void i915_set_scissor_state( struct pipe_context *pipe, const struct pipe_scissor_state *scissor ) { struct i915_context *i915 = i915_context(pipe); + draw_flush(i915->draw); memcpy( &i915->scissor, scissor, sizeof(*scissor) ); i915->dirty |= I915_NEW_SCISSOR; @@ -451,6 +462,7 @@ static void i915_bind_fs_state(struct pipe_context *pipe, void *shader) { struct i915_context *i915 = i915_context(pipe); + draw_flush(i915->draw); i915->fs = (struct i915_fragment_shader*) shader; @@ -506,6 +518,7 @@ static void i915_set_constant_buffer(struct pipe_context *pipe, { struct i915_context *i915 = i915_context(pipe); struct pipe_winsys *ws = pipe->winsys; + draw_flush(i915->draw); assert(shader < PIPE_SHADER_TYPES); assert(index == 0); @@ -574,6 +587,7 @@ static void i915_set_framebuffer_state(struct pipe_context *pipe, const struct pipe_framebuffer_state *fb) { struct i915_context *i915 = i915_context(pipe); + draw_flush(i915->draw); i915->framebuffer = *fb; /* struct copy */ @@ -586,6 +600,7 @@ static void i915_set_clip_state( struct pipe_context *pipe, const struct pipe_clip_state *clip ) { struct i915_context *i915 = i915_context(pipe); + draw_flush(i915->draw); draw_set_clip_state(i915->draw, clip); @@ -698,6 +713,10 @@ static void i915_set_vertex_buffers(struct pipe_context *pipe, const struct pipe_vertex_buffer *buffers) { struct i915_context *i915 = i915_context(pipe); + /* Because we change state before the draw_set_vertex_buffers call + * we need a flush here, just to be sure. + */ + draw_flush(i915->draw); memcpy(i915->vertex_buffer, buffers, count * sizeof(buffers[0])); i915->num_vertex_buffers = count; @@ -711,6 +730,11 @@ static void i915_set_vertex_elements(struct pipe_context *pipe, const struct pipe_vertex_element *elements) { struct i915_context *i915 = i915_context(pipe); + /* Because we change state before the draw_set_vertex_buffers call + * we need a flush here, just to be sure. + */ + draw_flush(i915->draw); + i915->num_vertex_elements = count; /* pass-through to draw module */ draw_set_vertex_elements(i915->draw, count, elements); diff --git a/src/gallium/drivers/i915simple/i915_state_emit.c b/src/gallium/drivers/i915simple/i915_state_emit.c index 6f947d4346..bc801a82f0 100644 --- a/src/gallium/drivers/i915simple/i915_state_emit.c +++ b/src/gallium/drivers/i915simple/i915_state_emit.c @@ -211,33 +211,43 @@ i915_emit_hardware_state(struct i915_context *i915 ) struct pipe_surface *depth_surface = i915->framebuffer.zsbuf; if (cbuf_surface) { - unsigned pitch = (cbuf_surface->pitch * cbuf_surface->cpp); + unsigned cpitch = (cbuf_surface->pitch * cbuf_surface->cpp); + unsigned ctile = BUF_3D_USE_FENCE; +#if 0 + if (!((cpitch - 1) & cpitch) && cpitch >= 512) + ctile = BUF_3D_TILED_SURFACE; +#endif OUT_BATCH(_3DSTATE_BUF_INFO_CMD); OUT_BATCH(BUF_3D_ID_COLOR_BACK | - BUF_3D_PITCH(pitch) | /* pitch in bytes */ - BUF_3D_USE_FENCE); + BUF_3D_PITCH(cpitch) | /* pitch in bytes */ + ctile); OUT_RELOC(cbuf_surface->buffer, I915_BUFFER_ACCESS_WRITE, - 0); + cbuf_surface->offset); } /* What happens if no zbuf?? */ if (depth_surface) { unsigned zpitch = (depth_surface->pitch * depth_surface->cpp); - + unsigned ztile = BUF_3D_USE_FENCE; +#if 0 + if (!((zpitch - 1) & zpitch) && zpitch >= 512) + ztile = BUF_3D_TILED_SURFACE; +#endif + OUT_BATCH(_3DSTATE_BUF_INFO_CMD); OUT_BATCH(BUF_3D_ID_DEPTH | BUF_3D_PITCH(zpitch) | /* pitch in bytes */ - BUF_3D_USE_FENCE); + ztile); OUT_RELOC(depth_surface->buffer, I915_BUFFER_ACCESS_WRITE, - 0); + depth_surface->offset); } { @@ -376,6 +386,7 @@ i915_emit_hardware_state(struct i915_context *i915 ) { uint w, h; boolean k = framebuffer_size(&i915->framebuffer, &w, &h); + (void)k; assert(k); OUT_BATCH(_3DSTATE_DRAW_RECT_CMD); diff --git a/src/gallium/drivers/i915simple/i915_state_immediate.c b/src/gallium/drivers/i915simple/i915_state_immediate.c index dfbbcab624..2501f2d7cb 100644 --- a/src/gallium/drivers/i915simple/i915_state_immediate.c +++ b/src/gallium/drivers/i915simple/i915_state_immediate.c @@ -54,7 +54,7 @@ static void upload_S0S1(struct i915_context *i915) /* INTEL_NEW_VBO */ /* TODO: re-use vertex buffers here? */ - LIS0 = 0; + LIS0 = i915->vbo_offset; /* INTEL_NEW_VERTEX_SIZE -- do this where the vertex size is calculated! */ @@ -156,8 +156,12 @@ const struct i915_tracked_state i915_upload_S5 = { */ static void upload_S6( struct i915_context *i915 ) { - unsigned LIS6 = (S6_COLOR_WRITE_ENABLE | - (2 << S6_TRISTRIP_PV_SHIFT)); + unsigned LIS6 = (2 << S6_TRISTRIP_PV_SHIFT); + + /* I915_NEW_FRAMEBUFFER + */ + if (i915->framebuffer.cbufs[0]) + LIS6 |= S6_COLOR_WRITE_ENABLE; /* I915_NEW_BLEND */ @@ -174,7 +178,7 @@ static void upload_S6( struct i915_context *i915 ) } const struct i915_tracked_state i915_upload_S6 = { - I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL, + I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL | I915_NEW_FRAMEBUFFER, upload_S6 }; diff --git a/src/gallium/drivers/i915simple/i915_state_sampler.c b/src/gallium/drivers/i915simple/i915_state_sampler.c index 982eec4a1b..24440843f3 100644 --- a/src/gallium/drivers/i915simple/i915_state_sampler.c +++ b/src/gallium/drivers/i915simple/i915_state_sampler.c @@ -35,6 +35,35 @@ #include "i915_state.h" +/* + * A note about min_lod & max_lod. + * + * There is a circular dependancy between the sampler state + * and the map state to be submitted to hw. + * + * Two condition must be meet: + * min_lod =< max_lod == true + * max_lod =< last_level == true + * + * + * This is all fine and dandy if it where for the fact that max_lod + * is set on the map state instead of the sampler state. That is + * the max_lod we submit on map is: + * max_lod = MIN2(last_level, max_lod); + * + * So we need to update the map state when we change samplers and + * we need to be change the sampler state when map state is changed. + * The first part is done by calling i915_update_texture in + * i915_update_samplers and the second part is done else where in + * code tracking the state changes. + */ + +static void +i915_update_texture(struct i915_context *i915, + uint unit, + const struct i915_texture *tex, + const struct i915_sampler_state *sampler, + uint state[6]); /** * Compute i915 texture sampling state. * @@ -50,6 +79,7 @@ static void update_sampler(struct i915_context *i915, unsigned state[3] ) { const struct pipe_texture *pt = &tex->base; + unsigned minlod, lastlod; /* Need to do this after updating the maps, which call the * intel_finalize_mipmap_tree and hence can update firstLevel: @@ -95,6 +125,15 @@ static void update_sampler(struct i915_context *i915, } #endif + /* See note at the top of file */ + minlod = sampler->minlod; + lastlod = pt->last_level << 4; + + if (lastlod < minlod) { + minlod = lastlod; + } + + state[1] |= (sampler->minlod << SS3_MIN_LOD_SHIFT); state[1] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT); } @@ -112,18 +151,23 @@ void i915_update_samplers( struct i915_context *i915 ) /* could also examine the fragment program? */ if (i915->texture[unit]) { update_sampler( i915, - unit, - i915->sampler[unit], /* sampler state */ - i915->texture[unit], /* texture */ - i915->current.sampler[unit] /* the result */ - ); - - i915->current.sampler_enable_nr++; - i915->current.sampler_enable_flags |= (1 << unit); + unit, + i915->sampler[unit], /* sampler state */ + i915->texture[unit], /* texture */ + i915->current.sampler[unit] /* the result */ + ); + i915_update_texture( i915, + unit, + i915->texture[unit], /* texture */ + i915->sampler[unit], /* sampler state */ + i915->current.texbuffer[unit] ); + + i915->current.sampler_enable_nr++; + i915->current.sampler_enable_flags |= (1 << unit); } } - i915->hardware_dirty |= I915_HW_SAMPLER; + i915->hardware_dirty |= I915_HW_SAMPLER | I915_HW_MAP; } @@ -168,7 +212,7 @@ translate_texture_format(enum pipe_format pipeFormat) return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5); #endif case PIPE_FORMAT_S8Z24_UNORM: - return (MAPSURF_32BIT | MT_32BIT_xL824); + return (MAPSURF_32BIT | MT_32BIT_xI824); default: debug_printf("i915: translate_texture_format() bad image format %x\n", pipeFormat); @@ -179,14 +223,17 @@ translate_texture_format(enum pipe_format pipeFormat) static void -i915_update_texture(struct i915_context *i915, uint unit, +i915_update_texture(struct i915_context *i915, + uint unit, + const struct i915_texture *tex, + const struct i915_sampler_state *sampler, uint state[6]) { - const struct i915_texture *tex = i915->texture[unit]; const struct pipe_texture *pt = &tex->base; uint format, pitch; const uint width = pt->width[0], height = pt->height[0], depth = pt->depth[0]; const uint num_levels = pt->last_level; + unsigned max_lod = num_levels * 4; assert(tex); assert(width); @@ -207,16 +254,19 @@ i915_update_texture(struct i915_context *i915, uint unit, | MS3_USE_FENCE_REGS); /* - * XXX sampler->max_lod should be used to program the MAX_LOD field below. - * Also, when min_filter != mag_filter and there's just one mipmap level, + * XXX When min_filter != mag_filter and there's just one mipmap level, * set max_lod = 1 to make sure i915 chooses between min/mag filtering. */ + /* See note at the top of file */ + if (max_lod > (sampler->maxlod >> 2)) + max_lod = sampler->maxlod >> 2; + /* MS4 state */ state[1] = ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) | MS4_CUBE_FACE_ENA_MASK - | ((num_levels * 4) << MS4_MAX_LOD_SHIFT) + | ((max_lod) << MS4_MAX_LOD_SHIFT) | ((depth - 1) << MS4_VOLUME_DEPTH_SHIFT)); } @@ -231,7 +281,11 @@ i915_update_textures(struct i915_context *i915) /* determine unit enable/disable by looking for a bound texture */ /* could also examine the fragment program? */ if (i915->texture[unit]) { - i915_update_texture(i915, unit, i915->current.texbuffer[unit]); + i915_update_texture( i915, + unit, + i915->texture[unit], /* texture */ + i915->sampler[unit], /* sampler state */ + i915->current.texbuffer[unit] ); } } diff --git a/src/gallium/drivers/i915simple/i915_texture.c b/src/gallium/drivers/i915simple/i915_texture.c index df11ba0544..9cd32e3919 100644 --- a/src/gallium/drivers/i915simple/i915_texture.c +++ b/src/gallium/drivers/i915simple/i915_texture.c @@ -42,12 +42,58 @@ #include "i915_debug.h" #include "i915_screen.h" +/* + * Helper function and arrays + */ + +/** + * Initial offset for Cube map. + */ +static const int initial_offsets[6][2] = { + {0, 0}, + {0, 2}, + {1, 0}, + {1, 2}, + {1, 1}, + {1, 3} +}; + +/** + * Step offsets for Cube map. + */ +static const int step_offsets[6][2] = { + {0, 2}, + {0, 2}, + {-1, 2}, + {-1, 2}, + {-1, 1}, + {-1, 1} +}; static unsigned minify( unsigned d ) { return MAX2(1, d>>1); } +static unsigned +power_of_two(unsigned x) +{ + unsigned value = 1; + while (value <= x) + value = value << 1; + return value; +} + +static unsigned +round_up(unsigned n, unsigned multiple) +{ + return (n + multiple - 1) & ~(multiple - 1); +} + + +/* + * More advanced helper funcs + */ static void @@ -86,7 +132,6 @@ i915_miptree_set_level_info(struct i915_texture *tex, tex->image_offset[level][0] = 0; } - static void i915_miptree_set_image_offset(struct i915_texture *tex, unsigned level, unsigned img, unsigned x, unsigned y) @@ -99,57 +144,51 @@ i915_miptree_set_image_offset(struct i915_texture *tex, tex->image_offset[level][img] = (x + y * tex->pitch); /* - DBG("%s level %d img %d pos %d,%d image_offset %x\n", + printf("%s level %d img %d pos %d,%d image_offset %x\n", __FUNCTION__, level, img, x, y, tex->image_offset[level][img]); */ } -/* Hack it up to use the old winsys->surface_alloc_storage() - * method for now: +/* + * Layout functions + */ + + +/** + * Special case to deal with display targets. */ static boolean -i915_displaytarget_layout(struct pipe_screen *screen, - struct i915_texture *tex) +i915_displaytarget_layout(struct i915_texture *tex) { - struct pipe_winsys *ws = screen->winsys; - struct pipe_surface surf; - unsigned flags = (PIPE_BUFFER_USAGE_CPU_READ | - PIPE_BUFFER_USAGE_CPU_WRITE | - PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_GPU_WRITE); - - - memset(&surf, 0, sizeof(surf)); - - ws->surface_alloc_storage( ws, - &surf, - tex->base.width[0], - tex->base.height[0], - tex->base.format, - flags, - tex->base.tex_usage); - - /* Now extract the goodies: - */ + struct pipe_texture *pt = &tex->base; + + if (pt->last_level > 0 || pt->cpp != 4) + return 0; + i915_miptree_set_level_info( tex, 0, 1, 0, 0, tex->base.width[0], tex->base.height[0], 1 ); i915_miptree_set_image_offset( tex, 0, 0, 0, 0 ); - tex->buffer = surf.buffer; - tex->pitch = surf.pitch; - tex->total_height = 0; + if (tex->base.width[0] >= 128) { + tex->pitch = power_of_two(tex->base.width[0] * pt->cpp) / pt->cpp; + tex->total_height = round_up(tex->base.height[0], 8); + } else { + tex->pitch = round_up(tex->base.width[0], 64 / pt->cpp); + tex->total_height = tex->base.height[0]; + } + /* + printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__, + tex->base.width[0], tex->base.height[0], pt->cpp, + tex->pitch, tex->total_height, tex->pitch * tex->total_height * 4); + */ - return tex->buffer != NULL; + return 1; } - - - - static void i945_miptree_layout_2d( struct i915_texture *tex ) { @@ -161,6 +200,12 @@ i945_miptree_layout_2d( struct i915_texture *tex ) unsigned width = pt->width[0]; unsigned height = pt->height[0]; +#if 0 /* used for tiled display targets */ + if (pt->last_level == 0 && pt->cpp == 4) + if (i915_displaytarget_layout(tex)) + return; +#endif + tex->pitch = pt->width[0]; /* May need to adjust pitch to accomodate the placement of @@ -179,7 +224,7 @@ i945_miptree_layout_2d( struct i915_texture *tex ) /* Pitch must be a whole number of dwords, even though we * express it in texels. */ - tex->pitch = align_int(tex->pitch * pt->cpp, 4) / pt->cpp; + tex->pitch = align_int(tex->pitch * pt->cpp, 64) / pt->cpp; tex->total_height = 0; for (level = 0; level <= pt->last_level; level++) { @@ -212,25 +257,108 @@ i945_miptree_layout_2d( struct i915_texture *tex ) } } +static void +i945_miptree_layout_cube(struct i915_texture *tex) +{ + struct pipe_texture *pt = &tex->base; + unsigned level; -static const int initial_offsets[6][2] = { - {0, 0}, - {0, 2}, - {1, 0}, - {1, 2}, - {1, 1}, - {1, 3} -}; + const unsigned dim = pt->width[0]; + unsigned face; + unsigned lvlWidth = pt->width[0], lvlHeight = pt->height[0]; -static const int step_offsets[6][2] = { - {0, 2}, - {0, 2}, - {-1, 2}, - {-1, 2}, - {-1, 1}, - {-1, 1} -}; + /* + printf("%s %i, %i\n", __FUNCTION__, pt->width[0], pt->height[0]); + */ + + assert(lvlWidth == lvlHeight); /* cubemap images are square */ + + /* + * XXX Should only be used for compressed formats. But lets + * keep this code active just in case. + * + * Depending on the size of the largest images, pitch can be + * determined either by the old-style packing of cubemap faces, + * or the final row of 4x4, 2x2 and 1x1 faces below this. + */ + if (dim > 32) + tex->pitch = ((dim * pt->cpp * 2 + 3) & ~3) / pt->cpp; + else + tex->pitch = 14 * 8; + + /* + * XXX The 4 is only needed for compressed formats. See above. + */ + tex->total_height = dim * 4 + 4; + + /* Set all the levels to effectively occupy the whole rectangular region. + */ + for (level = 0; level <= pt->last_level; level++) { + i915_miptree_set_level_info(tex, level, 6, 0, 0, lvlWidth, lvlHeight, 1); + lvlWidth /= 2; + lvlHeight /= 2; + } + for (face = 0; face < 6; face++) { + unsigned x = initial_offsets[face][0] * dim; + unsigned y = initial_offsets[face][1] * dim; + unsigned d = dim; + +#if 0 /* Fix and enable this code for compressed formats */ + if (dim == 4 && face >= 4) { + y = tex->total_height - 4; + x = (face - 4) * 8; + } + else if (dim < 4 && (face > 0)) { + y = tex->total_height - 4; + x = face * 8; + } +#endif + + for (level = 0; level <= pt->last_level; level++) { + i915_miptree_set_image_offset(tex, level, face, x, y); + + d >>= 1; + +#if 0 /* Fix and enable this code for compressed formats */ + switch (d) { + case 4: + switch (face) { + case PIPE_TEX_FACE_POS_X: + case PIPE_TEX_FACE_NEG_X: + x += step_offsets[face][0] * d; + y += step_offsets[face][1] * d; + break; + case PIPE_TEX_FACE_POS_Y: + case PIPE_TEX_FACE_NEG_Y: + y += 12; + x -= 8; + break; + case PIPE_TEX_FACE_POS_Z: + case PIPE_TEX_FACE_NEG_Z: + y = tex->total_height - 4; + x = (face - 4) * 8; + break; + } + case 2: + y = tex->total_height - 4; + x = 16 + face * 8; + break; + + case 1: + x += 48; + break; + default: +#endif + x += step_offsets[face][0] * d; + y += step_offsets[face][1] * d; +#if 0 + break; + } +#endif + } + } +} static boolean i915_miptree_layout(struct i915_texture * tex) @@ -363,99 +491,15 @@ i945_miptree_layout(struct i915_texture * tex) unsigned level; switch (pt->target) { - case PIPE_TEXTURE_CUBE:{ - const unsigned dim = pt->width[0]; - unsigned face; - unsigned lvlWidth = pt->width[0], lvlHeight = pt->height[0]; - - assert(lvlWidth == lvlHeight); /* cubemap images are square */ - - /* Depending on the size of the largest images, pitch can be - * determined either by the old-style packing of cubemap faces, - * or the final row of 4x4, 2x2 and 1x1 faces below this. - */ - if (dim > 32) - tex->pitch = ((dim * pt->cpp * 2 + 3) & ~3) / pt->cpp; - else - tex->pitch = 14 * 8; - - tex->total_height = dim * 4 + 4; - - /* Set all the levels to effectively occupy the whole rectangular region. - */ - for (level = 0; level <= pt->last_level; level++) { - i915_miptree_set_level_info(tex, level, 6, - 0, 0, - lvlWidth, lvlHeight, 1); - lvlWidth /= 2; - lvlHeight /= 2; - } - - - for (face = 0; face < 6; face++) { - unsigned x = initial_offsets[face][0] * dim; - unsigned y = initial_offsets[face][1] * dim; - unsigned d = dim; - - if (dim == 4 && face >= 4) { - y = tex->total_height - 4; - x = (face - 4) * 8; - } - else if (dim < 4 && (face > 0)) { - y = tex->total_height - 4; - x = face * 8; - } - - for (level = 0; level <= pt->last_level; level++) { - i915_miptree_set_image_offset(tex, level, face, x, y); - - d >>= 1; - - switch (d) { - case 4: - switch (face) { - case PIPE_TEX_FACE_POS_X: - case PIPE_TEX_FACE_NEG_X: - x += step_offsets[face][0] * d; - y += step_offsets[face][1] * d; - break; - case PIPE_TEX_FACE_POS_Y: - case PIPE_TEX_FACE_NEG_Y: - y += 12; - x -= 8; - break; - case PIPE_TEX_FACE_POS_Z: - case PIPE_TEX_FACE_NEG_Z: - y = tex->total_height - 4; - x = (face - 4) * 8; - break; - } - - case 2: - y = tex->total_height - 4; - x = 16 + face * 8; - break; - - case 1: - x += 48; - break; - - default: - x += step_offsets[face][0] * d; - y += step_offsets[face][1] * d; - break; - } - } - } - break; - } + case PIPE_TEXTURE_CUBE: + i945_miptree_layout_cube(tex); + break; case PIPE_TEXTURE_3D:{ unsigned width = pt->width[0]; unsigned height = pt->height[0]; unsigned depth = pt->depth[0]; unsigned pack_x_pitch, pack_x_nr; unsigned pack_y_pitch; - unsigned level; tex->pitch = ((pt->width[0] * pt->cpp + 3) & ~3) / pt->cpp; tex->total_height = 0; @@ -532,39 +576,32 @@ i915_texture_create(struct pipe_screen *screen, struct pipe_winsys *ws = screen->winsys; struct i915_texture *tex = CALLOC_STRUCT(i915_texture); - if (!tex) + if (!tex) return NULL; tex->base = *templat; tex->base.refcount = 1; tex->base.screen = screen; - if (tex->base.tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) { - if (!i915_displaytarget_layout(screen, tex)) - goto fail; - } - else { - if (i915screen->is_i945) { - if (!i945_miptree_layout(tex)) - goto fail; - } - else { - if (!i915_miptree_layout(tex)) - goto fail; - } - - tex->buffer = ws->buffer_create(ws, 64, - PIPE_BUFFER_USAGE_PIXEL, - tex->pitch * tex->base.cpp * - tex->total_height); - - if (!tex->buffer) - goto fail; + if (i915screen->is_i945) { + if (!i945_miptree_layout(tex)) + goto fail; + } else { + if (!i915_miptree_layout(tex)) + goto fail; } + tex->buffer = ws->buffer_create(ws, 64, + PIPE_BUFFER_USAGE_PIXEL, + tex->pitch * tex->base.cpp * + tex->total_height); + + if (!tex->buffer) + goto fail; + return &tex->base; - fail: +fail: FREE(tex); return NULL; } @@ -600,11 +637,6 @@ i915_texture_release(struct pipe_screen *screen, *pt = NULL; } - - -/* - * XXX note: same as code in sp_surface.c - */ static struct pipe_surface * i915_get_tex_surface(struct pipe_screen *screen, struct pipe_texture *pt, @@ -629,10 +661,10 @@ i915_get_tex_surface(struct pipe_screen *screen, assert(zslice == 0); } - ps = ws->surface_alloc(ws); + ps = CALLOC_STRUCT(pipe_surface); if (ps) { - assert(ps->refcount); - assert(ps->winsys); + ps->refcount = 1; + ps->winsys = ws; pipe_texture_reference(&ps->texture, pt); pipe_buffer_reference(ws, &ps->buffer, tex->buffer); ps->format = pt->format; @@ -642,11 +674,11 @@ i915_get_tex_surface(struct pipe_screen *screen, ps->pitch = tex->pitch; ps->offset = offset; ps->usage = flags; + ps->status = PIPE_SURFACE_STATUS_DEFINED; } return ps; } - void i915_init_texture_functions(struct i915_context *i915) { diff --git a/src/gallium/drivers/i915simple/i915_winsys.h b/src/gallium/drivers/i915simple/i915_winsys.h index 5e16543f4e..9afaa16a62 100644 --- a/src/gallium/drivers/i915simple/i915_winsys.h +++ b/src/gallium/drivers/i915simple/i915_winsys.h @@ -55,6 +55,7 @@ extern "C" { * etc. */ +struct i915_batchbuffer; struct pipe_buffer; struct pipe_fence_handle; struct pipe_winsys; @@ -75,20 +76,10 @@ struct pipe_screen; struct i915_winsys { /** - * Reserve space on batch buffer. - * - * Returns a null pointer if there is insufficient space in the batch buffer - * to hold the requested number of dwords and relocations. - * - * The number of dwords should also include the number of relocations. + * Get the current batch buffer from the winsys. */ - unsigned *(*batch_start)( struct i915_winsys *sws, - unsigned dwords, - unsigned relocs ); - - void (*batch_dword)( struct i915_winsys *sws, - unsigned dword ); - + struct i915_batchbuffer *(*batch_get)( struct i915_winsys *sws ); + /** * Emit a relocation to a buffer. * @@ -103,7 +94,10 @@ struct i915_winsys { struct pipe_buffer *buf, unsigned access_flags, unsigned delta ); - + + /** + * Flush the batch. + */ void (*batch_flush)( struct i915_winsys *sws, struct pipe_fence_handle **fence ); }; diff --git a/src/gallium/drivers/i965simple/brw_sf.c b/src/gallium/drivers/i965simple/brw_sf.c index c3b815a82b..96f8fb87a3 100644 --- a/src/gallium/drivers/i965simple/brw_sf.c +++ b/src/gallium/drivers/i965simple/brw_sf.c @@ -169,9 +169,9 @@ static void upload_sf_prog( struct brw_context *brw ) case TGSI_TOKEN_TYPE_DECLARATION: if (parse.FullToken.FullDeclaration.Declaration.File == TGSI_FILE_INPUT) { - int first = parse.FullToken.FullDeclaration.u.DeclarationRange.First; - int last = parse.FullToken.FullDeclaration.u.DeclarationRange.Last; - int interp_mode = parse.FullToken.FullDeclaration.Interpolation.Interpolate; + int first = parse.FullToken.FullDeclaration.DeclarationRange.First; + int last = parse.FullToken.FullDeclaration.DeclarationRange.Last; + int interp_mode = parse.FullToken.FullDeclaration.Declaration.Interpolate; //int semantic = parse.FullToken.FullDeclaration.Semantic.SemanticName; //int semantic_index = parse.FullToken.FullDeclaration.Semantic.SemanticIndex; @@ -291,8 +291,8 @@ static void update_sf_linkage( struct brw_context *brw ) case TGSI_TOKEN_TYPE_DECLARATION: if (parse.FullToken.FullDeclaration.Declaration.File == TGSI_FILE_INPUT) { - int first = parse.FullToken.FullDeclaration.u.DeclarationRange.First; - int last = parse.FullToken.FullDeclaration.u.DeclarationRange.Last; + int first = parse.FullToken.FullDeclaration.DeclarationRange.First; + int last = parse.FullToken.FullDeclaration.DeclarationRange.Last; for (i = first; i < last; i++) { vp_semantic[i].semantic = diff --git a/src/gallium/drivers/i965simple/brw_shader_info.c b/src/gallium/drivers/i965simple/brw_shader_info.c index f4694a4433..fb3da92421 100644 --- a/src/gallium/drivers/i965simple/brw_shader_info.c +++ b/src/gallium/drivers/i965simple/brw_shader_info.c @@ -26,9 +26,7 @@ void brw_shader_info(const struct tgsi_token *tokens, case TGSI_TOKEN_TYPE_DECLARATION: { const struct tgsi_full_declaration *decl = &parse.FullToken.FullDeclaration; - unsigned last = decl->u.DeclarationRange.Last; - - assert( decl->Declaration.Declare == TGSI_DECLARE_RANGE ); + unsigned last = decl->DeclarationRange.Last; // Broken by crazy wpos init: //assert( info->nr_regs[decl->Declaration.File] <= last); diff --git a/src/gallium/drivers/i965simple/brw_vs_emit.c b/src/gallium/drivers/i965simple/brw_vs_emit.c index 9020fcc001..81423e2d7d 100644 --- a/src/gallium/drivers/i965simple/brw_vs_emit.c +++ b/src/gallium/drivers/i965simple/brw_vs_emit.c @@ -988,10 +988,8 @@ post_vs_emit( struct brw_vs_compile *c, struct brw_instruction *end_inst ) static void process_declaration(const struct tgsi_full_declaration *decl, struct brw_prog_info *info) { - int first = decl->u.DeclarationRange.First; - int last = decl->u.DeclarationRange.Last; - - assert (decl->Declaration.Declare != TGSI_DECLARE_MASK); + int first = decl->DeclarationRange.First; + int last = decl->DeclarationRange.Last; switch(decl->Declaration.File) { case TGSI_FILE_CONSTANT: @@ -1137,8 +1135,8 @@ static void process_instruction(struct brw_vs_compile *c, emit_min(p, dst, args[0], args[1]); break; case TGSI_OPCODE_MOV: -#if 0 case TGSI_OPCODE_SWZ: +#if 0 /* The args[0] value can't be used here as it won't have * correctly encoded the full swizzle: */ diff --git a/src/gallium/drivers/i965simple/brw_wm_decl.c b/src/gallium/drivers/i965simple/brw_wm_decl.c index 74ccfd494a..bf1b4d961a 100644 --- a/src/gallium/drivers/i965simple/brw_wm_decl.c +++ b/src/gallium/drivers/i965simple/brw_wm_decl.c @@ -351,18 +351,16 @@ void brw_wm_emit_decls(struct brw_wm_compile *c) case TGSI_TOKEN_TYPE_DECLARATION: { const struct tgsi_full_declaration *decl = &parse.FullToken.FullDeclaration; - unsigned first = decl->u.DeclarationRange.First; - unsigned last = decl->u.DeclarationRange.Last; + unsigned first = decl->DeclarationRange.First; + unsigned last = decl->DeclarationRange.Last; unsigned mask = decl->Declaration.UsageMask; /* ? */ unsigned i; if (decl->Declaration.File != TGSI_FILE_INPUT) break; - assert(decl->Declaration.Interpolate); - for( i = first; i <= last; i++ ) { - switch (decl->Interpolation.Interpolate) { + switch (decl->Declaration.Interpolate) { case TGSI_INTERPOLATE_CONSTANT: emit_cinterp(c, i, mask); break; diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c index 2af0db3714..626c3a9d4e 100644 --- a/src/gallium/drivers/softpipe/sp_context.c +++ b/src/gallium/drivers/softpipe/sp_context.c @@ -88,7 +88,8 @@ static void softpipe_destroy( struct pipe_context *pipe ) struct pipe_winsys *ws = pipe->winsys; uint i; - draw_destroy( softpipe->draw ); + if (softpipe->draw) + draw_destroy( softpipe->draw ); softpipe->quad.polygon_stipple->destroy( softpipe->quad.polygon_stipple ); softpipe->quad.earlyz->destroy( softpipe->quad.earlyz ); @@ -128,12 +129,12 @@ softpipe_create( struct pipe_screen *screen, uint i; #ifdef PIPE_ARCH_X86 - softpipe->use_sse = GETENV( "GALLIUM_NOSSE" ) == NULL; + softpipe->use_sse = !debug_get_bool_option( "GALLIUM_NOSSE", FALSE ); #else softpipe->use_sse = FALSE; #endif - softpipe->dump_fs = GETENV( "GALLIUM_DUMP_FS" ) != NULL; + softpipe->dump_fs = debug_get_bool_option( "GALLIUM_DUMP_FS", FALSE ); softpipe->pipe.winsys = pipe_winsys; softpipe->pipe.screen = screen; @@ -178,6 +179,7 @@ softpipe_create( struct pipe_screen *screen, softpipe->pipe.draw_arrays = softpipe_draw_arrays; softpipe->pipe.draw_elements = softpipe_draw_elements; + softpipe->pipe.draw_range_elements = softpipe_draw_range_elements; softpipe->pipe.set_edgeflags = softpipe_set_edgeflags; @@ -216,17 +218,23 @@ softpipe_create( struct pipe_screen *screen, * Create drawing context and plug our rendering stage into it. */ softpipe->draw = draw_create(); - assert(softpipe->draw); + if (!softpipe->draw) + goto fail; + softpipe->setup = sp_draw_render_stage(softpipe); + if (!softpipe->setup) + goto fail; - if (GETENV( "SP_NO_RAST" ) != NULL) + if (debug_get_bool_option( "SP_NO_RAST", FALSE )) softpipe->no_rast = TRUE; - if (GETENV( "SP_VBUF" ) != NULL) { - sp_init_vbuf(softpipe); + if (debug_get_bool_option( "SP_NO_VBUF", FALSE )) { + /* Deprecated path -- vbuf is the intended interface to the draw module: + */ + draw_set_rasterize_stage(softpipe->draw, softpipe->setup); } else { - draw_set_rasterize_stage(softpipe->draw, softpipe->setup); + sp_init_vbuf(softpipe); } /* plug in AA line/point stages */ @@ -241,4 +249,8 @@ softpipe_create( struct pipe_screen *screen, sp_init_surface_functions(softpipe); return &softpipe->pipe; + + fail: + softpipe_destroy(&softpipe->pipe); + return NULL; } diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h index 62eabfb30e..078886f93c 100644 --- a/src/gallium/drivers/softpipe/sp_context.h +++ b/src/gallium/drivers/softpipe/sp_context.h @@ -69,7 +69,7 @@ struct softpipe_context { struct pipe_blend_color blend_color; struct pipe_clip_state clip; - struct pipe_constant_buffer constants[2]; + struct pipe_constant_buffer constants[PIPE_SHADER_TYPES]; struct pipe_framebuffer_state framebuffer; struct pipe_poly_stipple poly_stipple; struct pipe_scissor_state scissor; diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c index 6c58f9909d..12b44a8211 100644 --- a/src/gallium/drivers/softpipe/sp_draw_arrays.c +++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c @@ -47,14 +47,15 @@ softpipe_map_constant_buffers(struct softpipe_context *sp) { struct pipe_winsys *ws = sp->pipe.winsys; uint i; - for (i = 0; i < 2; i++) { + for (i = 0; i < PIPE_SHADER_TYPES; i++) { if (sp->constants[i].size) sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i].buffer, PIPE_BUFFER_USAGE_CPU_READ); } draw_set_mapped_constant_buffer(sp->draw, - sp->mapped_constants[PIPE_SHADER_VERTEX]); + sp->mapped_constants[PIPE_SHADER_VERTEX], + sp->constants[PIPE_SHADER_VERTEX].size); } static void @@ -68,7 +69,7 @@ softpipe_unmap_constant_buffers(struct softpipe_context *sp) */ draw_flush(sp->draw); - draw_set_mapped_constant_buffer(sp->draw, NULL); + draw_set_mapped_constant_buffer(sp->draw, NULL, 0); for (i = 0; i < 2; i++) { if (sp->constants[i].size) @@ -108,11 +109,14 @@ softpipe_draw_arrays(struct pipe_context *pipe, unsigned mode, * * XXX should the element buffer be specified/bound with a separate function? */ + boolean -softpipe_draw_elements(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, - unsigned indexSize, - unsigned mode, unsigned start, unsigned count) +softpipe_draw_range_elements(struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, + unsigned indexSize, + unsigned min_index, + unsigned max_index, + unsigned mode, unsigned start, unsigned count) { struct softpipe_context *sp = softpipe_context(pipe); struct draw_context *draw = sp->draw; @@ -141,11 +145,14 @@ softpipe_draw_elements(struct pipe_context *pipe, void *mapped_indexes = pipe->winsys->buffer_map(pipe->winsys, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ); - draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes); + draw_set_mapped_element_buffer_range(draw, indexSize, + min_index, + max_index, + mapped_indexes); } else { /* no index/element buffer */ - draw_set_mapped_element_buffer(draw, 0, NULL); + draw_set_mapped_element_buffer_range(draw, 0, start, start + count - 1, NULL); } @@ -171,6 +178,19 @@ softpipe_draw_elements(struct pipe_context *pipe, return TRUE; } +boolean +softpipe_draw_elements(struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, + unsigned indexSize, + unsigned mode, unsigned start, unsigned count) +{ + return softpipe_draw_range_elements( pipe, indexBuffer, + indexSize, + 0, 0xffffffff, + mode, start, count ); +} + + void softpipe_set_edgeflags(struct pipe_context *pipe, const unsigned *edgeflags) diff --git a/src/gallium/drivers/softpipe/sp_fs_sse.c b/src/gallium/drivers/softpipe/sp_fs_sse.c index 55741cc1df..69f7f960aa 100644 --- a/src/gallium/drivers/softpipe/sp_fs_sse.c +++ b/src/gallium/drivers/softpipe/sp_fs_sse.c @@ -46,7 +46,7 @@ /* Surely this should be defined somewhere in a tgsi header: */ -typedef void (XSTDCALL *codegen_function)( +typedef void (PIPE_CDECL *codegen_function)( const struct tgsi_exec_vector *input, struct tgsi_exec_vector *output, const float (*constant)[4], diff --git a/src/gallium/drivers/softpipe/sp_prim_setup.c b/src/gallium/drivers/softpipe/sp_prim_setup.c index 1cf9ffa632..941ab62e00 100644 --- a/src/gallium/drivers/softpipe/sp_prim_setup.c +++ b/src/gallium/drivers/softpipe/sp_prim_setup.c @@ -64,16 +64,17 @@ static INLINE struct setup_stage *setup_stage( struct draw_stage *stage ) } +typedef const float (*cptrf4)[4]; static void do_tri(struct draw_stage *stage, struct prim_header *prim) { struct setup_stage *setup = setup_stage( stage ); - + setup_tri( setup->setup, - prim->v[0]->data, - prim->v[1]->data, - prim->v[2]->data ); + (cptrf4)prim->v[0]->data, + (cptrf4)prim->v[1]->data, + (cptrf4)prim->v[2]->data ); } static void @@ -82,8 +83,8 @@ do_line(struct draw_stage *stage, struct prim_header *prim) struct setup_stage *setup = setup_stage( stage ); setup_line( setup->setup, - prim->v[0]->data, - prim->v[1]->data ); + (cptrf4)prim->v[0]->data, + (cptrf4)prim->v[1]->data ); } static void @@ -92,7 +93,7 @@ do_point(struct draw_stage *stage, struct prim_header *prim) struct setup_stage *setup = setup_stage( stage ); setup_point( setup->setup, - prim->v[0]->data ); + (cptrf4)prim->v[0]->data ); } diff --git a/src/gallium/drivers/softpipe/sp_prim_vbuf.c b/src/gallium/drivers/softpipe/sp_prim_vbuf.c index e063fe82ef..e9fae951e0 100644 --- a/src/gallium/drivers/softpipe/sp_prim_vbuf.c +++ b/src/gallium/drivers/softpipe/sp_prim_vbuf.c @@ -116,30 +116,28 @@ sp_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim) - if (prim == PIPE_PRIM_TRIANGLES || - prim == PIPE_PRIM_LINES || - prim == PIPE_PRIM_POINTS) { - cvbr->prim = prim; - return TRUE; - } - else { - return FALSE; - } + cvbr->prim = prim; + return TRUE; } +static INLINE cptrf4 get_vert( const void *vertex_buffer, + int index, + int stride ) +{ + return (cptrf4)((char *)vertex_buffer + index * stride); +} static void -sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr_indices) +sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) { struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); struct softpipe_context *softpipe = cvbr->softpipe; - unsigned vertex_size = softpipe->vertex_info_vbuf.size * sizeof(float); - unsigned i, j; - void *vertex_buffer = cvbr->vertex_buffer; - cptrf4 v[3]; + unsigned stride = softpipe->vertex_info_vbuf.size * sizeof(float); + unsigned i; + const void *vertex_buffer = cvbr->vertex_buffer; /* XXX: break this dependency - make setup_context live under * softpipe, rename the old "setup" draw stage to something else. @@ -149,40 +147,98 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr_indices) switch (cvbr->prim) { - case PIPE_PRIM_TRIANGLES: - for (i = 0; i < nr_indices; i += 3) { - for (j = 0; j < 3; j++) - v[j] = (cptrf4)((char *)vertex_buffer + - indices[i+j] * vertex_size); - - setup_tri( setup_ctx, - v[0], - v[1], - v[2]); + case PIPE_PRIM_POINTS: + for (i = 0; i < nr; i++) { + setup_point( setup_ctx, + get_vert(vertex_buffer, indices[i-0], stride) ); } break; case PIPE_PRIM_LINES: - for (i = 0; i < nr_indices; i += 2) { - for (j = 0; j < 2; j++) - v[j] = (cptrf4)((char *)vertex_buffer + - indices[i+j] * vertex_size); + for (i = 1; i < nr; i += 2) { + setup_line( setup_ctx, + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + } + break; + case PIPE_PRIM_LINE_STRIP: + for (i = 1; i < nr; i ++) { setup_line( setup_ctx, - v[0], - v[1] ); + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); } break; - case PIPE_PRIM_POINTS: - for (i = 0; i < nr_indices; i++) { - v[0] = (cptrf4)((char *)vertex_buffer + - indices[i] * vertex_size); + case PIPE_PRIM_LINE_LOOP: + for (i = 1; i < nr; i ++) { + setup_line( setup_ctx, + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + } + if (nr) { + setup_line( setup_ctx, + get_vert(vertex_buffer, indices[nr-1], stride), + get_vert(vertex_buffer, indices[0], stride) ); + } + break; - setup_point( setup_ctx, - v[0] ); + + case PIPE_PRIM_TRIANGLES: + for (i = 2; i < nr; i += 3) { + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride)); + } + break; + + case PIPE_PRIM_TRIANGLE_STRIP: + for (i = 2; i < nr; i += 1) { + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[i+(i&1)-2], stride), + get_vert(vertex_buffer, indices[i-(i&1)-1], stride), + get_vert(vertex_buffer, indices[i-0], stride)); + } + break; + + case PIPE_PRIM_TRIANGLE_FAN: + case PIPE_PRIM_POLYGON: + for (i = 2; i < nr; i += 1) { + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[0], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride)); } break; + case PIPE_PRIM_QUADS: + for (i = 3; i < nr; i += 4) { + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-0], stride)); + + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride)); + } + break; + case PIPE_PRIM_QUAD_STRIP: + for (i = 3; i < nr; i += 2) { + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-0], stride)); + + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-0], stride)); + } + break; + default: + assert(0); } /* XXX: why are we calling this??? If we had to call something, it @@ -202,131 +258,107 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); struct softpipe_context *softpipe = cvbr->softpipe; struct draw_stage *setup = softpipe->setup; - const void *vertex_buffer = cvbr->vertex_buffer; - const unsigned vertex_size = softpipe->vertex_info_vbuf.size * sizeof(float); + const void *vertex_buffer = NULL; + const unsigned stride = softpipe->vertex_info_vbuf.size * sizeof(float); unsigned i; struct setup_context *setup_ctx = sp_draw_setup_context(setup); - cptrf4 v[3]; -#define VERTEX(I) \ - (cptrf4) ((char *) vertex_buffer + (I) * vertex_size) + vertex_buffer = (void *)get_vert(cvbr->vertex_buffer, start, stride); switch (cvbr->prim) { case PIPE_PRIM_POINTS: for (i = 0; i < nr; i++) { - v[0] = VERTEX(i); - setup_point( setup_ctx, v[0] ); + setup_point( setup_ctx, + get_vert(vertex_buffer, i-0, stride) ); } break; + case PIPE_PRIM_LINES: - assert(nr % 2 == 0); - for (i = 0; i < nr; i += 2) { - v[0] = VERTEX(i); - v[1] = VERTEX(i + 1); - setup_line( setup_ctx, v[0], v[1] ); + for (i = 1; i < nr; i += 2) { + setup_line( setup_ctx, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); } break; + case PIPE_PRIM_LINE_STRIP: - for (i = 1; i < nr; i++) { - v[0] = VERTEX(i - 1); - v[1] = VERTEX(i); - setup_line( setup_ctx, v[0], v[1] ); + for (i = 1; i < nr; i ++) { + setup_line( setup_ctx, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); } break; + + case PIPE_PRIM_LINE_LOOP: + for (i = 1; i < nr; i ++) { + setup_line( setup_ctx, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); + } + if (nr) { + setup_line( setup_ctx, + get_vert(vertex_buffer, nr-1, stride), + get_vert(vertex_buffer, 0, stride) ); + } + break; + + case PIPE_PRIM_TRIANGLES: - assert(nr % 3 == 0); - for (i = 0; i < nr; i += 3) { - v[0] = VERTEX(i + 0); - v[1] = VERTEX(i + 1); - v[2] = VERTEX(i + 2); + for (i = 2; i < nr; i += 3) { setup_tri( setup_ctx, - v[0], - v[1], - v[2] ); + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride)); } break; + case PIPE_PRIM_TRIANGLE_STRIP: - assert(nr >= 3); - for (i = 2; i < nr; i++) { - v[0] = VERTEX(i - 2); - v[1] = VERTEX(i - 1); - v[2] = VERTEX(i); + for (i = 2; i < nr; i += 1) { setup_tri( setup_ctx, - v[0], - v[1], - v[2] ); + get_vert(vertex_buffer, i+(i&1)-2, stride), + get_vert(vertex_buffer, i-(i&1)-1, stride), + get_vert(vertex_buffer, i-0, stride)); } break; + case PIPE_PRIM_TRIANGLE_FAN: - assert(nr >= 3); - for (i = 2; i < nr; i++) { - v[0] = VERTEX(0); - v[1] = VERTEX(i - 1); - v[2] = VERTEX(i); + case PIPE_PRIM_POLYGON: + for (i = 2; i < nr; i += 1) { setup_tri( setup_ctx, - v[0], - v[1], - v[2] ); + get_vert(vertex_buffer, 0, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride)); } break; case PIPE_PRIM_QUADS: - assert(nr % 4 == 0); - for (i = 0; i < nr; i += 4) { - v[0] = VERTEX(i + 0); - v[1] = VERTEX(i + 1); - v[2] = VERTEX(i + 2); + for (i = 3; i < nr; i += 4) { setup_tri( setup_ctx, - v[0], - v[1], - v[2] ); + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-0, stride)); - v[0] = VERTEX(i + 0); - v[1] = VERTEX(i + 2); - v[2] = VERTEX(i + 3); setup_tri( setup_ctx, - v[0], - v[1], - v[2] ); + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride)); } break; case PIPE_PRIM_QUAD_STRIP: - assert(nr >= 4); - for (i = 2; i < nr; i += 2) { - v[0] = VERTEX(i - 2); - v[1] = VERTEX(i); - v[2] = VERTEX(i + 1); + for (i = 3; i < nr; i += 2) { setup_tri( setup_ctx, - v[0], - v[1], - v[2] ); + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-0, stride)); - v[0] = VERTEX(i - 2); - v[1] = VERTEX(i + 1); - v[2] = VERTEX(i - 1); setup_tri( setup_ctx, - v[0], - v[1], - v[2] ); - } - break; - case PIPE_PRIM_POLYGON: - /* draw as tri fan */ - for (i = 2; i < nr; i++) { - v[0] = VERTEX(0); - v[1] = VERTEX(i - 1); - v[2] = VERTEX(i); - setup_tri( setup_ctx, - v[0], - v[1], - v[2] ); + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-0, stride)); } break; default: - /* XXX finish remaining prim types */ assert(0); } - -#undef VERTEX } diff --git a/src/gallium/drivers/softpipe/sp_quad_depth_test.c b/src/gallium/drivers/softpipe/sp_quad_depth_test.c index a1859f9883..33888abcc5 100644 --- a/src/gallium/drivers/softpipe/sp_quad_depth_test.c +++ b/src/gallium/drivers/softpipe/sp_quad_depth_test.c @@ -230,7 +230,7 @@ sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad) int x = quad->x0 % TILE_SIZE + (j & 1); int y = quad->y0 % TILE_SIZE + (j >> 1); uint z24s8 = tile->data.depth32[y][x]; - z24s8 = (z24s8 & 0xff) | (bzzzz[j] << 24); + z24s8 = (z24s8 & 0xff) | (bzzzz[j] << 8); tile->data.depth32[y][x] = z24s8; } break; diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h index 452e51fa79..701e02b295 100644 --- a/src/gallium/drivers/softpipe/sp_state.h +++ b/src/gallium/drivers/softpipe/sp_state.h @@ -171,6 +171,13 @@ boolean softpipe_draw_elements(struct pipe_context *pipe, struct pipe_buffer *indexBuffer, unsigned indexSize, unsigned mode, unsigned start, unsigned count); +boolean +softpipe_draw_range_elements(struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, + unsigned indexSize, + unsigned min_index, + unsigned max_index, + unsigned mode, unsigned start, unsigned count); void softpipe_set_edgeflags(struct pipe_context *pipe, const unsigned *edgeflags); diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index 1d7a1fffe4..ef8c5bd6b0 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -207,12 +207,19 @@ softpipe_get_tex_surface(struct pipe_screen *screen, * done with the CPU. Let's adjust the flags to take that into * account. */ - if (ps->usage & PIPE_BUFFER_USAGE_GPU_WRITE) - ps->usage |= PIPE_BUFFER_USAGE_CPU_WRITE; + if (ps->usage & PIPE_BUFFER_USAGE_GPU_WRITE) { + /* GPU_WRITE means "render" and that can involve reads (blending) */ + ps->usage |= PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_CPU_READ; + } if (ps->usage & PIPE_BUFFER_USAGE_GPU_READ) ps->usage |= PIPE_BUFFER_USAGE_CPU_READ; + if (ps->usage & (PIPE_BUFFER_USAGE_CPU_WRITE | + PIPE_BUFFER_USAGE_GPU_WRITE)) { + /* Mark the surface as dirty. The tile cache will look for this. */ + spt->modified = TRUE; + } pipe_texture_reference(&ps->texture, pt); ps->face = face; diff --git a/src/gallium/drivers/softpipe/sp_texture.h b/src/gallium/drivers/softpipe/sp_texture.h index 779a9d8fc9..0e1017632c 100644 --- a/src/gallium/drivers/softpipe/sp_texture.h +++ b/src/gallium/drivers/softpipe/sp_texture.h @@ -47,6 +47,8 @@ struct softpipe_texture /* The data is held here: */ struct pipe_buffer *buffer; + + boolean modified; }; diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c index 28c29da87c..2d5d2b50f5 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tile_cache.c @@ -37,6 +37,7 @@ #include "util/p_tile.h" #include "sp_context.h" #include "sp_surface.h" +#include "sp_texture.h" #include "sp_tile_cache.h" #define NUM_ENTRIES 32 @@ -169,6 +170,7 @@ sp_tile_cache_set_surface(struct softpipe_tile_cache *tc, PIPE_BUFFER_USAGE_CPU_WRITE); tc->depth_stencil = (ps->format == PIPE_FORMAT_S8Z24_UNORM || + ps->format == PIPE_FORMAT_Z24S8_UNORM || ps->format == PIPE_FORMAT_Z16_UNORM || ps->format == PIPE_FORMAT_Z32_UNORM || ps->format == PIPE_FORMAT_S8_UNORM); @@ -505,6 +507,15 @@ sp_get_cached_tile_tex(struct pipe_context *pipe, face, level); struct softpipe_cached_tile *tile = tc->entries + pos; + if (tc->texture) { + struct softpipe_texture *spt = softpipe_texture(tc->texture); + if (spt->modified) { + /* texture was modified, force a cache reload */ + tile->x = -1; + spt->modified = FALSE; + } + } + if (tile_x != tile->x || tile_y != tile->y || z != tile->z || diff --git a/src/gallium/include/pipe/p_compiler.h b/src/gallium/include/pipe/p_compiler.h index a4b772bc4f..521ef2d189 100644 --- a/src/gallium/include/pipe/p_compiler.h +++ b/src/gallium/include/pipe/p_compiler.h @@ -52,39 +52,63 @@ #endif /* __MSC__ */ -typedef unsigned int uint; -typedef unsigned char ubyte; -typedef unsigned char boolean; -typedef unsigned short ushort; -typedef unsigned long long uint64; - - #if defined(__MSC__) -typedef char int8_t; -typedef unsigned char uint8_t; -typedef short int16_t; -typedef unsigned short uint16_t; -typedef long int32_t; -typedef unsigned long uint32_t; -typedef long long int64_t; -typedef unsigned long long uint64_t; +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +#ifndef __eglplatform_h_ +typedef __int32 int32_t; +#endif +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; #if defined(_WIN64) typedef __int64 intptr_t; typedef unsigned __int64 uintptr_t; #else -typedef int intptr_t; -typedef unsigned int uintptr_t; +typedef __int32 intptr_t; +typedef unsigned __int32 uintptr_t; #endif +#define INT64_C(__val) __val##i64 +#define UINT64_C(__val) __val##ui64 + +#ifndef __cplusplus +#define false 0 +#define true 1 +#define bool _Bool +typedef int _Bool; +#define __bool_true_false_are_defined 1 +#endif /* !__cplusplus */ + #else +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif #include <stdint.h> +#include <stdbool.h> #endif -#define TRUE 1 -#define FALSE 0 +typedef unsigned int uint; +typedef unsigned char ubyte; +typedef unsigned short ushort; +typedef uint64_t uint64; + +#if 0 +#define boolean bool +#else +typedef unsigned char boolean; +#endif +#ifndef TRUE +#define TRUE true +#endif +#ifndef FALSE +#define FALSE false +#endif /* Function inlining */ @@ -103,6 +127,17 @@ typedef unsigned int uintptr_t; #endif +/* This should match linux gcc cdecl semantics everywhere, so that we + * just codegen one calling convention on all platforms. + */ +#ifdef _MSC_VER +#define PIPE_CDECL __cdecl +#else +#define PIPE_CDECL +#endif + + + #if defined __GNUC__ #define ALIGN16_DECL(TYPE, NAME, SIZE) TYPE NAME##___aligned[SIZE] __attribute__(( aligned( 16 ) )) #define ALIGN16_ASSIGN(NAME) NAME##___aligned @@ -115,14 +150,4 @@ typedef unsigned int uintptr_t; -/** For calling code-gen'd functions */ -#if !defined(XSTDCALL) -#if defined(WIN32) -#define XSTDCALL __stdcall -#else -#define XSTDCALL -#endif -#endif - - #endif /* P_COMPILER_H */ diff --git a/src/gallium/include/pipe/p_config.h b/src/gallium/include/pipe/p_config.h index 5c030bdfff..af3746c026 100644 --- a/src/gallium/include/pipe/p_config.h +++ b/src/gallium/include/pipe/p_config.h @@ -33,7 +33,12 @@ * architecture, and operating system being used. These defines should be used * throughout the code to facilitate porting to new platforms. It is likely that * this file is auto-generated by an autoconf-like tool at some point, as some - * things cannot be determined by existing defines alone. + * things cannot be determined by pre-defined environment alone. + * + * See also: + * - http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html + * - echo | gcc -dM -E - | sort + * - http://msdn.microsoft.com/en-us/library/b0084kay.aspx * * @author José Fonseca <jrfonseca@tungstengraphics.com> */ @@ -50,6 +55,15 @@ #define PIPE_CC_GCC #endif +/* + * Meaning of _MSC_VER value: + * - 1400: Visual C++ 2005 + * - 1310: Visual C++ .NET 2003 + * - 1300: Visual C++ .NET 2002 + * + * __MSC__ seems to be an old macro -- it is not pre-defined on recent MSVC + * versions. + */ #if defined(_MSC_VER) || defined(__MSC__) #define PIPE_CC_MSVC #endif @@ -63,11 +77,11 @@ * Processor architecture */ -#if defined(_X86_) || defined(__i386__) || defined(__386__) || defined(i386) +#if defined(__i386__) /* gcc */ || defined(_M_IX86) /* msvc */ || defined(_X86_) || defined(__386__) || defined(i386) #define PIPE_ARCH_X86 #endif -#if 0 /* FIXME */ +#if defined(__x86_64__) /* gcc */ || defined(_M_X64) /* msvc */ || defined(_M_AMD64) /* msvc */ #define PIPE_ARCH_X86_64 #endif @@ -77,7 +91,9 @@ /* - * Operating system + * Operating system family. + * + * See subsystem below for a more fine-grained distinction. */ #if defined(__linux__) @@ -90,30 +106,30 @@ /* - * Subsystem + * Subsystem. * - * XXX: There is no way to autodetect this. + * NOTE: There is no way to auto-detect most of these. */ #if defined(PIPE_OS_LINUX) #define PIPE_SUBSYSTEM_DRI -#endif +#endif /* PIPE_OS_LINUX */ #if defined(PIPE_OS_WINDOWS) -#if !defined(PIPE_SUBSYSTEM_USER) && !defined(PIPE_SUBSYSTEM_KERNEL) -#error Neither PIPE_SUBSYSTEM_USER or PIPE_SUBSYSTEM_KERNEL defined. -#endif -#if defined(PIPE_SUBSYSTEM_KERNEL) -#define PIPE_SUBSYSTEM_WINDOWS_DISPLAY -#endif -#if 0 /* FIXME */ -#define PIPE_SUBSYSTEM_WINDOWS_MINIPORT -#endif -#if 0 /* FIXME */ +#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) +/* Windows 2000/XP Display Driver */ +#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT) +/* Windows 2000/XP Miniport Driver */ +#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) +/* Windows User-space Library */ +#elif defined(PIPE_SUBSYSTEM_WINDOWS_CE) +/* Windows CE 5.0/6.0 */ +#else +#ifdef _WIN32_WCE #define PIPE_SUBSYSTEM_WINDOWS_CE -#endif -#if defined(PIPE_SUBSYSTEM_USER) -#define PIPE_SUBSYSTEM_WINDOWS_USER +#else /* !_WIN32_WCE */ +#error No PIPE_SUBSYSTEM_WINDOWS_xxx subsystem defined. +#endif /* !_WIN32_WCE */ #endif #endif /* PIPE_OS_WINDOWS */ diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h index 0f68f592f7..faf112c6d6 100644 --- a/src/gallium/include/pipe/p_context.h +++ b/src/gallium/include/pipe/p_context.h @@ -76,6 +76,20 @@ struct pipe_context { struct pipe_buffer *indexBuffer, unsigned indexSize, unsigned mode, unsigned start, unsigned count); + + /* XXX: this is (probably) a temporary entrypoint, as the range + * information should be available from the vertex_buffer state. + * Using this to quickly evaluate a specialized path in the draw + * module. + */ + boolean (*draw_range_elements)( struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, + unsigned indexSize, + unsigned minIndex, + unsigned maxIndex, + unsigned mode, + unsigned start, + unsigned count); /*@}*/ diff --git a/src/gallium/include/pipe/p_debug.h b/src/gallium/include/pipe/p_debug.h index 0af635be57..9011557006 100644 --- a/src/gallium/include/pipe/p_debug.h +++ b/src/gallium/include/pipe/p_debug.h @@ -59,6 +59,13 @@ extern "C" { #endif #endif + +/* MSVC bebore VC7 does not have the __FUNCTION__ macro */ +#if defined(_MSC_VER) && _MSC_VER < 1300 +#define __FUNCTION__ "???" +#endif + + void _debug_vprintf(const char *format, va_list ap); @@ -127,8 +134,8 @@ void _debug_break(void); #ifdef DEBUG #if (defined(__i386__) || defined(__386__)) && defined(__GNUC__) #define debug_break() __asm("int3") -#elif (defined(__i386__) || defined(__386__)) && defined(__MSC__) -#define debug_break() _asm {int 3} +#elif defined(_M_IX86) && defined(_MSC_VER) +#define debug_break() do { _asm {int 3} } while(0) #else #define debug_break() _debug_break() #endif @@ -282,7 +289,7 @@ boolean debug_get_bool_option(const char *name, boolean dfault); long -debug_get_unsigned_option(const char *name, long dfault); +debug_get_num_option(const char *name, long dfault); unsigned long debug_get_flags_option(const char *name, diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index 83330ef22f..f8fadf31b6 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -274,6 +274,10 @@ enum pipe_texture_target { #define PIPE_CAP_MAX_POINT_WIDTH_AA 17 #define PIPE_CAP_MAX_TEXTURE_ANISOTROPY 18 #define PIPE_CAP_MAX_TEXTURE_LOD_BIAS 19 +#define PIPE_CAP_GUARD_BAND_LEFT 20 /*< float */ +#define PIPE_CAP_GUARD_BAND_TOP 21 /*< float */ +#define PIPE_CAP_GUARD_BAND_RIGHT 22 /*< float */ +#define PIPE_CAP_GUARD_BAND_BOTTOM 23 /*< float */ #ifdef __cplusplus diff --git a/src/gallium/include/pipe/p_format.h b/src/gallium/include/pipe/p_format.h index 9ba00f8d7b..579fdb2957 100644 --- a/src/gallium/include/pipe/p_format.h +++ b/src/gallium/include/pipe/p_format.h @@ -50,7 +50,7 @@ extern "C" { #define PIPE_FORMAT_LAYOUT_RGBAZS 0 #define PIPE_FORMAT_LAYOUT_YCBCR 1 #define PIPE_FORMAT_LAYOUT_DXT 2 /**< XXX temporary? */ - +#define PIPE_FORMAT_LAYOUT_MIXED 3 static INLINE uint pf_layout(uint f) /**< PIPE_FORMAT_LAYOUT_ */ { @@ -62,7 +62,7 @@ static INLINE uint pf_layout(uint f) /**< PIPE_FORMAT_LAYOUT_ */ */ /** - * Format component selectors for RGBAZS layout. + * Format component selectors for RGBAZS & MIXED layout. */ #define PIPE_FORMAT_COMP_R 0 #define PIPE_FORMAT_COMP_G 1 @@ -109,8 +109,6 @@ static INLINE uint pf_get(pipe_format_rgbazs_t f, uint shift, uint mask) return (f >> shift) & mask; } -/* XXX: The bit layout needs to be revised, can't currently encode 10-bit components. */ - #define pf_swizzle_x(f) pf_get(f, 2, 0x7) /**< PIPE_FORMAT_COMP_ */ #define pf_swizzle_y(f) pf_get(f, 5, 0x7) /**< PIPE_FORMAT_COMP_ */ #define pf_swizzle_z(f) pf_get(f, 8, 0x7) /**< PIPE_FORMAT_COMP_ */ @@ -121,21 +119,21 @@ static INLINE uint pf_get(pipe_format_rgbazs_t f, uint shift, uint mask) #define pf_size_z(f) pf_get(f, 20, 0x7) /**< Size of Z */ #define pf_size_w(f) pf_get(f, 23, 0x7) /**< Size of W */ #define pf_size_xyzw(f,i) pf_get(f, 14+((i)*3), 0x7) -#define pf_exp8(f) pf_get(f, 26, 0x3) /**< Scale size by 8 ^ exp8 */ -#define pf_type(f) pf_get(f, 28, 0xf) /**< PIPE_FORMAT_TYPE_ */ +#define pf_exp2(f) pf_get(f, 26, 0x7) /**< Scale size by 2 ^ exp2 */ +#define pf_type(f) pf_get(f, 29, 0x7) /**< PIPE_FORMAT_TYPE_ */ /** * Helper macro to encode the above structure into a 32-bit value. */ -#define _PIPE_FORMAT_RGBAZS( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, EXP8, TYPE ) (\ +#define _PIPE_FORMAT_RGBAZS( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, EXP2, TYPE ) (\ (PIPE_FORMAT_LAYOUT_RGBAZS << 0) |\ ((SWZ) << 2) |\ ((SIZEX) << 14) |\ ((SIZEY) << 17) |\ ((SIZEZ) << 20) |\ ((SIZEW) << 23) |\ - ((EXP8) << 26) |\ - ((TYPE) << 28) ) + ((EXP2) << 26) |\ + ((TYPE) << 29) ) /** * Helper macro to encode the swizzle part of the structure above. @@ -149,16 +147,52 @@ static INLINE uint pf_get(pipe_format_rgbazs_t f, uint shift, uint mask) _PIPE_FORMAT_RGBAZS( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, 0, TYPE ) /** + * Shorthand macro for RGBAZS layout with component sizes in 2-bit units. + */ +#define _PIPE_FORMAT_RGBAZS_2( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, TYPE )\ + _PIPE_FORMAT_RGBAZS( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, 1, TYPE ) + +/** * Shorthand macro for RGBAZS layout with component sizes in 8-bit units. */ #define _PIPE_FORMAT_RGBAZS_8( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, TYPE )\ - _PIPE_FORMAT_RGBAZS( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, 1, TYPE ) + _PIPE_FORMAT_RGBAZS( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, 3, TYPE ) /** * Shorthand macro for RGBAZS layout with component sizes in 64-bit units. */ #define _PIPE_FORMAT_RGBAZS_64( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, TYPE )\ - _PIPE_FORMAT_RGBAZS( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, 2, TYPE ) + _PIPE_FORMAT_RGBAZS( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, 6, TYPE ) + +typedef uint pipe_format_mixed_t; + +/* NOTE: Use pf_swizzle_* and pf_size_* macros for swizzles and sizes. + */ + +#define pf_mixed_sign_x(f) pf_get( f, 26, 0x1 ) /*< Sign of X */ +#define pf_mixed_sign_y(f) pf_get( f, 27, 0x1 ) /*< Sign of Y */ +#define pf_mixed_sign_z(f) pf_get( f, 28, 0x1 ) /*< Sign of Z */ +#define pf_mixed_sign_w(f) pf_get( f, 29, 0x1 ) /*< Sign of W */ +#define pf_mixed_sign_xyzw(f, i) pf_get( f, 26 + (i), 0x1 ) +#define pf_mixed_normalized(f) pf_get( f, 30, 0x1 ) /*< Type is NORM (1) or SCALED (0) */ +#define pf_mixed_scale8(f) pf_get( f, 31, 0x1 ) /*< Scale size by either one (0) or eight (1) */ + +/** + * Helper macro to encode the above structure into a 32-bit value. + */ +#define _PIPE_FORMAT_MIXED( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, SIGNX, SIGNY, SIGNZ, SIGNW, NORMALIZED, SCALE8 ) (\ + (PIPE_FORMAT_LAYOUT_MIXED << 0) |\ + ((SWZ) << 2) |\ + ((SIZEX) << 14) |\ + ((SIZEY) << 17) |\ + ((SIZEZ) << 20) |\ + ((SIZEW) << 23) |\ + ((SIGNX) << 26) |\ + ((SIGNY) << 27) |\ + ((SIGNZ) << 28) |\ + ((SIGNW) << 29) |\ + ((NORMALIZED) << 30) |\ + ((SCALE8) << 31) ) /** * Shorthand macro for common format swizzles. @@ -168,8 +202,10 @@ static INLINE uint pf_get(pipe_format_rgbazs_t f, uint shift, uint mask) #define _PIPE_FORMAT_RGB1 _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_G, PIPE_FORMAT_COMP_B, PIPE_FORMAT_COMP_1 ) #define _PIPE_FORMAT_RGBA _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_G, PIPE_FORMAT_COMP_B, PIPE_FORMAT_COMP_A ) #define _PIPE_FORMAT_ARGB _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_A, PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_G, PIPE_FORMAT_COMP_B ) +#define _PIPE_FORMAT_ABGR _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_A, PIPE_FORMAT_COMP_B, PIPE_FORMAT_COMP_G, PIPE_FORMAT_COMP_R ) #define _PIPE_FORMAT_BGRA _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_B, PIPE_FORMAT_COMP_G, PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_A ) #define _PIPE_FORMAT_1RGB _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_1, PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_G, PIPE_FORMAT_COMP_B ) +#define _PIPE_FORMAT_1BGR _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_1, PIPE_FORMAT_COMP_B, PIPE_FORMAT_COMP_G, PIPE_FORMAT_COMP_R ) #define _PIPE_FORMAT_BGR1 _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_B, PIPE_FORMAT_COMP_G, PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_1 ) #define _PIPE_FORMAT_0000 _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_0 ) #define _PIPE_FORMAT_000R _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_R ) @@ -238,10 +274,12 @@ enum pipe_format { PIPE_FORMAT_A1R5G5B5_UNORM = _PIPE_FORMAT_RGBAZS_1 ( _PIPE_FORMAT_ARGB, 1, 5, 5, 5, PIPE_FORMAT_TYPE_UNORM ), PIPE_FORMAT_A4R4G4B4_UNORM = _PIPE_FORMAT_RGBAZS_1 ( _PIPE_FORMAT_ARGB, 4, 4, 4, 4, PIPE_FORMAT_TYPE_UNORM ), PIPE_FORMAT_R5G6B5_UNORM = _PIPE_FORMAT_RGBAZS_1 ( _PIPE_FORMAT_RGB1, 5, 6, 5, 0, PIPE_FORMAT_TYPE_UNORM ), + PIPE_FORMAT_A2B10G10R10_UNORM = _PIPE_FORMAT_RGBAZS_2 ( _PIPE_FORMAT_ABGR, 1, 5, 5, 5, PIPE_FORMAT_TYPE_UNORM ), PIPE_FORMAT_L8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RRR1, 1, 1, 1, 0, PIPE_FORMAT_TYPE_UNORM ), /**< ubyte luminance */ PIPE_FORMAT_A8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_000R, 0, 0, 0, 1, PIPE_FORMAT_TYPE_UNORM ), /**< ubyte alpha */ PIPE_FORMAT_I8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RRRR, 1, 1, 1, 1, PIPE_FORMAT_TYPE_UNORM ), /**< ubyte intensity */ PIPE_FORMAT_A8L8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RRRG, 1, 1, 1, 1, PIPE_FORMAT_TYPE_UNORM ), /**< ubyte alpha, luminance */ + PIPE_FORMAT_L16_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RRR1, 2, 2, 2, 0, PIPE_FORMAT_TYPE_UNORM ), /**< ushort luminance */ PIPE_FORMAT_YCBCR = _PIPE_FORMAT_YCBCR( 0 ), PIPE_FORMAT_YCBCR_REV = _PIPE_FORMAT_YCBCR( 1 ), PIPE_FORMAT_Z16_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_Z000, 2, 0, 0, 0, PIPE_FORMAT_TYPE_UNORM ), @@ -322,6 +360,10 @@ enum pipe_format { PIPE_FORMAT_R8G8B8A8_SRGB = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGBA, 1, 1, 1, 1, PIPE_FORMAT_TYPE_SRGB ), PIPE_FORMAT_R8G8B8X8_SRGB = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 1, 1, 1, 1, PIPE_FORMAT_TYPE_SRGB ), + /* mixed formats */ + PIPE_FORMAT_X8UB8UG8SR8S_NORM = _PIPE_FORMAT_MIXED( _PIPE_FORMAT_1BGR, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1 ), + PIPE_FORMAT_B6UG5SR5S_NORM = _PIPE_FORMAT_MIXED( _PIPE_FORMAT_BGR1, 6, 5, 5, 0, 0, 1, 1, 0, 1, 0 ), + /* compressed formats */ PIPE_FORMAT_DXT1_RGB = _PIPE_FORMAT_DXT( 1, 8, 8, 8, 0 ), PIPE_FORMAT_DXT1_RGBA = _PIPE_FORMAT_DXT( 1, 8, 8, 8, 8 ), @@ -329,7 +371,6 @@ enum pipe_format { PIPE_FORMAT_DXT5_RGBA = _PIPE_FORMAT_DXT( 5, 8, 8, 8, 8 ) }; - /** * Builds pipe format name from format token. */ @@ -358,7 +399,9 @@ static INLINE uint pf_get_component_bits( enum pipe_format format, uint comp ) else { size = 0; } - return size << (pf_exp8(format) * 3); + if (pf_layout( format ) == PIPE_FORMAT_LAYOUT_RGBAZS) + return size << pf_exp2( format ); + return size << (pf_mixed_scale8( format ) * 3); } /** @@ -368,6 +411,7 @@ static INLINE uint pf_get_bits( enum pipe_format format ) { switch (pf_layout(format)) { case PIPE_FORMAT_LAYOUT_RGBAZS: + case PIPE_FORMAT_LAYOUT_MIXED: return pf_get_component_bits( format, PIPE_FORMAT_COMP_0 ) + pf_get_component_bits( format, PIPE_FORMAT_COMP_1 ) + diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h index f05e1a34b3..84e5096418 100644 --- a/src/gallium/include/pipe/p_shader_tokens.h +++ b/src/gallium/include/pipe/p_shader_tokens.h @@ -55,9 +55,6 @@ enum tgsi_file_type { }; -#define TGSI_DECLARE_RANGE 0 -#define TGSI_DECLARE_MASK 1 - #define TGSI_WRITEMASK_NONE 0x00 #define TGSI_WRITEMASK_X 0x01 #define TGSI_WRITEMASK_Y 0x02 @@ -75,16 +72,19 @@ enum tgsi_file_type { #define TGSI_WRITEMASK_YZW 0x0E #define TGSI_WRITEMASK_XYZW 0x0F +#define TGSI_INTERPOLATE_CONSTANT 0 +#define TGSI_INTERPOLATE_LINEAR 1 +#define TGSI_INTERPOLATE_PERSPECTIVE 2 + struct tgsi_declaration { unsigned Type : 4; /* TGSI_TOKEN_TYPE_DECLARATION */ unsigned Size : 8; /* UINT */ unsigned File : 4; /* one of TGSI_FILE_x */ - unsigned Declare : 4; /* one of TGSI_DECLARE_x */ unsigned UsageMask : 4; /* bitmask of TGSI_WRITEMASK_x flags */ - unsigned Interpolate : 1; /* BOOL, any interpolation info? */ + unsigned Interpolate : 4; /* TGSI_INTERPOLATE_ */ unsigned Semantic : 1; /* BOOL, any semantic info? */ - unsigned Padding : 5; + unsigned Padding : 6; unsigned Extended : 1; /* BOOL */ }; @@ -94,21 +94,6 @@ struct tgsi_declaration_range unsigned Last : 16; /* UINT */ }; -struct tgsi_declaration_mask -{ - unsigned Mask : 32; /* UINT */ -}; - -#define TGSI_INTERPOLATE_CONSTANT 0 -#define TGSI_INTERPOLATE_LINEAR 1 -#define TGSI_INTERPOLATE_PERSPECTIVE 2 - -struct tgsi_declaration_interpolation -{ - unsigned Interpolate : 4; /* TGSI_INTERPOLATE_ */ - unsigned Padding : 28; -}; - #define TGSI_SEMANTIC_POSITION 0 #define TGSI_SEMANTIC_COLOR 1 #define TGSI_SEMANTIC_BCOLOR 2 /**< back-face color */ @@ -247,7 +232,7 @@ struct tgsi_immediate_float32 /* * GL_ARB_vertex_program */ -#define TGSI_OPCODE_SWZ TGSI_OPCODE_MOV +#define TGSI_OPCODE_SWZ 118 #define TGSI_OPCODE_XPD TGSI_OPCODE_CROSSPRODUCT /* @@ -403,7 +388,7 @@ struct tgsi_immediate_float32 #define TGSI_OPCODE_KIL 116 /* unpredicated kill */ #define TGSI_OPCODE_END 117 /* aka HALT */ -#define TGSI_OPCODE_LAST 118 +#define TGSI_OPCODE_LAST 119 #define TGSI_SAT_NONE 0 /* do not saturate */ #define TGSI_SAT_ZERO_ONE 1 /* clamp to [0,1] */ @@ -636,6 +621,10 @@ struct tgsi_src_register_ext * * NegateX, NegateY, NegateZ and NegateW negate individual components of the * source register. + * + * NOTE: To simplify matter, if this token is present, the corresponding Swizzle + * and Negate fields in tgsi_src_register should be set to X,Y,Z,W + * and FALSE, respectively. */ struct tgsi_src_register_ext_swz diff --git a/src/gallium/include/pipe/p_util.h b/src/gallium/include/pipe/p_util.h index 597354ca96..8b3003bcef 100644 --- a/src/gallium/include/pipe/p_util.h +++ b/src/gallium/include/pipe/p_util.h @@ -140,8 +140,6 @@ REALLOC( void *old_ptr, unsigned old_size, unsigned new_size ) #define CALLOC_STRUCT(T) (struct T *) CALLOC(1, sizeof(struct T)) -#define GETENV( X ) debug_get_option( X, NULL ) - /** * Return memory on given byte alignment @@ -410,10 +408,9 @@ extern void pipe_copy_rect(ubyte * dst, unsigned cpp, unsigned dst_pitch, -#ifdef WIN32 - -#if !defined(_INC_MATH) || !defined(__cplusplus) - +#if defined(_MSC_VER) +#if _MSC_VER < 1400 && !defined(__cplusplus) + static INLINE float cosf( float f ) { return (float) cos( (double) f ); @@ -451,10 +448,17 @@ static INLINE float fabsf( float f ) static INLINE float logf( float f ) { - return (float) cos( (double) f ); + return (float) log( (double) f ); } -#endif /* _INC_MATH */ + +#else +/* Work-around an extra semi-colon in VS 2005 logf definition */ +#ifdef logf +#undef logf +#define logf(x) ((float)log((double)(x))) +#endif /* logf */ #endif +#endif /* _MSC_VER */ #ifdef __cplusplus diff --git a/src/gallium/winsys/SConscript b/src/gallium/winsys/SConscript index e8a581adb2..bf1718e7a5 100644 --- a/src/gallium/winsys/SConscript +++ b/src/gallium/winsys/SConscript @@ -1,11 +1,16 @@ Import('*') -if 'intel' in env['winsys'] and dri: +if env['dri']: SConscript([ 'dri/SConscript', ]) -if 'xlib' in env['winsys'] and not dri: +if 'xlib' in env['winsys']: SConscript([ 'xlib/SConscript', ]) + +if 'gdi' in env['winsys']: + SConscript([ + 'gdi/SConscript', + ]) diff --git a/src/gallium/winsys/common/Makefile b/src/gallium/winsys/common/Makefile new file mode 100644 index 0000000000..4c0f3545a5 --- /dev/null +++ b/src/gallium/winsys/common/Makefile @@ -0,0 +1,20 @@ +TOP = ../../../.. +include $(TOP)/configs/current + + +SUBDIRS = $(GALLIUM_WINSYS_COMMON_DIRS) + + +default: subdirs + + +subdirs: + @for dir in $(SUBDIRS) ; do \ + if [ -d $$dir ] ; then \ + (cd $$dir && $(MAKE)) || exit 1 ; \ + fi \ + done + + +clean: + rm -f `find . -name \*.[oa]` diff --git a/src/gallium/winsys/common/Makefile.template b/src/gallium/winsys/common/Makefile.template new file mode 100644 index 0000000000..67af778157 --- /dev/null +++ b/src/gallium/winsys/common/Makefile.template @@ -0,0 +1,64 @@ +# -*-makefile-*- + + +# We still have a dependency on the "dri" buffer manager. Most likely +# the interface can be reused in non-dri environments, and also as a +# frontend to simpler memory managers. +# +COMMON_SOURCES = + +OBJECTS = $(C_SOURCES:.c=.o) \ + $(CPP_SOURCES:.cpp=.o) \ + $(ASM_SOURCES:.S=.o) + + +### Include directories +INCLUDES = \ + -I. \ + -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/auxiliary \ + -I$(TOP)/src/gallium/drivers \ + -I$(TOP)/include \ + $(DRIVER_INCLUDES) + + +##### RULES ##### + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@ + +.cpp.o: + $(CXX) -c $(INCLUDES) $(CXXFLAGS) $(DRIVER_DEFINES) $< -o $@ + +.S.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@ + + +##### TARGETS ##### + +default: depend symlinks $(LIBNAME) + + +$(LIBNAME): $(OBJECTS) Makefile $(TOP)/src/gallium/winsys/common/Makefile.template + $(TOP)/bin/mklib -o $@ -static $(OBJECTS) $(DRIVER_LIBS) + + +depend: $(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES) $(SYMLINKS) + rm -f depend + touch depend + $(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) $(C_SOURCES) $(CPP_SOURCES) \ + $(ASM_SOURCES) 2> /dev/null + + +# Emacs tags +tags: + etags `find . -name \*.[ch]` `find ../include` + + +# Remove .o and backup files +clean:: + -rm -f *.o */*.o *~ *.so *~ server/*.o $(SYMLINKS) + -rm -f depend depend.bak + + +include depend diff --git a/src/gallium/winsys/common/intel_drm/Makefile b/src/gallium/winsys/common/intel_drm/Makefile new file mode 100644 index 0000000000..913dbeff20 --- /dev/null +++ b/src/gallium/winsys/common/intel_drm/Makefile @@ -0,0 +1,23 @@ +TOP = ../../../../.. +include $(TOP)/configs/current + +LIBNAME = inteldrm + +C_SOURCES = \ + intel_be_batchbuffer.c \ + intel_be_context.c \ + intel_be_device.c \ + ws_dri_bufmgr.c \ + ws_dri_drmpool.c \ + ws_dri_fencemgr.c \ + ws_dri_mallocpool.c \ + ws_dri_slabpool.c + + +include ../Makefile.template + +DRIVER_DEFINES = $(shell pkg-config libdrm --cflags \ + && pkg-config libdrm --atleast-version=2.3.1 \ + && echo "-DDRM_VBLANK_FLIP=DRM_VBLANK_FLIP") +symlinks: + diff --git a/src/gallium/winsys/common/intel_drm/glthread.h b/src/gallium/winsys/common/intel_drm/glthread.h new file mode 100644 index 0000000000..b8e9d5f59b --- /dev/null +++ b/src/gallium/winsys/common/intel_drm/glthread.h @@ -0,0 +1,359 @@ +/* + * 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. + */ + + +/* + * Thread support for gl dispatch. + * + * Initial version by John Stone (j.stone@acm.org) (johns@cs.umr.edu) + * and Christoph Poliwoda (poliwoda@volumegraphics.com) + * Revised by Keith Whitwell + * Adapted for new gl dispatcher by Brian Paul + * + * + * + * DOCUMENTATION + * + * This thread module exports the following types: + * _glthread_TSD Thread-specific data area + * _glthread_Thread Thread datatype + * _glthread_Mutex Mutual exclusion lock + * + * Macros: + * _glthread_DECLARE_STATIC_MUTEX(name) Declare a non-local mutex + * _glthread_INIT_MUTEX(name) Initialize a mutex + * _glthread_LOCK_MUTEX(name) Lock a mutex + * _glthread_UNLOCK_MUTEX(name) Unlock a mutex + * + * Functions: + * _glthread_GetID(v) Get integer thread ID + * _glthread_InitTSD() Initialize thread-specific data + * _glthread_GetTSD() Get thread-specific data + * _glthread_SetTSD() Set thread-specific data + * + */ + +/* + * If this file is accidentally included by a non-threaded build, + * it should not cause the build to fail, or otherwise cause problems. + * In general, it should only be included when needed however. + */ + +#ifndef GLTHREAD_H +#define GLTHREAD_H + + +#if defined(USE_MGL_NAMESPACE) +#define _glapi_Dispatch _mglapi_Dispatch +#endif + + + +#if (defined(PTHREADS) || defined(SOLARIS_THREADS) ||\ + defined(WIN32_THREADS) || defined(USE_XTHREADS) || defined(BEOS_THREADS)) \ + && !defined(THREADS) +# define THREADS +#endif + +#ifdef VMS +#include <GL/vms_x_fix.h> +#endif + +/* + * POSIX threads. This should be your choice in the Unix world + * whenever possible. When building with POSIX threads, be sure + * to enable any compiler flags which will cause the MT-safe + * libc (if one exists) to be used when linking, as well as any + * header macros for MT-safe errno, etc. For Solaris, this is the -mt + * compiler flag. On Solaris with gcc, use -D_REENTRANT to enable + * proper compiling for MT-safe libc etc. + */ +#if defined(PTHREADS) +#include <pthread.h> /* POSIX threads headers */ + +typedef struct { + pthread_key_t key; + int initMagic; +} _glthread_TSD; + +typedef pthread_t _glthread_Thread; + +typedef pthread_mutex_t _glthread_Mutex; + +#define _glthread_DECLARE_STATIC_MUTEX(name) \ + static _glthread_Mutex name = PTHREAD_MUTEX_INITIALIZER + +#define _glthread_INIT_MUTEX(name) \ + pthread_mutex_init(&(name), NULL) + +#define _glthread_DESTROY_MUTEX(name) \ + pthread_mutex_destroy(&(name)) + +#define _glthread_LOCK_MUTEX(name) \ + (void) pthread_mutex_lock(&(name)) + +#define _glthread_UNLOCK_MUTEX(name) \ + (void) pthread_mutex_unlock(&(name)) + +typedef pthread_cond_t _glthread_Cond; + +#define _glthread_DECLARE_STATIC_COND(name) \ + static _glthread_Cond name = PTHREAD_COND_INITIALIZER + +#define _glthread_INIT_COND(cond) \ + pthread_cond_init(&(cond), NULL) + +#define _glthread_DESTROY_COND(name) \ + pthread_cond_destroy(&(name)) + +#define _glthread_COND_WAIT(cond, mutex) \ + pthread_cond_wait(&(cond), &(mutex)) + +#define _glthread_COND_SIGNAL(cond) \ + pthread_cond_signal(&(cond)) + +#define _glthread_COND_BROADCAST(cond) \ + pthread_cond_broadcast(&(cond)) + + +#else /* PTHREADS */ + +typedef unsigned int _glthread_Cond; +#define _glthread_DECLARE_STATIC_COND(name) \ +// #warning Condition variables not implemented. + +#define _glthread_INIT_COND(cond) \ + abort(); + +#define _glthread_DESTROY_COND(name) \ + abort(); + +#define _glthread_COND_WAIT(cond, mutex) \ + abort(); + +#define _glthread_COND_SIGNAL(cond) \ + abort(); + +#define _glthread_COND_BROADCAST(cond) \ + abort(); + +#endif + + +/* + * Solaris threads. Use only up to Solaris 2.4. + * Solaris 2.5 and higher provide POSIX threads. + * Be sure to compile with -mt on the Solaris compilers, or + * use -D_REENTRANT if using gcc. + */ +#ifdef SOLARIS_THREADS +#include <thread.h> + +typedef struct { + thread_key_t key; + mutex_t keylock; + int initMagic; +} _glthread_TSD; + +typedef thread_t _glthread_Thread; + +typedef mutex_t _glthread_Mutex; + +/* XXX need to really implement mutex-related macros */ +#define _glthread_DECLARE_STATIC_MUTEX(name) static _glthread_Mutex name = 0 +#define _glthread_INIT_MUTEX(name) (void) name +#define _glthread_DESTROY_MUTEX(name) (void) name +#define _glthread_LOCK_MUTEX(name) (void) name +#define _glthread_UNLOCK_MUTEX(name) (void) name + +#endif /* SOLARIS_THREADS */ + + + + +/* + * Windows threads. Should work with Windows NT and 95. + * IMPORTANT: Link with multithreaded runtime library when THREADS are + * used! + */ +#ifdef WIN32_THREADS +#include <windows.h> + +typedef struct { + DWORD key; + int initMagic; +} _glthread_TSD; + +typedef HANDLE _glthread_Thread; + +typedef CRITICAL_SECTION _glthread_Mutex; + +#define _glthread_DECLARE_STATIC_MUTEX(name) /*static*/ _glthread_Mutex name = {0,0,0,0,0,0} +#define _glthread_INIT_MUTEX(name) InitializeCriticalSection(&name) +#define _glthread_DESTROY_MUTEX(name) DeleteCriticalSection(&name) +#define _glthread_LOCK_MUTEX(name) EnterCriticalSection(&name) +#define _glthread_UNLOCK_MUTEX(name) LeaveCriticalSection(&name) + +#endif /* WIN32_THREADS */ + + + + +/* + * XFree86 has its own thread wrapper, Xthreads.h + * We wrap it again for GL. + */ +#ifdef USE_XTHREADS +#include <X11/Xthreads.h> + +typedef struct { + xthread_key_t key; + int initMagic; +} _glthread_TSD; + +typedef xthread_t _glthread_Thread; + +typedef xmutex_rec _glthread_Mutex; + +#ifdef XMUTEX_INITIALIZER +#define _glthread_DECLARE_STATIC_MUTEX(name) \ + static _glthread_Mutex name = XMUTEX_INITIALIZER +#else +#define _glthread_DECLARE_STATIC_MUTEX(name) \ + static _glthread_Mutex name +#endif + +#define _glthread_INIT_MUTEX(name) \ + xmutex_init(&(name)) + +#define _glthread_DESTROY_MUTEX(name) \ + xmutex_clear(&(name)) + +#define _glthread_LOCK_MUTEX(name) \ + (void) xmutex_lock(&(name)) + +#define _glthread_UNLOCK_MUTEX(name) \ + (void) xmutex_unlock(&(name)) + +#endif /* USE_XTHREADS */ + + + +/* + * BeOS threads. R5.x required. + */ +#ifdef BEOS_THREADS + +#include <kernel/OS.h> +#include <support/TLS.h> + +typedef struct { + int32 key; + int initMagic; +} _glthread_TSD; + +typedef thread_id _glthread_Thread; + +/* Use Benaphore, aka speeder semaphore */ +typedef struct { + int32 lock; + sem_id sem; +} benaphore; +typedef benaphore _glthread_Mutex; + +#define _glthread_DECLARE_STATIC_MUTEX(name) static _glthread_Mutex name = { 0, 0 } +#define _glthread_INIT_MUTEX(name) name.sem = create_sem(0, #name"_benaphore"), name.lock = 0 +#define _glthread_DESTROY_MUTEX(name) delete_sem(name.sem), name.lock = 0 +#define _glthread_LOCK_MUTEX(name) if (name.sem == 0) _glthread_INIT_MUTEX(name); \ + if (atomic_add(&(name.lock), 1) >= 1) acquire_sem(name.sem) +#define _glthread_UNLOCK_MUTEX(name) if (atomic_add(&(name.lock), -1) > 1) release_sem(name.sem) + +#endif /* BEOS_THREADS */ + + + +#ifndef THREADS + +/* + * THREADS not defined + */ + +typedef GLuint _glthread_TSD; + +typedef GLuint _glthread_Thread; + +typedef GLuint _glthread_Mutex; + +#define _glthread_DECLARE_STATIC_MUTEX(name) static _glthread_Mutex name = 0 + +#define _glthread_INIT_MUTEX(name) (void) name + +#define _glthread_DESTROY_MUTEX(name) (void) name + +#define _glthread_LOCK_MUTEX(name) (void) name + +#define _glthread_UNLOCK_MUTEX(name) (void) name + +#endif /* THREADS */ + + + +/* + * Platform independent thread specific data API. + */ + +extern unsigned long +_glthread_GetID(void); + + +extern void +_glthread_InitTSD(_glthread_TSD *); + + +extern void * +_glthread_GetTSD(_glthread_TSD *); + + +extern void +_glthread_SetTSD(_glthread_TSD *, void *); + +#if defined(GLX_USE_TLS) + +extern __thread struct _glapi_table * _glapi_tls_Dispatch + __attribute__((tls_model("initial-exec"))); + +#define GET_DISPATCH() _glapi_tls_Dispatch + +#elif !defined(GL_CALL) +# if defined(THREADS) +# define GET_DISPATCH() \ + ((__builtin_expect( _glapi_Dispatch != NULL, 1 )) \ + ? _glapi_Dispatch : _glapi_get_dispatch()) +# else +# define GET_DISPATCH() _glapi_Dispatch +# endif /* defined(THREADS) */ +#endif /* ndef GL_CALL */ + + +#endif /* THREADS_H */ diff --git a/src/gallium/winsys/dri/intel/intel_batchbuffer.c b/src/gallium/winsys/common/intel_drm/intel_be_batchbuffer.c index aa2eed53b8..bc13a5761e 100644 --- a/src/gallium/winsys/dri/intel/intel_batchbuffer.c +++ b/src/gallium/winsys/common/intel_drm/intel_be_batchbuffer.c @@ -1,52 +1,16 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. - * 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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. - * - **************************************************************************/ - -#include "intel_batchbuffer.h" -#include "intel_context.h" + +#include "intel_be_batchbuffer.h" +#include "intel_be_context.h" +#include "intel_be_device.h" #include <errno.h> -#if 0 -static void -intel_dump_batchbuffer(GLuint offset, GLuint * ptr, GLuint count) -{ - int i; - fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count / 4); - for (i = 0; i < count / 4; i += 4) - fprintf(stderr, "0x%x:\t0x%08x 0x%08x 0x%08x 0x%08x\n", - offset + i * 4, ptr[i], ptr[i + 1], ptr[i + 2], ptr[i + 3]); - fprintf(stderr, "END BATCH\n\n\n"); -} -#endif +#include "xf86drm.h" -static void -intel_realloc_relocs(struct intel_batchbuffer *batch, int num_relocs) +static void +intel_realloc_relocs(struct intel_be_batchbuffer *batch, int num_relocs) { unsigned long size = num_relocs * I915_RELOC0_STRIDE + I915_RELOC_HEADER; - + size *= sizeof(uint32_t); batch->reloc = realloc(batch->reloc, size); batch->reloc_size = num_relocs; @@ -54,19 +18,21 @@ intel_realloc_relocs(struct intel_batchbuffer *batch, int num_relocs) void -intel_batchbuffer_reset(struct intel_batchbuffer *batch) +intel_be_batchbuffer_reset(struct intel_be_batchbuffer *batch) { /* * Get a new, free batchbuffer. */ drmBO *bo; struct drm_bo_info_req *req; - + driBOUnrefUserList(batch->list); driBOResetList(batch->list); - batch->size = 4 * 4096; // ZZZ JB batch->intel->intelScreen->maxBatchSize; - driBOData(batch->buffer, batch->size, NULL, NULL, 0); + /* base.size is the size available to the i915simple driver */ + batch->base.size = batch->device->max_batch_size - BATCH_RESERVED; + batch->base.actual_size = batch->device->max_batch_size; + driBOData(batch->buffer, batch->base.actual_size, NULL, NULL, 0); /* * Add the batchbuffer to the validate list. @@ -96,18 +62,18 @@ intel_batchbuffer_reset(struct intel_batchbuffer *batch) */ if (batch->reloc_size > INTEL_MAX_RELOCS || - batch->reloc == NULL) + batch->reloc == NULL) intel_realloc_relocs(batch, INTEL_DEFAULT_RELOCS); - + assert(batch->reloc != NULL); batch->reloc[0] = 0; /* No relocs yet. */ batch->reloc[1] = 1; /* Reloc type 1 */ batch->reloc[2] = 0; /* Only a single relocation list. */ batch->reloc[3] = 0; /* Only a single relocation list. */ - batch->map = driBOMap(batch->buffer, DRM_BO_FLAG_WRITE, 0); + batch->base.map = driBOMap(batch->buffer, DRM_BO_FLAG_WRITE, 0); batch->poolOffset = driBOPoolOffset(batch->buffer); - batch->ptr = batch->map; + batch->base.ptr = batch->base.map; batch->dirty_state = ~0; batch->nr_relocs = 0; batch->flags = 0; @@ -117,34 +83,35 @@ intel_batchbuffer_reset(struct intel_batchbuffer *batch) /*====================================================================== * Public functions */ -struct intel_batchbuffer * -intel_batchbuffer_alloc(struct intel_context *intel) +struct intel_be_batchbuffer * +intel_be_batchbuffer_alloc(struct intel_be_context *intel) { - struct intel_batchbuffer *batch = calloc(sizeof(*batch), 1); + struct intel_be_batchbuffer *batch = calloc(sizeof(*batch), 1); batch->intel = intel; + batch->device = intel->device; - driGenBuffers(intel->intelScreen->batchPool, "batchbuffer", 1, + driGenBuffers(intel->device->batchPool, "batchbuffer", 1, &batch->buffer, 4096, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE, 0); batch->last_fence = NULL; batch->list = driBOCreateList(20); batch->reloc = NULL; - intel_batchbuffer_reset(batch); + intel_be_batchbuffer_reset(batch); return batch; } void -intel_batchbuffer_free(struct intel_batchbuffer *batch) +intel_be_batchbuffer_free(struct intel_be_batchbuffer *batch) { if (batch->last_fence) { driFenceFinish(batch->last_fence, - DRM_FENCE_TYPE_EXE, GL_FALSE); + DRM_FENCE_TYPE_EXE, FALSE); driFenceUnReference(&batch->last_fence); } - if (batch->map) { + if (batch->base.map) { driBOUnmap(batch->buffer); - batch->map = NULL; + batch->base.map = NULL; } driBOUnReference(batch->buffer); driBOFreeList(batch->list); @@ -155,7 +122,7 @@ intel_batchbuffer_free(struct intel_batchbuffer *batch) } void -intel_offset_relocation(struct intel_batchbuffer *batch, +intel_be_offset_relocation(struct intel_be_batchbuffer *batch, unsigned pre_add, struct _DriBufferObject *driBO, uint64_t val_flags, @@ -165,7 +132,7 @@ intel_offset_relocation(struct intel_batchbuffer *batch, struct _drmBONode *node; uint32_t *reloc; struct drm_bo_info_req *req; - + driBOAddListItem(batch->list, driBO, val_flags, val_mask, &itemLoc, &node); req = &node->bo_arg.d.req.bo_req; @@ -182,17 +149,17 @@ intel_offset_relocation(struct intel_batchbuffer *batch, driReadUnlockKernelBO(); req->hint = DRM_BO_HINT_PRESUMED_OFFSET; } - + pre_add += driBOPoolOffset(driBO); if (batch->nr_relocs == batch->reloc_size) intel_realloc_relocs(batch, batch->reloc_size * 2); - reloc = batch->reloc + + reloc = batch->reloc + (I915_RELOC_HEADER + batch->nr_relocs * I915_RELOC0_STRIDE); - reloc[0] = ((uint8_t *)batch->ptr - batch->drmBOVirtual); - intel_batchbuffer_emit_dword(batch, req->presumed_offset + pre_add); + reloc[0] = ((uint8_t *)batch->base.ptr - batch->drmBOVirtual); + i915_batchbuffer_dword(&batch->base, req->presumed_offset + pre_add); reloc[1] = pre_add; reloc[2] = itemLoc; reloc[3] = batch->dest_location; @@ -214,14 +181,14 @@ i915_drm_copy_reply(const struct drm_bo_info_rep * rep, drmBO * buf) buf->pageAlignment = rep->page_alignment; } -static int -i915_execbuf(struct intel_batchbuffer *batch, - GLuint used, - GLboolean ignore_cliprects, +static int +i915_execbuf(struct intel_be_batchbuffer *batch, + unsigned int used, + boolean ignore_cliprects, drmBOList *list, struct drm_i915_execbuffer *ea) { - struct intel_context *intel = batch->intel; +// struct intel_be_context *intel = batch->intel; drmBONode *node; drmMMListHead *l; struct drm_i915_op_arg *arg, *first; @@ -235,16 +202,16 @@ i915_execbuf(struct intel_batchbuffer *batch, first = NULL; for (l = list->list.next; l != &list->list; l = l->next) { node = DRMLISTENTRY(drmBONode, l, head); - + arg = &node->bo_arg; req = &arg->d.req; - + if (!first) first = arg; - + if (prevNext) *prevNext = (unsigned long)arg; - + prevNext = &arg->next; req->bo_req.handle = node->buf->handle; req->op = drm_bo_validate; @@ -277,7 +244,7 @@ i915_execbuf(struct intel_batchbuffer *batch, //return -EFAULT; do { - ret = drmCommandWriteRead(intel->driFd, DRM_I915_EXECBUFFER, ea, + ret = drmCommandWriteRead(batch->device->fd, DRM_I915_EXECBUFFER, ea, sizeof(*ea)); } while (ret == -EAGAIN); @@ -304,11 +271,11 @@ i915_execbuf(struct intel_batchbuffer *batch, /* TODO: Push this whole function into bufmgr. */ static struct _DriFenceObject * -do_flush_locked(struct intel_batchbuffer *batch, - GLuint used, - GLboolean ignore_cliprects, GLboolean allow_unlock) +do_flush_locked(struct intel_be_batchbuffer *batch, + unsigned int used, + boolean ignore_cliprects, boolean allow_unlock) { - struct intel_context *intel = batch->intel; + struct intel_be_context *intel = batch->intel; struct _DriFenceObject *fo; drmFence fence; drmBOList *boList; @@ -356,7 +323,7 @@ do_flush_locked(struct intel_batchbuffer *batch, fence.flags = ea.fence_arg.flags; fence.signaled = ea.fence_arg.signaled; - fo = driBOFenceUserList(batch->intel->intelScreen->mgr, batch->list, + fo = driBOFenceUserList(batch->device->fenceMgr, batch->list, "SuperFence", &fence); if (driFenceType(fo) & DRM_I915_FENCE_TYPE_RW) { @@ -367,7 +334,7 @@ do_flush_locked(struct intel_batchbuffer *batch, */ batch->last_fence = fo; driFenceReference(fo); - } + } out: #if 0 /* ZZZ JB: fix this */ intel->vtbl.lost_hardware(intel); @@ -379,11 +346,11 @@ do_flush_locked(struct intel_batchbuffer *batch, struct _DriFenceObject * -intel_batchbuffer_flush(struct intel_batchbuffer *batch) +intel_be_batchbuffer_flush(struct intel_be_batchbuffer *batch) { - struct intel_context *intel = batch->intel; - GLuint used = batch->ptr - batch->map; - GLboolean was_locked = intel->locked; + struct intel_be_context *intel = batch->intel; + unsigned int used = batch->base.ptr - batch->base.map; + boolean was_locked = batch->intel->hardware_locked(intel); struct _DriFenceObject *fence; if (used == 0) { @@ -396,65 +363,67 @@ intel_batchbuffer_flush(struct intel_batchbuffer *batch) */ #if 0 /* ZZZ JB: what should we do here? */ if (used & 4) { - ((int *) batch->ptr)[0] = intel->vtbl.flush_cmd(); - ((int *) batch->ptr)[1] = 0; - ((int *) batch->ptr)[2] = MI_BATCH_BUFFER_END; + ((int *) batch->base.ptr)[0] = intel->vtbl.flush_cmd(); + ((int *) batch->base.ptr)[1] = 0; + ((int *) batch->base.ptr)[2] = MI_BATCH_BUFFER_END; used += 12; } else { - ((int *) batch->ptr)[0] = intel->vtbl.flush_cmd(); - ((int *) batch->ptr)[1] = MI_BATCH_BUFFER_END; + ((int *) batch->base.ptr)[0] = intel->vtbl.flush_cmd(); + ((int *) batch->base.ptr)[1] = MI_BATCH_BUFFER_END; used += 8; } #else if (used & 4) { - ((int *) batch->ptr)[0] = ((0<<29)|(4<<23)); // MI_FLUSH; - ((int *) batch->ptr)[1] = 0; - ((int *) batch->ptr)[2] = (0xA<<23); // MI_BATCH_BUFFER_END; + ((int *) batch->base.ptr)[0] = ((0<<29)|(4<<23)); // MI_FLUSH; + ((int *) batch->base.ptr)[1] = 0; + ((int *) batch->base.ptr)[2] = (0xA<<23); // MI_BATCH_BUFFER_END; used += 12; } else { - ((int *) batch->ptr)[0] = ((0<<29)|(4<<23)); // MI_FLUSH; - ((int *) batch->ptr)[1] = (0xA<<23); // MI_BATCH_BUFFER_END; + ((int *) batch->base.ptr)[0] = ((0<<29)|(4<<23)); // MI_FLUSH; + ((int *) batch->base.ptr)[1] = (0xA<<23); // MI_BATCH_BUFFER_END; used += 8; } #endif driBOUnmap(batch->buffer); - batch->ptr = NULL; - batch->map = NULL; + batch->base.ptr = NULL; + batch->base.map = NULL; /* TODO: Just pass the relocation list and dma buffer up to the * kernel. */ if (!was_locked) - LOCK_HARDWARE(intel); + intel->hardware_lock(intel); fence = do_flush_locked(batch, used, !(batch->flags & INTEL_BATCH_CLIPRECTS), - GL_FALSE); + FALSE); if (!was_locked) - UNLOCK_HARDWARE(intel); + intel->hardware_unlock(intel); /* Reset the buffer: */ - intel_batchbuffer_reset(batch); + intel_be_batchbuffer_reset(batch); return fence; } void -intel_batchbuffer_finish(struct intel_batchbuffer *batch) +intel_be_batchbuffer_finish(struct intel_be_batchbuffer *batch) { - struct _DriFenceObject *fence = intel_batchbuffer_flush(batch); - driFenceFinish(fence, driFenceType(fence), GL_FALSE); + struct _DriFenceObject *fence = intel_be_batchbuffer_flush(batch); + driFenceFinish(fence, driFenceType(fence), FALSE); driFenceUnReference(&fence); } +#if 0 void -intel_batchbuffer_data(struct intel_batchbuffer *batch, - const void *data, GLuint bytes, GLuint flags) +intel_be_batchbuffer_data(struct intel_be_batchbuffer *batch, + const void *data, unsigned int bytes, unsigned int flags) { assert((bytes & 3) == 0); intel_batchbuffer_require_space(batch, bytes, flags); - memcpy(batch->ptr, data, bytes); - batch->ptr += bytes; + memcpy(batch->base.ptr, data, bytes); + batch->base.ptr += bytes; } +#endif diff --git a/src/gallium/winsys/common/intel_drm/intel_be_batchbuffer.h b/src/gallium/winsys/common/intel_drm/intel_be_batchbuffer.h new file mode 100644 index 0000000000..f150e3a674 --- /dev/null +++ b/src/gallium/winsys/common/intel_drm/intel_be_batchbuffer.h @@ -0,0 +1,69 @@ + +#ifndef INTEL_BE_BATCHBUFFER_H +#define INTEL_BE_BATCHBUFFER_H + +#include "i915simple/i915_batch.h" + +#include "ws_dri_bufmgr.h" + +#define BATCH_RESERVED 16 + +#define INTEL_DEFAULT_RELOCS 100 +#define INTEL_MAX_RELOCS 400 + +#define INTEL_BATCH_NO_CLIPRECTS 0x1 +#define INTEL_BATCH_CLIPRECTS 0x2 + +struct intel_be_context; +struct intel_be_device; + +struct intel_be_batchbuffer +{ + struct i915_batchbuffer base; + + struct intel_be_context *intel; + struct intel_be_device *device; + + struct _DriBufferObject *buffer; + struct _DriFenceObject *last_fence; + uint32_t flags; + + struct _DriBufferList *list; + size_t list_count; + + uint32_t *reloc; + size_t reloc_size; + size_t nr_relocs; + + uint32_t dirty_state; + uint32_t id; + + uint32_t poolOffset; + uint8_t *drmBOVirtual; + struct _drmBONode *node; /* Validation list node for this buffer */ + int dest_location; /* Validation list sequence for this buffer */ +}; + +struct intel_be_batchbuffer * +intel_be_batchbuffer_alloc(struct intel_be_context *intel); + +void +intel_be_batchbuffer_free(struct intel_be_batchbuffer *batch); + +void +intel_be_batchbuffer_finish(struct intel_be_batchbuffer *batch); + +struct _DriFenceObject * +intel_be_batchbuffer_flush(struct intel_be_batchbuffer *batch); + +void +intel_be_batchbuffer_reset(struct intel_be_batchbuffer *batch); + +void +intel_be_offset_relocation(struct intel_be_batchbuffer *batch, + unsigned pre_add, + struct _DriBufferObject *driBO, + uint64_t val_flags, + uint64_t val_mask); + +#endif diff --git a/src/gallium/winsys/common/intel_drm/intel_be_context.c b/src/gallium/winsys/common/intel_drm/intel_be_context.c new file mode 100644 index 0000000000..1af39674f4 --- /dev/null +++ b/src/gallium/winsys/common/intel_drm/intel_be_context.c @@ -0,0 +1,107 @@ + +/* + * Authors: Jakob Bornecrantz <jakob-at-tungstengraphics.com> + */ + +#include "ws_dri_fencemgr.h" +#include "intel_be_device.h" +#include "intel_be_context.h" +#include "intel_be_batchbuffer.h" + +static INLINE struct intel_be_context * +intel_be_context(struct i915_winsys *sws) +{ + return (struct intel_be_context *)sws; +} + +/* Simple batchbuffer interface: + */ + +static struct i915_batchbuffer* +intel_i915_batch_get(struct i915_winsys *sws) +{ + struct intel_be_context *intel = intel_be_context(sws); + return &intel->batch->base; +} + +static void intel_i915_batch_reloc(struct i915_winsys *sws, + struct pipe_buffer *buf, + unsigned access_flags, + unsigned delta) +{ + struct intel_be_context *intel = intel_be_context(sws); + + unsigned flags = DRM_BO_FLAG_MEM_TT; + unsigned mask = DRM_BO_MASK_MEM; + + if (access_flags & I915_BUFFER_ACCESS_WRITE) { + flags |= DRM_BO_FLAG_WRITE; + mask |= DRM_BO_FLAG_WRITE; + } + + if (access_flags & I915_BUFFER_ACCESS_READ) { + flags |= DRM_BO_FLAG_READ; + mask |= DRM_BO_FLAG_READ; + } + + intel_be_offset_relocation(intel->batch, + delta, + dri_bo(buf), + flags, + mask); +} + +static void intel_i915_batch_flush(struct i915_winsys *sws, + struct pipe_fence_handle **fence) +{ + struct intel_be_context *intel = intel_be_context(sws); + + union { + struct _DriFenceObject *dri; + struct pipe_fence_handle *pipe; + } fu; + + if (fence) + assert(!*fence); + + fu.dri = intel_be_batchbuffer_flush(intel->batch); + + if (!fu.dri) { + assert(0); + *fence = NULL; + return; + } + + if (fu.dri) { + if (fence) + *fence = fu.pipe; + else + driFenceUnReference(&fu.dri); + } + +} + +boolean +intel_be_init_context(struct intel_be_context *intel, struct intel_be_device *device) +{ + assert(intel); + assert(device); + + intel->device = device; + + /* TODO move framebuffer createion to the driver */ + + intel->base.batch_get = intel_i915_batch_get; + intel->base.batch_reloc = intel_i915_batch_reloc; + intel->base.batch_flush = intel_i915_batch_flush; + + intel->batch = intel_be_batchbuffer_alloc(intel); + + return true; +} + +void +intel_be_destroy_context(struct intel_be_context *intel) +{ + intel_be_batchbuffer_free(intel->batch); +} diff --git a/src/gallium/winsys/common/intel_drm/intel_be_context.h b/src/gallium/winsys/common/intel_drm/intel_be_context.h new file mode 100644 index 0000000000..d5cbc93594 --- /dev/null +++ b/src/gallium/winsys/common/intel_drm/intel_be_context.h @@ -0,0 +1,40 @@ +/* These need to be diffrent from the intel winsys */ +#ifndef INTEL_BE_CONTEXT_H +#define INTEL_BE_CONTEXT_H + +#include "i915simple/i915_winsys.h" + +struct intel_be_context +{ + /** Interface to i915simple driver */ + struct i915_winsys base; + + struct intel_be_device *device; + struct intel_be_batchbuffer *batch; + + /* + * Hardware lock functions. + * + * Needs to be filled in by the winsys. + */ + void (*hardware_lock)(struct intel_be_context *context); + void (*hardware_unlock)(struct intel_be_context *context); + boolean (*hardware_locked)(struct intel_be_context *context); +}; + +/** + * Intialize a allocated intel_be_context struct. + * + * Remember to set the hardware_* functions. + */ +boolean +intel_be_init_context(struct intel_be_context *intel, + struct intel_be_device *device); + +/** + * Destroy a intel_be_context. + * Does not free the struct that is up to the winsys. + */ +void +intel_be_destroy_context(struct intel_be_context *intel); +#endif diff --git a/src/gallium/winsys/common/intel_drm/intel_be_device.c b/src/gallium/winsys/common/intel_drm/intel_be_device.c new file mode 100644 index 0000000000..3eed0fe410 --- /dev/null +++ b/src/gallium/winsys/common/intel_drm/intel_be_device.c @@ -0,0 +1,268 @@ + + +/* + * Authors: Keith Whitwell <keithw-at-tungstengraphics-dot-com> + * Jakob Bornecrantz <jakob-at-tungstengraphics-dot-com> + */ + +#include "intel_be_device.h" +#include "ws_dri_bufmgr.h" +#include "ws_dri_bufpool.h" +#include "ws_dri_fencemgr.h" + +#include "pipe/p_winsys.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" +#include "pipe/p_util.h" +#include "pipe/p_inlines.h" + +/* Turn a pipe winsys into an intel/pipe winsys: + */ +static INLINE struct intel_be_device * +intel_be_device( struct pipe_winsys *winsys ) +{ + return (struct intel_be_device *)winsys; +} + + +/* + * Buffer functions. + * + * Most callbacks map direcly onto dri_bufmgr operations: + */ + +static void *intel_be_buffer_map(struct pipe_winsys *winsys, + struct pipe_buffer *buf, + unsigned flags ) +{ + unsigned drm_flags = 0; + + if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) + drm_flags |= DRM_BO_FLAG_WRITE; + + if (flags & PIPE_BUFFER_USAGE_CPU_READ) + drm_flags |= DRM_BO_FLAG_READ; + + return driBOMap( dri_bo(buf), drm_flags, 0 ); +} + +static void intel_be_buffer_unmap(struct pipe_winsys *winsys, + struct pipe_buffer *buf) +{ + driBOUnmap( dri_bo(buf) ); +} + +static void +intel_be_buffer_destroy(struct pipe_winsys *winsys, + struct pipe_buffer *buf) +{ + driBOUnReference( dri_bo(buf) ); + FREE(buf); +} + +static struct pipe_buffer * +intel_be_buffer_create(struct pipe_winsys *winsys, + unsigned alignment, + unsigned usage, + unsigned size ) +{ + struct intel_be_buffer *buffer = CALLOC_STRUCT( intel_be_buffer ); + struct intel_be_device *iws = intel_be_device(winsys); + unsigned flags = 0; + struct _DriBufferPool *pool; + + buffer->base.refcount = 1; + buffer->base.alignment = alignment; + buffer->base.usage = usage; + buffer->base.size = size; + + if (usage & (PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_CONSTANT)) { + flags |= DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED; + pool = iws->mallocPool; + } else if (usage & PIPE_BUFFER_USAGE_CUSTOM) { + /* For vertex buffers */ + flags |= DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MEM_TT; + pool = iws->vertexPool; + } else { + flags |= DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MEM_TT; + pool = iws->regionPool; + } + + if (usage & PIPE_BUFFER_USAGE_GPU_READ) + flags |= DRM_BO_FLAG_READ; + + if (usage & PIPE_BUFFER_USAGE_GPU_WRITE) + flags |= DRM_BO_FLAG_WRITE; + + /* drm complains if we don't set any read/write flags. + */ + if ((flags & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE)) == 0) + flags |= DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE; + + buffer->pool = pool; + driGenBuffers( buffer->pool, + "pipe buffer", 1, &buffer->driBO, alignment, flags, 0 ); + + driBOData( buffer->driBO, size, NULL, buffer->pool, 0 ); + + return &buffer->base; +} + + +static struct pipe_buffer * +intel_be_user_buffer_create(struct pipe_winsys *winsys, void *ptr, unsigned bytes) +{ + struct intel_be_buffer *buffer = CALLOC_STRUCT( intel_be_buffer ); + struct intel_be_device *iws = intel_be_device(winsys); + + driGenUserBuffer( iws->regionPool, + "pipe user buffer", &buffer->driBO, ptr, bytes ); + + buffer->base.refcount = 1; + + return &buffer->base; +} + + +/* + * Surface functions. + * + * Deprecated! + */ + +static struct pipe_surface * +intel_i915_surface_alloc(struct pipe_winsys *winsys) +{ + assert((size_t)"intel_i915_surface_alloc is deprecated" & 0); + return NULL; +} + +static int +intel_i915_surface_alloc_storage(struct pipe_winsys *winsys, + struct pipe_surface *surf, + unsigned width, unsigned height, + enum pipe_format format, + unsigned flags, + unsigned tex_usage) +{ + assert((size_t)"intel_i915_surface_alloc_storage is deprecated" & 0); + return -1; +} + +static void +intel_i915_surface_release(struct pipe_winsys *winsys, struct pipe_surface **s) +{ + assert((size_t)"intel_i915_surface_release is deprecated" & 0); +} + +/* + * Fence functions + */ + +static void +intel_be_fence_reference( struct pipe_winsys *sws, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence ) +{ + if (*ptr) + driFenceUnReference((struct _DriFenceObject **)ptr); + + if (fence) + *ptr = (struct pipe_fence_handle *)driFenceReference((struct _DriFenceObject *)fence); +} + +static int +intel_be_fence_signalled( struct pipe_winsys *sws, + struct pipe_fence_handle *fence, + unsigned flag ) +{ + return driFenceSignaled((struct _DriFenceObject *)fence, flag); +} + +static int +intel_be_fence_finish( struct pipe_winsys *sws, + struct pipe_fence_handle *fence, + unsigned flag ) +{ + return driFenceFinish((struct _DriFenceObject *)fence, flag, 0); +} + +/* + * Misc functions + */ + +boolean +intel_be_init_device(struct intel_be_device *dev, int fd) +{ + dev->fd = fd; + dev->max_batch_size = 16 * 4096; + dev->max_vertex_size = 128 * 4096; + + dev->base.buffer_create = intel_be_buffer_create; + dev->base.user_buffer_create = intel_be_user_buffer_create; + dev->base.buffer_map = intel_be_buffer_map; + dev->base.buffer_unmap = intel_be_buffer_unmap; + dev->base.buffer_destroy = intel_be_buffer_destroy; + dev->base.surface_alloc = intel_i915_surface_alloc; + dev->base.surface_alloc_storage = intel_i915_surface_alloc_storage; + dev->base.surface_release = intel_i915_surface_release; + dev->base.fence_reference = intel_be_fence_reference; + dev->base.fence_signalled = intel_be_fence_signalled; + dev->base.fence_finish = intel_be_fence_finish; + +#if 0 /* Set by the winsys */ + dev->base.flush_frontbuffer = intel_flush_frontbuffer; + dev->base.get_name = intel_get_name; +#endif + + dev->fMan = driInitFreeSlabManager(10, 10); + dev->fenceMgr = driFenceMgrTTMInit(dev->fd); + + dev->mallocPool = driMallocPoolInit(); + dev->staticPool = driDRMPoolInit(dev->fd); + /* Sizes: 64 128 256 512 1024 2048 4096 8192 16384 32768 */ + dev->regionPool = driSlabPoolInit(dev->fd, + DRM_BO_FLAG_READ | + DRM_BO_FLAG_WRITE | + DRM_BO_FLAG_MEM_TT, + DRM_BO_FLAG_READ | + DRM_BO_FLAG_WRITE | + DRM_BO_FLAG_MEM_TT, + 64, + 10, 120, 4096 * 64, 0, + dev->fMan); + + dev->vertexPool = driSlabPoolInit(dev->fd, + DRM_BO_FLAG_READ | + DRM_BO_FLAG_WRITE | + DRM_BO_FLAG_MEM_TT, + DRM_BO_FLAG_READ | + DRM_BO_FLAG_WRITE | + DRM_BO_FLAG_MEM_TT, + dev->max_vertex_size, + 1, 120, dev->max_vertex_size * 4, 0, + dev->fMan); + + dev->batchPool = driSlabPoolInit(dev->fd, + DRM_BO_FLAG_EXE | + DRM_BO_FLAG_MEM_TT, + DRM_BO_FLAG_EXE | + DRM_BO_FLAG_MEM_TT, + dev->max_batch_size, + 1, 40, dev->max_batch_size * 16, 0, + dev->fMan); + + return true; +} + +void +intel_be_destroy_device(struct intel_be_device *dev) +{ + driPoolTakeDown(dev->mallocPool); + driPoolTakeDown(dev->staticPool); + driPoolTakeDown(dev->regionPool); + driPoolTakeDown(dev->vertexPool); + driPoolTakeDown(dev->batchPool); + + /** TODO takedown fenceMgr and fMan */ +} diff --git a/src/gallium/winsys/common/intel_drm/intel_be_device.h b/src/gallium/winsys/common/intel_drm/intel_be_device.h new file mode 100644 index 0000000000..ec5cace71c --- /dev/null +++ b/src/gallium/winsys/common/intel_drm/intel_be_device.h @@ -0,0 +1,58 @@ +#ifndef INTEL_DRM_DEVICE_H +#define INTEL_DRM_DEVICE_H + +#include "pipe/p_winsys.h" +#include "pipe/p_context.h" + +/* + * Device + */ + +struct intel_be_device +{ + struct pipe_winsys base; + + int fd; /**< Drm file discriptor */ + + size_t max_batch_size; + size_t max_vertex_size; + + struct _DriFenceMgr *fenceMgr; + + struct _DriBufferPool *batchPool; + struct _DriBufferPool *regionPool; + struct _DriBufferPool *mallocPool; + struct _DriBufferPool *vertexPool; + struct _DriBufferPool *staticPool; + struct _DriFreeSlabManager *fMan; +}; + +boolean +intel_be_init_device(struct intel_be_device *device, int fd); + +void +intel_be_destroy_device(struct intel_be_device *dev); + +/* + * Buffer + */ + +struct intel_be_buffer { + struct pipe_buffer base; + struct _DriBufferPool *pool; + struct _DriBufferObject *driBO; +}; + +static INLINE struct intel_be_buffer * +intel_be_buffer( struct pipe_buffer *buf ) +{ + return (struct intel_be_buffer *)buf; +} + +static INLINE struct _DriBufferObject * +dri_bo( struct pipe_buffer *buf ) +{ + return intel_be_buffer(buf)->driBO; +} + +#endif diff --git a/src/gallium/winsys/egl_drm/intel/ws_dri_bufmgr.c b/src/gallium/winsys/common/intel_drm/ws_dri_bufmgr.c index 1bc1089352..b6d901f85e 100644 --- a/src/gallium/winsys/egl_drm/intel/ws_dri_bufmgr.c +++ b/src/gallium/winsys/common/intel_drm/ws_dri_bufmgr.c @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA * 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 @@ -10,20 +10,20 @@ * 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 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 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS 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 + * 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. * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. - * - * + * + * **************************************************************************/ /* * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> @@ -32,20 +32,22 @@ #include <xf86drm.h> #include <stdlib.h> +#include <stdio.h> #include "glthread.h" #include "errno.h" #include "ws_dri_bufmgr.h" #include "string.h" -#include "imports.h" +#include "pipe/p_debug.h" #include "ws_dri_bufpool.h" #include "ws_dri_fencemgr.h" + /* * This lock is here to protect drmBO structs changing underneath us during a * validate list call, since validatelist cannot take individiual locks for * each drmBO. Validatelist takes this lock in write mode. Any access to an * individual drmBO should take this lock in read mode, since in that case, the - * driBufferObject mutex will protect the access. Locking order is + * driBufferObject mutex will protect the access. Locking order is * driBufferObject mutex - > this rw lock. */ @@ -84,7 +86,7 @@ static void *drmBOListNext(drmBOList *list, void *iterator) return ret; } -static drmBONode *drmAddListItem(drmBOList *list, drmBO *item, +static drmBONode *drmAddListItem(drmBOList *list, drmBO *item, uint64_t arg0, uint64_t arg1) { @@ -110,8 +112,8 @@ static drmBONode *drmAddListItem(drmBOList *list, drmBO *item, list->numOnList++; return node; } - -static int drmAddValidateItem(drmBOList *list, drmBO *buf, uint64_t flags, + +static int drmAddValidateItem(drmBOList *list, drmBO *buf, uint64_t flags, uint64_t mask, int *newItem) { drmBONode *node, *cur; @@ -243,11 +245,11 @@ void driWriteLockKernelBO(void) while(kernelReaders != 0) _glthread_COND_WAIT(bmCond, bmMutex); } - + void driWriteUnlockKernelBO(void) { _glthread_UNLOCK_MUTEX(bmMutex); -} +} void driReadLockKernelBO(void) { @@ -268,7 +270,7 @@ void driReadUnlockKernelBO(void) /* - * TODO: Introduce fence pools in the same way as + * TODO: Introduce fence pools in the same way as * buffer object pools. */ @@ -298,11 +300,11 @@ typedef struct _DriBufferList { void bmError(int val, const char *file, const char *function, int line) { - _mesa_printf("Fatal video memory manager error \"%s\".\n" - "Check kernel logs or set the LIBGL_DEBUG\n" - "environment variable to \"verbose\" for more info.\n" - "Detected in file %s, line %d, function %s.\n", - strerror(-val), file, line, function); + printf("Fatal video memory manager error \"%s\".\n" + "Check kernel logs or set the LIBGL_DEBUG\n" + "environment variable to \"verbose\" for more info.\n" + "Detected in file %s, line %d, function %s.\n", + strerror(-val), file, line, function); #ifndef NDEBUG abort(); #else @@ -353,7 +355,7 @@ driBOMap(struct _DriBufferObject *buf, unsigned flags, unsigned hint) _glthread_LOCK_MUTEX(buf->mutex); assert(buf->private != NULL); - retval = buf->pool->map(buf->pool, buf->private, flags, hint, + retval = buf->pool->map(buf->pool, buf->private, flags, hint, &buf->mutex, &virtual); _glthread_UNLOCK_MUTEX(buf->mutex); @@ -398,7 +400,7 @@ driBOPoolOffset(struct _DriBufferObject *buf) return ret; } -uint64_t +uint64_t driBOFlags(struct _DriBufferObject *buf) { uint64_t ret; @@ -448,7 +450,7 @@ driBOUnReference(struct _DriBufferObject *buf) else num_buffers--; free(buf); - } else + } else _glthread_UNLOCK_MUTEX(buf->mutex); } @@ -456,8 +458,8 @@ driBOUnReference(struct _DriBufferObject *buf) int driBOData(struct _DriBufferObject *buf, - unsigned size, const void *data, - DriBufferPool *newPool, + unsigned size, const void *data, + DriBufferPool *newPool, uint64_t flags) { void *virtual = NULL; @@ -478,8 +480,7 @@ driBOData(struct _DriBufferObject *buf, newPool = pool; if (!pool->create) { - _mesa_error(NULL, GL_INVALID_OPERATION, - "driBOData called on invalid buffer\n"); + assert((size_t)"driBOData called on invalid buffer\n" & 0); BM_CKFATAL(-EINVAL); } @@ -492,9 +493,7 @@ driBOData(struct _DriBufferObject *buf, if (newBuffer) { if (buf->createdByReference) { - _mesa_error(NULL, GL_INVALID_OPERATION, - "driBOData requiring resizing called on " - "shared buffer.\n"); + assert((size_t)"driBOData requiring resizing called on shared buffer.\n" & 0); BM_CKFATAL(-EINVAL); } @@ -531,7 +530,7 @@ driBOData(struct _DriBufferObject *buf, DRM_BO_FLAG_WRITE, 0, &buf->mutex, &virtual); } else { uint64_t flag_diff = flags ^ buf->flags; - + /* * We might need to change buffer flags. */ @@ -558,7 +557,7 @@ driBOData(struct _DriBufferObject *buf, out: _glthread_UNLOCK_MUTEX(buf->mutex); - + return retval; } @@ -605,23 +604,20 @@ driBOSetReferenced(struct _DriBufferObject *buf, { _glthread_LOCK_MUTEX(buf->mutex); if (buf->private != NULL) { - _mesa_error(NULL, GL_INVALID_OPERATION, - "Invalid buffer for setReferenced\n"); + assert((size_t)"Invalid buffer for setReferenced\n" & 0); BM_CKFATAL(-EINVAL); - + } if (buf->pool->reference == NULL) { - _mesa_error(NULL, GL_INVALID_OPERATION, - "Invalid buffer pool for setReferenced\n"); + assert((size_t)"Invalid buffer pool for setReferenced\n" & 0); BM_CKFATAL(-EINVAL); } buf->private = buf->pool->reference(buf->pool, handle); if (!buf->private) { - _mesa_error(NULL, GL_OUT_OF_MEMORY, - "Invalid buffer pool for setStatic\n"); + assert((size_t)"Invalid buffer pool for setStatic\n" & 0); BM_CKFATAL(-ENOMEM); } - buf->createdByReference = GL_TRUE; + buf->createdByReference = TRUE; buf->flags = buf->pool->kernel(buf->pool, buf->private)->flags; _glthread_UNLOCK_MUTEX(buf->mutex); } @@ -769,7 +765,7 @@ driAddListItem(drmBOList * list, drmBO * item, static int driAddValidateItem(drmBOList * list, drmBO * buf, uint64_t flags, - uint64_t mask, int *itemLoc, + uint64_t mask, int *itemLoc, struct _drmBONode **pnode) { drmBONode *node, *cur; @@ -817,18 +813,18 @@ driAddValidateItem(drmBOList * list, drmBO * buf, uint64_t flags, void driBOAddListItem(struct _DriBufferList * list, struct _DriBufferObject *buf, - uint64_t flags, uint64_t mask, int *itemLoc, + uint64_t flags, uint64_t mask, int *itemLoc, struct _drmBONode **node) { int newItem; - + _glthread_LOCK_MUTEX(buf->mutex); BM_CKFATAL(driAddValidateItem(&list->drmBuffers, buf->pool->kernel(buf->pool, buf->private), flags, mask, itemLoc, node)); BM_CKFATAL(drmAddValidateItem(&list->driBuffers, (drmBO *) buf, flags, mask, &newItem)); - if (newItem) + if (newItem) buf->refCount++; _glthread_UNLOCK_MUTEX(buf->mutex); @@ -897,7 +893,7 @@ driBOFenceUserList(struct _DriFenceMgr *mgr, driBOResetList(list); return fence; } - + void driBOValidateUserList(struct _DriBufferList * list) { @@ -928,7 +924,7 @@ driPoolTakeDown(struct _DriBufferPool *pool) } -unsigned long +unsigned long driBOSize(struct _DriBufferObject *buf) { unsigned long size; @@ -950,4 +946,4 @@ drmBOList *driBOGetDRIBuffers(struct _DriBufferList *list) { return &list->driBuffers; } - + diff --git a/src/gallium/winsys/dri/intel/ws_dri_bufmgr.h b/src/gallium/winsys/common/intel_drm/ws_dri_bufmgr.h index fdaf5ee93a..e6c0cff0a0 100644 --- a/src/gallium/winsys/dri/intel/ws_dri_bufmgr.h +++ b/src/gallium/winsys/common/intel_drm/ws_dri_bufmgr.h @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA * 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 @@ -10,20 +10,20 @@ * 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 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 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS 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 + * 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. * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. - * - * + * + * **************************************************************************/ /* * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> @@ -76,7 +76,7 @@ extern struct _DriBufferObject *driBOReference(struct _DriBufferObject *buf); extern void driBOUnReference(struct _DriBufferObject *buf); extern int driBOData(struct _DriBufferObject *r_buf, - unsigned size, const void *data, + unsigned size, const void *data, struct _DriBufferPool *pool, uint64_t flags); extern void driBOSubData(struct _DriBufferObject *buf, @@ -98,7 +98,7 @@ extern void driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[]); extern void driInitBufMgr(int fd); extern struct _DriBufferList *driBOCreateList(int target); extern int driBOResetList(struct _DriBufferList * list); -extern void driBOAddListItem(struct _DriBufferList * list, +extern void driBOAddListItem(struct _DriBufferList * list, struct _DriBufferObject *buf, uint64_t flags, uint64_t mask, int *itemLoc, struct _drmBONode **node); diff --git a/src/gallium/winsys/egl_drm/intel/ws_dri_bufpool.h b/src/gallium/winsys/common/intel_drm/ws_dri_bufpool.h index 3a302e13d3..bf60798924 100644 --- a/src/gallium/winsys/egl_drm/intel/ws_dri_bufpool.h +++ b/src/gallium/winsys/common/intel_drm/ws_dri_bufpool.h @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA * 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 @@ -10,20 +10,20 @@ * 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 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 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS 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 + * 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. * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. - * - * + * + * **************************************************************************/ /* * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> @@ -40,7 +40,7 @@ typedef struct _DriBufferPool { int fd; int (*map) (struct _DriBufferPool * pool, void *private, - unsigned flags, int hint, _glthread_Mutex *mutex, + unsigned flags, int hint, _glthread_Mutex *mutex, void **virtual); int (*unmap) (struct _DriBufferPool * pool, void *private); int (*destroy) (struct _DriBufferPool * pool, void *private); diff --git a/src/gallium/winsys/egl_drm/intel/ws_dri_drmpool.c b/src/gallium/winsys/common/intel_drm/ws_dri_drmpool.c index 7c55dbc674..40929efa2f 100644 --- a/src/gallium/winsys/egl_drm/intel/ws_dri_drmpool.c +++ b/src/gallium/winsys/common/intel_drm/ws_dri_drmpool.c @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA * 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 @@ -10,20 +10,20 @@ * 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 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 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS 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 + * 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. * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. - * - * + * + * **************************************************************************/ /* * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> @@ -117,7 +117,7 @@ pool_map(struct _DriBufferPool *pool, void *private, unsigned flags, { drmBO *buf = (drmBO *) private; int ret; - + driReadLockKernelBO(); ret = drmBOMap(pool->fd, buf, flags, hint, virtual); driReadUnlockKernelBO(); @@ -133,7 +133,7 @@ pool_unmap(struct _DriBufferPool *pool, void *private) driReadLockKernelBO(); ret = drmBOUnmap(pool->fd, buf); driReadUnlockKernelBO(); - + return ret; } @@ -144,7 +144,7 @@ pool_offset(struct _DriBufferPool *pool, void *private) unsigned long offset; driReadLockKernelBO(); - assert(buf->flags & DRM_BO_FLAG_NO_MOVE); + assert(buf->flags & DRM_BO_FLAG_NO_MOVE); offset = buf->offset; driReadUnlockKernelBO(); @@ -202,7 +202,7 @@ pool_kernel(struct _DriBufferPool *pool, void *private) } static int -pool_waitIdle(struct _DriBufferPool *pool, void *private, _glthread_Mutex *mutex, +pool_waitIdle(struct _DriBufferPool *pool, void *private, _glthread_Mutex *mutex, int lazy) { drmBO *buf = (drmBO *) private; @@ -215,7 +215,7 @@ pool_waitIdle(struct _DriBufferPool *pool, void *private, _glthread_Mutex *mutex return ret; } - + static void pool_takedown(struct _DriBufferPool *pool) { @@ -223,7 +223,7 @@ pool_takedown(struct _DriBufferPool *pool) } /*static int -pool_setStatus(struct _DriBufferPool *pool, void *private, +pool_setStatus(struct _DriBufferPool *pool, void *private, uint64_t flag_diff, uint64_t old_flags) { drmBO *buf = (drmBO *) private; diff --git a/src/gallium/winsys/dri/intel/ws_dri_fencemgr.c b/src/gallium/winsys/common/intel_drm/ws_dri_fencemgr.c index 1f893b47ce..b56bc269da 100644 --- a/src/gallium/winsys/dri/intel/ws_dri_fencemgr.c +++ b/src/gallium/winsys/common/intel_drm/ws_dri_fencemgr.c @@ -261,7 +261,7 @@ driFenceReference(struct _DriFenceObject *fence) void driFenceUnReference(struct _DriFenceObject **pFence) { - struct _DriFenceMgr *mgr; + struct _DriFenceMgr *mgr; if (*pFence == NULL) return; diff --git a/src/gallium/winsys/dri/intel/ws_dri_fencemgr.h b/src/gallium/winsys/common/intel_drm/ws_dri_fencemgr.h index 4ea58dfe18..4ea58dfe18 100644 --- a/src/gallium/winsys/dri/intel/ws_dri_fencemgr.h +++ b/src/gallium/winsys/common/intel_drm/ws_dri_fencemgr.h diff --git a/src/gallium/winsys/dri/intel/ws_dri_mallocpool.c b/src/gallium/winsys/common/intel_drm/ws_dri_mallocpool.c index bf97d7e440..a80555c9c7 100644 --- a/src/gallium/winsys/dri/intel/ws_dri_mallocpool.c +++ b/src/gallium/winsys/common/intel_drm/ws_dri_mallocpool.c @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, TX., USA * 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 @@ -10,20 +10,20 @@ * 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 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 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS 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 + * 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. * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. - * - * + * + * **************************************************************************/ /* * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> @@ -32,11 +32,10 @@ #include <xf86drm.h> #include <stdlib.h> #include <errno.h> -#include "imports.h" +#include "pipe/p_debug.h" #include "glthread.h" #include "ws_dri_bufpool.h" #include "ws_dri_bufmgr.h" -#include "intel_screen.h" static void * pool_create(struct _DriBufferPool *pool, @@ -60,7 +59,7 @@ pool_destroy(struct _DriBufferPool *pool, void *private) } static int -pool_waitIdle(struct _DriBufferPool *pool, void *private, +pool_waitIdle(struct _DriBufferPool *pool, void *private, _glthread_Mutex *mutex, int lazy) { return 0; diff --git a/src/gallium/winsys/dri/intel/ws_dri_slabpool.c b/src/gallium/winsys/common/intel_drm/ws_dri_slabpool.c index 62d82bbd94..dfcf6d6b19 100644 --- a/src/gallium/winsys/dri/intel/ws_dri_slabpool.c +++ b/src/gallium/winsys/common/intel_drm/ws_dri_slabpool.c @@ -636,7 +636,7 @@ pool_destroy(struct _DriBufferPool *driPool, void *private) } static int -pool_waitIdle(struct _DriBufferPool *driPool, void *private, +pool_waitIdle(struct _DriBufferPool *driPool, void *private, _glthread_Mutex *mutex, int lazy) { struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; @@ -688,7 +688,7 @@ pool_unmap(struct _DriBufferPool *pool, void *private) struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; --buf->mapCount; - if (buf->mapCount == 0 && buf->isSlabBuffer) + if (buf->mapCount == 0 && buf->isSlabBuffer) _glthread_COND_BROADCAST(buf->event); return 0; @@ -774,14 +774,14 @@ pool_kernel(struct _DriBufferPool *pool, void *private) } static int -pool_validate(struct _DriBufferPool *pool, void *private, +pool_validate(struct _DriBufferPool *pool, void *private, _glthread_Mutex *mutex) { struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; - if (!buf->isSlabBuffer) + if (!buf->isSlabBuffer) return 0; - + while(buf->mapCount != 0) _glthread_COND_WAIT(buf->event, *mutex); diff --git a/src/gallium/winsys/dri/Makefile.template b/src/gallium/winsys/dri/Makefile.template index 3bc1fdd4d4..07abfa53f3 100644 --- a/src/gallium/winsys/dri/Makefile.template +++ b/src/gallium/winsys/dri/Makefile.template @@ -54,6 +54,7 @@ SHARED_INCLUDES = \ -I$(TOP)/src/gallium/include \ -I$(TOP)/src/gallium/auxiliary \ -I$(TOP)/src/gallium/drivers \ + -I$(TOP)/src/gallium/winsys/common \ -I$(TOP)/src/mesa \ -I$(TOP)/src/mesa/main \ -I$(TOP)/src/mesa/glapi \ diff --git a/src/gallium/winsys/dri/SConscript b/src/gallium/winsys/dri/SConscript index 8c56ce917c..aef5210a32 100644 --- a/src/gallium/winsys/dri/SConscript +++ b/src/gallium/winsys/dri/SConscript @@ -1,51 +1,54 @@ Import('*') -drienv = env.Clone() - -drienv.Replace(CPPPATH = [ - '#src/mesa/drivers/dri/common', - '#include', - '#include/GL/internal', - '#src/gallium/include', - '#src/gallium/auxiliary', - '#src/gallium/drivers', - '#src/mesa', - '#src/mesa/main', - '#src/mesa/glapi', - '#src/mesa/math', - '#src/mesa/transform', - '#src/mesa/shader', - '#src/mesa/swrast', - '#src/mesa/swrast_setup', - '#src/egl/main', - '#src/egl/drivers/dri', -]) - -drienv.ParseConfig('pkg-config --cflags --libs libdrm') - -COMMON_GALLIUM_SOURCES = [ - '#src/mesa/drivers/dri/common/utils.c', - '#src/mesa/drivers/dri/common/vblank.c', - '#src/mesa/drivers/dri/common/dri_util.c', - '#src/mesa/drivers/dri/common/xmlconfig.c', -] - -COMMON_BM_SOURCES = [ - '#src/mesa/drivers/dri/common/dri_bufmgr.c', - '#src/mesa/drivers/dri/common/dri_drmpool.c', -] - -Export([ - 'drienv', - 'COMMON_GALLIUM_SOURCES', - 'COMMON_BM_SOURCES', -]) - -# TODO: Installation -#install: $(LIBNAME) -# $(INSTALL) -d $(DRI_DRIVER_INSTALL_DIR) -# $(INSTALL) -m 755 $(LIBNAME) $(DRI_DRIVER_INSTALL_DIR) - -SConscript([ - 'intel/SConscript', -]) +if env['dri']: + + drienv = env.Clone() + + drienv.Replace(CPPPATH = [ + '#src/mesa/drivers/dri/common', + '#include', + '#include/GL/internal', + '#src/gallium/include', + '#src/gallium/auxiliary', + '#src/gallium/drivers', + '#src/mesa', + '#src/mesa/main', + '#src/mesa/glapi', + '#src/mesa/math', + '#src/mesa/transform', + '#src/mesa/shader', + '#src/mesa/swrast', + '#src/mesa/swrast_setup', + '#src/egl/main', + '#src/egl/drivers/dri', + ]) + + drienv.ParseConfig('pkg-config --cflags --libs libdrm') + + COMMON_GALLIUM_SOURCES = [ + '#src/mesa/drivers/dri/common/utils.c', + '#src/mesa/drivers/dri/common/vblank.c', + '#src/mesa/drivers/dri/common/dri_util.c', + '#src/mesa/drivers/dri/common/xmlconfig.c', + ] + + COMMON_BM_SOURCES = [ + '#src/mesa/drivers/dri/common/dri_bufmgr.c', + '#src/mesa/drivers/dri/common/dri_drmpool.c', + ] + + Export([ + 'drienv', + 'COMMON_GALLIUM_SOURCES', + 'COMMON_BM_SOURCES', + ]) + + # TODO: Installation + #install: $(LIBNAME) + # $(INSTALL) -d $(DRI_DRIVER_INSTALL_DIR) + # $(INSTALL) -m 755 $(LIBNAME) $(DRI_DRIVER_INSTALL_DIR) + + if 'intel' in env['winsys']: + SConscript([ + 'intel/SConscript', + ]) diff --git a/src/gallium/winsys/dri/intel/Makefile b/src/gallium/winsys/dri/intel/Makefile index c0ce2f927b..00ce21f690 100644 --- a/src/gallium/winsys/dri/intel/Makefile +++ b/src/gallium/winsys/dri/intel/Makefile @@ -4,26 +4,17 @@ include $(TOP)/configs/current LIBNAME = i915_dri.so -MINIGLX_SOURCES = server/intel_dri.c - PIPE_DRIVERS = \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ - $(TOP)/src/gallium/drivers/i915simple/libi915simple.a + $(TOP)/src/gallium/drivers/i915simple/libi915simple.a \ + $(TOP)/src/gallium/winsys/common/intel_drm/libinteldrm.a DRIVER_SOURCES = \ - intel_winsys_pipe.c \ intel_winsys_softpipe.c \ - intel_winsys_i915.c \ - intel_batchbuffer.c \ intel_swapbuffers.c \ intel_context.c \ intel_lock.c \ - intel_screen.c \ - ws_dri_bufmgr.c \ - ws_dri_drmpool.c \ - ws_dri_fencemgr.c \ - ws_dri_mallocpool.c \ - ws_dri_slabpool.c + intel_screen.c C_SOURCES = \ $(COMMON_GALLIUM_SOURCES) \ @@ -36,6 +27,6 @@ DRIVER_DEFINES = -I$(TOP)/src/mesa/drivers/dri/intel $(shell pkg-config libdrm - include ../Makefile.template -intel_tex_layout.o: $(TOP)/src/mesa/drivers/dri/intel/intel_tex_layout.c +#intel_tex_layout.o: $(TOP)/src/mesa/drivers/dri/intel/intel_tex_layout.c symlinks: diff --git a/src/gallium/winsys/dri/intel/SConscript b/src/gallium/winsys/dri/intel/SConscript index 0ad19d42a8..6a4f50afcc 100644 --- a/src/gallium/winsys/dri/intel/SConscript +++ b/src/gallium/winsys/dri/intel/SConscript @@ -1,39 +1,41 @@ Import('*') -env = drienv.Clone() - -env.Append(CPPPATH = [ - '../intel', - 'server' -]) - -#MINIGLX_SOURCES = server/intel_dri.c - -DRIVER_SOURCES = [ - 'intel_winsys_pipe.c', - 'intel_winsys_softpipe.c', - 'intel_winsys_i915.c', - 'intel_batchbuffer.c', - 'intel_swapbuffers.c', - 'intel_context.c', - 'intel_lock.c', - 'intel_screen.c', - 'intel_batchpool.c', -] - -sources = \ - COMMON_GALLIUM_SOURCES + \ - COMMON_BM_SOURCES + \ - DRIVER_SOURCES - -drivers = [ - softpipe, - i915simple -] - -# TODO: write a wrapper function http://www.scons.org/wiki/WrapperFunctions -env.SharedLibrary( - target ='i915tex_dri.so', - source = sources, - LIBS = drivers + mesa + auxiliaries + env['LIBS'], -)
\ No newline at end of file +if 'mesa' in env['statetrackers']: + + env = drienv.Clone() + + env.Append(CPPPATH = [ + '../intel', + 'server' + ]) + + #MINIGLX_SOURCES = server/intel_dri.c + + DRIVER_SOURCES = [ + 'intel_winsys_pipe.c', + 'intel_winsys_softpipe.c', + 'intel_winsys_i915.c', + 'intel_batchbuffer.c', + 'intel_swapbuffers.c', + 'intel_context.c', + 'intel_lock.c', + 'intel_screen.c', + 'intel_batchpool.c', + ] + + sources = \ + COMMON_GALLIUM_SOURCES + \ + COMMON_BM_SOURCES + \ + DRIVER_SOURCES + + drivers = [ + softpipe, + i915simple + ] + + # TODO: write a wrapper function http://www.scons.org/wiki/WrapperFunctions + env.SharedLibrary( + target ='i915tex_dri.so', + source = sources, + LIBS = drivers + mesa + auxiliaries + env['LIBS'], + ) diff --git a/src/gallium/winsys/dri/intel/intel_batchbuffer.h b/src/gallium/winsys/dri/intel/intel_batchbuffer.h index 9e4b8043bf..1fa2719845 100644 --- a/src/gallium/winsys/dri/intel/intel_batchbuffer.h +++ b/src/gallium/winsys/dri/intel/intel_batchbuffer.h @@ -1,134 +1,24 @@ #ifndef INTEL_BATCHBUFFER_H #define INTEL_BATCHBUFFER_H -#include "mtypes.h" -#include "ws_dri_bufmgr.h" +#include "intel_drm/intel_be_batchbuffer.h" -struct intel_context; - -#define BATCH_SZ 16384 -#define BATCH_RESERVED 16 - -#define INTEL_DEFAULT_RELOCS 100 -#define INTEL_MAX_RELOCS 400 - -#define INTEL_BATCH_NO_CLIPRECTS 0x1 -#define INTEL_BATCH_CLIPRECTS 0x2 - -struct intel_batchbuffer -{ - struct bufmgr *bm; - struct intel_context *intel; - - struct _DriBufferObject *buffer; - struct _DriFenceObject *last_fence; - GLuint flags; - - struct _DriBufferList *list; - GLuint list_count; - GLubyte *map; - GLubyte *ptr; - - uint32_t *reloc; - GLuint reloc_size; - GLuint nr_relocs; - - GLuint size; - - GLuint dirty_state; - GLuint id; - - uint32_t poolOffset; - uint8_t *drmBOVirtual; - struct _drmBONode *node; /* Validation list node for this buffer */ - int dest_location; /* Validation list sequence for this buffer */ -}; - -struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_context - *intel); - -void intel_batchbuffer_free(struct intel_batchbuffer *batch); - - -void intel_batchbuffer_finish(struct intel_batchbuffer *batch); - -struct _DriFenceObject *intel_batchbuffer_flush(struct intel_batchbuffer - *batch); - -void intel_batchbuffer_reset(struct intel_batchbuffer *batch); - - -/* Unlike bmBufferData, this currently requires the buffer be mapped. - * Consider it a convenience function wrapping multple - * intel_buffer_dword() calls. - */ -void intel_batchbuffer_data(struct intel_batchbuffer *batch, - const void *data, GLuint bytes, GLuint flags); - -void intel_batchbuffer_release_space(struct intel_batchbuffer *batch, - GLuint bytes); - -void -intel_offset_relocation(struct intel_batchbuffer *batch, - unsigned pre_add, - struct _DriBufferObject *driBO, - uint64_t val_flags, - uint64_t val_mask); - -/* Inline functions - might actually be better off with these - * non-inlined. Certainly better off switching all command packets to - * be passed as structs rather than dwords, but that's a little bit of - * work... - */ -static INLINE GLuint -intel_batchbuffer_space(struct intel_batchbuffer *batch) -{ - return (batch->size - BATCH_RESERVED) - (batch->ptr - batch->map); -} - - -static INLINE void -intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch, GLuint dword) -{ - assert(batch->map); - assert(intel_batchbuffer_space(batch) >= 4); - *(GLuint *) (batch->ptr) = dword; - batch->ptr += 4; -} - -static INLINE void -intel_batchbuffer_require_space(struct intel_batchbuffer *batch, - GLuint sz, GLuint flags) -{ - struct _DriFenceObject *fence; - - assert(sz < batch->size - 8); - if (intel_batchbuffer_space(batch) < sz || - (batch->flags != 0 && flags != 0 && batch->flags != flags)) { - fence = intel_batchbuffer_flush(batch); - driFenceUnReference(&fence); - } - - batch->flags |= flags; -} - -/* Here are the crusty old macros, to be removed: +/* + * Need to redefine the BATCH defines */ -#define BATCH_LOCALS -#define BEGIN_BATCH(n, flags) do { \ - assert(!intel->prim.flush); \ - intel_batchbuffer_require_space(intel->batch, (n)*4, flags); \ -} while (0) +#undef BEGIN_BATCH +#define BEGIN_BATCH(dwords, relocs) \ + (i915_batchbuffer_check(&intel->base.batch->base, dwords, relocs)) -#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel->batch, d) +#undef OUT_BATCH +#define OUT_BATCH(d) \ + i915_batchbuffer_dword(&intel->base.batch->base, d) -#define OUT_RELOC(buf,flags,mask,delta) do { \ +#undef OUT_RELOC +#define OUT_RELOC(buf,flags,mask,delta) do { \ assert((delta) >= 0); \ - intel_offset_relocation(intel->batch, delta, buf, flags, mask); \ + intel_be_offset_relocation(intel->base.batch, delta, buf, flags, mask); \ } while (0) -#define ADVANCE_BATCH() do { } while(0) - - #endif diff --git a/src/gallium/winsys/dri/intel/intel_context.c b/src/gallium/winsys/dri/intel/intel_context.c index cc2fc11c5e..8284e0edbb 100644 --- a/src/gallium/winsys/dri/intel/intel_context.c +++ b/src/gallium/winsys/dri/intel/intel_context.c @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * 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 @@ -10,11 +10,11 @@ * 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. @@ -22,7 +22,7 @@ * 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. - * + * **************************************************************************/ @@ -31,10 +31,13 @@ #include "intel_screen.h" #include "intel_context.h" #include "intel_swapbuffers.h" -#include "intel_winsys.h" #include "intel_batchbuffer.h" +#include "intel_winsys_softpipe.h" + +#include "i915simple/i915_screen.h" #include "state_tracker/st_public.h" +#include "state_tracker/st_context.h" #include "pipe/p_defines.h" #include "pipe/p_context.h" @@ -131,6 +134,46 @@ static const struct dri_debug_control debug_control[] = { +/** + * Create i915 hardware rendering context. + */ +static struct pipe_context * +intel_create_i915simple(struct intel_context *intel, + struct pipe_winsys *winsys) +{ + struct pipe_screen *screen; + + /* Fill in this struct with callbacks that i915simple will need to + * communicate with the window system, buffer manager, etc. + */ + screen = i915_create_screen(winsys, intel->intelScreen->deviceID); + + /* Create the i915simple context: + */ + return i915_create_context(screen, winsys, &intel->base.base ); +} + +static void +intel_lock_hardware(struct intel_be_context *context) +{ + struct intel_context *intel = (struct intel_context *)context; + LOCK_HARDWARE(intel); +} + +static void +intel_unlock_hardware(struct intel_be_context *context) +{ + struct intel_context *intel = (struct intel_context *)context; + UNLOCK_HARDWARE(intel); +} + +static boolean +intel_locked_hardware(struct intel_be_context *context) +{ + struct intel_context *intel = (struct intel_context *)context; + return intel->locked ? TRUE : FALSE; +} + GLboolean intelCreateContext(const __GLcontextModes * visual, __DRIcontextPrivate * driContextPriv, @@ -178,20 +221,24 @@ intelCreateContext(const __GLcontextModes * visual, intel->iw.irq_seq = -1; intel->irqsEmitted = 0; - intel->batch = intel_batchbuffer_alloc(intel); intel->last_swap_fence = NULL; intel->first_swap_fence = NULL; #ifdef DEBUG __intel_debug = driParseDebugString(getenv("INTEL_DEBUG"), debug_control); #endif + intel->base.hardware_lock = intel_lock_hardware; + intel->base.hardware_unlock = intel_unlock_hardware; + intel->base.hardware_locked = intel_locked_hardware; + + intel_be_init_context(&intel->base, &intelScreen->base); /* * Pipe-related setup */ if (getenv("INTEL_SP")) { /* use softpipe driver instead of hw */ - pipe = intel_create_softpipe( intel, intelScreen->winsys ); + pipe = intel_create_softpipe( intel, &intelScreen->base.base ); } else { switch (intel->intelScreen->deviceID) { @@ -203,13 +250,13 @@ intelCreateContext(const __GLcontextModes * visual, case PCI_CHIP_Q35_G: case PCI_CHIP_I915_G: case PCI_CHIP_I915_GM: - pipe = intel_create_i915simple( intel, intelScreen->winsys ); + pipe = intel_create_i915simple( intel, &intelScreen->base.base ); break; default: - fprintf(stderr, "Unknown PCIID %x in %s, using software driver\n", + fprintf(stderr, "Unknown PCIID %x in %s, using software driver\n", intel->intelScreen->deviceID, __FUNCTION__); - pipe = intel_create_softpipe( intel, intelScreen->winsys ); + pipe = intel_create_softpipe( intel, &intelScreen->base.base ); break; } } @@ -218,6 +265,8 @@ intelCreateContext(const __GLcontextModes * visual, intel->st = st_create_context(pipe, visual, st_share); + driInitExtensions( intel->st->ctx, card_extensions, GL_TRUE ); + return GL_TRUE; } @@ -231,8 +280,6 @@ intelDestroyContext(__DRIcontextPrivate * driContextPriv) if (intel) { st_finish(intel->st); - intel_batchbuffer_free(intel->batch); - if (intel->last_swap_fence) { driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE); driFenceUnReference(&intel->last_swap_fence); @@ -248,6 +295,7 @@ intelDestroyContext(__DRIcontextPrivate * driContextPriv) intel->intelScreen->dummyContext = NULL; st_destroy_context(intel->st); + intel_be_destroy_context(&intel->base); free(intel); } } diff --git a/src/gallium/winsys/dri/intel/intel_context.h b/src/gallium/winsys/dri/intel/intel_context.h index 597dc13830..ced18da143 100644 --- a/src/gallium/winsys/dri/intel/intel_context.h +++ b/src/gallium/winsys/dri/intel/intel_context.h @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * 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 @@ -10,11 +10,11 @@ * 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. @@ -22,7 +22,7 @@ * 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 INTEL_CONTEXT_H @@ -36,6 +36,8 @@ #include "intel_screen.h" #include "i915_drm.h" +#include "intel_drm/intel_be_context.h" + struct pipe_context; struct intel_context; @@ -50,12 +52,13 @@ struct st_context; */ struct intel_context { + struct intel_be_context base; struct st_context *st; struct _DriFenceObject *last_swap_fence; struct _DriFenceObject *first_swap_fence; - struct intel_batchbuffer *batch; +// struct intel_batchbuffer *batch; boolean locked; char *prevLockFile; @@ -123,7 +126,7 @@ extern int __intel_debug; } while(0) #else -#define DBG(flag, ...) +#define DBG(flag, ...) #endif diff --git a/src/gallium/winsys/dri/intel/intel_lock.c b/src/gallium/winsys/dri/intel/intel_lock.c index 70aa7ea5f4..406284c98f 100644 --- a/src/gallium/winsys/dri/intel/intel_lock.c +++ b/src/gallium/winsys/dri/intel/intel_lock.c @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * 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 @@ -10,11 +10,11 @@ * 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. @@ -22,7 +22,7 @@ * 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. - * + * **************************************************************************/ @@ -87,7 +87,7 @@ void LOCK_HARDWARE( struct intel_context *intel ) } -/* Unlock the hardware using the global current context +/* Unlock the hardware using the global current context */ void UNLOCK_HARDWARE( struct intel_context *intel ) { @@ -99,4 +99,4 @@ void UNLOCK_HARDWARE( struct intel_context *intel ) _glthread_UNLOCK_MUTEX(lockMutex); DBG(LOCK, "%s - unlocked\n", __progname); -} +} diff --git a/src/gallium/winsys/dri/intel/intel_reg.h b/src/gallium/winsys/dri/intel/intel_reg.h index f37c24fda9..4f33bee438 100644 --- a/src/gallium/winsys/dri/intel/intel_reg.h +++ b/src/gallium/winsys/dri/intel/intel_reg.h @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * 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 @@ -10,11 +10,11 @@ * 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. @@ -22,7 +22,7 @@ * 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. - * + * **************************************************************************/ diff --git a/src/gallium/winsys/dri/intel/intel_screen.c b/src/gallium/winsys/dri/intel/intel_screen.c index 58bebbe972..8817a80a5a 100644 --- a/src/gallium/winsys/dri/intel/intel_screen.c +++ b/src/gallium/winsys/dri/intel/intel_screen.c @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * 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 @@ -10,11 +10,11 @@ * 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. @@ -22,7 +22,7 @@ * 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 "utils.h" @@ -32,12 +32,10 @@ #include "intel_context.h" #include "intel_screen.h" #include "intel_batchbuffer.h" -//#include "intel_batchpool.h" #include "intel_swapbuffers.h" -#include "intel_winsys.h" #include "i830_dri.h" -#include "ws_dri_bufpool.h" +#include "intel_drm/ws_dri_bufpool.h" #include "pipe/p_context.h" #include "state_tracker/st_public.h" @@ -50,11 +48,11 @@ PUBLIC const char __driConfigOptions[] = DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS) DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0) DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY - DRI_CONF_FORCE_S3TC_ENABLE(false) +// DRI_CONF_FORCE_S3TC_ENABLE(false) DRI_CONF_ALLOW_LARGE_TEXTURES(1) DRI_CONF_SECTION_END DRI_CONF_END; -const uint __driNConfigOptions = 4; +const uint __driNConfigOptions = 3; #ifdef USE_NEW_INTERFACE static PFNGLXCREATECONTEXTMODES create_context_modes = NULL; @@ -152,16 +150,16 @@ intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea) DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_NO_MOVE | DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0); - driBOSetStatic(intelScreen->front.buffer, - intelScreen->front.offset, - intelScreen->front.pitch * intelScreen->front.height, + driBOSetStatic(intelScreen->front.buffer, + intelScreen->front.offset, + intelScreen->front.pitch * intelScreen->front.height, intelScreen->front.map, 0); } #else - if (intelScreen->staticPool) { + if (intelScreen->base.staticPool) { if (intelScreen->front.buffer) driBOUnReference(intelScreen->front.buffer); - driGenBuffers(intelScreen->staticPool, "front", 1, &intelScreen->front.buffer, 0, 0, 0); + driGenBuffers(intelScreen->base.staticPool, "front", 1, &intelScreen->front.buffer, 0, 0, 0); driBOSetReferenced(intelScreen->front.buffer, sarea->front_bo_handle); } #endif @@ -177,33 +175,6 @@ intelCreatePools(__DRIscreenPrivate * sPriv) if (intelScreen->havePools) return GL_TRUE; -#if 0 /* ZZZ JB fix this */ - intelScreen->staticPool = driDRMStaticPoolInit(sPriv->fd); - if (!intelScreen->staticPool) - return GL_FALSE; - - batchPoolSize /= BATCH_SZ; - intelScreen->batchPool = driBatchPoolInit(sPriv->fd, - DRM_BO_FLAG_EXE | - DRM_BO_FLAG_MEM_TT | - DRM_BO_FLAG_MEM_LOCAL, - BATCH_SZ, - batchPoolSize, 5); - if (!intelScreen->batchPool) { - fprintf(stderr, "Failed to initialize batch pool - possible incorrect agpgart installed\n"); - return GL_FALSE; - } -#else - intelScreen->staticPool = driDRMPoolInit(sPriv->fd); - intelScreen->batchPool = driSlabPoolInit(sPriv->fd, - DRM_BO_FLAG_EXE | - DRM_BO_FLAG_MEM_TT, - DRM_BO_FLAG_EXE | - DRM_BO_FLAG_MEM_TT, - 4 * 4096, //intelScreen->maxBatchSize, - 1, 40, 16*16384, 0, - intelScreen->fMan); -#endif intelScreen->havePools = GL_TRUE; intelUpdateScreenRotation(sPriv, intelScreen->sarea); @@ -211,6 +182,27 @@ intelCreatePools(__DRIscreenPrivate * sPriv) return GL_TRUE; } +static const char * +intel_get_name( struct pipe_winsys *winsys ) +{ + return "Intel/DRI/ttm"; +} + +/* + * The state tracker (should!) keep track of whether the fake + * frontbuffer has been touched by any rendering since the last time + * we copied its contents to the real frontbuffer. Our task is easy: + */ +static void +intel_flush_frontbuffer( struct pipe_winsys *winsys, + struct pipe_surface *surf, + void *context_private) +{ + struct intel_context *intel = (struct intel_context *) context_private; + __DRIdrawablePrivate *dPriv = intel->driDrawable; + + intelDisplaySurface(dPriv, surf, NULL); +} static boolean intelInitDriver(__DRIscreenPrivate * sPriv) @@ -231,7 +223,7 @@ intelInitDriver(__DRIscreenPrivate * sPriv) /* Allocate the private area */ intelScreen = CALLOC_STRUCT(intel_screen); - if (!intelScreen) + if (!intelScreen) return GL_FALSE; /* parse information in __driConfigOptions */ @@ -262,26 +254,9 @@ intelInitDriver(__DRIscreenPrivate * sPriv) (*glx_enable_extension) (psc, "GLX_SGI_make_current_read"); } - - -#if 1 // ZZZ JB - intelScreen->mgr = driFenceMgrTTMInit(sPriv->fd); - if (!intelScreen->mgr) { - fprintf(stderr, "Failed to create fence manager.\n"); - return GL_FALSE; - } - - intelScreen->fMan = driInitFreeSlabManager(10, 10); - if (!intelScreen->fMan) { - fprintf(stderr, "Failed to create free slab manager.\n"); - return GL_FALSE; - } - - if (!intelCreatePools(sPriv)) - return GL_FALSE; -#endif - - intelScreen->winsys = intel_create_pipe_winsys(sPriv->fd, intelScreen->fMan); + intel_be_init_device(&intelScreen->base, sPriv->fd); + intelScreen->base.base.flush_frontbuffer = intel_flush_frontbuffer; + intelScreen->base.base.get_name = intel_get_name; return GL_TRUE; } @@ -292,12 +267,9 @@ intelDestroyScreen(__DRIscreenPrivate * sPriv) { struct intel_screen *intelScreen = intel_screen(sPriv); + intel_be_destroy_device(&intelScreen->base); /* intelUnmapScreenRegions(intelScreen); */ - if (intelScreen->havePools) { - driPoolTakeDown(intelScreen->staticPool); - driPoolTakeDown(intelScreen->batchPool); - } FREE(intelScreen); sPriv->private = NULL; } @@ -518,8 +490,8 @@ intelFillInModes(unsigned pixel_bits, unsigned depth_bits, * This routine also fills in the linked list pointed to by \c driver_modes * with the \c __GLcontextModes that the driver can support for windows or * pbuffers. - * - * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on + * + * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on * failure. */ PUBLIC void * diff --git a/src/gallium/winsys/dri/intel/intel_screen.h b/src/gallium/winsys/dri/intel/intel_screen.h index c17f0202e4..8036917903 100644 --- a/src/gallium/winsys/dri/intel/intel_screen.h +++ b/src/gallium/winsys/dri/intel/intel_screen.h @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * 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 @@ -10,11 +10,11 @@ * 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. @@ -22,7 +22,7 @@ * 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 _INTEL_SCREEN_H_ @@ -31,13 +31,16 @@ #include "dri_util.h" #include "i830_common.h" #include "xmlconfig.h" -#include "ws_dri_bufpool.h" +#include "intel_drm/ws_dri_bufpool.h" #include "pipe/p_compiler.h" +#include "intel_drm/intel_be_device.h" struct intel_screen { + struct intel_be_device base; + struct { drm_handle_t handle; @@ -51,7 +54,7 @@ struct intel_screen int width; int height; int size; - int cpp; /* for front and back buffers */ + int cpp; /* for front and back buffers */ } front; int deviceID; @@ -64,8 +67,6 @@ struct intel_screen */ driOptionCache optionCache; - struct _DriBufferPool *batchPool; - struct _DriBufferPool *staticPool; /** for the X screen/framebuffer */ boolean havePools; /** @@ -74,13 +75,12 @@ struct intel_screen */ struct intel_context *dummyContext; - /* + /* * New stuff form the i915tex integration */ - struct _DriFenceMgr *mgr; - struct _DriFreeSlabManager *fMan; unsigned batch_id; + struct pipe_winsys *winsys; }; diff --git a/src/gallium/winsys/dri/intel/intel_swapbuffers.c b/src/gallium/winsys/dri/intel/intel_swapbuffers.c index 923b542771..7f3babd98e 100644 --- a/src/gallium/winsys/dri/intel/intel_swapbuffers.c +++ b/src/gallium/winsys/dri/intel/intel_swapbuffers.c @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * 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 @@ -10,11 +10,11 @@ * 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. @@ -22,21 +22,22 @@ * 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 "intel_screen.h" #include "intel_context.h" #include "intel_swapbuffers.h" -#include "intel_batchbuffer.h" + #include "intel_reg.h" -#include "intel_winsys.h" #include "pipe/p_context.h" #include "state_tracker/st_public.h" #include "state_tracker/st_context.h" #include "state_tracker/st_cb_fbo.h" +#include "intel_drm/ws_dri_bufmgr.h" +#include "intel_batchbuffer.h" /** * Display a colorbuffer surface in an X window. @@ -114,7 +115,7 @@ intelDisplaySurface(__DRIdrawablePrivate *dPriv, if (pbox->x1 > pbox->x2 || pbox->y1 > pbox->y2 || - pbox->x2 > intelScreen->front.width || + pbox->x2 > intelScreen->front.width || pbox->y2 > intelScreen->front.height) { /* invalid cliprect, skip it */ continue; @@ -159,13 +160,22 @@ intelDisplaySurface(__DRIdrawablePrivate *dPriv, assert(box.y1 < box.y2); /* XXX this could be done with pipe->surface_copy() */ - BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); + /* XXX should have its own batch buffer */ + if (!BEGIN_BATCH(8, 2)) { + /* + * Since we share this batch buffer with a context + * we can't flush it since that risks a GPU lockup + */ + assert(0); + continue; + } + OUT_BATCH(CMD); OUT_BATCH(BR13); OUT_BATCH((box.y1 << 16) | box.x1); OUT_BATCH((box.y2 << 16) | box.x2); - OUT_RELOC(intelScreen->front.buffer, + OUT_RELOC(intelScreen->front.buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0); OUT_BATCH((sbox.y1 << 16) | sbox.x1); @@ -174,12 +184,11 @@ intelDisplaySurface(__DRIdrawablePrivate *dPriv, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0); - ADVANCE_BATCH(); } if (intel->first_swap_fence) driFenceUnReference(&intel->first_swap_fence); - intel->first_swap_fence = intel_batchbuffer_flush(intel->batch); + intel->first_swap_fence = intel_be_batchbuffer_flush(intel->base.batch); } UNLOCK_HARDWARE(intel); diff --git a/src/gallium/winsys/dri/intel/intel_swapbuffers.h b/src/gallium/winsys/dri/intel/intel_swapbuffers.h index 7ae5fd15a5..46c9bab3af 100644 --- a/src/gallium/winsys/dri/intel/intel_swapbuffers.h +++ b/src/gallium/winsys/dri/intel/intel_swapbuffers.h @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. * 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 @@ -10,11 +10,11 @@ * 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. @@ -22,7 +22,7 @@ * 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 INTEL_SWAPBUFFERS_H diff --git a/src/gallium/winsys/dri/intel/intel_winsys.h b/src/gallium/winsys/dri/intel/intel_winsys.h deleted file mode 100644 index 3d32db10a4..0000000000 --- a/src/gallium/winsys/dri/intel/intel_winsys.h +++ /dev/null @@ -1,73 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. - * 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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. - * - **************************************************************************/ - -#ifndef INTEL_WINSYS_H -#define INTEL_WINSYS_H - -#include "pipe/p_state.h" - -struct intel_context; -struct pipe_context; -struct pipe_winsys; -struct pipe_buffer; -struct _DriBufferObject; - -struct pipe_winsys * -intel_create_pipe_winsys( int fd, struct _DriFreeSlabManager *fMan ); - -void -intel_destroy_pipe_winsys( struct pipe_winsys *winsys ); - -struct pipe_context * -intel_create_softpipe( struct intel_context *intel, - struct pipe_winsys *winsys ); - -struct pipe_context * -intel_create_i915simple( struct intel_context *intel, - struct pipe_winsys *winsys ); - - -struct intel_buffer { - struct pipe_buffer base; - struct _DriBufferPool *pool; - struct _DriBufferObject *driBO; -}; - -static INLINE struct intel_buffer * -intel_buffer( struct pipe_buffer *buf ) -{ - return (struct intel_buffer *)buf; -} - -static INLINE struct _DriBufferObject * -dri_bo( struct pipe_buffer *buf ) -{ - return intel_buffer(buf)->driBO; -} - - -#endif diff --git a/src/gallium/winsys/dri/intel/intel_winsys_i915.c b/src/gallium/winsys/dri/intel/intel_winsys_i915.c deleted file mode 100644 index a35825d36a..0000000000 --- a/src/gallium/winsys/dri/intel/intel_winsys_i915.c +++ /dev/null @@ -1,183 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA - * 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, 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 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 - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS 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. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ -/* - * Authors: Keith Whitwell <keithw-at-tungstengraphics-dot-com> - */ - -#include <stdlib.h> -#include <xf86drm.h> -#include "ws_dri_bufpool.h" -#include "ws_dri_bufmgr.h" - -#include "intel_context.h" -#include "intel_batchbuffer.h" -#include "intel_winsys.h" - -#include "pipe/p_util.h" -#include "pipe/p_winsys.h" -#include "i915simple/i915_winsys.h" -#include "i915simple/i915_screen.h" - - -struct intel_i915_winsys { - struct i915_winsys winsys; /**< batch buffer funcs */ - struct pipe_winsys *pws; - struct intel_context *intel; -}; - - -/* Turn a i915simple winsys into an intel/i915simple winsys: - */ -static inline struct intel_i915_winsys * -intel_i915_winsys( struct i915_winsys *sws ) -{ - return (struct intel_i915_winsys *)sws; -} - - -/* Simple batchbuffer interface: - */ - -static unsigned *intel_i915_batch_start( struct i915_winsys *sws, - unsigned dwords, - unsigned relocs ) -{ - struct intel_context *intel = intel_i915_winsys(sws)->intel; - - /* XXX: check relocs. - */ - if (intel_batchbuffer_space( intel->batch ) >= dwords * 4) { - /* XXX: Hmm, the driver can't really do much with this pointer: - */ - return (unsigned *)intel->batch->ptr; - } - else - return NULL; -} - -static void intel_i915_batch_dword( struct i915_winsys *sws, - unsigned dword ) -{ - struct intel_context *intel = intel_i915_winsys(sws)->intel; - intel_batchbuffer_emit_dword( intel->batch, dword ); -} - -static void intel_i915_batch_reloc( struct i915_winsys *sws, - struct pipe_buffer *buf, - unsigned access_flags, - unsigned delta ) -{ - struct intel_context *intel = intel_i915_winsys(sws)->intel; - unsigned flags = DRM_BO_FLAG_MEM_TT; - unsigned mask = DRM_BO_MASK_MEM; - - if (access_flags & I915_BUFFER_ACCESS_WRITE) { - flags |= DRM_BO_FLAG_WRITE; - mask |= DRM_BO_FLAG_WRITE; - } - - if (access_flags & I915_BUFFER_ACCESS_READ) { - flags |= DRM_BO_FLAG_READ; - mask |= DRM_BO_FLAG_READ; - } - -#if 0 /* JB old */ - intel_batchbuffer_emit_reloc( intel->batch, - dri_bo( buf ), - flags, mask, - delta ); -#else /* new */ - intel_offset_relocation( intel->batch, - delta, - dri_bo( buf ), - flags, - mask ); -#endif -} - - - -static void intel_i915_batch_flush( struct i915_winsys *sws, - struct pipe_fence_handle **fence ) -{ - struct intel_i915_winsys *iws = intel_i915_winsys(sws); - struct intel_context *intel = iws->intel; - union { - struct _DriFenceObject *dri; - struct pipe_fence_handle *pipe; - } fu; - - if (fence) - assert(!*fence); - - fu.dri = intel_batchbuffer_flush( intel->batch ); - - if (!fu.dri) { - assert(0); - *fence = NULL; - return; - } - - if (fu.dri) { - if (fence) - *fence = fu.pipe; - else - driFenceUnReference(&fu.dri); - } - -} - - -/** - * Create i915 hardware rendering context. - */ -struct pipe_context * -intel_create_i915simple( struct intel_context *intel, - struct pipe_winsys *winsys ) -{ - struct intel_i915_winsys *iws = CALLOC_STRUCT( intel_i915_winsys ); - struct pipe_screen *screen; - - /* Fill in this struct with callbacks that i915simple will need to - * communicate with the window system, buffer manager, etc. - */ - iws->winsys.batch_start = intel_i915_batch_start; - iws->winsys.batch_dword = intel_i915_batch_dword; - iws->winsys.batch_reloc = intel_i915_batch_reloc; - iws->winsys.batch_flush = intel_i915_batch_flush; - iws->pws = winsys; - iws->intel = intel; - - screen = i915_create_screen(winsys, intel->intelScreen->deviceID); - - /* Create the i915simple context: - */ - return i915_create_context( screen, - winsys, - &iws->winsys ); -} diff --git a/src/gallium/winsys/dri/intel/intel_winsys_pipe.c b/src/gallium/winsys/dri/intel/intel_winsys_pipe.c deleted file mode 100644 index 10e1a84cc1..0000000000 --- a/src/gallium/winsys/dri/intel/intel_winsys_pipe.c +++ /dev/null @@ -1,354 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA - * 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, 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 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 - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS 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. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ -/* - * Authors: Keith Whitwell <keithw-at-tungstengraphics-dot-com> - */ - -#include <stdlib.h> -#include <xf86drm.h> -//#include "dri_bufpool.h" -//#include "dri_bufmgr.h" - -#include "intel_context.h" -#include "intel_winsys.h" -#include "intel_swapbuffers.h" -#include "intel_batchbuffer.h" - -#include "pipe/p_winsys.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "pipe/p_util.h" -#include "pipe/p_inlines.h" - - - -struct intel_pipe_winsys { - struct pipe_winsys winsys; - struct _DriBufferPool *regionPool; - struct _DriBufferPool *mallocPool; - struct _DriBufferPool *vertexPool; - struct _DriFreeSlabManager *fMan; /** shared between all pipes */ -}; - - - -/* Turn a pipe winsys into an intel/pipe winsys: - */ -static inline struct intel_pipe_winsys * -intel_pipe_winsys( struct pipe_winsys *winsys ) -{ - return (struct intel_pipe_winsys *)winsys; -} - - -/* Most callbacks map direcly onto dri_bufmgr operations: - */ -static void *intel_buffer_map(struct pipe_winsys *winsys, - struct pipe_buffer *buf, - unsigned flags ) -{ - unsigned drm_flags = 0; - - if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) - drm_flags |= DRM_BO_FLAG_WRITE; - - if (flags & PIPE_BUFFER_USAGE_CPU_READ) - drm_flags |= DRM_BO_FLAG_READ; - - return driBOMap( dri_bo(buf), drm_flags, 0 ); -} - -static void intel_buffer_unmap(struct pipe_winsys *winsys, - struct pipe_buffer *buf) -{ - driBOUnmap( dri_bo(buf) ); -} - - -static void -intel_buffer_destroy(struct pipe_winsys *winsys, - struct pipe_buffer *buf) -{ - driBOUnReference( dri_bo(buf) ); - FREE(buf); -} - - -/* Pipe has no concept of pools. We choose the tex/region pool - * for all buffers. - * Grabs the hardware lock! - */ -static struct pipe_buffer * -intel_buffer_create(struct pipe_winsys *winsys, - unsigned alignment, - unsigned usage, - unsigned size ) -{ - struct intel_buffer *buffer = CALLOC_STRUCT( intel_buffer ); - struct intel_pipe_winsys *iws = intel_pipe_winsys(winsys); - unsigned flags = 0; - struct _DriBufferPool *pool; - - buffer->base.refcount = 1; - buffer->base.alignment = alignment; - buffer->base.usage = usage; - buffer->base.size = size; - - if (usage & (PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_CONSTANT)) { - flags |= DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED; - pool = iws->mallocPool; - } else if (usage & PIPE_BUFFER_USAGE_CUSTOM) { - /* For vertex buffers */ - flags |= DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MEM_TT; - pool = iws->vertexPool; - } else { - flags |= DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MEM_TT; - pool = iws->regionPool; - } - - if (usage & PIPE_BUFFER_USAGE_GPU_READ) - flags |= DRM_BO_FLAG_READ; - - if (usage & PIPE_BUFFER_USAGE_GPU_WRITE) - flags |= DRM_BO_FLAG_WRITE; - - /* drm complains if we don't set any read/write flags. - */ - if ((flags & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE)) == 0) - flags |= DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE; - -#if 0 - if (flags & IWS_BUFFER_USAGE_EXE) - flags |= DRM_BO_FLAG_EXE; - - if (usage & IWS_BUFFER_USAGE_CACHED) - flags |= DRM_BO_FLAG_CACHED; -#endif - - buffer->pool = pool; - driGenBuffers( buffer->pool, - "pipe buffer", 1, &buffer->driBO, alignment, flags, 0 ); - - driBOData( buffer->driBO, size, NULL, buffer->pool, 0 ); - - return &buffer->base; -} - - -static struct pipe_buffer * -intel_user_buffer_create(struct pipe_winsys *winsys, void *ptr, unsigned bytes) -{ - struct intel_buffer *buffer = CALLOC_STRUCT( intel_buffer ); - struct intel_pipe_winsys *iws = intel_pipe_winsys(winsys); - - driGenUserBuffer( iws->regionPool, - "pipe user buffer", &buffer->driBO, ptr, bytes ); - - buffer->base.refcount = 1; - - return &buffer->base; -} - - -/* The state tracker (should!) keep track of whether the fake - * frontbuffer has been touched by any rendering since the last time - * we copied its contents to the real frontbuffer. Our task is easy: - */ -static void -intel_flush_frontbuffer( struct pipe_winsys *winsys, - struct pipe_surface *surf, - void *context_private) -{ - struct intel_context *intel = (struct intel_context *) context_private; - __DRIdrawablePrivate *dPriv = intel->driDrawable; - - intelDisplaySurface(dPriv, surf, NULL); -} - - -static struct pipe_surface * -intel_i915_surface_alloc(struct pipe_winsys *winsys) -{ - struct pipe_surface *surf = CALLOC_STRUCT(pipe_surface); - if (surf) { - surf->refcount = 1; - surf->winsys = winsys; - } - return surf; -} - - -/** - * Round n up to next multiple. - */ -static INLINE unsigned -round_up(unsigned n, unsigned multiple) -{ - return (n + multiple - 1) & ~(multiple - 1); -} - -/** - * Copied from xm_winsys.c - */ -static int -intel_i915_surface_alloc_storage(struct pipe_winsys *winsys, - struct pipe_surface *surf, - unsigned width, unsigned height, - enum pipe_format format, - unsigned flags, - unsigned tex_usage) -{ - const unsigned alignment = 64; - //int ret; - - surf->width = width; - surf->height = height; - surf->format = format; - surf->cpp = pf_get_size(format); - surf->pitch = round_up(width, alignment / surf->cpp); - - assert(!surf->buffer); - surf->buffer = winsys->buffer_create(winsys, alignment, - PIPE_BUFFER_USAGE_PIXEL, - surf->pitch * surf->cpp * height); - if(!surf->buffer) - return -1; - - return 0; -} - - -static void -intel_i915_surface_release(struct pipe_winsys *winsys, struct pipe_surface **s) -{ - struct pipe_surface *surf = *s; - surf->refcount--; - if (surf->refcount == 0) { - if (surf->buffer) - pipe_buffer_reference(winsys, &surf->buffer, NULL); - free(surf); - } - *s = NULL; -} - - - -static const char * -intel_get_name( struct pipe_winsys *winsys ) -{ - return "Intel/DRI/ttm"; -} - -static void -intel_fence_reference( struct pipe_winsys *sws, - struct pipe_fence_handle **ptr, - struct pipe_fence_handle *fence ) -{ - if (*ptr) - driFenceUnReference((struct _DriFenceObject **)ptr); - - if (fence) - *ptr = (struct pipe_fence_handle *)driFenceReference((struct _DriFenceObject *)fence); -} - -static int -intel_fence_signalled( struct pipe_winsys *sws, - struct pipe_fence_handle *fence, - unsigned flag ) -{ - return driFenceSignaled((struct _DriFenceObject *)fence, flag); -} - -static int -intel_fence_finish( struct pipe_winsys *sws, - struct pipe_fence_handle *fence, - unsigned flag ) -{ - return driFenceFinish((struct _DriFenceObject *)fence, flag, 0); -} - -struct pipe_winsys * -intel_create_pipe_winsys( int fd, struct _DriFreeSlabManager *fMan ) -{ - struct intel_pipe_winsys *iws = CALLOC_STRUCT( intel_pipe_winsys ); - - /* Fill in this struct with callbacks that pipe will need to - * communicate with the window system, buffer manager, etc. - * - * Pipe would be happy with a malloc based memory manager, but - * the SwapBuffers implementation in this winsys driver requires - * that rendering be done to an appropriate _DriBufferObject. - */ - iws->winsys.buffer_create = intel_buffer_create; - iws->winsys.user_buffer_create = intel_user_buffer_create; - iws->winsys.buffer_map = intel_buffer_map; - iws->winsys.buffer_unmap = intel_buffer_unmap; - iws->winsys.buffer_destroy = intel_buffer_destroy; - iws->winsys.flush_frontbuffer = intel_flush_frontbuffer; - iws->winsys.get_name = intel_get_name; - iws->winsys.surface_alloc = intel_i915_surface_alloc; - iws->winsys.surface_alloc_storage = intel_i915_surface_alloc_storage; - iws->winsys.surface_release = intel_i915_surface_release; - - iws->winsys.fence_reference = intel_fence_reference; - iws->winsys.fence_signalled = intel_fence_signalled; - iws->winsys.fence_finish = intel_fence_finish; - - if (fd) { - iws->regionPool = driDRMPoolInit(fd); - iws->vertexPool = driSlabPoolInit(fd, - DRM_BO_FLAG_READ | - DRM_BO_FLAG_WRITE | - DRM_BO_FLAG_MEM_TT, - DRM_BO_FLAG_READ | - DRM_BO_FLAG_WRITE | - DRM_BO_FLAG_MEM_TT, - 32 * 4096, - 1, 40, 32 * 4096 * 2, 0, - fMan); - } - - iws->mallocPool = driMallocPoolInit(); - - return &iws->winsys; -} - - -void -intel_destroy_pipe_winsys( struct pipe_winsys *winsys ) -{ - struct intel_pipe_winsys *iws = intel_pipe_winsys(winsys); - if (iws->regionPool) { - driPoolTakeDown(iws->regionPool); - } - if (iws->mallocPool) { - driPoolTakeDown(iws->mallocPool); - } - free(iws); -} - diff --git a/src/gallium/winsys/dri/intel/intel_winsys_softpipe.c b/src/gallium/winsys/dri/intel/intel_winsys_softpipe.c index 0bc2dc4002..0d98d16cf1 100644 --- a/src/gallium/winsys/dri/intel/intel_winsys_softpipe.c +++ b/src/gallium/winsys/dri/intel/intel_winsys_softpipe.c @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA * 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 @@ -10,27 +10,27 @@ * 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 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 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS 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 + * 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. * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. - * - * + * + * **************************************************************************/ /* * Authors: Keith Whitwell <keithw-at-tungstengraphics-dot-com> */ #include "intel_context.h" -#include "intel_winsys.h" +#include "intel_winsys_softpipe.h" #include "pipe/p_defines.h" #include "pipe/p_util.h" #include "pipe/p_format.h" @@ -69,9 +69,9 @@ intel_create_softpipe( struct intel_context *intel, { struct intel_softpipe_winsys *isws = CALLOC_STRUCT( intel_softpipe_winsys ); struct pipe_screen *screen = softpipe_create_screen(winsys); - + /* Fill in this struct with callbacks that softpipe will need to - * communicate with the window system, buffer manager, etc. + * communicate with the window system, buffer manager, etc. */ isws->sws.is_format_supported = intel_is_format_supported; isws->intel = intel; diff --git a/src/gallium/winsys/egl_drm/intel/intel_swapbuffers.h b/src/gallium/winsys/dri/intel/intel_winsys_softpipe.h index 904f26732e..5fa14cb749 100644 --- a/src/gallium/winsys/egl_drm/intel/intel_swapbuffers.h +++ b/src/gallium/winsys/dri/intel/intel_winsys_softpipe.h @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. * 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 @@ -10,11 +10,11 @@ * 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. @@ -22,26 +22,18 @@ * 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 INTEL_SWAPBUFFERS_H -#define INTEL_SWAPBUFFERS_H +#ifndef INTEL_SOFTPIPE_H +#define INTEL_SOFTPIPE_H +struct pipe_winsys; +struct pipe_context; +struct intel_context; -struct pipe_surface; +struct pipe_context * +intel_create_softpipe( struct intel_context *intel, + struct pipe_winsys *winsys ); -#if 0 -extern void intelDisplaySurface(__DRIdrawablePrivate * dPriv, - struct pipe_surface *surf, - const drm_clip_rect_t * rect); - -extern void intelSwapBuffers(__DRIdrawablePrivate * dPriv); - -extern void intelCopySubBuffer(__DRIdrawablePrivate * dPriv, - int x, int y, int w, int h); - -extern void intelUpdateWindowSize(__DRIdrawablePrivate *dPriv); #endif - -#endif /* INTEL_SWAPBUFFERS_H */ diff --git a/src/gallium/winsys/dri/intel/server/i830_common.h b/src/gallium/winsys/dri/intel/server/i830_common.h index f84f453309..3452ddb3c9 100644 --- a/src/gallium/winsys/dri/intel/server/i830_common.h +++ b/src/gallium/winsys/dri/intel/server/i830_common.h @@ -88,9 +88,9 @@ typedef struct { /** Last context that used the buffer manager. */ int texAge; int pf_enabled; /* is pageflipping allowed? */ - int pf_active; + int pf_active; int pf_current_page; /* which buffer is being displayed? */ - int perf_boxes; /* performance boxes to be displayed */ + int perf_boxes; /* performance boxes to be displayed */ int width, height; /* screen size in pixels */ drm_handle_t front_handle; @@ -173,7 +173,7 @@ typedef struct { int num_cliprects; /* mulitpass with multiple cliprects? */ drm_clip_rect_t *cliprects; /* pointer to userspace cliprects */ } drmI830CmdBuffer; - + typedef struct { int *irq_seq; } drmI830IrqEmit; @@ -188,7 +188,7 @@ typedef struct { } drmI830GetParam; #define I830_PARAM_IRQ_ACTIVE 1 -#define I830_PARAM_ALLOW_BATCHBUFFER 2 +#define I830_PARAM_ALLOW_BATCHBUFFER 2 typedef struct { int param; diff --git a/src/gallium/winsys/dri/intel/server/i830_dri.h b/src/gallium/winsys/dri/intel/server/i830_dri.h index 685de4a551..0d514b6c38 100644 --- a/src/gallium/winsys/dri/intel/server/i830_dri.h +++ b/src/gallium/winsys/dri/intel/server/i830_dri.h @@ -40,7 +40,7 @@ typedef struct _I830DRIRec { int bitsPerPixel; int unused11[8]; /* was front/back/depth/rotated offset/pitch */ - + int unused12; /* logTextureGranularity */ int unused13; /* textureOffset */ diff --git a/src/gallium/winsys/dri/intel/server/intel.h b/src/gallium/winsys/dri/intel/server/intel.h deleted file mode 100644 index 6ea72499c1..0000000000 --- a/src/gallium/winsys/dri/intel/server/intel.h +++ /dev/null @@ -1,331 +0,0 @@ -#ifndef _INTEL_H_ -#define _INTEL_H_ - -#include "xf86drm.h" /* drm_handle_t, etc */ - -/* Intel */ -#ifndef PCI_CHIP_I810 -#define PCI_CHIP_I810 0x7121 -#define PCI_CHIP_I810_DC100 0x7123 -#define PCI_CHIP_I810_E 0x7125 -#define PCI_CHIP_I815 0x1132 -#define PCI_CHIP_I810_BRIDGE 0x7120 -#define PCI_CHIP_I810_DC100_BRIDGE 0x7122 -#define PCI_CHIP_I810_E_BRIDGE 0x7124 -#define PCI_CHIP_I815_BRIDGE 0x1130 -#endif - -#define PCI_CHIP_845_G 0x2562 -#define PCI_CHIP_I830_M 0x3577 - -#ifndef PCI_CHIP_I855_GM -#define PCI_CHIP_I855_GM 0x3582 -#define PCI_CHIP_I855_GM_BRIDGE 0x3580 -#endif - -#ifndef PCI_CHIP_I865_G -#define PCI_CHIP_I865_G 0x2572 -#define PCI_CHIP_I865_G_BRIDGE 0x2570 -#endif - -#ifndef PCI_CHIP_I915_G -#define PCI_CHIP_I915_G 0x2582 -#define PCI_CHIP_I915_G_BRIDGE 0x2580 -#endif - -#ifndef PCI_CHIP_I915_GM -#define PCI_CHIP_I915_GM 0x2592 -#define PCI_CHIP_I915_GM_BRIDGE 0x2590 -#endif - -#ifndef PCI_CHIP_E7221_G -#define PCI_CHIP_E7221_G 0x258A -/* Same as I915_G_BRIDGE */ -#define PCI_CHIP_E7221_G_BRIDGE 0x2580 -#endif - -#ifndef PCI_CHIP_I945_G -#define PCI_CHIP_I945_G 0x2772 -#define PCI_CHIP_I945_G_BRIDGE 0x2770 -#endif - -#ifndef PCI_CHIP_I945_GM -#define PCI_CHIP_I945_GM 0x27A2 -#define PCI_CHIP_I945_GM_BRIDGE 0x27A0 -#endif - -#define IS_I810(pI810) (pI810->Chipset == PCI_CHIP_I810 || \ - pI810->Chipset == PCI_CHIP_I810_DC100 || \ - pI810->Chipset == PCI_CHIP_I810_E) -#define IS_I815(pI810) (pI810->Chipset == PCI_CHIP_I815) -#define IS_I830(pI810) (pI810->Chipset == PCI_CHIP_I830_M) -#define IS_845G(pI810) (pI810->Chipset == PCI_CHIP_845_G) -#define IS_I85X(pI810) (pI810->Chipset == PCI_CHIP_I855_GM) -#define IS_I852(pI810) (pI810->Chipset == PCI_CHIP_I855_GM && (pI810->variant == I852_GM || pI810->variant == I852_GME)) -#define IS_I855(pI810) (pI810->Chipset == PCI_CHIP_I855_GM && (pI810->variant == I855_GM || pI810->variant == I855_GME)) -#define IS_I865G(pI810) (pI810->Chipset == PCI_CHIP_I865_G) - -#define IS_I915G(pI810) (pI810->Chipset == PCI_CHIP_I915_G || pI810->Chipset == PCI_CHIP_E7221_G) -#define IS_I915GM(pI810) (pI810->Chipset == PCI_CHIP_I915_GM) -#define IS_I945G(pI810) (pI810->Chipset == PCI_CHIP_I945_G) -#define IS_I945GM(pI810) (pI810->Chipset == PCI_CHIP_I945_GM) -#define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810)) - -#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810)) - -#define I830_GMCH_CTRL 0x52 - -#define I830_GMCH_MEM_MASK 0x1 -#define I830_GMCH_MEM_64M 0x1 -#define I830_GMCH_MEM_128M 0 - -#define I830_GMCH_GMS_MASK 0x70 -#define I830_GMCH_GMS_DISABLED 0x00 -#define I830_GMCH_GMS_LOCAL 0x10 -#define I830_GMCH_GMS_STOLEN_512 0x20 -#define I830_GMCH_GMS_STOLEN_1024 0x30 -#define I830_GMCH_GMS_STOLEN_8192 0x40 - -#define I855_GMCH_GMS_MASK (0x7 << 4) -#define I855_GMCH_GMS_DISABLED 0x00 -#define I855_GMCH_GMS_STOLEN_1M (0x1 << 4) -#define I855_GMCH_GMS_STOLEN_4M (0x2 << 4) -#define I855_GMCH_GMS_STOLEN_8M (0x3 << 4) -#define I855_GMCH_GMS_STOLEN_16M (0x4 << 4) -#define I855_GMCH_GMS_STOLEN_32M (0x5 << 4) -#define I915G_GMCH_GMS_STOLEN_48M (0x6 << 4) -#define I915G_GMCH_GMS_STOLEN_64M (0x7 << 4) - -typedef unsigned char Bool; -#define TRUE 1 -#define FALSE 0 - -#define PIPE_NONE 0<<0 -#define PIPE_CRT 1<<0 -#define PIPE_TV 1<<1 -#define PIPE_DFP 1<<2 -#define PIPE_LFP 1<<3 -#define PIPE_CRT2 1<<4 -#define PIPE_TV2 1<<5 -#define PIPE_DFP2 1<<6 -#define PIPE_LFP2 1<<7 - -typedef struct _I830MemPool *I830MemPoolPtr; -typedef struct _I830MemRange *I830MemRangePtr; -typedef struct _I830MemRange { - long Start; - long End; - long Size; - unsigned long Physical; - unsigned long Offset; /* Offset of AGP-allocated portion */ - unsigned long Alignment; - drm_handle_t Key; - unsigned long Pitch; // add pitch - I830MemPoolPtr Pool; -} I830MemRange; - -typedef struct _I830MemPool { - I830MemRange Total; - I830MemRange Free; - I830MemRange Fixed; - I830MemRange Allocated; -} I830MemPool; - -typedef struct { - int tail_mask; - I830MemRange mem; - unsigned char *virtual_start; - int head; - int tail; - int space; -} I830RingBuffer; - -typedef struct _I830Rec { - unsigned char *MMIOBase; - unsigned char *FbBase; - int cpp; - uint32_t aper_size; - unsigned int bios_version; - - /* These are set in PreInit and never changed. */ - long FbMapSize; - long TotalVideoRam; - I830MemRange StolenMemory; /* pre-allocated memory */ - long BIOSMemorySize; /* min stolen pool size */ - int BIOSMemSizeLoc; - - /* These change according to what has been allocated. */ - long FreeMemory; - I830MemRange MemoryAperture; - I830MemPool StolenPool; - long allocatedMemory; - - /* Regions allocated either from the above pools, or from agpgart. */ - /* for single and dual head configurations */ - I830MemRange FrontBuffer; - I830MemRange FrontBuffer2; - I830MemRange Scratch; - I830MemRange Scratch2; - - I830RingBuffer *LpRing; - - I830MemRange BackBuffer; - I830MemRange DepthBuffer; - I830MemRange TexMem; - int TexGranularity; - I830MemRange ContextMem; - int drmMinor; - Bool have3DWindows; - - Bool NeedRingBufferLow; - Bool allowPageFlip; - Bool disableTiling; - - int Chipset; - unsigned long LinearAddr; - unsigned long MMIOAddr; - - drmSize registerSize; /**< \brief MMIO register map size */ - drm_handle_t registerHandle; /**< \brief MMIO register map handle */ - // IOADDRESS ioBase; - int irq; /**< \brief IRQ number */ - int GttBound; - - drm_handle_t ring_map; - unsigned int Fence[8]; - -} I830Rec; - -/* - * 12288 is set as the maximum, chosen because it is enough for - * 1920x1440@32bpp with a 2048 pixel line pitch with some to spare. - */ -#define I830_MAXIMUM_VBIOS_MEM 12288 -#define I830_DEFAULT_VIDEOMEM_2D (MB(32) / 1024) -#define I830_DEFAULT_VIDEOMEM_3D (MB(64) / 1024) - -/* Flags for memory allocation function */ -#define FROM_ANYWHERE 0x00000000 -#define FROM_POOL_ONLY 0x00000001 -#define FROM_NEW_ONLY 0x00000002 -#define FROM_MASK 0x0000000f - -#define ALLOCATE_AT_TOP 0x00000010 -#define ALLOCATE_AT_BOTTOM 0x00000020 -#define FORCE_GAPS 0x00000040 - -#define NEED_PHYSICAL_ADDR 0x00000100 -#define ALIGN_BOTH_ENDS 0x00000200 -#define FORCE_LOW 0x00000400 - -#define ALLOC_NO_TILING 0x00001000 -#define ALLOC_INITIAL 0x00002000 - -#define ALLOCATE_DRY_RUN 0x80000000 - -/* Chipset registers for VIDEO BIOS memory RW access */ -#define _855_DRAM_RW_CONTROL 0x58 -#define _845_DRAM_RW_CONTROL 0x90 -#define DRAM_WRITE 0x33330000 - -#define KB(x) ((x) * 1024) -#define MB(x) ((x) * KB(1024)) - -#define GTT_PAGE_SIZE KB(4) -#define ROUND_TO(x, y) (((x) + (y) - 1) / (y) * (y)) -#define ROUND_DOWN_TO(x, y) ((x) / (y) * (y)) -#define ROUND_TO_PAGE(x) ROUND_TO((x), GTT_PAGE_SIZE) -#define ROUND_TO_MB(x) ROUND_TO((x), MB(1)) -#define PRIMARY_RINGBUFFER_SIZE KB(128) - - -/* Ring buffer registers, p277, overview p19 - */ -#define LP_RING 0x2030 -#define HP_RING 0x2040 - -#define RING_TAIL 0x00 -#define TAIL_ADDR 0x000FFFF8 -#define I830_TAIL_MASK 0x001FFFF8 - -#define RING_HEAD 0x04 -#define HEAD_WRAP_COUNT 0xFFE00000 -#define HEAD_WRAP_ONE 0x00200000 -#define HEAD_ADDR 0x001FFFFC -#define I830_HEAD_MASK 0x001FFFFC - -#define RING_START 0x08 -#define START_ADDR 0x03FFFFF8 -#define I830_RING_START_MASK 0xFFFFF000 - -#define RING_LEN 0x0C -#define RING_NR_PAGES 0x001FF000 -#define I830_RING_NR_PAGES 0x001FF000 -#define RING_REPORT_MASK 0x00000006 -#define RING_REPORT_64K 0x00000002 -#define RING_REPORT_128K 0x00000004 -#define RING_NO_REPORT 0x00000000 -#define RING_VALID_MASK 0x00000001 -#define RING_VALID 0x00000001 -#define RING_INVALID 0x00000000 - - -/* Fence/Tiling ranges [0..7] - */ -#define FENCE 0x2000 -#define FENCE_NR 8 - -#define I915G_FENCE_START_MASK 0x0ff00000 - -#define I830_FENCE_START_MASK 0x07f80000 - -#define FENCE_START_MASK 0x03F80000 -#define FENCE_X_MAJOR 0x00000000 -#define FENCE_Y_MAJOR 0x00001000 -#define FENCE_SIZE_MASK 0x00000700 -#define FENCE_SIZE_512K 0x00000000 -#define FENCE_SIZE_1M 0x00000100 -#define FENCE_SIZE_2M 0x00000200 -#define FENCE_SIZE_4M 0x00000300 -#define FENCE_SIZE_8M 0x00000400 -#define FENCE_SIZE_16M 0x00000500 -#define FENCE_SIZE_32M 0x00000600 -#define FENCE_SIZE_64M 0x00000700 -#define I915G_FENCE_SIZE_1M 0x00000000 -#define I915G_FENCE_SIZE_2M 0x00000100 -#define I915G_FENCE_SIZE_4M 0x00000200 -#define I915G_FENCE_SIZE_8M 0x00000300 -#define I915G_FENCE_SIZE_16M 0x00000400 -#define I915G_FENCE_SIZE_32M 0x00000500 -#define I915G_FENCE_SIZE_64M 0x00000600 -#define I915G_FENCE_SIZE_128M 0x00000700 -#define FENCE_PITCH_1 0x00000000 -#define FENCE_PITCH_2 0x00000010 -#define FENCE_PITCH_4 0x00000020 -#define FENCE_PITCH_8 0x00000030 -#define FENCE_PITCH_16 0x00000040 -#define FENCE_PITCH_32 0x00000050 -#define FENCE_PITCH_64 0x00000060 -#define FENCE_VALID 0x00000001 - -#include <mmio.h> - -# define MMIO_IN8(base, offset) \ - *(volatile unsigned char *)(((unsigned char*)(base)) + (offset)) -# define MMIO_IN32(base, offset) \ - read_MMIO_LE32(base, offset) -# define MMIO_OUT8(base, offset, val) \ - *(volatile unsigned char *)(((unsigned char*)(base)) + (offset)) = (val) -# define MMIO_OUT32(base, offset, val) \ - *(volatile unsigned int *)(void *)(((unsigned char*)(base)) + (offset)) = CPU_TO_LE32(val) - - - /* Memory mapped register access macros */ -#define INREG8(addr) MMIO_IN8(MMIO, addr) -#define INREG(addr) MMIO_IN32(MMIO, addr) -#define OUTREG8(addr, val) MMIO_OUT8(MMIO, addr, val) -#define OUTREG(addr, val) MMIO_OUT32(MMIO, addr, val) - -#define DSPABASE 0x70184 - -#endif diff --git a/src/gallium/winsys/dri/intel/server/intel_dri.c b/src/gallium/winsys/dri/intel/server/intel_dri.c deleted file mode 100644 index e49c4214ad..0000000000 --- a/src/gallium/winsys/dri/intel/server/intel_dri.c +++ /dev/null @@ -1,1306 +0,0 @@ -/** - * \file server/intel_dri.c - * \brief File to perform the device-specific initialization tasks typically - * done in the X server. - * - * Here they are converted to run in the client (or perhaps a standalone - * process), and to work with the frame buffer device rather than the X - * server infrastructure. - * - * Copyright (C) 2006 Dave Airlie (airlied@linux.ie) - - 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, 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 THE COPYRIGHT HOLDERS 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. -*/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> - -#include "driver.h" -#include "drm.h" - -#include "intel.h" -#include "i830_dri.h" - -#include "memops.h" -#include "pciaccess.h" - -static size_t drm_page_size; -static int nextTile = 0; -#define xf86DrvMsg(...) do {} while(0) - -static const int pitches[] = { - 128 * 8, - 128 * 16, - 128 * 32, - 128 * 64, - 0 -}; - -static Bool I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea); - -static unsigned long -GetBestTileAlignment(unsigned long size) -{ - unsigned long i; - - for (i = KB(512); i < size; i <<= 1) - ; - - if (i > MB(64)) - i = MB(64); - - return i; -} - -static void SetFenceRegs(const DRIDriverContext *ctx, I830Rec *pI830) -{ - int i; - unsigned char *MMIO = ctx->MMIOAddress; - - for (i = 0; i < 8; i++) { - OUTREG(FENCE + i * 4, pI830->Fence[i]); - // if (I810_DEBUG & DEBUG_VERBOSE_VGA) - fprintf(stderr,"Fence Register : %x\n", pI830->Fence[i]); - } -} - -/* Tiled memory is good... really, really good... - * - * Need to make it less likely that we miss out on this - probably - * need to move the frontbuffer away from the 'guarenteed' alignment - * of the first memory segment, or perhaps allocate a discontigous - * framebuffer to get more alignment 'sweet spots'. - */ -static void -SetFence(const DRIDriverContext *ctx, I830Rec *pI830, - int nr, unsigned int start, unsigned int pitch, - unsigned int size) -{ - unsigned int val; - unsigned int fence_mask = 0; - unsigned int fence_pitch; - - if (nr < 0 || nr > 7) { - fprintf(stderr, - "SetFence: fence %d out of range\n",nr); - return; - } - - pI830->Fence[nr] = 0; - - if (IS_I9XX(pI830)) - fence_mask = ~I915G_FENCE_START_MASK; - else - fence_mask = ~I830_FENCE_START_MASK; - - if (start & fence_mask) { - fprintf(stderr, - "SetFence: %d: start (0x%08x) is not %s aligned\n", - nr, start, (IS_I9XX(pI830)) ? "1MB" : "512k"); - return; - } - - if (start % size) { - fprintf(stderr, - "SetFence: %d: start (0x%08x) is not size (%dk) aligned\n", - nr, start, size / 1024); - return; - } - - if (pitch & 127) { - fprintf(stderr, - "SetFence: %d: pitch (%d) not a multiple of 128 bytes\n", - nr, pitch); - return; - } - - val = (start | FENCE_X_MAJOR | FENCE_VALID); - - if (IS_I9XX(pI830)) { - switch (size) { - case MB(1): - val |= I915G_FENCE_SIZE_1M; - break; - case MB(2): - val |= I915G_FENCE_SIZE_2M; - break; - case MB(4): - val |= I915G_FENCE_SIZE_4M; - break; - case MB(8): - val |= I915G_FENCE_SIZE_8M; - break; - case MB(16): - val |= I915G_FENCE_SIZE_16M; - break; - case MB(32): - val |= I915G_FENCE_SIZE_32M; - break; - case MB(64): - val |= I915G_FENCE_SIZE_64M; - break; - default: - fprintf(stderr, - "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024); - return; - } - } else { - switch (size) { - case KB(512): - val |= FENCE_SIZE_512K; - break; - case MB(1): - val |= FENCE_SIZE_1M; - break; - case MB(2): - val |= FENCE_SIZE_2M; - break; - case MB(4): - val |= FENCE_SIZE_4M; - break; - case MB(8): - val |= FENCE_SIZE_8M; - break; - case MB(16): - val |= FENCE_SIZE_16M; - break; - case MB(32): - val |= FENCE_SIZE_32M; - break; - case MB(64): - val |= FENCE_SIZE_64M; - break; - default: - fprintf(stderr, - "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024); - return; - } - } - - if (IS_I9XX(pI830)) - fence_pitch = pitch / 512; - else - fence_pitch = pitch / 128; - - switch (fence_pitch) { - case 1: - val |= FENCE_PITCH_1; - break; - case 2: - val |= FENCE_PITCH_2; - break; - case 4: - val |= FENCE_PITCH_4; - break; - case 8: - val |= FENCE_PITCH_8; - break; - case 16: - val |= FENCE_PITCH_16; - break; - case 32: - val |= FENCE_PITCH_32; - break; - case 64: - val |= FENCE_PITCH_64; - break; - default: - fprintf(stderr, - "SetFence: %d: illegal pitch (%d)\n", nr, pitch); - return; - } - - pI830->Fence[nr] = val; -} - -static Bool -MakeTiles(const DRIDriverContext *ctx, I830Rec *pI830, I830MemRange *pMem) -{ - int pitch, ntiles, i; - - pitch = pMem->Pitch * ctx->cpp; - /* - * Simply try to break the region up into at most four pieces of size - * equal to the alignment. - */ - ntiles = ROUND_TO(pMem->Size, pMem->Alignment) / pMem->Alignment; - if (ntiles >= 4) { - return FALSE; - } - - for (i = 0; i < ntiles; i++, nextTile++) { - SetFence(ctx, pI830, nextTile, pMem->Start + i * pMem->Alignment, - pitch, pMem->Alignment); - } - return TRUE; -} - -static void I830SetupMemoryTiling(const DRIDriverContext *ctx, I830Rec *pI830) -{ - int i; - - /* Clear out */ - for (i = 0; i < 8; i++) - pI830->Fence[i] = 0; - - nextTile = 0; - - if (pI830->BackBuffer.Alignment >= KB(512)) { - if (MakeTiles(ctx, pI830, &(pI830->BackBuffer))) { - fprintf(stderr, - "Activating tiled memory for the back buffer.\n"); - } else { - fprintf(stderr, - "MakeTiles failed for the back buffer.\n"); - pI830->allowPageFlip = FALSE; - } - } - - if (pI830->DepthBuffer.Alignment >= KB(512)) { - if (MakeTiles(ctx, pI830, &(pI830->DepthBuffer))) { - fprintf(stderr, - "Activating tiled memory for the depth buffer.\n"); - } else { - fprintf(stderr, - "MakeTiles failed for the depth buffer.\n"); - } - } - - return; -} - -static int I830DetectMemory(const DRIDriverContext *ctx, I830Rec *pI830) -{ - struct pci_device host_bridge, ig_dev; - uint32_t gmch_ctrl; - int memsize = 0; - int range; - uint32_t aper_size; - uint32_t membase2 = 0; - - memset(&host_bridge, 0, sizeof(host_bridge)); - memset(&ig_dev, 0, sizeof(ig_dev)); - - ig_dev.dev = 2; - - pci_device_cfg_read_u32(&host_bridge, &gmch_ctrl, I830_GMCH_CTRL); - - if (IS_I830(pI830) || IS_845G(pI830)) { - if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) { - aper_size = 0x80000000; - } else { - aper_size = 0x40000000; - } - } else { - if (IS_I9XX(pI830)) { - int ret; - ret = pci_device_cfg_read_u32(&ig_dev, &membase2, 0x18); - if (membase2 & 0x08000000) - aper_size = 0x8000000; - else - aper_size = 0x10000000; - - fprintf(stderr,"aper size is %08X %08x %d\n", aper_size, membase2, ret); - } else - aper_size = 0x8000000; - } - - pI830->aper_size = aper_size; - - - /* We need to reduce the stolen size, by the GTT and the popup. - * The GTT varying according the the FbMapSize and the popup is 4KB */ - range = (ctx->shared.fbSize / (1024*1024)) + 4; - - if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I9XX(pI830)) { - switch (gmch_ctrl & I830_GMCH_GMS_MASK) { - case I855_GMCH_GMS_STOLEN_1M: - memsize = MB(1) - KB(range); - break; - case I855_GMCH_GMS_STOLEN_4M: - memsize = MB(4) - KB(range); - break; - case I855_GMCH_GMS_STOLEN_8M: - memsize = MB(8) - KB(range); - break; - case I855_GMCH_GMS_STOLEN_16M: - memsize = MB(16) - KB(range); - break; - case I855_GMCH_GMS_STOLEN_32M: - memsize = MB(32) - KB(range); - break; - case I915G_GMCH_GMS_STOLEN_48M: - if (IS_I9XX(pI830)) - memsize = MB(48) - KB(range); - break; - case I915G_GMCH_GMS_STOLEN_64M: - if (IS_I9XX(pI830)) - memsize = MB(64) - KB(range); - break; - } - } else { - switch (gmch_ctrl & I830_GMCH_GMS_MASK) { - case I830_GMCH_GMS_STOLEN_512: - memsize = KB(512) - KB(range); - break; - case I830_GMCH_GMS_STOLEN_1024: - memsize = MB(1) - KB(range); - break; - case I830_GMCH_GMS_STOLEN_8192: - memsize = MB(8) - KB(range); - break; - case I830_GMCH_GMS_LOCAL: - memsize = 0; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Local memory found, but won't be used.\n"); - break; - } - } - if (memsize > 0) { - fprintf(stderr, - "detected %d kB stolen memory.\n", memsize / 1024); - } else { - fprintf(stderr, - "no video memory detected.\n"); - } - return memsize; -} - -static int AgpInit(const DRIDriverContext *ctx, I830Rec *info) -{ - unsigned long mode = 0x4; - - if (drmAgpAcquire(ctx->drmFD) < 0) { - fprintf(stderr, "[gart] AGP not available\n"); - return 0; - } - - if (drmAgpEnable(ctx->drmFD, mode) < 0) { - fprintf(stderr, "[gart] AGP not enabled\n"); - drmAgpRelease(ctx->drmFD); - return 0; - } - else - fprintf(stderr, "[gart] AGP enabled at %dx\n", ctx->agpmode); - - return 1; -} - -/* - * Allocate memory from the given pool. Grow the pool if needed and if - * possible. - */ -static unsigned long -AllocFromPool(const DRIDriverContext *ctx, I830Rec *pI830, - I830MemRange *result, I830MemPool *pool, - long size, unsigned long alignment, int flags) -{ - long needed, start, end; - - if (!result || !pool || !size) - return 0; - - /* Calculate how much space is needed. */ - if (alignment <= GTT_PAGE_SIZE) - needed = size; - else { - start = ROUND_TO(pool->Free.Start, alignment); - end = ROUND_TO(start + size, alignment); - needed = end - pool->Free.Start; - } - if (needed > pool->Free.Size) { - return 0; - } - - result->Start = ROUND_TO(pool->Free.Start, alignment); - pool->Free.Start += needed; - result->End = pool->Free.Start; - - pool->Free.Size = pool->Free.End - pool->Free.Start; - result->Size = result->End - result->Start; - result->Pool = pool; - result->Alignment = alignment; - return needed; -} - -static unsigned long AllocFromAGP(const DRIDriverContext *ctx, I830Rec *pI830, long size, unsigned long alignment, I830MemRange *result) -{ - unsigned long start, end; - unsigned long newApStart, newApEnd; - int ret; - if (!result || !size) - return 0; - - if (!alignment) - alignment = 4; - - start = ROUND_TO(pI830->MemoryAperture.Start, alignment); - end = ROUND_TO(start + size, alignment); - newApStart = end; - newApEnd = pI830->MemoryAperture.End; - - ret=drmAgpAlloc(ctx->drmFD, size, 0, &(result->Physical), (drm_handle_t *)&(result->Key)); - - if (ret) - { - fprintf(stderr,"drmAgpAlloc failed %d\n", ret); - return 0; - } - pI830->allocatedMemory += size; - pI830->MemoryAperture.Start = newApStart; - pI830->MemoryAperture.End = newApEnd; - pI830->MemoryAperture.Size = newApEnd - newApStart; - // pI830->FreeMemory -= size; - result->Start = start; - result->End = start + size; - result->Size = size; - result->Offset = start; - result->Alignment = alignment; - result->Pool = NULL; - - return size; -} - -unsigned long -I830AllocVidMem(const DRIDriverContext *ctx, I830Rec *pI830, - I830MemRange *result, I830MemPool *pool, long size, - unsigned long alignment, int flags) -{ - unsigned long ret; - - if (!result) - return 0; - - /* Make sure these are initialised. */ - result->Size = 0; - result->Key = -1; - - if (!size) { - return 0; - } - - if (pool->Free.Size < size) { - ret = AllocFromAGP(ctx, pI830, size, alignment, result); - } - else { - ret = AllocFromPool(ctx, pI830, result, pool, size, alignment, flags); - if (ret == 0) - ret = AllocFromAGP(ctx, pI830, size, alignment, result); - } - return ret; -} - -static Bool BindAgpRange(const DRIDriverContext *ctx, I830MemRange *mem) -{ - if (!mem) - return FALSE; - - if (mem->Key == -1) - return TRUE; - - return !drmAgpBind(ctx->drmFD, mem->Key, mem->Offset); -} - -/* simple memory allocation routines needed */ -/* put ring buffer in low memory */ -/* need to allocate front, back, depth buffers aligned correctly, - allocate ring buffer, -*/ - -/* */ -static Bool -I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830) -{ - unsigned long size, ret; - unsigned long lines, lineSize, align; - - /* allocate ring buffer */ - memset(pI830->LpRing, 0, sizeof(I830RingBuffer)); - pI830->LpRing->mem.Key = -1; - - size = PRIMARY_RINGBUFFER_SIZE; - - ret = I830AllocVidMem(ctx, pI830, &pI830->LpRing->mem, &pI830->StolenPool, size, 0x1000, 0); - - if (ret != size) - { - fprintf(stderr,"unable to allocate ring buffer %ld\n", ret); - return FALSE; - } - - pI830->LpRing->tail_mask = pI830->LpRing->mem.Size - 1; - - - /* allocate front buffer */ - memset(&(pI830->FrontBuffer), 0, sizeof(pI830->FrontBuffer)); - pI830->FrontBuffer.Key = -1; - pI830->FrontBuffer.Pitch = ctx->shared.virtualWidth; - - align = KB(512); - - lineSize = ctx->shared.virtualWidth * ctx->cpp; - lines = (ctx->shared.virtualHeight + 15) / 16 * 16; - size = lineSize * lines; - size = ROUND_TO_PAGE(size); - - align = GetBestTileAlignment(size); - - ret = I830AllocVidMem(ctx, pI830, &pI830->FrontBuffer, &pI830->StolenPool, size, align, 0); - if (ret < size) - { - fprintf(stderr,"unable to allocate front buffer %ld\n", ret); - return FALSE; - } - - memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer)); - pI830->BackBuffer.Key = -1; - pI830->BackBuffer.Pitch = ctx->shared.virtualWidth; - - ret = I830AllocVidMem(ctx, pI830, &pI830->BackBuffer, &pI830->StolenPool, size, align, 0); - if (ret < size) - { - fprintf(stderr,"unable to allocate back buffer %ld\n", ret); - return FALSE; - } - - memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer)); - pI830->DepthBuffer.Key = -1; - pI830->DepthBuffer.Pitch = ctx->shared.virtualWidth; - - ret = I830AllocVidMem(ctx, pI830, &pI830->DepthBuffer, &pI830->StolenPool, size, align, 0); - if (ret < size) - { - fprintf(stderr,"unable to allocate depth buffer %ld\n", ret); - return FALSE; - } - - memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem)); - pI830->ContextMem.Key = -1; - size = KB(32); - - ret = I830AllocVidMem(ctx, pI830, &pI830->ContextMem, &pI830->StolenPool, size, align, 0); - if (ret < size) - { - fprintf(stderr,"unable to allocate context buffer %ld\n", ret); - return FALSE; - } - -#if 0 - memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem)); - pI830->TexMem.Key = -1; - - size = 32768 * 1024; - ret = AllocFromAGP(ctx, pI830, size, align, &pI830->TexMem); - if (ret < size) - { - fprintf(stderr,"unable to allocate texture memory %ld\n", ret); - return FALSE; - } -#endif - - return TRUE; -} - -static Bool -I830BindMemory(const DRIDriverContext *ctx, I830Rec *pI830) -{ - if (!BindAgpRange(ctx, &pI830->LpRing->mem)) - return FALSE; - if (!BindAgpRange(ctx, &pI830->FrontBuffer)) - return FALSE; - if (!BindAgpRange(ctx, &pI830->BackBuffer)) - return FALSE; - if (!BindAgpRange(ctx, &pI830->DepthBuffer)) - return FALSE; - if (!BindAgpRange(ctx, &pI830->ContextMem)) - return FALSE; -#if 0 - if (!BindAgpRange(ctx, &pI830->TexMem)) - return FALSE; -#endif - return TRUE; -} - -static void SetupDRIMM(const DRIDriverContext *ctx, I830Rec *pI830) -{ - unsigned long aperEnd = ROUND_DOWN_TO(pI830->aper_size, GTT_PAGE_SIZE) / GTT_PAGE_SIZE; - unsigned long aperStart = ROUND_TO(pI830->aper_size - KB(32768), GTT_PAGE_SIZE) / GTT_PAGE_SIZE; - - fprintf(stderr, "aper size is %08X\n", ctx->shared.fbSize); - if (drmMMInit(ctx->drmFD, aperStart, aperEnd - aperStart, DRM_BO_MEM_TT)) { - fprintf(stderr, - "DRM MM Initialization Failed\n"); - } else { - fprintf(stderr, - "DRM MM Initialized at offset 0x%lx length %d page\n", aperStart, aperEnd-aperStart); - } - -} - -static Bool -I830CleanupDma(const DRIDriverContext *ctx) -{ - drmI830Init info; - - memset(&info, 0, sizeof(drmI830Init)); - info.func = I830_CLEANUP_DMA; - - if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT, - &info, sizeof(drmI830Init))) { - fprintf(stderr, "I830 Dma Cleanup Failed\n"); - return FALSE; - } - - return TRUE; -} - -static Bool -I830InitDma(const DRIDriverContext *ctx, I830Rec *pI830) -{ - I830RingBuffer *ring = pI830->LpRing; - drmI830Init info; - - memset(&info, 0, sizeof(drmI830Init)); - info.func = I830_INIT_DMA; - - info.ring_start = ring->mem.Start + pI830->LinearAddr; - info.ring_end = ring->mem.End + pI830->LinearAddr; - info.ring_size = ring->mem.Size; - - info.mmio_offset = (unsigned int)ctx->MMIOStart; - - info.sarea_priv_offset = sizeof(drm_sarea_t); - - info.front_offset = pI830->FrontBuffer.Start; - info.back_offset = pI830->BackBuffer.Start; - info.depth_offset = pI830->DepthBuffer.Start; - info.w = ctx->shared.virtualWidth; - info.h = ctx->shared.virtualHeight; - info.pitch = ctx->shared.virtualWidth; - info.back_pitch = pI830->BackBuffer.Pitch; - info.depth_pitch = pI830->DepthBuffer.Pitch; - info.cpp = ctx->cpp; - - if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT, - &info, sizeof(drmI830Init))) { - fprintf(stderr, - "I830 Dma Initialization Failed\n"); - return FALSE; - } - - return TRUE; -} - -static int I830CheckDRMVersion( const DRIDriverContext *ctx, - I830Rec *pI830 ) -{ - drmVersionPtr version; - - version = drmGetVersion(ctx->drmFD); - - if (version) { - int req_minor, req_patch; - - req_minor = 4; - req_patch = 0; - - if (version->version_major != 1 || - version->version_minor < req_minor || - (version->version_minor == req_minor && - version->version_patchlevel < req_patch)) { - /* Incompatible drm version */ - fprintf(stderr, - "[dri] I830DRIScreenInit failed because of a version " - "mismatch.\n" - "[dri] i915.o kernel module version is %d.%d.%d " - "but version 1.%d.%d or newer is needed.\n" - "[dri] Disabling DRI.\n", - version->version_major, - version->version_minor, - version->version_patchlevel, - req_minor, - req_patch); - drmFreeVersion(version); - return 0; - } - - pI830->drmMinor = version->version_minor; - drmFreeVersion(version); - } - return 1; -} - -static void -I830SetRingRegs(const DRIDriverContext *ctx, I830Rec *pI830) -{ - unsigned int itemp; - unsigned char *MMIO = ctx->MMIOAddress; - - OUTREG(LP_RING + RING_LEN, 0); - OUTREG(LP_RING + RING_TAIL, 0); - OUTREG(LP_RING + RING_HEAD, 0); - - if ((long)(pI830->LpRing->mem.Start & I830_RING_START_MASK) != - pI830->LpRing->mem.Start) { - fprintf(stderr, - "I830SetRingRegs: Ring buffer start (%lx) violates its " - "mask (%x)\n", pI830->LpRing->mem.Start, I830_RING_START_MASK); - } - /* Don't care about the old value. Reserved bits must be zero anyway. */ - itemp = pI830->LpRing->mem.Start & I830_RING_START_MASK; - OUTREG(LP_RING + RING_START, itemp); - - if (((pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES) != - pI830->LpRing->mem.Size - 4096) { - fprintf(stderr, - "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its " - "mask (%x)\n", pI830->LpRing->mem.Size - 4096, - I830_RING_NR_PAGES); - } - /* Don't care about the old value. Reserved bits must be zero anyway. */ - itemp = (pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES; - itemp |= (RING_NO_REPORT | RING_VALID); - OUTREG(LP_RING + RING_LEN, itemp); - - pI830->LpRing->head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK; - pI830->LpRing->tail = INREG(LP_RING + RING_TAIL); - pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8); - if (pI830->LpRing->space < 0) - pI830->LpRing->space += pI830->LpRing->mem.Size; - - SetFenceRegs(ctx, pI830); - - /* RESET THE DISPLAY PIPE TO POINT TO THE FRONTBUFFER - hacky - hacky hacky */ - OUTREG(DSPABASE, pI830->FrontBuffer.Start + pI830->LinearAddr); - -} - -static Bool -I830SetParam(const DRIDriverContext *ctx, int param, int value) -{ - drmI830SetParam sp; - - memset(&sp, 0, sizeof(sp)); - sp.param = param; - sp.value = value; - - if (drmCommandWrite(ctx->drmFD, DRM_I830_SETPARAM, &sp, sizeof(sp))) { - fprintf(stderr, "I830 SetParam Failed\n"); - return FALSE; - } - - return TRUE; -} - -static Bool -I830DRIMapScreenRegions(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea) -{ - fprintf(stderr, - "[drm] Mapping front buffer\n"); - - if (drmAddMap(ctx->drmFD, - (drm_handle_t)(sarea->front_offset + pI830->LinearAddr), - sarea->front_size, - DRM_FRAME_BUFFER, /*DRM_AGP,*/ - 0, - &sarea->front_handle) < 0) { - fprintf(stderr, - "[drm] drmAddMap(front_handle) failed. Disabling DRI\n"); - return FALSE; - } - ctx->shared.hFrameBuffer = sarea->front_handle; - ctx->shared.fbSize = sarea->front_size; - fprintf(stderr, "[drm] Front Buffer = 0x%08x\n", - sarea->front_handle); - - if (drmAddMap(ctx->drmFD, - (drm_handle_t)(sarea->back_offset), - sarea->back_size, DRM_AGP, 0, - &sarea->back_handle) < 0) { - fprintf(stderr, - "[drm] drmAddMap(back_handle) failed. Disabling DRI\n"); - return FALSE; - } - fprintf(stderr, "[drm] Back Buffer = 0x%08x\n", - sarea->back_handle); - - if (drmAddMap(ctx->drmFD, - (drm_handle_t)sarea->depth_offset, - sarea->depth_size, DRM_AGP, 0, - &sarea->depth_handle) < 0) { - fprintf(stderr, - "[drm] drmAddMap(depth_handle) failed. Disabling DRI\n"); - return FALSE; - } - fprintf(stderr, "[drm] Depth Buffer = 0x%08x\n", - sarea->depth_handle); - -#if 0 - if (drmAddMap(ctx->drmFD, - (drm_handle_t)sarea->tex_offset, - sarea->tex_size, DRM_AGP, 0, - &sarea->tex_handle) < 0) { - fprintf(stderr, - "[drm] drmAddMap(tex_handle) failed. Disabling DRI\n"); - return FALSE; - } - fprintf(stderr, "[drm] textures = 0x%08x\n", - sarea->tex_handle); -#endif - return TRUE; -} - - -static void -I830DRIUnmapScreenRegions(const DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea) -{ -#if 1 - if (sarea->front_handle) { - drmRmMap(ctx->drmFD, sarea->front_handle); - sarea->front_handle = 0; - } -#endif - if (sarea->back_handle) { - drmRmMap(ctx->drmFD, sarea->back_handle); - sarea->back_handle = 0; - } - if (sarea->depth_handle) { - drmRmMap(ctx->drmFD, sarea->depth_handle); - sarea->depth_handle = 0; - } - if (sarea->tex_handle) { - drmRmMap(ctx->drmFD, sarea->tex_handle); - sarea->tex_handle = 0; - } -} - -static Bool -I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea) -{ - if (drmAddMap(ctx->drmFD, - (drm_handle_t)pI830->LpRing->mem.Start, - pI830->LpRing->mem.Size, DRM_AGP, 0, - &pI830->ring_map) < 0) { - fprintf(stderr, - "[drm] drmAddMap(ring_map) failed. Disabling DRI\n"); - return FALSE; - } - fprintf(stderr, "[drm] ring buffer = 0x%08x\n", - pI830->ring_map); - - if (I830InitDma(ctx, pI830) == FALSE) { - return FALSE; - } - - /* init to zero to be safe */ - - I830DRIMapScreenRegions(ctx, pI830, sarea); - SetupDRIMM(ctx, pI830); - - if (ctx->pciDevice != PCI_CHIP_845_G && - ctx->pciDevice != PCI_CHIP_I830_M) { - I830SetParam(ctx, I830_SETPARAM_USE_MI_BATCHBUFFER_START, 1 ); - } - - /* Okay now initialize the dma engine */ - { - pI830->irq = drmGetInterruptFromBusID(ctx->drmFD, - ctx->pciBus, - ctx->pciDevice, - ctx->pciFunc); - - if (drmCtlInstHandler(ctx->drmFD, pI830->irq)) { - fprintf(stderr, - "[drm] failure adding irq handler\n"); - pI830->irq = 0; - return FALSE; - } - else - fprintf(stderr, - "[drm] dma control initialized, using IRQ %d\n", - pI830->irq); - } - - fprintf(stderr, "[dri] visual configs initialized\n"); - - return TRUE; -} - -static Bool -I830ClearScreen(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea) -{ - /* need to drmMap front and back buffers and zero them */ - drmAddress map_addr; - int ret; - - ret = drmMap(ctx->drmFD, - sarea->front_handle, - sarea->front_size, - &map_addr); - - if (ret) - { - fprintf(stderr, "Unable to map front buffer\n"); - return FALSE; - } - - drimemsetio((char *)map_addr, - 0, - sarea->front_size); - drmUnmap(map_addr, sarea->front_size); - - - ret = drmMap(ctx->drmFD, - sarea->back_handle, - sarea->back_size, - &map_addr); - - if (ret) - { - fprintf(stderr, "Unable to map back buffer\n"); - return FALSE; - } - - drimemsetio((char *)map_addr, - 0, - sarea->back_size); - drmUnmap(map_addr, sarea->back_size); - - return TRUE; -} - -static Bool -I830ScreenInit(DRIDriverContext *ctx, I830Rec *pI830) - -{ - I830DRIPtr pI830DRI; - drmI830Sarea *pSAREAPriv; - int err; - - drm_page_size = getpagesize(); - - pI830->registerSize = ctx->MMIOSize; - /* This is a hack for now. We have to have more than a 4k page here - * because of the size of the state. However, the state should be - * in a per-context mapping. This will be added in the Mesa 3.5 port - * of the I830 driver. - */ - ctx->shared.SAREASize = SAREA_MAX; - - /* Note that drmOpen will try to load the kernel module, if needed. */ - ctx->drmFD = drmOpen("i915", NULL ); - if (ctx->drmFD < 0) { - fprintf(stderr, "[drm] drmOpen failed\n"); - return 0; - } - - if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) { - fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n", - ctx->drmFD, ctx->pciBusID, strerror(-err)); - return 0; - } - - if (drmAddMap( ctx->drmFD, - 0, - ctx->shared.SAREASize, - DRM_SHM, - DRM_CONTAINS_LOCK, - &ctx->shared.hSAREA) < 0) - { - fprintf(stderr, "[drm] drmAddMap failed\n"); - return 0; - } - - fprintf(stderr, "[drm] added %d byte SAREA at 0x%08x\n", - ctx->shared.SAREASize, ctx->shared.hSAREA); - - if (drmMap( ctx->drmFD, - ctx->shared.hSAREA, - ctx->shared.SAREASize, - (drmAddressPtr)(&ctx->pSAREA)) < 0) - { - fprintf(stderr, "[drm] drmMap failed\n"); - return 0; - - } - - memset(ctx->pSAREA, 0, ctx->shared.SAREASize); - fprintf(stderr, "[drm] mapped SAREA 0x%08x to %p, size %d\n", - ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize); - - - if (drmAddMap(ctx->drmFD, - ctx->MMIOStart, - ctx->MMIOSize, - DRM_REGISTERS, - DRM_READ_ONLY, - &pI830->registerHandle) < 0) { - fprintf(stderr, "[drm] drmAddMap mmio failed\n"); - return 0; - } - fprintf(stderr, - "[drm] register handle = 0x%08x\n", pI830->registerHandle); - - - if (!I830CheckDRMVersion(ctx, pI830)) { - return FALSE; - } - - /* Create a 'server' context so we can grab the lock for - * initialization ioctls. - */ - if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) { - fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err); - return 0; - } - - DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0); - - /* Initialize the SAREA private data structure */ - pSAREAPriv = (drmI830Sarea *)(((char*)ctx->pSAREA) + - sizeof(drm_sarea_t)); - memset(pSAREAPriv, 0, sizeof(*pSAREAPriv)); - - pI830->StolenMemory.Size = I830DetectMemory(ctx, pI830); - pI830->StolenMemory.Start = 0; - pI830->StolenMemory.End = pI830->StolenMemory.Size; - - pI830->MemoryAperture.Start = pI830->StolenMemory.End; - pI830->MemoryAperture.End = KB(40000); - pI830->MemoryAperture.Size = pI830->MemoryAperture.End - pI830->MemoryAperture.Start; - - pI830->StolenPool.Fixed = pI830->StolenMemory; - pI830->StolenPool.Total = pI830->StolenMemory; - pI830->StolenPool.Free = pI830->StolenPool.Total; - pI830->FreeMemory = pI830->StolenPool.Total.Size; - - if (!AgpInit(ctx, pI830)) - return FALSE; - - if (I830AllocateMemory(ctx, pI830) == FALSE) - { - return FALSE; - } - - if (I830BindMemory(ctx, pI830) == FALSE) - { - return FALSE; - } - - pSAREAPriv->rotated_offset = -1; - pSAREAPriv->rotated_size = 0; - pSAREAPriv->rotated_pitch = ctx->shared.virtualWidth; - - pSAREAPriv->front_offset = pI830->FrontBuffer.Start; - pSAREAPriv->front_size = pI830->FrontBuffer.Size; - pSAREAPriv->width = ctx->shared.virtualWidth; - pSAREAPriv->height = ctx->shared.virtualHeight; - pSAREAPriv->pitch = ctx->shared.virtualWidth; - pSAREAPriv->virtualX = ctx->shared.virtualWidth; - pSAREAPriv->virtualY = ctx->shared.virtualHeight; - pSAREAPriv->back_offset = pI830->BackBuffer.Start; - pSAREAPriv->back_size = pI830->BackBuffer.Size; - pSAREAPriv->depth_offset = pI830->DepthBuffer.Start; - pSAREAPriv->depth_size = pI830->DepthBuffer.Size; -#if 0 - pSAREAPriv->tex_offset = pI830->TexMem.Start; - pSAREAPriv->tex_size = pI830->TexMem.Size; -#endif - pSAREAPriv->log_tex_granularity = pI830->TexGranularity; - - ctx->driverClientMsg = malloc(sizeof(I830DRIRec)); - ctx->driverClientMsgSize = sizeof(I830DRIRec); - pI830DRI = (I830DRIPtr)ctx->driverClientMsg; - pI830DRI->deviceID = pI830->Chipset; - pI830DRI->regsSize = I830_REG_SIZE; - pI830DRI->width = ctx->shared.virtualWidth; - pI830DRI->height = ctx->shared.virtualHeight; - pI830DRI->mem = ctx->shared.fbSize; - pI830DRI->cpp = ctx->cpp; - - pI830DRI->bitsPerPixel = ctx->bpp; - pI830DRI->sarea_priv_offset = sizeof(drm_sarea_t); - - err = I830DRIDoMappings(ctx, pI830, pSAREAPriv); - if (err == FALSE) - return FALSE; - - I830SetupMemoryTiling(ctx, pI830); - - /* Quick hack to clear the front & back buffers. Could also use - * the clear ioctl to do this, but would need to setup hw state - * first. - */ - I830ClearScreen(ctx, pI830, pSAREAPriv); - - I830SetRingRegs(ctx, pI830); - - return TRUE; -} - - -/** - * \brief Validate the fbdev mode. - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Saves some registers and returns 1. - * - * \sa radeonValidateMode(). - */ -static int i830ValidateMode( const DRIDriverContext *ctx ) -{ - return 1; -} - -/** - * \brief Examine mode returned by fbdev. - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Restores registers that fbdev has clobbered and returns 1. - * - * \sa i810ValidateMode(). - */ -static int i830PostValidateMode( const DRIDriverContext *ctx ) -{ - I830Rec *pI830 = ctx->driverPrivate; - - I830SetRingRegs(ctx, pI830); - return 1; -} - - -/** - * \brief Initialize the framebuffer device mode - * - * \param ctx display handle. - * - * \return one on success, or zero on failure. - * - * Fills in \p info with some default values and some information from \p ctx - * and then calls I810ScreenInit() for the screen initialization. - * - * Before exiting clears the framebuffer memory accessing it directly. - */ -static int i830InitFBDev( DRIDriverContext *ctx ) -{ - I830Rec *pI830 = calloc(1, sizeof(I830Rec)); - int i; - - { - int dummy = ctx->shared.virtualWidth; - - switch (ctx->bpp / 8) { - case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break; - case 2: dummy = (ctx->shared.virtualWidth + 31) & ~31; break; - case 3: - case 4: dummy = (ctx->shared.virtualWidth + 15) & ~15; break; - } - - ctx->shared.virtualWidth = dummy; - ctx->shared.Width = ctx->shared.virtualWidth; - } - - - for (i = 0; pitches[i] != 0; i++) { - if (pitches[i] >= ctx->shared.virtualWidth) { - ctx->shared.virtualWidth = pitches[i]; - break; - } - } - - ctx->driverPrivate = (void *)pI830; - - pI830->LpRing = calloc(1, sizeof(I830RingBuffer)); - pI830->Chipset = ctx->chipset; - pI830->LinearAddr = ctx->FBStart; - - if (!I830ScreenInit( ctx, pI830 )) - return 0; - - - return 1; -} - - -/** - * \brief The screen is being closed, so clean up any state and free any - * resources used by the DRI. - * - * \param ctx display handle. - * - * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver - * private data. - */ -static void i830HaltFBDev( DRIDriverContext *ctx ) -{ - drmI830Sarea *pSAREAPriv; - I830Rec *pI830 = ctx->driverPrivate; - - if (pI830->irq) { - drmCtlUninstHandler(ctx->drmFD); - pI830->irq = 0; } - - I830CleanupDma(ctx); - - pSAREAPriv = (drmI830Sarea *)(((char*)ctx->pSAREA) + - sizeof(drm_sarea_t)); - - I830DRIUnmapScreenRegions(ctx, pI830, pSAREAPriv); - drmUnmap( ctx->pSAREA, ctx->shared.SAREASize ); - drmClose(ctx->drmFD); - - if (ctx->driverPrivate) { - free(ctx->driverPrivate); - ctx->driverPrivate = 0; - } -} - - -extern void i810NotifyFocus( int ); - -/** - * \brief Exported driver interface for Mini GLX. - * - * \sa DRIDriverRec. - */ -const struct DRIDriverRec __driDriver = { - i830ValidateMode, - i830PostValidateMode, - i830InitFBDev, - i830HaltFBDev, - NULL,//I830EngineShutdown, - NULL, //I830EngineRestore, -#ifndef _EMBEDDED - 0, -#else - i810NotifyFocus, -#endif -}; diff --git a/src/gallium/winsys/dri/intel/ws_dri_bufmgr.c b/src/gallium/winsys/dri/intel/ws_dri_bufmgr.c deleted file mode 100644 index 1bc1089352..0000000000 --- a/src/gallium/winsys/dri/intel/ws_dri_bufmgr.c +++ /dev/null @@ -1,953 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA - * 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, 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 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 - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS 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. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ -/* - * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> - * Keith Whitwell <keithw-at-tungstengraphics-dot-com> - */ - -#include <xf86drm.h> -#include <stdlib.h> -#include "glthread.h" -#include "errno.h" -#include "ws_dri_bufmgr.h" -#include "string.h" -#include "imports.h" -#include "ws_dri_bufpool.h" -#include "ws_dri_fencemgr.h" - -/* - * This lock is here to protect drmBO structs changing underneath us during a - * validate list call, since validatelist cannot take individiual locks for - * each drmBO. Validatelist takes this lock in write mode. Any access to an - * individual drmBO should take this lock in read mode, since in that case, the - * driBufferObject mutex will protect the access. Locking order is - * driBufferObject mutex - > this rw lock. - */ - -_glthread_DECLARE_STATIC_MUTEX(bmMutex); -_glthread_DECLARE_STATIC_COND(bmCond); - -static int kernelReaders = 0; -static int num_buffers = 0; -static int num_user_buffers = 0; - -static drmBO *drmBOListBuf(void *iterator) -{ - drmBONode *node; - drmMMListHead *l = (drmMMListHead *) iterator; - node = DRMLISTENTRY(drmBONode, l, head); - return node->buf; -} - -static void *drmBOListIterator(drmBOList *list) -{ - void *ret = list->list.next; - - if (ret == &list->list) - return NULL; - return ret; -} - -static void *drmBOListNext(drmBOList *list, void *iterator) -{ - void *ret; - - drmMMListHead *l = (drmMMListHead *) iterator; - ret = l->next; - if (ret == &list->list) - return NULL; - return ret; -} - -static drmBONode *drmAddListItem(drmBOList *list, drmBO *item, - uint64_t arg0, - uint64_t arg1) -{ - drmBONode *node; - drmMMListHead *l; - - l = list->free.next; - if (l == &list->free) { - node = (drmBONode *) malloc(sizeof(*node)); - if (!node) { - return NULL; - } - list->numCurrent++; - } - else { - DRMLISTDEL(l); - node = DRMLISTENTRY(drmBONode, l, head); - } - node->buf = item; - node->arg0 = arg0; - node->arg1 = arg1; - DRMLISTADD(&node->head, &list->list); - list->numOnList++; - return node; -} - -static int drmAddValidateItem(drmBOList *list, drmBO *buf, uint64_t flags, - uint64_t mask, int *newItem) -{ - drmBONode *node, *cur; - drmMMListHead *l; - - *newItem = 0; - cur = NULL; - - for (l = list->list.next; l != &list->list; l = l->next) { - node = DRMLISTENTRY(drmBONode, l, head); - if (node->buf == buf) { - cur = node; - break; - } - } - if (!cur) { - cur = drmAddListItem(list, buf, flags, mask); - if (!cur) { - return -ENOMEM; - } - *newItem = 1; - cur->arg0 = flags; - cur->arg1 = mask; - } - else { - uint64_t memFlags = cur->arg0 & flags & DRM_BO_MASK_MEM; - uint64_t accFlags = (cur->arg0 | flags) & ~DRM_BO_MASK_MEM; - - if (mask & cur->arg1 & ~DRM_BO_MASK_MEM & (cur->arg0 ^ flags)) { - return -EINVAL; - } - - cur->arg1 |= mask; - cur->arg0 = (cur->arg0 & ~mask) | ((memFlags | accFlags) & mask); - - if (((cur->arg1 & DRM_BO_MASK_MEM) != 0) && - (cur->arg0 & DRM_BO_MASK_MEM) == 0) { - return -EINVAL; - } - } - return 0; -} - -static void drmBOFreeList(drmBOList *list) -{ - drmBONode *node; - drmMMListHead *l; - - l = list->list.next; - while(l != &list->list) { - DRMLISTDEL(l); - node = DRMLISTENTRY(drmBONode, l, head); - free(node); - l = list->list.next; - list->numCurrent--; - list->numOnList--; - } - - l = list->free.next; - while(l != &list->free) { - DRMLISTDEL(l); - node = DRMLISTENTRY(drmBONode, l, head); - free(node); - l = list->free.next; - list->numCurrent--; - } -} - -static int drmAdjustListNodes(drmBOList *list) -{ - drmBONode *node; - drmMMListHead *l; - int ret = 0; - - while(list->numCurrent < list->numTarget) { - node = (drmBONode *) malloc(sizeof(*node)); - if (!node) { - ret = -ENOMEM; - break; - } - list->numCurrent++; - DRMLISTADD(&node->head, &list->free); - } - - while(list->numCurrent > list->numTarget) { - l = list->free.next; - if (l == &list->free) - break; - DRMLISTDEL(l); - node = DRMLISTENTRY(drmBONode, l, head); - free(node); - list->numCurrent--; - } - return ret; -} - -static int drmBOCreateList(int numTarget, drmBOList *list) -{ - DRMINITLISTHEAD(&list->list); - DRMINITLISTHEAD(&list->free); - list->numTarget = numTarget; - list->numCurrent = 0; - list->numOnList = 0; - return drmAdjustListNodes(list); -} - -static int drmBOResetList(drmBOList *list) -{ - drmMMListHead *l; - int ret; - - ret = drmAdjustListNodes(list); - if (ret) - return ret; - - l = list->list.next; - while (l != &list->list) { - DRMLISTDEL(l); - DRMLISTADD(l, &list->free); - list->numOnList--; - l = list->list.next; - } - return drmAdjustListNodes(list); -} - -void driWriteLockKernelBO(void) -{ - _glthread_LOCK_MUTEX(bmMutex); - while(kernelReaders != 0) - _glthread_COND_WAIT(bmCond, bmMutex); -} - -void driWriteUnlockKernelBO(void) -{ - _glthread_UNLOCK_MUTEX(bmMutex); -} - -void driReadLockKernelBO(void) -{ - _glthread_LOCK_MUTEX(bmMutex); - kernelReaders++; - _glthread_UNLOCK_MUTEX(bmMutex); -} - -void driReadUnlockKernelBO(void) -{ - _glthread_LOCK_MUTEX(bmMutex); - if (--kernelReaders == 0) - _glthread_COND_BROADCAST(bmCond); - _glthread_UNLOCK_MUTEX(bmMutex); -} - - - - -/* - * TODO: Introduce fence pools in the same way as - * buffer object pools. - */ - -typedef struct _DriBufferObject -{ - DriBufferPool *pool; - _glthread_Mutex mutex; - int refCount; - const char *name; - uint64_t flags; - unsigned hint; - unsigned alignment; - unsigned createdByReference; - void *private; - /* user-space buffer: */ - unsigned userBuffer; - void *userData; - unsigned userSize; -} DriBufferObject; - -typedef struct _DriBufferList { - drmBOList drmBuffers; /* List of kernel buffers needing validation */ - drmBOList driBuffers; /* List of user-space buffers needing validation */ -} DriBufferList; - - -void -bmError(int val, const char *file, const char *function, int line) -{ - _mesa_printf("Fatal video memory manager error \"%s\".\n" - "Check kernel logs or set the LIBGL_DEBUG\n" - "environment variable to \"verbose\" for more info.\n" - "Detected in file %s, line %d, function %s.\n", - strerror(-val), file, line, function); -#ifndef NDEBUG - abort(); -#else - abort(); -#endif -} - -extern drmBO * -driBOKernel(struct _DriBufferObject *buf) -{ - drmBO *ret; - - driReadLockKernelBO(); - _glthread_LOCK_MUTEX(buf->mutex); - assert(buf->private != NULL); - ret = buf->pool->kernel(buf->pool, buf->private); - if (!ret) - BM_CKFATAL(-EINVAL); - _glthread_UNLOCK_MUTEX(buf->mutex); - driReadUnlockKernelBO(); - - return ret; -} - -void -driBOWaitIdle(struct _DriBufferObject *buf, int lazy) -{ - - /* - * This function may block. Is it sane to keep the mutex held during - * that time?? - */ - - _glthread_LOCK_MUTEX(buf->mutex); - BM_CKFATAL(buf->pool->waitIdle(buf->pool, buf->private, &buf->mutex, lazy)); - _glthread_UNLOCK_MUTEX(buf->mutex); -} - -void * -driBOMap(struct _DriBufferObject *buf, unsigned flags, unsigned hint) -{ - void *virtual; - int retval; - - if (buf->userBuffer) { - return buf->userData; - } - - _glthread_LOCK_MUTEX(buf->mutex); - assert(buf->private != NULL); - retval = buf->pool->map(buf->pool, buf->private, flags, hint, - &buf->mutex, &virtual); - _glthread_UNLOCK_MUTEX(buf->mutex); - - return retval == 0 ? virtual : NULL; -} - -void -driBOUnmap(struct _DriBufferObject *buf) -{ - if (buf->userBuffer) - return; - - assert(buf->private != NULL); - _glthread_LOCK_MUTEX(buf->mutex); - BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private)); - _glthread_UNLOCK_MUTEX(buf->mutex); -} - -unsigned long -driBOOffset(struct _DriBufferObject *buf) -{ - unsigned long ret; - - assert(buf->private != NULL); - - _glthread_LOCK_MUTEX(buf->mutex); - ret = buf->pool->offset(buf->pool, buf->private); - _glthread_UNLOCK_MUTEX(buf->mutex); - return ret; -} - -unsigned long -driBOPoolOffset(struct _DriBufferObject *buf) -{ - unsigned long ret; - - assert(buf->private != NULL); - - _glthread_LOCK_MUTEX(buf->mutex); - ret = buf->pool->poolOffset(buf->pool, buf->private); - _glthread_UNLOCK_MUTEX(buf->mutex); - return ret; -} - -uint64_t -driBOFlags(struct _DriBufferObject *buf) -{ - uint64_t ret; - - assert(buf->private != NULL); - - driReadLockKernelBO(); - _glthread_LOCK_MUTEX(buf->mutex); - ret = buf->pool->flags(buf->pool, buf->private); - _glthread_UNLOCK_MUTEX(buf->mutex); - driReadUnlockKernelBO(); - return ret; -} - -struct _DriBufferObject * -driBOReference(struct _DriBufferObject *buf) -{ - _glthread_LOCK_MUTEX(buf->mutex); - if (++buf->refCount == 1) { - _glthread_UNLOCK_MUTEX(buf->mutex); - BM_CKFATAL(-EINVAL); - } - _glthread_UNLOCK_MUTEX(buf->mutex); - return buf; -} - -void -driBOUnReference(struct _DriBufferObject *buf) -{ - int tmp; - - if (!buf) - return; - - _glthread_LOCK_MUTEX(buf->mutex); - tmp = --buf->refCount; - if (!tmp) { - _glthread_UNLOCK_MUTEX(buf->mutex); - if (buf->private) { - if (buf->createdByReference) - buf->pool->unreference(buf->pool, buf->private); - else - buf->pool->destroy(buf->pool, buf->private); - } - if (buf->userBuffer) - num_user_buffers--; - else - num_buffers--; - free(buf); - } else - _glthread_UNLOCK_MUTEX(buf->mutex); - -} - - -int -driBOData(struct _DriBufferObject *buf, - unsigned size, const void *data, - DriBufferPool *newPool, - uint64_t flags) -{ - void *virtual = NULL; - int newBuffer; - int retval = 0; - struct _DriBufferPool *pool; - - assert(!buf->userBuffer); /* XXX just do a memcpy? */ - - _glthread_LOCK_MUTEX(buf->mutex); - pool = buf->pool; - - if (pool == NULL && newPool != NULL) { - buf->pool = newPool; - pool = newPool; - } - if (newPool == NULL) - newPool = pool; - - if (!pool->create) { - _mesa_error(NULL, GL_INVALID_OPERATION, - "driBOData called on invalid buffer\n"); - BM_CKFATAL(-EINVAL); - } - - newBuffer = (!buf->private || pool != newPool || - pool->size(pool, buf->private) < size); - - if (!flags) - flags = buf->flags; - - if (newBuffer) { - - if (buf->createdByReference) { - _mesa_error(NULL, GL_INVALID_OPERATION, - "driBOData requiring resizing called on " - "shared buffer.\n"); - BM_CKFATAL(-EINVAL); - } - - if (buf->private) - buf->pool->destroy(buf->pool, buf->private); - - pool = newPool; - buf->pool = newPool; - buf->private = pool->create(pool, size, flags, DRM_BO_HINT_DONT_FENCE, - buf->alignment); - if (!buf->private) - retval = -ENOMEM; - - if (retval == 0) - retval = pool->map(pool, buf->private, - DRM_BO_FLAG_WRITE, - DRM_BO_HINT_DONT_BLOCK, &buf->mutex, &virtual); - } else if (pool->map(pool, buf->private, DRM_BO_FLAG_WRITE, - DRM_BO_HINT_DONT_BLOCK, &buf->mutex, &virtual)) { - /* - * Buffer is busy. need to create a new one. - */ - - void *newBuf; - - newBuf = pool->create(pool, size, flags, DRM_BO_HINT_DONT_FENCE, - buf->alignment); - if (newBuf) { - buf->pool->destroy(buf->pool, buf->private); - buf->private = newBuf; - } - - retval = pool->map(pool, buf->private, - DRM_BO_FLAG_WRITE, 0, &buf->mutex, &virtual); - } else { - uint64_t flag_diff = flags ^ buf->flags; - - /* - * We might need to change buffer flags. - */ - - if (flag_diff){ - assert(pool->setStatus != NULL); - BM_CKFATAL(pool->unmap(pool, buf->private)); - BM_CKFATAL(pool->setStatus(pool, buf->private, flag_diff, - buf->flags)); - if (!data) - goto out; - - retval = pool->map(pool, buf->private, - DRM_BO_FLAG_WRITE, 0, &buf->mutex, &virtual); - } - } - - if (retval == 0) { - if (data) - memcpy(virtual, data, size); - - BM_CKFATAL(pool->unmap(pool, buf->private)); - } - - out: - _glthread_UNLOCK_MUTEX(buf->mutex); - - return retval; -} - -void -driBOSubData(struct _DriBufferObject *buf, - unsigned long offset, unsigned long size, const void *data) -{ - void *virtual; - - assert(!buf->userBuffer); /* XXX just do a memcpy? */ - - _glthread_LOCK_MUTEX(buf->mutex); - if (size && data) { - BM_CKFATAL(buf->pool->map(buf->pool, buf->private, - DRM_BO_FLAG_WRITE, 0, &buf->mutex, - &virtual)); - memcpy((unsigned char *) virtual + offset, data, size); - BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private)); - } - _glthread_UNLOCK_MUTEX(buf->mutex); -} - -void -driBOGetSubData(struct _DriBufferObject *buf, - unsigned long offset, unsigned long size, void *data) -{ - void *virtual; - - assert(!buf->userBuffer); /* XXX just do a memcpy? */ - - _glthread_LOCK_MUTEX(buf->mutex); - if (size && data) { - BM_CKFATAL(buf->pool->map(buf->pool, buf->private, - DRM_BO_FLAG_READ, 0, &buf->mutex, &virtual)); - memcpy(data, (unsigned char *) virtual + offset, size); - BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private)); - } - _glthread_UNLOCK_MUTEX(buf->mutex); -} - -void -driBOSetReferenced(struct _DriBufferObject *buf, - unsigned long handle) -{ - _glthread_LOCK_MUTEX(buf->mutex); - if (buf->private != NULL) { - _mesa_error(NULL, GL_INVALID_OPERATION, - "Invalid buffer for setReferenced\n"); - BM_CKFATAL(-EINVAL); - - } - if (buf->pool->reference == NULL) { - _mesa_error(NULL, GL_INVALID_OPERATION, - "Invalid buffer pool for setReferenced\n"); - BM_CKFATAL(-EINVAL); - } - buf->private = buf->pool->reference(buf->pool, handle); - if (!buf->private) { - _mesa_error(NULL, GL_OUT_OF_MEMORY, - "Invalid buffer pool for setStatic\n"); - BM_CKFATAL(-ENOMEM); - } - buf->createdByReference = GL_TRUE; - buf->flags = buf->pool->kernel(buf->pool, buf->private)->flags; - _glthread_UNLOCK_MUTEX(buf->mutex); -} - -int -driGenBuffers(struct _DriBufferPool *pool, - const char *name, - unsigned n, - struct _DriBufferObject *buffers[], - unsigned alignment, uint64_t flags, unsigned hint) -{ - struct _DriBufferObject *buf; - int i; - - flags = (flags) ? flags : DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MEM_VRAM | - DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE; - - ++num_buffers; - - assert(pool); - - for (i = 0; i < n; ++i) { - buf = (struct _DriBufferObject *) calloc(1, sizeof(*buf)); - if (!buf) - return -ENOMEM; - - _glthread_INIT_MUTEX(buf->mutex); - _glthread_LOCK_MUTEX(buf->mutex); - buf->refCount = 1; - buf->flags = flags; - buf->hint = hint; - buf->name = name; - buf->alignment = alignment; - buf->pool = pool; - buf->createdByReference = 0; - _glthread_UNLOCK_MUTEX(buf->mutex); - buffers[i] = buf; - } - return 0; -} - -void -driGenUserBuffer(struct _DriBufferPool *pool, - const char *name, - struct _DriBufferObject **buffers, - void *ptr, unsigned bytes) -{ - const unsigned alignment = 1, flags = 0, hint = 0; - - --num_buffers; /* JB: is inced in GenBuffes */ - driGenBuffers(pool, name, 1, buffers, alignment, flags, hint); - ++num_user_buffers; - - (*buffers)->userBuffer = 1; - (*buffers)->userData = ptr; - (*buffers)->userSize = bytes; -} - -void -driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[]) -{ - int i; - - for (i = 0; i < n; ++i) { - driBOUnReference(buffers[i]); - } -} - - -void -driInitBufMgr(int fd) -{ - ; -} - -/* - * Note that lists are per-context and don't need mutex protection. - */ - -struct _DriBufferList * -driBOCreateList(int target) -{ - struct _DriBufferList *list = calloc(sizeof(*list), 1); - - BM_CKFATAL(drmBOCreateList(target, &list->drmBuffers)); - BM_CKFATAL(drmBOCreateList(target, &list->driBuffers)); - return list; -} - -int -driBOResetList(struct _DriBufferList * list) -{ - int ret; - ret = drmBOResetList(&list->drmBuffers); - if (ret) - return ret; - ret = drmBOResetList(&list->driBuffers); - return ret; -} - -void -driBOFreeList(struct _DriBufferList * list) -{ - drmBOFreeList(&list->drmBuffers); - drmBOFreeList(&list->driBuffers); - free(list); -} - - -/* - * Copied from libdrm, because it is needed by driAddValidateItem. - */ - -static drmBONode * -driAddListItem(drmBOList * list, drmBO * item, - uint64_t arg0, uint64_t arg1) -{ - drmBONode *node; - drmMMListHead *l; - - l = list->free.next; - if (l == &list->free) { - node = (drmBONode *) malloc(sizeof(*node)); - if (!node) { - return NULL; - } - list->numCurrent++; - } else { - DRMLISTDEL(l); - node = DRMLISTENTRY(drmBONode, l, head); - } - memset(&node->bo_arg, 0, sizeof(node->bo_arg)); - node->buf = item; - node->arg0 = arg0; - node->arg1 = arg1; - DRMLISTADDTAIL(&node->head, &list->list); - list->numOnList++; - return node; -} - -/* - * Slightly modified version compared to the libdrm version. - * This one returns the list index of the buffer put on the list. - */ - -static int -driAddValidateItem(drmBOList * list, drmBO * buf, uint64_t flags, - uint64_t mask, int *itemLoc, - struct _drmBONode **pnode) -{ - drmBONode *node, *cur; - drmMMListHead *l; - int count = 0; - - cur = NULL; - - for (l = list->list.next; l != &list->list; l = l->next) { - node = DRMLISTENTRY(drmBONode, l, head); - if (node->buf == buf) { - cur = node; - break; - } - count++; - } - if (!cur) { - cur = driAddListItem(list, buf, flags, mask); - if (!cur) - return -ENOMEM; - - cur->arg0 = flags; - cur->arg1 = mask; - } else { - uint64_t memFlags = cur->arg0 & flags & DRM_BO_MASK_MEM; - uint64_t accFlags = (cur->arg0 | flags) & ~DRM_BO_MASK_MEM; - - if (mask & cur->arg1 & ~DRM_BO_MASK_MEM & (cur->arg0 ^ flags)) { - return -EINVAL; - } - - cur->arg1 |= mask; - cur->arg0 = (cur->arg0 & ~mask) | ((memFlags | accFlags) & mask); - - if (((cur->arg1 & DRM_BO_MASK_MEM) != 0) && - (cur->arg0 & DRM_BO_MASK_MEM) == 0) { - return -EINVAL; - } - } - *itemLoc = count; - *pnode = cur; - return 0; -} - - -void -driBOAddListItem(struct _DriBufferList * list, struct _DriBufferObject *buf, - uint64_t flags, uint64_t mask, int *itemLoc, - struct _drmBONode **node) -{ - int newItem; - - _glthread_LOCK_MUTEX(buf->mutex); - BM_CKFATAL(driAddValidateItem(&list->drmBuffers, - buf->pool->kernel(buf->pool, buf->private), - flags, mask, itemLoc, node)); - BM_CKFATAL(drmAddValidateItem(&list->driBuffers, (drmBO *) buf, - flags, mask, &newItem)); - if (newItem) - buf->refCount++; - - _glthread_UNLOCK_MUTEX(buf->mutex); -} - -drmBOList *driGetdrmBOList(struct _DriBufferList *list) -{ - driWriteLockKernelBO(); - return &list->drmBuffers; -} - -void driPutdrmBOList(struct _DriBufferList *list) -{ - driWriteUnlockKernelBO(); -} - - -void -driBOFence(struct _DriBufferObject *buf, struct _DriFenceObject *fence) -{ - _glthread_LOCK_MUTEX(buf->mutex); - if (buf->pool->fence) - BM_CKFATAL(buf->pool->fence(buf->pool, buf->private, fence)); - _glthread_UNLOCK_MUTEX(buf->mutex); - -} - -void -driBOUnrefUserList(struct _DriBufferList *list) -{ - struct _DriBufferObject *buf; - void *curBuf; - - curBuf = drmBOListIterator(&list->driBuffers); - while (curBuf) { - buf = (struct _DriBufferObject *)drmBOListBuf(curBuf); - driBOUnReference(buf); - curBuf = drmBOListNext(&list->driBuffers, curBuf); - } -} - -struct _DriFenceObject * -driBOFenceUserList(struct _DriFenceMgr *mgr, - struct _DriBufferList *list, const char *name, - drmFence *kFence) -{ - struct _DriFenceObject *fence; - struct _DriBufferObject *buf; - void *curBuf; - - fence = driFenceCreate(mgr, kFence->fence_class, kFence->type, - kFence, sizeof(*kFence)); - curBuf = drmBOListIterator(&list->driBuffers); - - /* - * User-space fencing callbacks. - */ - - while (curBuf) { - buf = (struct _DriBufferObject *) drmBOListBuf(curBuf); - driBOFence(buf, fence); - driBOUnReference(buf); - curBuf = drmBOListNext(&list->driBuffers, curBuf); - } - - driBOResetList(list); - return fence; -} - -void -driBOValidateUserList(struct _DriBufferList * list) -{ - void *curBuf; - struct _DriBufferObject *buf; - - curBuf = drmBOListIterator(&list->driBuffers); - - /* - * User-space validation callbacks. - */ - - while (curBuf) { - buf = (struct _DriBufferObject *) drmBOListBuf(curBuf); - _glthread_LOCK_MUTEX(buf->mutex); - if (buf->pool->validate) - BM_CKFATAL(buf->pool->validate(buf->pool, buf->private, &buf->mutex)); - _glthread_UNLOCK_MUTEX(buf->mutex); - curBuf = drmBOListNext(&list->driBuffers, curBuf); - } -} - - -void -driPoolTakeDown(struct _DriBufferPool *pool) -{ - pool->takeDown(pool); - -} - -unsigned long -driBOSize(struct _DriBufferObject *buf) -{ - unsigned long size; - - _glthread_LOCK_MUTEX(buf->mutex); - size = buf->pool->size(buf->pool, buf->private); - _glthread_UNLOCK_MUTEX(buf->mutex); - - return size; - -} - -drmBOList *driBOGetDRMBuffers(struct _DriBufferList *list) -{ - return &list->drmBuffers; -} - -drmBOList *driBOGetDRIBuffers(struct _DriBufferList *list) -{ - return &list->driBuffers; -} - diff --git a/src/gallium/winsys/dri/intel/ws_dri_bufpool.h b/src/gallium/winsys/dri/intel/ws_dri_bufpool.h deleted file mode 100644 index 3a302e13d3..0000000000 --- a/src/gallium/winsys/dri/intel/ws_dri_bufpool.h +++ /dev/null @@ -1,102 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA - * 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, 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 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 - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS 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. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ -/* - * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> - */ - -#ifndef _PSB_BUFPOOL_H_ -#define _PSB_BUFPOOL_H_ - -#include <xf86drm.h> -#include <glthread.h> -struct _DriFenceObject; - -typedef struct _DriBufferPool -{ - int fd; - int (*map) (struct _DriBufferPool * pool, void *private, - unsigned flags, int hint, _glthread_Mutex *mutex, - void **virtual); - int (*unmap) (struct _DriBufferPool * pool, void *private); - int (*destroy) (struct _DriBufferPool * pool, void *private); - unsigned long (*offset) (struct _DriBufferPool * pool, void *private); - unsigned long (*poolOffset) (struct _DriBufferPool * pool, void *private); - uint64_t (*flags) (struct _DriBufferPool * pool, void *private); - unsigned long (*size) (struct _DriBufferPool * pool, void *private); - void *(*create) (struct _DriBufferPool * pool, unsigned long size, - uint64_t flags, unsigned hint, unsigned alignment); - void *(*reference) (struct _DriBufferPool * pool, unsigned handle); - int (*unreference) (struct _DriBufferPool * pool, void *private); - int (*fence) (struct _DriBufferPool * pool, void *private, - struct _DriFenceObject * fence); - drmBO *(*kernel) (struct _DriBufferPool * pool, void *private); - int (*validate) (struct _DriBufferPool * pool, void *private, _glthread_Mutex *mutex); - int (*waitIdle) (struct _DriBufferPool *pool, void *private, _glthread_Mutex *mutex, - int lazy); - int (*setStatus) (struct _DriBufferPool *pool, void *private, - uint64_t flag_diff, uint64_t old_flags); - void (*takeDown) (struct _DriBufferPool * pool); - void *data; -} DriBufferPool; - -extern void bmError(int val, const char *file, const char *function, - int line); -#define BM_CKFATAL(val) \ - do{ \ - int tstVal = (val); \ - if (tstVal) \ - bmError(tstVal, __FILE__, __FUNCTION__, __LINE__); \ - } while(0); - - -/* - * Builtin pools. - */ - -/* - * Kernel buffer objects. Size in multiples of page size. Page size aligned. - */ - -extern struct _DriBufferPool *driDRMPoolInit(int fd); -extern struct _DriBufferPool *driMallocPoolInit(void); - -struct _DriFreeSlabManager; -extern struct _DriBufferPool * driSlabPoolInit(int fd, uint64_t flags, - uint64_t validMask, - uint32_t smallestSize, - uint32_t numSizes, - uint32_t desiredNumBuffers, - uint32_t maxSlabSize, - uint32_t pageAlignment, - struct _DriFreeSlabManager *fMan); -extern void driFinishFreeSlabManager(struct _DriFreeSlabManager *fMan); -extern struct _DriFreeSlabManager * -driInitFreeSlabManager(uint32_t checkIntervalMsec, uint32_t slabTimeoutMsec); - - -#endif diff --git a/src/gallium/winsys/dri/intel/ws_dri_drmpool.c b/src/gallium/winsys/dri/intel/ws_dri_drmpool.c deleted file mode 100644 index 7c55dbc674..0000000000 --- a/src/gallium/winsys/dri/intel/ws_dri_drmpool.c +++ /dev/null @@ -1,268 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA - * 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, 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 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 - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS 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. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ -/* - * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> - */ - -#include <xf86drm.h> -#include <stdlib.h> -#include <unistd.h> -#include "ws_dri_bufpool.h" -#include "ws_dri_bufmgr.h" -#include "assert.h" - -/* - * Buffer pool implementation using DRM buffer objects as DRI buffer objects. - */ - -static void * -pool_create(struct _DriBufferPool *pool, - unsigned long size, uint64_t flags, unsigned hint, - unsigned alignment) -{ - drmBO *buf = (drmBO *) malloc(sizeof(*buf)); - int ret; - unsigned pageSize = getpagesize(); - - if (!buf) - return NULL; - - if ((alignment > pageSize) && (alignment % pageSize)) { - free(buf); - return NULL; - } - - ret = drmBOCreate(pool->fd, size, alignment / pageSize, - NULL, - flags, hint, buf); - if (ret) { - free(buf); - return NULL; - } - - return (void *) buf; -} - -static void * -pool_reference(struct _DriBufferPool *pool, unsigned handle) -{ - drmBO *buf = (drmBO *) malloc(sizeof(*buf)); - int ret; - - if (!buf) - return NULL; - - ret = drmBOReference(pool->fd, handle, buf); - - if (ret) { - free(buf); - return NULL; - } - - return (void *) buf; -} - -static int -pool_destroy(struct _DriBufferPool *pool, void *private) -{ - int ret; - drmBO *buf = (drmBO *) private; - driReadLockKernelBO(); - ret = drmBOUnreference(pool->fd, buf); - free(buf); - driReadUnlockKernelBO(); - return ret; -} - -static int -pool_unreference(struct _DriBufferPool *pool, void *private) -{ - int ret; - drmBO *buf = (drmBO *) private; - driReadLockKernelBO(); - ret = drmBOUnreference(pool->fd, buf); - free(buf); - driReadUnlockKernelBO(); - return ret; -} - -static int -pool_map(struct _DriBufferPool *pool, void *private, unsigned flags, - int hint, _glthread_Mutex *mutex, void **virtual) -{ - drmBO *buf = (drmBO *) private; - int ret; - - driReadLockKernelBO(); - ret = drmBOMap(pool->fd, buf, flags, hint, virtual); - driReadUnlockKernelBO(); - return ret; -} - -static int -pool_unmap(struct _DriBufferPool *pool, void *private) -{ - drmBO *buf = (drmBO *) private; - int ret; - - driReadLockKernelBO(); - ret = drmBOUnmap(pool->fd, buf); - driReadUnlockKernelBO(); - - return ret; -} - -static unsigned long -pool_offset(struct _DriBufferPool *pool, void *private) -{ - drmBO *buf = (drmBO *) private; - unsigned long offset; - - driReadLockKernelBO(); - assert(buf->flags & DRM_BO_FLAG_NO_MOVE); - offset = buf->offset; - driReadUnlockKernelBO(); - - return buf->offset; -} - -static unsigned long -pool_poolOffset(struct _DriBufferPool *pool, void *private) -{ - return 0; -} - -static uint64_t -pool_flags(struct _DriBufferPool *pool, void *private) -{ - drmBO *buf = (drmBO *) private; - uint64_t flags; - - driReadLockKernelBO(); - flags = buf->flags; - driReadUnlockKernelBO(); - - return flags; -} - - -static unsigned long -pool_size(struct _DriBufferPool *pool, void *private) -{ - drmBO *buf = (drmBO *) private; - unsigned long size; - - driReadLockKernelBO(); - size = buf->size; - driReadUnlockKernelBO(); - - return buf->size; -} - -static int -pool_fence(struct _DriBufferPool *pool, void *private, - struct _DriFenceObject *fence) -{ - /* - * Noop. The kernel handles all fencing. - */ - - return 0; -} - -static drmBO * -pool_kernel(struct _DriBufferPool *pool, void *private) -{ - return (drmBO *) private; -} - -static int -pool_waitIdle(struct _DriBufferPool *pool, void *private, _glthread_Mutex *mutex, - int lazy) -{ - drmBO *buf = (drmBO *) private; - int ret; - - driReadLockKernelBO(); - ret = drmBOWaitIdle(pool->fd, buf, (lazy) ? DRM_BO_HINT_WAIT_LAZY:0); - driReadUnlockKernelBO(); - - return ret; -} - - -static void -pool_takedown(struct _DriBufferPool *pool) -{ - free(pool); -} - -/*static int -pool_setStatus(struct _DriBufferPool *pool, void *private, - uint64_t flag_diff, uint64_t old_flags) -{ - drmBO *buf = (drmBO *) private; - uint64_t new_flags = old_flags ^ flag_diff; - int ret; - - driReadLockKernelBO(); - ret = drmBOSetStatus(pool->fd, buf, new_flags, flag_diff, - 0, 0, 0); - driReadUnlockKernelBO(); - return ret; -}*/ - -struct _DriBufferPool * -driDRMPoolInit(int fd) -{ - struct _DriBufferPool *pool; - - pool = (struct _DriBufferPool *) malloc(sizeof(*pool)); - - if (!pool) - return NULL; - - pool->fd = fd; - pool->map = &pool_map; - pool->unmap = &pool_unmap; - pool->destroy = &pool_destroy; - pool->offset = &pool_offset; - pool->poolOffset = &pool_poolOffset; - pool->flags = &pool_flags; - pool->size = &pool_size; - pool->create = &pool_create; - pool->fence = &pool_fence; - pool->kernel = &pool_kernel; - pool->validate = NULL; - pool->waitIdle = &pool_waitIdle; - pool->takeDown = &pool_takedown; - pool->reference = &pool_reference; - pool->unreference = &pool_unreference; - pool->data = NULL; - return pool; -} diff --git a/src/gallium/winsys/egl_drm/Makefile.template b/src/gallium/winsys/egl_drm/Makefile.template index 3bc1fdd4d4..07abfa53f3 100644 --- a/src/gallium/winsys/egl_drm/Makefile.template +++ b/src/gallium/winsys/egl_drm/Makefile.template @@ -54,6 +54,7 @@ SHARED_INCLUDES = \ -I$(TOP)/src/gallium/include \ -I$(TOP)/src/gallium/auxiliary \ -I$(TOP)/src/gallium/drivers \ + -I$(TOP)/src/gallium/winsys/common \ -I$(TOP)/src/mesa \ -I$(TOP)/src/mesa/main \ -I$(TOP)/src/mesa/glapi \ diff --git a/src/gallium/winsys/egl_drm/intel/Makefile b/src/gallium/winsys/egl_drm/intel/Makefile index 5778ba77c3..9c7ff065ff 100644 --- a/src/gallium/winsys/egl_drm/intel/Makefile +++ b/src/gallium/winsys/egl_drm/intel/Makefile @@ -6,22 +6,13 @@ LIBNAME = EGL_i915.so PIPE_DRIVERS = \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ - $(TOP)/src/gallium/drivers/i915simple/libi915simple.a + $(TOP)/src/gallium/drivers/i915simple/libi915simple.a \ + $(TOP)/src/gallium/winsys/common/intel_drm/libinteldrm.a DRIVER_SOURCES = \ - intel_winsys_pipe.c \ - intel_winsys_softpipe.c \ - intel_winsys_i915.c \ - intel_batchbuffer.c \ intel_swapbuffers.c \ intel_context.c \ - intel_lock.c \ intel_screen.c \ - ws_dri_bufmgr.c \ - ws_dri_drmpool.c \ - ws_dri_fencemgr.c \ - ws_dri_mallocpool.c \ - ws_dri_slabpool.c \ intel_egl.c C_SOURCES = \ @@ -35,6 +26,4 @@ DRIVER_DEFINES = -I$(TOP)/src/mesa/drivers/dri/intel $(shell pkg-config libdrm - include ../Makefile.template -intel_tex_layout.o: $(TOP)/src/mesa/drivers/dri/intel/intel_tex_layout.c - symlinks: diff --git a/src/gallium/winsys/egl_drm/intel/intel_batchbuffer.c b/src/gallium/winsys/egl_drm/intel/intel_batchbuffer.c deleted file mode 100644 index 7ffa05a6e6..0000000000 --- a/src/gallium/winsys/egl_drm/intel/intel_batchbuffer.c +++ /dev/null @@ -1,465 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. - * 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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. - * - **************************************************************************/ - -#include "intel_batchbuffer.h" -#include "intel_context.h" -#include "intel_egl.h" - -#include <errno.h> - -#if 0 -static void -intel_dump_batchbuffer(GLuint offset, GLuint * ptr, GLuint count) -{ - int i; - fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count / 4); - for (i = 0; i < count / 4; i += 4) - fprintf(stderr, "0x%x:\t0x%08x 0x%08x 0x%08x 0x%08x\n", - offset + i * 4, ptr[i], ptr[i + 1], ptr[i + 2], ptr[i + 3]); - fprintf(stderr, "END BATCH\n\n\n"); -} -#endif - -static void -intel_realloc_relocs(struct intel_batchbuffer *batch, int num_relocs) -{ - unsigned long size = num_relocs * I915_RELOC0_STRIDE + I915_RELOC_HEADER; - - size *= sizeof(uint32_t); - batch->reloc = realloc(batch->reloc, size); - batch->reloc_size = num_relocs; -} - - -void -intel_batchbuffer_reset(struct intel_batchbuffer *batch) -{ - /* - * Get a new, free batchbuffer. - */ - drmBO *bo; - struct drm_bo_info_req *req; - int ret; - - driBOUnrefUserList(batch->list); - driBOResetList(batch->list); - - batch->size = 4096; // ZZZ JB batch->intel->intelScreen->maxBatchSize; - ret = driBOData(batch->buffer, batch->size, NULL, NULL, 0); - assert(!ret); - - /* - * Add the batchbuffer to the validate list. - */ - - driBOAddListItem(batch->list, batch->buffer, - DRM_BO_FLAG_EXE | DRM_BO_FLAG_MEM_TT, - DRM_BO_FLAG_EXE | DRM_BO_MASK_MEM, - &batch->dest_location, &batch->node); - - req = &batch->node->bo_arg.d.req.bo_req; - - /* - * Set up information needed for us to make relocations - * relative to the underlying drm buffer objects. - */ - - driReadLockKernelBO(); - bo = driBOKernel(batch->buffer); - req->presumed_offset = (uint64_t) bo->offset; - req->hint = DRM_BO_HINT_PRESUMED_OFFSET; - batch->drmBOVirtual = (uint8_t *) bo->virtual; - driReadUnlockKernelBO(); - - /* - * Adjust the relocation buffer size. - */ - - if (batch->reloc_size > INTEL_MAX_RELOCS || - batch->reloc == NULL) - intel_realloc_relocs(batch, INTEL_DEFAULT_RELOCS); - - assert(batch->reloc != NULL); - batch->reloc[0] = 0; /* No relocs yet. */ - batch->reloc[1] = 1; /* Reloc type 1 */ - batch->reloc[2] = 0; /* Only a single relocation list. */ - batch->reloc[3] = 0; /* Only a single relocation list. */ - - batch->map = driBOMap(batch->buffer, DRM_BO_FLAG_WRITE, 0); - batch->poolOffset = driBOPoolOffset(batch->buffer); - batch->ptr = batch->map; - batch->dirty_state = ~0; - batch->nr_relocs = 0; - batch->flags = 0; - batch->id = 0;//batch->intel->intelScreen->batch_id++; -} - -/*====================================================================== - * Public functions - */ -struct intel_batchbuffer * -intel_batchbuffer_alloc(struct intel_screen *intel_screen) -{ - struct intel_batchbuffer *batch = calloc(sizeof(*batch), 1); - - batch->intel_screen = intel_screen; - - driGenBuffers(intel_screen->batchPool, "batchbuffer", 1, - &batch->buffer, 4096, - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE, 0); - batch->last_fence = NULL; - batch->list = driBOCreateList(20); - batch->reloc = NULL; - intel_batchbuffer_reset(batch); - return batch; -} - -void -intel_batchbuffer_free(struct intel_batchbuffer *batch) -{ - if (batch->last_fence) { - driFenceFinish(batch->last_fence, - DRM_FENCE_TYPE_EXE, GL_FALSE); - driFenceUnReference(&batch->last_fence); - } - if (batch->map) { - driBOUnmap(batch->buffer); - batch->map = NULL; - } - driBOUnReference(batch->buffer); - driBOFreeList(batch->list); - if (batch->reloc) - free(batch->reloc); - batch->buffer = NULL; - free(batch); -} - -void -intel_offset_relocation(struct intel_batchbuffer *batch, - unsigned pre_add, - struct _DriBufferObject *driBO, - uint64_t val_flags, - uint64_t val_mask) -{ - int itemLoc; - struct _drmBONode *node; - uint32_t *reloc; - struct drm_bo_info_req *req; - - driBOAddListItem(batch->list, driBO, val_flags, val_mask, - &itemLoc, &node); - req = &node->bo_arg.d.req.bo_req; - - if (!(req->hint & DRM_BO_HINT_PRESUMED_OFFSET)) { - - /* - * Stop other threads from tampering with the underlying - * drmBO while we're reading its offset. - */ - - driReadLockKernelBO(); - req->presumed_offset = (uint64_t) driBOKernel(driBO)->offset; - driReadUnlockKernelBO(); - req->hint = DRM_BO_HINT_PRESUMED_OFFSET; - } - - pre_add += driBOPoolOffset(driBO); - - if (batch->nr_relocs == batch->reloc_size) - intel_realloc_relocs(batch, batch->reloc_size * 2); - - reloc = batch->reloc + - (I915_RELOC_HEADER + batch->nr_relocs * I915_RELOC0_STRIDE); - - reloc[0] = ((uint8_t *)batch->ptr - batch->drmBOVirtual); - intel_batchbuffer_emit_dword(batch, req->presumed_offset + pre_add); - reloc[1] = pre_add; - reloc[2] = itemLoc; - reloc[3] = batch->dest_location; - batch->nr_relocs++; -} - -static void -i915_drm_copy_reply(const struct drm_bo_info_rep * rep, drmBO * buf) -{ - buf->handle = rep->handle; - buf->flags = rep->flags; - buf->size = rep->size; - buf->offset = rep->offset; - buf->mapHandle = rep->arg_handle; - buf->proposedFlags = rep->proposed_flags; - buf->start = rep->buffer_start; - buf->fenceFlags = rep->fence_flags; - buf->replyFlags = rep->rep_flags; - buf->pageAlignment = rep->page_alignment; -} - -static int -i915_execbuf(struct intel_batchbuffer *batch, - GLuint used, - GLboolean ignore_cliprects, - drmBOList *list, - struct drm_i915_execbuffer *ea) -{ - struct intel_screen *intel_screen = batch->intel_screen; - drmBONode *node; - drmMMListHead *l; - struct drm_i915_op_arg *arg, *first; - struct drm_bo_op_req *req; - struct drm_bo_info_rep *rep; - uint64_t *prevNext = NULL; - drmBO *buf; - int ret = 0; - uint32_t count = 0; - - first = NULL; - for (l = list->list.next; l != &list->list; l = l->next) { - node = DRMLISTENTRY(drmBONode, l, head); - - arg = &node->bo_arg; - req = &arg->d.req; - - if (!first) - first = arg; - - if (prevNext) - *prevNext = (unsigned long)arg; - - prevNext = &arg->next; - req->bo_req.handle = node->buf->handle; - req->op = drm_bo_validate; - req->bo_req.flags = node->arg0; - req->bo_req.mask = node->arg1; - req->bo_req.hint |= 0; - count++; - } - - memset(ea, 0, sizeof(*ea)); - ea->num_buffers = count; - ea->batch.start = batch->poolOffset; - ea->batch.used = used; -#if 0 /* ZZZ JB: no cliprects used */ - ea->batch.cliprects = intel->pClipRects; - ea->batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects; - ea->batch.DR1 = 0; - ea->batch.DR4 = 0;((((GLuint) intel->drawX) & 0xffff) | - (((GLuint) intel->drawY) << 16)); -#else - ea->batch.cliprects = NULL; - ea->batch.num_cliprects = 0; - ea->batch.DR1 = 0; - ea->batch.DR4 = 0; -#endif - ea->fence_arg.flags = DRM_I915_FENCE_FLAG_FLUSHED; - ea->ops_list = (unsigned long) first; - first->reloc_ptr = (unsigned long) batch->reloc; - batch->reloc[0] = batch->nr_relocs; - - //return -EFAULT; - do { - ret = drmCommandWriteRead(intel_screen->device->drmFD, DRM_I915_EXECBUFFER, ea, - sizeof(*ea)); - } while (ret == -EAGAIN); - - if (ret != 0) { - printf("%s somebody set us up the bomb\n", __FUNCTION__); - return ret; - } - - for (l = list->list.next; l != &list->list; l = l->next) { - node = DRMLISTENTRY(drmBONode, l, head); - arg = &node->bo_arg; - rep = &arg->d.rep.bo_info; - - if (!arg->handled) { - return -EFAULT; - } - if (arg->d.rep.ret) - return arg->d.rep.ret; - - buf = node->buf; - i915_drm_copy_reply(rep, buf); - } - return 0; -} - -/* TODO: Push this whole function into bufmgr. - */ -static struct _DriFenceObject * -do_flush_locked(struct intel_batchbuffer *batch, - GLuint used, - GLboolean ignore_cliprects, GLboolean allow_unlock) -{ - struct intel_screen *intel_screen = batch->intel_screen; - struct _DriFenceObject *fo; - drmFence fence; - drmBOList *boList; - struct drm_i915_execbuffer ea; - int ret = 0; - - driBOValidateUserList(batch->list); - boList = driGetdrmBOList(batch->list); - -#if 0 /* ZZZ JB Allways run */ - if (!(intel->numClipRects == 0 && !ignore_cliprects)) { -#else - if (1) { -#endif - ret = i915_execbuf(batch, used, ignore_cliprects, boList, &ea); - } else { - driPutdrmBOList(batch->list); - fo = NULL; - goto out; - } - driPutdrmBOList(batch->list); - if (ret) - abort(); - - if (ea.fence_arg.error != 0) { - - /* - * The hardware has been idled by the kernel. - * Don't fence the driBOs. - */ - - if (batch->last_fence) - driFenceUnReference(&batch->last_fence); -#if 0 /* ZZZ JB: no _mesa_* funcs in gallium */ - _mesa_printf("fence error\n"); -#endif - batch->last_fence = NULL; - fo = NULL; - goto out; - } - - fence.handle = ea.fence_arg.handle; - fence.fence_class = ea.fence_arg.fence_class; - fence.type = ea.fence_arg.type; - fence.flags = ea.fence_arg.flags; - fence.signaled = ea.fence_arg.signaled; - - fo = driBOFenceUserList(intel_screen->mgr, batch->list, - "SuperFence", &fence); - - if (driFenceType(fo) & DRM_I915_FENCE_TYPE_RW) { - if (batch->last_fence) - driFenceUnReference(&batch->last_fence); - /* - * FIXME: Context last fence?? - */ - batch->last_fence = fo; - driFenceReference(fo); - } - out: -#if 0 /* ZZZ JB: fix this */ - intel->vtbl.lost_hardware(intel); -#else -#endif - return fo; -} - - -struct _DriFenceObject * -intel_batchbuffer_flush(struct intel_batchbuffer *batch) -{ - //struct intel_context *intel = batch->intel; - GLuint used = batch->ptr - batch->map; - //GLboolean was_locked = 1; - struct _DriFenceObject *fence; - - if (used == 0) { - driFenceReference(batch->last_fence); - return batch->last_fence; - } - - /* Add the MI_BATCH_BUFFER_END. Always add an MI_FLUSH - this is a - * performance drain that we would like to avoid. - */ -#if 0 /* ZZZ JB: what should we do here? */ - if (used & 4) { - ((int *) batch->ptr)[0] = intel->vtbl.flush_cmd(); - ((int *) batch->ptr)[1] = 0; - ((int *) batch->ptr)[2] = MI_BATCH_BUFFER_END; - used += 12; - } - else { - ((int *) batch->ptr)[0] = intel->vtbl.flush_cmd(); - ((int *) batch->ptr)[1] = MI_BATCH_BUFFER_END; - used += 8; - } -#else - if (used & 4) { - ((int *) batch->ptr)[0] = ((0<<29)|(4<<23)); // MI_FLUSH; - ((int *) batch->ptr)[1] = 0; - ((int *) batch->ptr)[2] = (0xA<<23); // MI_BATCH_BUFFER_END; - used += 12; - } - else { - ((int *) batch->ptr)[0] = ((0<<29)|(4<<23)); // MI_FLUSH; - ((int *) batch->ptr)[1] = (0xA<<23); // MI_BATCH_BUFFER_END; - used += 8; - } -#endif - driBOUnmap(batch->buffer); - batch->ptr = NULL; - batch->map = NULL; - - /* TODO: Just pass the relocation list and dma buffer up to the - * kernel. - */ -/* if (!was_locked) - LOCK_HARDWARE(intel);*/ - - fence = do_flush_locked(batch, used, !(batch->flags & INTEL_BATCH_CLIPRECTS), - GL_FALSE); - -/* if (!was_locked) - UNLOCK_HARDWARE(intel);*/ - - /* Reset the buffer: - */ - intel_batchbuffer_reset(batch); - return fence; -} - -void -intel_batchbuffer_finish(struct intel_batchbuffer *batch) -{ - struct _DriFenceObject *fence = intel_batchbuffer_flush(batch); - driFenceFinish(fence, driFenceType(fence), GL_FALSE); - driFenceUnReference(&fence); -} - -void -intel_batchbuffer_data(struct intel_batchbuffer *batch, - const void *data, GLuint bytes, GLuint flags) -{ - assert((bytes & 3) == 0); - intel_batchbuffer_require_space(batch, bytes, flags); - memcpy(batch->ptr, data, bytes); - batch->ptr += bytes; -} diff --git a/src/gallium/winsys/egl_drm/intel/intel_batchbuffer.h b/src/gallium/winsys/egl_drm/intel/intel_batchbuffer.h index 6d35cf8b96..1fa2719845 100644 --- a/src/gallium/winsys/egl_drm/intel/intel_batchbuffer.h +++ b/src/gallium/winsys/egl_drm/intel/intel_batchbuffer.h @@ -1,133 +1,24 @@ #ifndef INTEL_BATCHBUFFER_H #define INTEL_BATCHBUFFER_H -#include "mtypes.h" -#include "ws_dri_bufmgr.h" +#include "intel_drm/intel_be_batchbuffer.h" -struct intel_screen; - -#define BATCH_SZ 16384 -#define BATCH_RESERVED 16 - -#define INTEL_DEFAULT_RELOCS 100 -#define INTEL_MAX_RELOCS 400 - -#define INTEL_BATCH_NO_CLIPRECTS 0x1 -#define INTEL_BATCH_CLIPRECTS 0x2 - -struct intel_batchbuffer -{ - struct bufmgr *bm; - struct intel_screen *intel_screen; - - struct _DriBufferObject *buffer; - struct _DriFenceObject *last_fence; - GLuint flags; - - struct _DriBufferList *list; - GLuint list_count; - GLubyte *map; - GLubyte *ptr; - - uint32_t *reloc; - GLuint reloc_size; - GLuint nr_relocs; - - GLuint size; - - GLuint dirty_state; - GLuint id; - - uint32_t poolOffset; - uint8_t *drmBOVirtual; - struct _drmBONode *node; /* Validation list node for this buffer */ - int dest_location; /* Validation list sequence for this buffer */ -}; - -struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_screen - *intel); - -void intel_batchbuffer_free(struct intel_batchbuffer *batch); - - -void intel_batchbuffer_finish(struct intel_batchbuffer *batch); - -struct _DriFenceObject *intel_batchbuffer_flush(struct intel_batchbuffer - *batch); - -void intel_batchbuffer_reset(struct intel_batchbuffer *batch); - - -/* Unlike bmBufferData, this currently requires the buffer be mapped. - * Consider it a convenience function wrapping multple - * intel_buffer_dword() calls. - */ -void intel_batchbuffer_data(struct intel_batchbuffer *batch, - const void *data, GLuint bytes, GLuint flags); - -void intel_batchbuffer_release_space(struct intel_batchbuffer *batch, - GLuint bytes); - -void -intel_offset_relocation(struct intel_batchbuffer *batch, - unsigned pre_add, - struct _DriBufferObject *driBO, - uint64_t val_flags, - uint64_t val_mask); - -/* Inline functions - might actually be better off with these - * non-inlined. Certainly better off switching all command packets to - * be passed as structs rather than dwords, but that's a little bit of - * work... +/* + * Need to redefine the BATCH defines */ -static INLINE GLuint -intel_batchbuffer_space(struct intel_batchbuffer *batch) -{ - return (batch->size - BATCH_RESERVED) - (batch->ptr - batch->map); -} - - -static INLINE void -intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch, GLuint dword) -{ - assert(batch->map); - assert(intel_batchbuffer_space(batch) >= 4); - *(GLuint *) (batch->ptr) = dword; - batch->ptr += 4; -} -static INLINE void -intel_batchbuffer_require_space(struct intel_batchbuffer *batch, - GLuint sz, GLuint flags) -{ - struct _DriFenceObject *fence; +#undef BEGIN_BATCH +#define BEGIN_BATCH(dwords, relocs) \ + (i915_batchbuffer_check(&intel->base.batch->base, dwords, relocs)) - assert(sz < batch->size - 8); - if (intel_batchbuffer_space(batch) < sz || - (batch->flags != 0 && flags != 0 && batch->flags != flags)) { - fence = intel_batchbuffer_flush(batch); - driFenceUnReference(&fence); - } +#undef OUT_BATCH +#define OUT_BATCH(d) \ + i915_batchbuffer_dword(&intel->base.batch->base, d) - batch->flags |= flags; -} - -/* Here are the crusty old macros, to be removed: - */ -#define BATCH_LOCALS - -#define BEGIN_BATCH(n, flags) do { \ - assert(!intel->prim.flush); \ - intel_batchbuffer_require_space(intel->batch, (n)*4, flags); \ -} while (0) - -#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel->batch, d) - -#define OUT_RELOC(buf,flags,mask,delta) do { \ +#undef OUT_RELOC +#define OUT_RELOC(buf,flags,mask,delta) do { \ assert((delta) >= 0); \ - intel_offset_relocation(intel->batch, delta, buf, flags, mask); \ + intel_be_offset_relocation(intel->base.batch, delta, buf, flags, mask); \ } while (0) -#define ADVANCE_BATCH() do { } while(0) - #endif diff --git a/src/gallium/winsys/egl_drm/intel/intel_context.c b/src/gallium/winsys/egl_drm/intel/intel_context.c index 394a40d714..fdbaa230e5 100644 --- a/src/gallium/winsys/egl_drm/intel/intel_context.c +++ b/src/gallium/winsys/egl_drm/intel/intel_context.c @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * 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 @@ -10,11 +10,11 @@ * 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. @@ -22,14 +22,13 @@ * 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 "i915simple/i915_screen.h" #include "intel_screen.h" #include "intel_context.h" -#include "intel_swapbuffers.h" -#include "intel_winsys.h" #include "intel_batchbuffer.h" #include "state_tracker/st_public.h" @@ -70,74 +69,109 @@ int __intel_debug = 0; * old i830-specific driver. */ const struct dri_extension card_extensions[] = { - {"GL_ARB_multisample", GL_ARB_multisample_functions}, - {"GL_ARB_multitexture", NULL}, - {"GL_ARB_point_parameters", GL_ARB_point_parameters_functions}, - {"GL_ARB_texture_border_clamp", NULL}, - {"GL_ARB_texture_compression", GL_ARB_texture_compression_functions}, - {"GL_ARB_texture_cube_map", NULL}, - {"GL_ARB_texture_env_add", NULL}, - {"GL_ARB_texture_env_combine", NULL}, - {"GL_ARB_texture_env_dot3", NULL}, - {"GL_ARB_texture_mirrored_repeat", NULL}, - {"GL_ARB_texture_rectangle", NULL}, - {"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions}, - {"GL_ARB_pixel_buffer_object", NULL}, - {"GL_ARB_vertex_program", GL_ARB_vertex_program_functions}, - {"GL_ARB_window_pos", GL_ARB_window_pos_functions}, - {"GL_EXT_blend_color", GL_EXT_blend_color_functions}, - {"GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions}, - {"GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions}, - {"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions}, - {"GL_EXT_blend_subtract", NULL}, - {"GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions}, - {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions}, - {"GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions}, - {"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions}, - {"GL_EXT_packed_depth_stencil", NULL}, - {"GL_EXT_pixel_buffer_object", NULL}, - {"GL_EXT_secondary_color", GL_EXT_secondary_color_functions}, - {"GL_EXT_stencil_wrap", NULL}, - {"GL_EXT_texture_edge_clamp", NULL}, - {"GL_EXT_texture_env_combine", NULL}, - {"GL_EXT_texture_env_dot3", NULL}, - {"GL_EXT_texture_filter_anisotropic", NULL}, - {"GL_EXT_texture_lod_bias", NULL}, - {"GL_3DFX_texture_compression_FXT1", NULL}, - {"GL_APPLE_client_storage", NULL}, - {"GL_MESA_pack_invert", NULL}, - {"GL_MESA_ycbcr_texture", NULL}, - {"GL_NV_blend_square", NULL}, - {"GL_NV_vertex_program", GL_NV_vertex_program_functions}, - {"GL_NV_vertex_program1_1", NULL}, - {"GL_SGIS_generate_mipmap", NULL }, - {NULL, NULL} + {"GL_ARB_multisample", GL_ARB_multisample_functions}, + {"GL_ARB_multitexture", NULL}, + {"GL_ARB_point_parameters", GL_ARB_point_parameters_functions}, + {"GL_ARB_texture_border_clamp", NULL}, + {"GL_ARB_texture_compression", GL_ARB_texture_compression_functions}, + {"GL_ARB_texture_cube_map", NULL}, + {"GL_ARB_texture_env_add", NULL}, + {"GL_ARB_texture_env_combine", NULL}, + {"GL_ARB_texture_env_dot3", NULL}, + {"GL_ARB_texture_mirrored_repeat", NULL}, + {"GL_ARB_texture_rectangle", NULL}, + {"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions}, + {"GL_ARB_pixel_buffer_object", NULL}, + {"GL_ARB_vertex_program", GL_ARB_vertex_program_functions}, + {"GL_ARB_window_pos", GL_ARB_window_pos_functions}, + {"GL_EXT_blend_color", GL_EXT_blend_color_functions}, + {"GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions}, + {"GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions}, + {"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions}, + {"GL_EXT_blend_subtract", NULL}, + {"GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions}, + {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions}, + {"GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions}, + {"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions}, + {"GL_EXT_packed_depth_stencil", NULL}, + {"GL_EXT_pixel_buffer_object", NULL}, + {"GL_EXT_secondary_color", GL_EXT_secondary_color_functions}, + {"GL_EXT_stencil_wrap", NULL}, + {"GL_EXT_texture_edge_clamp", NULL}, + {"GL_EXT_texture_env_combine", NULL}, + {"GL_EXT_texture_env_dot3", NULL}, + {"GL_EXT_texture_filter_anisotropic", NULL}, + {"GL_EXT_texture_lod_bias", NULL}, + {"GL_3DFX_texture_compression_FXT1", NULL}, + {"GL_APPLE_client_storage", NULL}, + {"GL_MESA_pack_invert", NULL}, + {"GL_MESA_ycbcr_texture", NULL}, + {"GL_NV_blend_square", NULL}, + {"GL_NV_vertex_program", GL_NV_vertex_program_functions}, + {"GL_NV_vertex_program1_1", NULL}, + {"GL_SGIS_generate_mipmap", NULL }, + {NULL, NULL} }; + +/* + * Hardware lock functions. + * Doesn't do anything in EGL + */ + +static void +intel_lock_hardware(struct intel_be_context *context) +{ + (void)context; +} + +static void +intel_unlock_hardware(struct intel_be_context *context) +{ + (void)context; +} + +static boolean +intel_locked_hardware(struct intel_be_context *context) +{ + (void)context; + return FALSE; +} + + +/* + * Misc functions. + */ + int -intel_create_context(struct egl_drm_context *eglCon, const __GLcontextModes *visual, void *sharedContextPrivate) +intel_create_context(struct egl_drm_context *egl_context, const __GLcontextModes *visual, void *sharedContextPrivate) { - struct intel_context *iCon = CALLOC_STRUCT(intel_context); - struct intel_screen *iScrn = (struct intel_screen *)eglCon->device->priv; + struct intel_context *intel = CALLOC_STRUCT(intel_context); + struct intel_screen *screen = (struct intel_screen *)egl_context->device->priv; struct pipe_context *pipe; struct st_context *st_share = NULL; - eglCon->priv = iCon; + egl_context->priv = intel; + + intel->intel_screen = screen; + intel->egl_context = egl_context; + intel->egl_device = egl_context->device; - iCon->intel_screen = iScrn; - iCon->egl_context = eglCon; - iCon->egl_device = eglCon->device; + intel->base.hardware_lock = intel_lock_hardware; + intel->base.hardware_unlock = intel_unlock_hardware; + intel->base.hardware_locked = intel_locked_hardware; - iCon->batch = intel_batchbuffer_alloc(iScrn); - iCon->last_swap_fence = NULL; - iCon->first_swap_fence = NULL; + intel_be_init_context(&intel->base, &screen->base); - pipe = intel_create_i915simple(iCon, iScrn->winsys); -// pipe = intel_create_softpipe(iCon, iScrn->winsys); +#if 0 + pipe = intel_create_softpipe(intel, screen->winsys); +#else + pipe = i915_create_context(screen->pipe, &screen->base.base, &intel->base.base); +#endif - pipe->priv = iCon; + pipe->priv = intel; - iCon->st = st_create_context(pipe, visual, st_share); + intel->st = st_create_context(pipe, visual, st_share); return TRUE; } @@ -161,7 +195,6 @@ intel_make_current(struct egl_drm_context *context, struct egl_drm_drawable *dra if (draw != read) st_resize_framebuffer(read_fb->stfb, read->w, read->h); - //intelUpdateWindowSize(driDrawPriv); } else { st_make_current(NULL, NULL, NULL); } @@ -173,7 +206,9 @@ intel_bind_frontbuffer(struct egl_drm_drawable *draw, struct egl_drm_frontbuffer struct intel_screen *intelScreen = (struct intel_screen *)draw->device->priv; struct intel_framebuffer *draw_fb = (struct intel_framebuffer *)draw->priv; - driBOUnReference(draw_fb->front_buffer); + if (draw_fb->front_buffer) + driBOUnReference(draw_fb->front_buffer); + draw_fb->front_buffer = NULL; draw_fb->front = NULL; @@ -183,184 +218,8 @@ intel_bind_frontbuffer(struct egl_drm_drawable *draw, struct egl_drm_frontbuffer draw_fb->front = front; - driGenBuffers(intelScreen->staticPool, "front", 1, &draw_fb->front_buffer, 0, 0, 0); + driGenBuffers(intelScreen->base.staticPool, "front", 1, &draw_fb->front_buffer, 0, 0, 0); driBOSetReferenced(draw_fb->front_buffer, front->handle); st_resize_framebuffer(draw_fb->stfb, draw->w, draw->h); } - -#if 0 -GLboolean -intelCreateContext(const __GLcontextModes * visual, - __DRIcontextPrivate * driContextPriv, - void *sharedContextPrivate) -{ - struct intel_context *intel = CALLOC_STRUCT(intel_context); - __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; - struct intel_screen *intelScreen = intel_screen(sPriv); - drmI830Sarea *saPriv = intelScreen->sarea; - int fthrottle_mode; - GLboolean havePools; - struct pipe_context *pipe; - struct st_context *st_share = NULL; - - if (sharedContextPrivate) { - st_share = ((struct intel_context *) sharedContextPrivate)->st; - } - - driContextPriv->driverPrivate = intel; - intel->intelScreen = intelScreen; - intel->driScreen = sPriv; - intel->sarea = saPriv; - - driParseConfigFiles(&intel->optionCache, &intelScreen->optionCache, - intel->driScreen->myNum, "i915"); - - - /* - * memory pools - */ - DRM_LIGHT_LOCK(sPriv->fd, &sPriv->pSAREA->lock, driContextPriv->hHWContext); - // ZZZ JB should be per screen and not be done per context - havePools = intelCreatePools(sPriv); - DRM_UNLOCK(sPriv->fd, &sPriv->pSAREA->lock, driContextPriv->hHWContext); - if (!havePools) - return GL_FALSE; - - - /* Dri stuff */ - intel->hHWContext = driContextPriv->hHWContext; - intel->driFd = sPriv->fd; - intel->driHwLock = (drmLock *) & sPriv->pSAREA->lock; - - fthrottle_mode = driQueryOptioni(&intel->optionCache, "fthrottle_mode"); - intel->iw.irq_seq = -1; - intel->irqsEmitted = 0; - - intel->batch = intel_batchbuffer_alloc(intel); - intel->last_swap_fence = NULL; - intel->first_swap_fence = NULL; - -#ifdef DEBUG - __intel_debug = driParseDebugString(getenv("INTEL_DEBUG"), debug_control); -#endif - - /* - * Pipe-related setup - */ - if (getenv("INTEL_SP")) { - /* use softpipe driver instead of hw */ - pipe = intel_create_softpipe( intel, intelScreen->winsys ); - } - else { - switch (intel->intelScreen->deviceID) { - case PCI_CHIP_I945_G: - case PCI_CHIP_I945_GM: - case PCI_CHIP_I945_GME: - case PCI_CHIP_G33_G: - case PCI_CHIP_Q33_G: - case PCI_CHIP_Q35_G: - case PCI_CHIP_I915_G: - case PCI_CHIP_I915_GM: - pipe = intel_create_i915simple( intel, intelScreen->winsys ); - break; - default: - fprintf(stderr, "Unknown PCIID %x in %s, using software driver\n", - intel->intelScreen->deviceID, __FUNCTION__); - - pipe = intel_create_softpipe( intel, intelScreen->winsys ); - break; - } - } - - pipe->priv = intel; - - intel->st = st_create_context(pipe, visual, st_share); - - return GL_TRUE; -} - - -void -intelDestroyContext(__DRIcontextPrivate * driContextPriv) -{ - struct intel_context *intel = intel_context(driContextPriv); - - assert(intel); /* should never be null */ - if (intel) { - st_finish(intel->st); - - intel_batchbuffer_free(intel->batch); - - if (intel->last_swap_fence) { - driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE); - driFenceUnReference(&intel->last_swap_fence); - intel->last_swap_fence = NULL; - } - if (intel->first_swap_fence) { - driFenceFinish(intel->first_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE); - driFenceUnReference(&intel->first_swap_fence); - intel->first_swap_fence = NULL; - } - - if (intel->intelScreen->dummyContext == intel) - intel->intelScreen->dummyContext = NULL; - - st_destroy_context(intel->st); - free(intel); - } -} - - -GLboolean -intelUnbindContext(__DRIcontextPrivate * driContextPriv) -{ - struct intel_context *intel = intel_context(driContextPriv); - st_flush(intel->st, PIPE_FLUSH_RENDER_CACHE, NULL); - /* XXX make_current(NULL)? */ - return GL_TRUE; -} - - -GLboolean -intelMakeCurrent(__DRIcontextPrivate * driContextPriv, - __DRIdrawablePrivate * driDrawPriv, - __DRIdrawablePrivate * driReadPriv) -{ - if (driContextPriv) { - struct intel_context *intel = intel_context(driContextPriv); - struct intel_framebuffer *draw_fb = intel_framebuffer(driDrawPriv); - struct intel_framebuffer *read_fb = intel_framebuffer(driReadPriv); - - assert(draw_fb->stfb); - assert(read_fb->stfb); - - /* This is for situations in which we need a rendering context but - * there may not be any currently bound. - */ - intel->intelScreen->dummyContext = intel; - - st_make_current(intel->st, draw_fb->stfb, read_fb->stfb); - - if ((intel->driDrawable != driDrawPriv) || - (intel->lastStamp != driDrawPriv->lastStamp)) { - intel->driDrawable = driDrawPriv; - intelUpdateWindowSize(driDrawPriv); - intel->lastStamp = driDrawPriv->lastStamp; - } - - /* The size of the draw buffer will have been updated above. - * If the readbuffer is a different window, check/update its size now. - */ - if (driReadPriv != driDrawPriv) { - intelUpdateWindowSize(driReadPriv); - } - - } - else { - st_make_current(NULL, NULL, NULL); - } - - return GL_TRUE; -} -#endif diff --git a/src/gallium/winsys/egl_drm/intel/intel_context.h b/src/gallium/winsys/egl_drm/intel/intel_context.h index aa9903f274..ccf8120761 100644 --- a/src/gallium/winsys/egl_drm/intel/intel_context.h +++ b/src/gallium/winsys/egl_drm/intel/intel_context.h @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * 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 @@ -10,11 +10,11 @@ * 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. @@ -22,61 +22,37 @@ * 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 INTEL_CONTEXT_H #define INTEL_CONTEXT_H -#include <stdint.h> -#include "drm.h" - #include "pipe/p_debug.h" - -#include "intel_screen.h" -#include "i915_drm.h" +#include "intel_drm/intel_be_context.h" -struct pipe_context; -struct intel_context; -struct _DriBufferObject; struct st_context; struct egl_drm_device; struct egl_drm_context; struct egl_drm_frontbuffer; -#define INTEL_MAX_FIXUP 64 - /** * Intel rendering context, contains a state tracker and intel-specific info. */ struct intel_context { - struct st_context *st; - - struct _DriFenceObject *last_swap_fence; - struct _DriFenceObject *first_swap_fence; + struct intel_be_context base; - struct intel_batchbuffer *batch; + struct st_context *st; -#if 0 - boolean locked; - char *prevLockFile; - int prevLockLine; -#endif - - /* pick this up from the screen instead - int drmFd; - */ + struct intel_screen *intel_screen; - struct intel_screen *intel_screen; - - uint lastStamp; - /* new egl stuff */ - struct egl_drm_device *egl_device; - struct egl_drm_context *egl_context; - struct egl_drm_drawable *egl_drawable; + /* new egl stuff */ + struct egl_drm_device *egl_device; + struct egl_drm_context *egl_context; + struct egl_drm_drawable *egl_drawable; }; @@ -86,12 +62,12 @@ struct intel_context */ struct intel_framebuffer { - struct st_framebuffer *stfb; + struct st_framebuffer *stfb; - /* other fields TBD */ - int other; - struct _DriBufferObject *front_buffer; - struct egl_drm_frontbuffer *front; + /* other fields TBD */ + int other; + struct _DriBufferObject *front_buffer; + struct egl_drm_frontbuffer *front; }; @@ -123,11 +99,10 @@ extern int __intel_debug; } while(0) #else -#define DBG(flag, ...) +#define DBG(flag, ...) #endif - #define PCI_CHIP_845_G 0x2562 #define PCI_CHIP_I830_M 0x3577 #define PCI_CHIP_I855_GM 0x3582 @@ -141,22 +116,4 @@ extern int __intel_debug; #define PCI_CHIP_Q35_G 0x29B2 #define PCI_CHIP_Q33_G 0x29D2 - -#if 0 -/** Cast wrapper */ -static INLINE struct intel_context * -intel_context(__DRIcontextPrivate *driContextPriv) -{ - return (struct intel_context *) driContextPriv->driverPrivate; -} - - -/** Cast wrapper */ -static INLINE struct intel_framebuffer * -intel_framebuffer(__DRIdrawablePrivate * driDrawPriv) -{ - return (struct intel_framebuffer *) driDrawPriv->driverPrivate; -} -#endif - #endif diff --git a/src/gallium/winsys/egl_drm/intel/intel_egl.c b/src/gallium/winsys/egl_drm/intel/intel_egl.c index ac1825210e..3b4ab330f5 100644 --- a/src/gallium/winsys/egl_drm/intel/intel_egl.c +++ b/src/gallium/winsys/egl_drm/intel/intel_egl.c @@ -3,6 +3,7 @@ #include <stdlib.h> #include <string.h> #include <stdio.h> +#include <stdint.h> #include "eglconfig.h" #include "eglcontext.h" @@ -13,7 +14,6 @@ #include "eglscreen.h" #include "eglsurface.h" -#include "glapi.h" #include "intel_egl.h" #include "xf86drm.h" @@ -21,9 +21,6 @@ #include "intel_context.h" -#include "ws_dri_bufmgr.h" - -#include "intel_winsys.h" #include "state_tracker/st_public.h" struct egl_drm_device* egl_drm_create_device(int drmFD); @@ -114,6 +111,7 @@ drm_initialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor) struct drm_screen *screen = NULL; drmModeOutputPtr output = NULL; drmModeResPtr res = NULL; + unsigned count_outputs = 0; EGLint i; int fd; @@ -131,8 +129,10 @@ drm_initialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor) drm_update_res(drm_drv); res = drm_drv->res; + if (res) + count_outputs = res->count_outputs; - for(i = 0; i < res->count_outputs; i++) { + for(i = 0; i < count_outputs; i++) { output = drmModeGetOutput(fd, res->outputs[i]); if (!output) @@ -280,9 +280,9 @@ drm_create_context(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext /* generate handle and insert into hash table */ _eglSaveContext(&c->base); - assert(c->base.Handle); + assert(_eglGetContextHandle(&c->base)); - return c->base.Handle; + return _eglGetContextHandle(&c->base); err_gl: free(context); err_c: @@ -431,10 +431,12 @@ prettyColors(int fd, unsigned int handle, size_t pitch) { drmBO bo; unsigned int *ptr; + void *p; int i; drmBOReference(fd, handle, &bo); - drmBOMap(fd, &bo, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, (void**)&ptr); + drmBOMap(fd, &bo, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &p); + ptr = (unsigned int*)p; for (i = 0; i < (bo.size / 4); i++) ptr[i] = 0xFFFFFFFF; @@ -457,8 +459,6 @@ drm_show_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy, struct drm_driver *drm_drv = (struct drm_driver *)drv; struct drm_surface *surf = lookup_drm_surface(surface); struct drm_screen *scrn = lookup_drm_screen(dpy, screen); - //struct intel_framebuffer *intel_fb = NULL; - //struct pipe_surface *front_surf = NULL; _EGLMode *mode = _eglLookupMode(dpy, m); size_t pitch = 2048 * 4; size_t size = mode->Height * pitch; @@ -466,8 +466,6 @@ drm_show_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy, /* TODO if allready shown take down */ - printf("setting mode to %i x %i\n", mode->Width, mode->Height); - ret = drmBOCreate(drm_drv->device->drmFD, size, 0, 0, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | @@ -476,12 +474,13 @@ drm_show_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy, DRM_BO_FLAG_NO_EVICT, DRM_BO_HINT_DONT_FENCE, &scrn->buffer); - prettyColors(drm_drv->device->drmFD, scrn->buffer.handle, pitch); if (ret) { printf("failed to create framebuffer (ret %d)\n", ret); return EGL_FALSE; } + prettyColors(drm_drv->device->drmFD, scrn->buffer.handle, pitch); + ret = drmModeAddFB(drm_drv->device->drmFD, mode->Width, mode->Height, 32, 32, pitch, scrn->buffer.handle, @@ -550,6 +549,7 @@ drm_make_current(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface re struct drm_context *ctx = lookup_drm_context(context); EGLBoolean b; + printf("drm_make_current\n"); b = _eglMakeCurrent(drv, dpy, draw, read, context); if (!b) return EGL_FALSE; @@ -559,6 +559,7 @@ drm_make_current(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface re (void) readSurf; (void) ctx; + printf("enter intel_make_current\n"); intel_make_current(ctx->context, drawSurf->drawable, readSurf->drawable); return EGL_TRUE; } @@ -584,7 +585,7 @@ drm_swap_buffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) * plug in API functions. */ _EGLDriver * -_eglMain(_EGLDisplay *dpy) +_eglMain(_EGLDisplay *dpy, const char *args) { struct drm_driver *drm; @@ -609,6 +610,8 @@ _eglMain(_EGLDisplay *dpy) 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*/; + /* enable supported extensions */ drm->base.Extensions.MESA_screen_surface = EGL_TRUE; drm->base.Extensions.MESA_copy_context = EGL_TRUE; diff --git a/src/gallium/winsys/egl_drm/intel/intel_lock.c b/src/gallium/winsys/egl_drm/intel/intel_lock.c deleted file mode 100644 index cec83c7585..0000000000 --- a/src/gallium/winsys/egl_drm/intel/intel_lock.c +++ /dev/null @@ -1,102 +0,0 @@ -/************************************************************************** - * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. - * 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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. - * - **************************************************************************/ - - -#include "main/glheader.h" -#include "glapi/glthread.h" -#include <GL/internal/glcore.h> -#include "state_tracker/st_public.h" -#include "intel_context.h" - -#if 0 - -_glthread_DECLARE_STATIC_MUTEX( lockMutex ); - - -static void -intelContendedLock(struct intel_context *intel, uint flags) -{ - __DRIdrawablePrivate *dPriv = intel->driDrawable; - __DRIscreenPrivate *sPriv = intel->driScreen; - struct intel_screen *intelScreen = intel_screen(sPriv); - drmI830Sarea *sarea = intel->sarea; - - drmGetLock(intel->driFd, intel->hHWContext, flags); - - DBG(LOCK, "%s - got contended lock\n", __progname); - - /* If the window moved, may need to set a new cliprect now. - * - * NOTE: This releases and regains the hw lock, so all state - * checking must be done *after* this call: - */ - if (dPriv) - DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv); - - if (sarea->width != intelScreen->front.width || - sarea->height != intelScreen->front.height) { - - intelUpdateScreenRotation(sPriv, sarea); - } -} - - -/* Lock the hardware and validate our state. - */ -void LOCK_HARDWARE( struct intel_context *intel ) -{ - char __ret = 0; - - _glthread_LOCK_MUTEX(lockMutex); - assert(!intel->locked); - - DRM_CAS(intel->driHwLock, intel->hHWContext, - (DRM_LOCK_HELD|intel->hHWContext), __ret); - - if (__ret) - intelContendedLock( intel, 0 ); - - DBG(LOCK, "%s - locked\n", __progname); - - intel->locked = 1; -} - - -/* Unlock the hardware using the global current context - */ -void UNLOCK_HARDWARE( struct intel_context *intel ) -{ - assert(intel->locked); - intel->locked = 0; - - DRM_UNLOCK(intel->driFd, intel->driHwLock, intel->hHWContext); - - _glthread_UNLOCK_MUTEX(lockMutex); - - DBG(LOCK, "%s - unlocked\n", __progname); -} -#endif diff --git a/src/gallium/winsys/egl_drm/intel/intel_reg.h b/src/gallium/winsys/egl_drm/intel/intel_reg.h index f37c24fda9..4f33bee438 100644 --- a/src/gallium/winsys/egl_drm/intel/intel_reg.h +++ b/src/gallium/winsys/egl_drm/intel/intel_reg.h @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * 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 @@ -10,11 +10,11 @@ * 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. @@ -22,7 +22,7 @@ * 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. - * + * **************************************************************************/ diff --git a/src/gallium/winsys/egl_drm/intel/intel_screen.c b/src/gallium/winsys/egl_drm/intel/intel_screen.c index 38c4098087..96b0bf1b85 100644 --- a/src/gallium/winsys/egl_drm/intel/intel_screen.c +++ b/src/gallium/winsys/egl_drm/intel/intel_screen.c @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * 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 @@ -10,11 +10,11 @@ * 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. @@ -22,62 +22,24 @@ * 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 "utils.h" -#include "vblank.h" -#include "xmlpool.h" + +#include "state_tracker/st_public.h" +#include "i915simple/i915_screen.h" #include "intel_context.h" #include "intel_screen.h" #include "intel_batchbuffer.h" -//#include "intel_batchpool.h" -#include "intel_swapbuffers.h" -#include "intel_winsys.h" - -#include "ws_dri_bufpool.h" - -#include "pipe/p_context.h" -#include "state_tracker/st_public.h" -#include "state_tracker/st_cb_fbo.h" #include "intel_egl.h" -static boolean -intel_create_pools(struct intel_screen *intel_screen) -{ - if (intel_screen->havePools) - return GL_TRUE; - - intel_screen->mgr = driFenceMgrTTMInit(intel_screen->device->drmFD); - if (!intel_screen->mgr) { - fprintf(stderr, "Failed to create fence manager.\n"); - return FALSE; - } - - intel_screen->fMan = driInitFreeSlabManager(10, 10); - if (!intel_screen->fMan) { - fprintf(stderr, "Failed to create free slab manager.\n"); - return FALSE; - } - - intel_screen->staticPool = driDRMPoolInit(intel_screen->device->drmFD); - intel_screen->batchPool = driSlabPoolInit(intel_screen->device->drmFD, - DRM_BO_FLAG_EXE | - DRM_BO_FLAG_MEM_TT, - DRM_BO_FLAG_EXE | - DRM_BO_FLAG_MEM_TT, - 4096, //intelScreen->maxBatchSize, - 1, 40, 16*16384, 0, - intel_screen->fMan); - - intel_screen->havePools = GL_TRUE; - - return GL_TRUE; -} extern const struct dri_extension card_extensions[]; + int intel_init_driver(struct egl_drm_device *device) { @@ -85,18 +47,18 @@ intel_init_driver(struct egl_drm_device *device) /* Allocate the private area */ intel_screen = CALLOC_STRUCT(intel_screen); - if (!intel_screen) + if (!intel_screen) return FALSE; device->priv = (void *)intel_screen; intel_screen->device = device; - if (!intel_create_pools(intel_screen)) - return FALSE; + /** TODO JB: ugly hack */ + intel_screen->deviceID = PCI_CHIP_I945_GM; - intel_screen->batch = intel_batchbuffer_alloc(intel_screen); + intel_be_init_device(&intel_screen->base, device->drmFD); - intel_screen->winsys = intel_create_pipe_winsys(device->drmFD, intel_screen->fMan); + intel_screen->pipe = i915_create_screen(&intel_screen->base.base, intel_screen->deviceID); /* hack */ driInitExtensions(NULL, card_extensions, GL_FALSE); @@ -147,534 +109,3 @@ intel_create_drawable(struct egl_drm_drawable *drawable, drawable->priv = (void *) intelfb; return GL_TRUE; } - -#if 0 -PUBLIC const char __driConfigOptions[] = - DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE - DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS) - DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0) - DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY - DRI_CONF_FORCE_S3TC_ENABLE(false) - DRI_CONF_ALLOW_LARGE_TEXTURES(1) - DRI_CONF_SECTION_END DRI_CONF_END; - -const uint __driNConfigOptions = 4; - -#ifdef USE_NEW_INTERFACE -static PFNGLXCREATECONTEXTMODES create_context_modes = NULL; -#endif /*USE_NEW_INTERFACE */ - -extern const struct dri_extension card_extensions[]; - - - - -static void -intelPrintDRIInfo(struct intel_screen * intelScreen, - __DRIscreenPrivate * sPriv, I830DRIPtr gDRIPriv) -{ - fprintf(stderr, "*** Front size: 0x%x offset: 0x%x pitch: %d\n", - intelScreen->front.size, intelScreen->front.offset, - intelScreen->front.pitch); - fprintf(stderr, "*** Memory : 0x%x\n", gDRIPriv->mem); -} - -static void -intelPrintSAREA(const drmI830Sarea * sarea) -{ - fprintf(stderr, "SAREA: sarea width %d height %d\n", sarea->width, - sarea->height); - fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch); - fprintf(stderr, - "SAREA: front offset: 0x%08x size: 0x%x handle: 0x%x\n", - sarea->front_offset, sarea->front_size, - (unsigned) sarea->front_handle); - fprintf(stderr, - "SAREA: back offset: 0x%08x size: 0x%x handle: 0x%x\n", - sarea->back_offset, sarea->back_size, - (unsigned) sarea->back_handle); - fprintf(stderr, "SAREA: depth offset: 0x%08x size: 0x%x handle: 0x%x\n", - sarea->depth_offset, sarea->depth_size, - (unsigned) sarea->depth_handle); - fprintf(stderr, "SAREA: tex offset: 0x%08x size: 0x%x handle: 0x%x\n", - sarea->tex_offset, sarea->tex_size, (unsigned) sarea->tex_handle); - fprintf(stderr, "SAREA: rotation: %d\n", sarea->rotation); - fprintf(stderr, - "SAREA: rotated offset: 0x%08x size: 0x%x\n", - sarea->rotated_offset, sarea->rotated_size); - fprintf(stderr, "SAREA: rotated pitch: %d\n", sarea->rotated_pitch); -} - -/** - * Use the information in the sarea to update the screen parameters - * related to screen rotation. Needs to be called locked. - */ -void -intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea) -{ - struct intel_screen *intelScreen = intel_screen(sPriv); - - if (intelScreen->front.map) { - drmUnmap(intelScreen->front.map, intelScreen->front.size); - intelScreen->front.map = NULL; - } - - if (intelScreen->front.buffer) - driDeleteBuffers(1, &intelScreen->front.buffer); - - intelScreen->front.width = sarea->width; - intelScreen->front.height = sarea->height; - intelScreen->front.offset = sarea->front_offset; - intelScreen->front.pitch = sarea->pitch * intelScreen->front.cpp; - intelScreen->front.size = sarea->front_size; - intelScreen->front.handle = sarea->front_handle; - - assert( sarea->front_size >= - intelScreen->front.pitch * intelScreen->front.height ); - -#if 0 /* JB not important */ - if (!sarea->front_handle) - return; - - if (drmMap(sPriv->fd, - sarea->front_handle, - intelScreen->front.size, - (drmAddress *) & intelScreen->front.map) != 0) { - fprintf(stderr, "drmMap(frontbuffer) failed!\n"); - return; - } -#endif - -#if 0 /* JB */ - if (intelScreen->staticPool) { - driGenBuffers(intelScreen->staticPool, "static region", 1, - &intelScreen->front.buffer, 64, - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_NO_MOVE | - DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0); - - driBOSetStatic(intelScreen->front.buffer, - intelScreen->front.offset, - intelScreen->front.pitch * intelScreen->front.height, - intelScreen->front.map, 0); - } -#else - if (intelScreen->staticPool) { - if (intelScreen->front.buffer) - driBOUnReference(intelScreen->front.buffer); - driGenBuffers(intelScreen->staticPool, "front", 1, &intelScreen->front.buffer, 0, 0, 0); - driBOSetReferenced(intelScreen->front.buffer, sarea->front_bo_handle); - } -#endif -} - - -boolean -intelCreatePools(__DRIscreenPrivate * sPriv) -{ - //unsigned batchPoolSize = 1024*1024; - struct intel_screen *intelScreen = intel_screen(sPriv); - - if (intelScreen->havePools) - return GL_TRUE; - -#if 0 /* ZZZ JB fix this */ - intelScreen->staticPool = driDRMStaticPoolInit(sPriv->fd); - if (!intelScreen->staticPool) - return GL_FALSE; - - batchPoolSize /= BATCH_SZ; - intelScreen->batchPool = driBatchPoolInit(sPriv->fd, - DRM_BO_FLAG_EXE | - DRM_BO_FLAG_MEM_TT | - DRM_BO_FLAG_MEM_LOCAL, - BATCH_SZ, - batchPoolSize, 5); - if (!intelScreen->batchPool) { - fprintf(stderr, "Failed to initialize batch pool - possible incorrect agpgart installed\n"); - return GL_FALSE; - } -#else - intelScreen->staticPool = driDRMPoolInit(sPriv->fd); - intelScreen->batchPool = driSlabPoolInit(sPriv->fd, - DRM_BO_FLAG_EXE | - DRM_BO_FLAG_MEM_TT, - DRM_BO_FLAG_EXE | - DRM_BO_FLAG_MEM_TT, - 4096, //intelScreen->maxBatchSize, - 1, 40, 16*16384, 0, - intelScreen->fMan); -#endif - intelScreen->havePools = GL_TRUE; - - //intelUpdateScreenRotation(sPriv, intelScreen->sarea); - - return GL_TRUE; -} - - -static boolean -intelInitDriver(__DRIscreenPrivate * sPriv) -{ - struct intel_screen *intelScreen; - I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv; - - PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension = - (PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface-> - getProcAddress("glxEnableExtension")); - void *const psc = sPriv->psc->screenConfigs; - - if (sPriv->devPrivSize != sizeof(I830DRIRec)) { - fprintf(stderr, - "\nERROR! sizeof(I830DRIRec) does not match passed size from device driver\n"); - return GL_FALSE; - } - - /* Allocate the private area */ - intelScreen = CALLOC_STRUCT(intel_screen); - if (!intelScreen) - return GL_FALSE; - - /* parse information in __driConfigOptions */ - driParseOptionInfo(&intelScreen->optionCache, - __driConfigOptions, __driNConfigOptions); - - sPriv->private = (void *) intelScreen; - - intelScreen->sarea = (drmI830Sarea *) (((GLubyte *) sPriv->pSAREA) + - gDRIPriv->sarea_priv_offset); - intelScreen->deviceID = gDRIPriv->deviceID; - intelScreen->front.cpp = gDRIPriv->cpp; - intelScreen->drmMinor = sPriv->drmMinor; - - - assert(gDRIPriv->bitsPerPixel == 16 || - gDRIPriv->bitsPerPixel == 32); - - - intelUpdateScreenRotation(sPriv, intelScreen->sarea); - - if (0) - intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv); - - if (glx_enable_extension != NULL) { - (*glx_enable_extension) (psc, "GLX_SGI_swap_control"); - (*glx_enable_extension) (psc, "GLX_SGI_video_sync"); - (*glx_enable_extension) (psc, "GLX_MESA_swap_control"); - (*glx_enable_extension) (psc, "GLX_MESA_swap_frame_usage"); - (*glx_enable_extension) (psc, "GLX_SGI_make_current_read"); - } - - - -#if 1 // ZZZ JB - intelScreen->mgr = driFenceMgrTTMInit(sPriv->fd); - if (!intelScreen->mgr) { - fprintf(stderr, "Failed to create fence manager.\n"); - return GL_FALSE; - } - - intelScreen->fMan = driInitFreeSlabManager(10, 10); - if (!intelScreen->fMan) { - fprintf(stderr, "Failed to create free slab manager.\n"); - return GL_FALSE; - } - - if (!intelCreatePools(sPriv)) - return GL_FALSE; -#endif - - intelScreen->winsys = intel_create_pipe_winsys(sPriv->fd, intelScreen->fMan); - - return GL_TRUE; -} - - -static void -intelDestroyScreen(__DRIscreenPrivate * sPriv) -{ - struct intel_screen *intelScreen = intel_screen(sPriv); - - /* intelUnmapScreenRegions(intelScreen); */ - - if (intelScreen->havePools) { - driPoolTakeDown(intelScreen->staticPool); - driPoolTakeDown(intelScreen->batchPool); - } - FREE(intelScreen); - sPriv->private = NULL; -} - - -/** - * This is called when we need to set up GL rendering to a new X window. - */ -static boolean -intelCreateBuffer(__DRIscreenPrivate * driScrnPriv, - __DRIdrawablePrivate * driDrawPriv, - const __GLcontextModes * visual, boolean isPixmap) -{ - if (isPixmap) { - return GL_FALSE; /* not implemented */ - } - else { - enum pipe_format colorFormat, depthFormat, stencilFormat; - struct intel_framebuffer *intelfb = CALLOC_STRUCT(intel_framebuffer); - - if (!intelfb) - return GL_FALSE; - - if (visual->redBits == 5) - colorFormat = PIPE_FORMAT_R5G6B5_UNORM; - else - colorFormat = PIPE_FORMAT_A8R8G8B8_UNORM; - - if (visual->depthBits == 16) - depthFormat = PIPE_FORMAT_Z16_UNORM; - else if (visual->depthBits == 24) - depthFormat = PIPE_FORMAT_S8Z24_UNORM; - else - depthFormat = PIPE_FORMAT_NONE; - - if (visual->stencilBits == 8) - stencilFormat = PIPE_FORMAT_S8Z24_UNORM; - else - stencilFormat = PIPE_FORMAT_NONE; - - intelfb->stfb = st_create_framebuffer(visual, - colorFormat, - depthFormat, - stencilFormat, - driDrawPriv->w, - driDrawPriv->h, - (void*) intelfb); - if (!intelfb->stfb) { - free(intelfb); - return GL_FALSE; - } - - driDrawPriv->driverPrivate = (void *) intelfb; - return GL_TRUE; - } -} - -static void -intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv) -{ - struct intel_framebuffer *intelfb = intel_framebuffer(driDrawPriv); - assert(intelfb->stfb); - st_unreference_framebuffer(&intelfb->stfb); - free(intelfb); -} - - -/** - * Get information about previous buffer swaps. - */ -static int -intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo) -{ - if ((dPriv == NULL) || (dPriv->driverPrivate == NULL) - || (sInfo == NULL)) { - return -1; - } - - return 0; -} - - -static void -intelSetTexOffset(__DRIcontext *pDRICtx, int texname, - unsigned long long offset, int depth, uint pitch) -{ - abort(); -#if 0 - struct intel_context *intel = (struct intel_context*) - ((__DRIcontextPrivate*)pDRICtx->private)->driverPrivate; - struct gl_texture_object *tObj = _mesa_lookup_texture(&intel->ctx, texname); - struct st_texture_object *stObj = st_texture_object(tObj); - - if (!stObj) - return; - - if (stObj->pt) - st->pipe->texture_release(intel->st->pipe, &stObj->pt); - - stObj->imageOverride = GL_TRUE; - stObj->depthOverride = depth; - stObj->pitchOverride = pitch; - - if (offset) - stObj->textureOffset = offset; -#endif -} - - -static const struct __DriverAPIRec intelAPI = { - .InitDriver = intelInitDriver, - .DestroyScreen = intelDestroyScreen, - .CreateContext = intelCreateContext, - .DestroyContext = intelDestroyContext, - .CreateBuffer = intelCreateBuffer, - .DestroyBuffer = intelDestroyBuffer, - .SwapBuffers = intelSwapBuffers, - .MakeCurrent = intelMakeCurrent, - .UnbindContext = intelUnbindContext, - .GetSwapInfo = intelGetSwapInfo, - .GetMSC = driGetMSC32, - .WaitForMSC = driWaitForMSC32, - .WaitForSBC = NULL, - .SwapBuffersMSC = NULL, - .CopySubBuffer = intelCopySubBuffer, - .setTexOffset = intelSetTexOffset, -}; - - -static __GLcontextModes * -intelFillInModes(unsigned pixel_bits, unsigned depth_bits, - unsigned stencil_bits, boolean have_back_buffer) -{ - __GLcontextModes *modes; - __GLcontextModes *m; - unsigned num_modes; - unsigned depth_buffer_factor; - unsigned back_buffer_factor; - GLenum fb_format; - GLenum fb_type; - - /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't - * support pageflipping at all. - */ - static const GLenum back_buffer_modes[] = { - GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML - }; - - u_int8_t depth_bits_array[3]; - u_int8_t stencil_bits_array[3]; - - - depth_bits_array[0] = 0; - depth_bits_array[1] = depth_bits; - depth_bits_array[2] = depth_bits; - - /* Just like with the accumulation buffer, always provide some modes - * with a stencil buffer. It will be a sw fallback, but some apps won't - * care about that. - */ - stencil_bits_array[0] = 0; - stencil_bits_array[1] = 0; - if (depth_bits == 24) - stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits; - - stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits; - - depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1; - back_buffer_factor = (have_back_buffer) ? 3 : 1; - - num_modes = depth_buffer_factor * back_buffer_factor * 4; - - if (pixel_bits == 16) { - fb_format = GL_RGB; - fb_type = GL_UNSIGNED_SHORT_5_6_5; - } - else { - fb_format = GL_BGRA; - fb_type = GL_UNSIGNED_INT_8_8_8_8_REV; - } - - modes = - (*dri_interface->createContextModes) (num_modes, - sizeof(__GLcontextModes)); - m = modes; - if (!driFillInModes(&m, fb_format, fb_type, - depth_bits_array, stencil_bits_array, - depth_buffer_factor, back_buffer_modes, - back_buffer_factor, GLX_TRUE_COLOR)) { - fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, - __LINE__); - return NULL; - } - if (!driFillInModes(&m, fb_format, fb_type, - depth_bits_array, stencil_bits_array, - depth_buffer_factor, back_buffer_modes, - back_buffer_factor, GLX_DIRECT_COLOR)) { - fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, - __LINE__); - return NULL; - } - - /* Mark the visual as slow if there are "fake" stencil bits. - */ - for (m = modes; m != NULL; m = m->next) { - if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) { - m->visualRating = GLX_SLOW_CONFIG; - } - } - - return modes; -} - - -/** - * This is the bootstrap function for the driver. libGL supplies all of the - * requisite information about the system, and the driver initializes itself. - * This routine also fills in the linked list pointed to by \c driver_modes - * with the \c __GLcontextModes that the driver can support for windows or - * pbuffers. - * - * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on - * failure. - */ -PUBLIC void * -__driCreateNewScreen_20050727(__DRInativeDisplay * dpy, int scrn, - __DRIscreen * psc, - const __GLcontextModes * modes, - const __DRIversion * ddx_version, - const __DRIversion * dri_version, - const __DRIversion * drm_version, - const __DRIframebuffer * frame_buffer, - drmAddress pSAREA, int fd, - int internal_api_version, - const __DRIinterfaceMethods * interface, - __GLcontextModes ** driver_modes) -{ - __DRIscreenPrivate *psp; - static const __DRIversion ddx_expected = { 1, 7, 0 }; - static const __DRIversion dri_expected = { 4, 0, 0 }; - static const __DRIversion drm_expected = { 1, 7, 0 }; - - dri_interface = interface; - - if (!driCheckDriDdxDrmVersions2("i915", - dri_version, &dri_expected, - ddx_version, &ddx_expected, - drm_version, &drm_expected)) { - return NULL; - } - - psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL, - ddx_version, dri_version, drm_version, - frame_buffer, pSAREA, fd, - internal_api_version, &intelAPI); - - if (psp != NULL) { - I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv; - *driver_modes = intelFillInModes(dri_priv->cpp * 8, - (dri_priv->cpp == 2) ? 16 : 24, - (dri_priv->cpp == 2) ? 0 : 8, 1); - - /* Calling driInitExtensions here, with a NULL context pointer, - * does not actually enable the extensions. It just makes sure - * that all the dispatch offsets for all the extensions that - * *might* be enables are known. This is needed because the - * dispatch offsets need to be known when _mesa_context_create - * is called, but we can't enable the extensions until we have a - * context pointer. - * - * Hello chicken. Hello egg. How are you two today? - */ - driInitExtensions(NULL, card_extensions, GL_FALSE); - } - - return (void *) psp; -} -#endif diff --git a/src/gallium/winsys/egl_drm/intel/intel_screen.h b/src/gallium/winsys/egl_drm/intel/intel_screen.h index e8c1cdfca4..87c4406f54 100644 --- a/src/gallium/winsys/egl_drm/intel/intel_screen.h +++ b/src/gallium/winsys/egl_drm/intel/intel_screen.h @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * 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 @@ -10,11 +10,11 @@ * 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. @@ -22,112 +22,26 @@ * 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 _INTEL_SCREEN_H_ #define _INTEL_SCREEN_H_ -#include "ws_dri_bufpool.h" +#include "intel_drm/intel_be_device.h" #include "pipe/p_compiler.h" -struct egl_drm_device *device; +struct pipe_screen; +struct egl_drm_device; struct intel_screen { -#if 0 - struct { - drm_handle_t handle; + struct intel_be_device base; + struct pipe_screen *pipe; - /* We create a static dri buffer for the frontbuffer. - */ - struct _DriBufferObject *buffer; - - char *map; /* memory map */ - int offset; /* from start of video mem, in bytes */ - int pitch; /* row stride, in bytes */ - int width; - int height; - int size; - int cpp; /* for front and back buffers */ - } front; -#endif - - int drmFB; - -#if 0 - int deviceID; - int drmMinor; - - - drmI830Sarea *sarea;*/ - - - /** - * Configuration cache with default values for all contexts - */ - driOptionCache optionCache; -#endif - - struct _DriBufferPool *batchPool; - struct _DriBufferPool *staticPool; /** for the X screen/framebuffer */ - boolean havePools; - -#if 0 - /** - * Temporary(?) context to use for SwapBuffers or other situations in - * which we need a rendering context, but none is currently bound. - */ - struct intel_context *dummyContext; -#endif - - /* - * New stuff form the i915tex integration - */ - struct _DriFenceMgr *mgr; - struct _DriFreeSlabManager *fMan; - unsigned batch_id; - - struct pipe_winsys *winsys; - struct egl_drm_device *device; - - /* batch buffer used for swap buffers */ - struct intel_batchbuffer *batch; + int deviceID; + struct egl_drm_device *device; }; - - -/** cast wrapper */ -#if 0 -static INLINE struct intel_screen * -intel_screen(__DRIscreenPrivate *sPriv) -{ - return (struct intel_screen *) sPriv->private; -} - - -extern void -intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea); - - -extern void intelDestroyContext(__DRIcontextPrivate * driContextPriv); - -extern boolean intelUnbindContext(__DRIcontextPrivate * driContextPriv); - -extern boolean -intelMakeCurrent(__DRIcontextPrivate * driContextPriv, - __DRIdrawablePrivate * driDrawPriv, - __DRIdrawablePrivate * driReadPriv); - - -extern boolean -intelCreatePools(__DRIscreenPrivate *sPriv); - -extern boolean -intelCreateContext(const __GLcontextModes * visual, - __DRIcontextPrivate * driContextPriv, - void *sharedContextPrivate); - -#endif #endif diff --git a/src/gallium/winsys/egl_drm/intel/intel_swapbuffers.c b/src/gallium/winsys/egl_drm/intel/intel_swapbuffers.c index 1ce4b2754a..24e55f1568 100644 --- a/src/gallium/winsys/egl_drm/intel/intel_swapbuffers.c +++ b/src/gallium/winsys/egl_drm/intel/intel_swapbuffers.c @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * 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 @@ -10,11 +10,11 @@ * 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. @@ -22,15 +22,13 @@ * 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 "intel_screen.h" #include "intel_context.h" -#include "intel_swapbuffers.h" #include "intel_batchbuffer.h" #include "intel_reg.h" -#include "intel_winsys.h" #include "pipe/p_context.h" #include "state_tracker/st_public.h" @@ -54,7 +52,8 @@ void intel_swap_buffers(struct egl_drm_drawable *draw) back_surf = st_get_framebuffer_surface(intel_fb->stfb, ST_SURFACE_BACK_LEFT); if (back_surf) { st_notify_swapbuffers(intel_fb->stfb); - intel_display_surface(draw, back_surf); + if (intel_fb->front) + intel_display_surface(draw, back_surf); st_notify_swapbuffers_complete(intel_fb->stfb); } } @@ -63,7 +62,7 @@ static void intel_display_surface(struct egl_drm_drawable *draw, struct pipe_surface *surf) { - struct intel_screen *intel = (struct intel_screen *)draw->device->priv; + struct intel_context *intel = NULL; struct intel_framebuffer *intel_fb = (struct intel_framebuffer *)draw->priv; struct _DriFenceObject *fence; @@ -85,8 +84,7 @@ intel_display_surface(struct egl_drm_drawable *draw, CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB); - printf("srcPitch: %u, dstWidth: %u, dstHeight: %u, dstPitch: %u, cpp: %u\n", srcPitch, dstWidth, dstHeight, dstPitch, cpp); - BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); + BEGIN_BATCH(8, 2); OUT_BATCH(CMD); OUT_BATCH(BR13); OUT_BATCH((0 << 16) | 0); @@ -102,226 +100,7 @@ intel_display_surface(struct egl_drm_drawable *draw, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0); - ADVANCE_BATCH(); - - fence = intel_batchbuffer_flush(intel->batch); + fence = intel_be_batchbuffer_flush(intel->base.batch); driFenceUnReference(&fence); - intel_batchbuffer_finish(intel->batch); -} - -#if 0 -/** - * Display a colorbuffer surface in an X window. - * Used for SwapBuffers and flushing front buffer rendering. - * - * \param dPriv the window/drawable to display into - * \param surf the surface to display - * \param rect optional subrect of surface to display (may be NULL). - */ -void -intelDisplaySurface(__DRIdrawablePrivate *dPriv, - struct pipe_surface *surf, - const drm_clip_rect_t *rect) -{ - struct intel_screen *intelScreen = intel_screen(dPriv->driScreenPriv); - //struct intel_context *intel = intelScreen->dummyContext; - - DBG(SWAP, "%s\n", __FUNCTION__); - -#if 0 - if (!intel) { - /* XXX this is where some kind of extra/meta context could be useful */ - return; - } -#endif - - if (intel->last_swap_fence) { - driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, TRUE); - driFenceUnReference(&intel->last_swap_fence); - intel->last_swap_fence = NULL; - } - intel->last_swap_fence = intel->first_swap_fence; - intel->first_swap_fence = NULL; - - /* The LOCK_HARDWARE is required for the cliprects. Buffer offsets - * should work regardless. - */ - LOCK_HARDWARE(intel); - /* if this drawable isn't currently bound the LOCK_HARDWARE done on the - * current context (which is what intelScreenContext should return) might - * not get a contended lock and thus cliprects not updated (tests/manywin) - */ - if (intel_context(dPriv->driContextPriv) != intel) - DRI_VALIDATE_DRAWABLE_INFO(intel->driScreen, dPriv); - - - if (dPriv && dPriv->numClipRects) { - const int srcWidth = surf->width; - const int srcHeight = surf->height; - const int nbox = dPriv->numClipRects; - const drm_clip_rect_t *pbox = dPriv->pClipRects; - const int pitch = intelScreen->front.pitch / intelScreen->front.cpp; - const int cpp = intelScreen->front.cpp; - const int srcpitch = surf->pitch; - int BR13, CMD; - int i; - - ASSERT(surf->buffer); - ASSERT(surf->cpp == cpp); - - DBG(SWAP, "screen pitch %d src surface pitch %d\n", - pitch, surf->pitch); - - if (cpp == 2) { - BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24); - CMD = XY_SRC_COPY_BLT_CMD; - } - else { - BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25); - CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); - } - - for (i = 0; i < nbox; i++, pbox++) { - drm_clip_rect_t box; - drm_clip_rect_t sbox; - - if (pbox->x1 > pbox->x2 || - pbox->y1 > pbox->y2 || - pbox->x2 > intelScreen->front.width || - pbox->y2 > intelScreen->front.height) { - /* invalid cliprect, skip it */ - continue; - } - - box = *pbox; - - if (rect) { - /* intersect cliprect with user-provided src rect */ - drm_clip_rect_t rrect; - - rrect.x1 = dPriv->x + rect->x1; - rrect.y1 = (dPriv->h - rect->y1 - rect->y2) + dPriv->y; - rrect.x2 = rect->x2 + rrect.x1; - rrect.y2 = rect->y2 + rrect.y1; - if (rrect.x1 > box.x1) - box.x1 = rrect.x1; - if (rrect.y1 > box.y1) - box.y1 = rrect.y1; - if (rrect.x2 < box.x2) - box.x2 = rrect.x2; - if (rrect.y2 < box.y2) - box.y2 = rrect.y2; - - if (box.x1 > box.x2 || box.y1 > box.y2) - continue; - } - - /* restrict blit to size of actually rendered area */ - if (box.x2 - box.x1 > srcWidth) - box.x2 = srcWidth + box.x1; - if (box.y2 - box.y1 > srcHeight) - box.y2 = srcHeight + box.y1; - - DBG(SWAP, "box x1 x2 y1 y2 %d %d %d %d\n", - box.x1, box.x2, box.y1, box.y2); - - sbox.x1 = box.x1 - dPriv->x; - sbox.y1 = box.y1 - dPriv->y; - - assert(box.x1 < box.x2); - assert(box.y1 < box.y2); - - /* XXX this could be done with pipe->surface_copy() */ - BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); - OUT_BATCH(CMD); - OUT_BATCH(BR13); - OUT_BATCH((box.y1 << 16) | box.x1); - OUT_BATCH((box.y2 << 16) | box.x2); - - OUT_RELOC(intelScreen->front.buffer, - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, - DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0); - OUT_BATCH((sbox.y1 << 16) | sbox.x1); - OUT_BATCH((srcpitch * cpp) & 0xffff); - OUT_RELOC(dri_bo(surf->buffer), - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, - DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0); - - ADVANCE_BATCH(); - } - - if (intel->first_swap_fence) - driFenceUnReference(&intel->first_swap_fence); - intel->first_swap_fence = intel_batchbuffer_flush(intel->batch); - } - - UNLOCK_HARDWARE(intel); - - if (intel->lastStamp != dPriv->lastStamp) { - intelUpdateWindowSize(dPriv); - intel->lastStamp = dPriv->lastStamp; - } -} - - - -/** - * This will be called whenever the currently bound window is moved/resized. - */ -void -intelUpdateWindowSize(__DRIdrawablePrivate *dPriv) -{ - struct intel_framebuffer *intelfb = intel_framebuffer(dPriv); - assert(intelfb->stfb); - st_resize_framebuffer(intelfb->stfb, dPriv->w, dPriv->h); -} - - - -void -intelSwapBuffers(__DRIdrawablePrivate * dPriv) -{ - struct intel_framebuffer *intel_fb = intel_framebuffer(dPriv); - struct pipe_surface *back_surf; - - assert(intel_fb); - assert(intel_fb->stfb); - - back_surf = st_get_framebuffer_surface(intel_fb->stfb, - ST_SURFACE_BACK_LEFT); - if (back_surf) { - st_notify_swapbuffers(intel_fb->stfb); - intelDisplaySurface(dPriv, back_surf, NULL); - st_notify_swapbuffers_complete(intel_fb->stfb); - } -} - - -/** - * Called via glXCopySubBufferMESA() to copy a subrect of the back - * buffer to the front buffer/screen. - */ -void -intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h) -{ - struct intel_framebuffer *intel_fb = intel_framebuffer(dPriv); - struct pipe_surface *back_surf; - - assert(intel_fb); - assert(intel_fb->stfb); - - back_surf = st_get_framebuffer_surface(intel_fb->stfb, - ST_SURFACE_BACK_LEFT); - if (back_surf) { - drm_clip_rect_t rect; - rect.x1 = x; - rect.y1 = y; - rect.x2 = w; - rect.y2 = h; - - st_notify_swapbuffers(intel_fb->stfb); - intelDisplaySurface(dPriv, back_surf, &rect); - } + intel_be_batchbuffer_finish(intel->base.batch); } -#endif diff --git a/src/gallium/winsys/egl_drm/intel/intel_winsys_i915.c b/src/gallium/winsys/egl_drm/intel/intel_winsys_i915.c deleted file mode 100644 index 8ec5c7e82a..0000000000 --- a/src/gallium/winsys/egl_drm/intel/intel_winsys_i915.c +++ /dev/null @@ -1,184 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA - * 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, 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 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 - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS 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. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ -/* - * Authors: Keith Whitwell <keithw-at-tungstengraphics-dot-com> - */ - -#include <stdlib.h> -#include <xf86drm.h> -#include "ws_dri_bufpool.h" -#include "ws_dri_bufmgr.h" - -#include "intel_context.h" -#include "intel_batchbuffer.h" -#include "intel_winsys.h" - -#include "pipe/p_util.h" -#include "pipe/p_winsys.h" -#include "i915simple/i915_winsys.h" -#include "i915simple/i915_screen.h" - - -struct intel_i915_winsys { - struct i915_winsys winsys; /**< batch buffer funcs */ - struct pipe_winsys *pws; - struct intel_context *intel; -}; - - -/* Turn a i915simple winsys into an intel/i915simple winsys: - */ -static inline struct intel_i915_winsys * -intel_i915_winsys( struct i915_winsys *sws ) -{ - return (struct intel_i915_winsys *)sws; -} - - -/* Simple batchbuffer interface: - */ - -static unsigned *intel_i915_batch_start( struct i915_winsys *sws, - unsigned dwords, - unsigned relocs ) -{ - struct intel_context *intel = intel_i915_winsys(sws)->intel; - - /* XXX: check relocs. - */ - if (intel_batchbuffer_space( intel->batch ) >= dwords * 4) { - /* XXX: Hmm, the driver can't really do much with this pointer: - */ - return (unsigned *)intel->batch->ptr; - } - else - return NULL; -} - -static void intel_i915_batch_dword( struct i915_winsys *sws, - unsigned dword ) -{ - struct intel_context *intel = intel_i915_winsys(sws)->intel; - intel_batchbuffer_emit_dword( intel->batch, dword ); -} - -static void intel_i915_batch_reloc( struct i915_winsys *sws, - struct pipe_buffer *buf, - unsigned access_flags, - unsigned delta ) -{ - struct intel_context *intel = intel_i915_winsys(sws)->intel; - unsigned flags = DRM_BO_FLAG_MEM_TT; - unsigned mask = DRM_BO_MASK_MEM; - - if (access_flags & I915_BUFFER_ACCESS_WRITE) { - flags |= DRM_BO_FLAG_WRITE; - mask |= DRM_BO_FLAG_WRITE; - } - - if (access_flags & I915_BUFFER_ACCESS_READ) { - flags |= DRM_BO_FLAG_READ; - mask |= DRM_BO_FLAG_READ; - } - -#if 0 /* JB old */ - intel_batchbuffer_emit_reloc( intel->batch, - dri_bo( buf ), - flags, mask, - delta ); -#else /* new */ - intel_offset_relocation( intel->batch, - delta, - dri_bo( buf ), - flags, - mask ); -#endif -} - - - -static void intel_i915_batch_flush( struct i915_winsys *sws, - struct pipe_fence_handle **fence ) -{ - struct intel_i915_winsys *iws = intel_i915_winsys(sws); - struct intel_context *intel = iws->intel; - union { - struct _DriFenceObject *dri; - struct pipe_fence_handle *pipe; - } fu; - - if (fence) - assert(!*fence); - - fu.dri = intel_batchbuffer_flush( intel->batch ); - - if (!fu.dri) { - assert(0); - *fence = NULL; - return; - } - - if (fu.dri) { - if (fence) - *fence = fu.pipe; - else - driFenceUnReference(&fu.dri); - } - -} - - -/** - * Create i915 hardware rendering context. - */ -struct pipe_context * -intel_create_i915simple( struct intel_context *intel, - struct pipe_winsys *winsys ) -{ - struct intel_i915_winsys *iws = CALLOC_STRUCT( intel_i915_winsys ); - struct pipe_screen *screen; - - /* Fill in this struct with callbacks that i915simple will need to - * communicate with the window system, buffer manager, etc. - */ - iws->winsys.batch_start = intel_i915_batch_start; - iws->winsys.batch_dword = intel_i915_batch_dword; - iws->winsys.batch_reloc = intel_i915_batch_reloc; - iws->winsys.batch_flush = intel_i915_batch_flush; - iws->pws = winsys; - iws->intel = intel; - - screen = i915_create_screen(winsys, PCI_CHIP_I945_GM); - assert(screen); - - /* Create the i915simple context: - */ - return i915_create_context( screen, - winsys, - &iws->winsys ); -} diff --git a/src/gallium/winsys/egl_drm/intel/intel_winsys_pipe.c b/src/gallium/winsys/egl_drm/intel/intel_winsys_pipe.c deleted file mode 100644 index 8bf8c21439..0000000000 --- a/src/gallium/winsys/egl_drm/intel/intel_winsys_pipe.c +++ /dev/null @@ -1,338 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA - * 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, 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 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 - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS 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. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ -/* - * Authors: Keith Whitwell <keithw-at-tungstengraphics-dot-com> - */ - -#include <stdlib.h> -#include <xf86drm.h> -//#include "dri_bufpool.h" -//#include "dri_bufmgr.h" - -#include "intel_context.h" -#include "intel_winsys.h" -#include "intel_swapbuffers.h" -#include "intel_batchbuffer.h" - -#include "pipe/p_winsys.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "pipe/p_util.h" -#include "pipe/p_inlines.h" - - - -struct intel_pipe_winsys { - struct pipe_winsys winsys; - struct _DriBufferPool *regionPool; - struct _DriFreeSlabManager *fMan; -}; - - - -/* Turn a pipe winsys into an intel/pipe winsys: - */ -static inline struct intel_pipe_winsys * -intel_pipe_winsys( struct pipe_winsys *winsys ) -{ - return (struct intel_pipe_winsys *)winsys; -} - - -/* Most callbacks map direcly onto dri_bufmgr operations: - */ -static void *intel_buffer_map(struct pipe_winsys *winsys, - struct pipe_buffer *buf, - unsigned flags ) -{ - unsigned drm_flags = 0; - - if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) - drm_flags |= DRM_BO_FLAG_WRITE; - - if (flags & PIPE_BUFFER_USAGE_CPU_READ) - drm_flags |= DRM_BO_FLAG_READ; - - return driBOMap( dri_bo(buf), drm_flags, 0 ); -} - -static void intel_buffer_unmap(struct pipe_winsys *winsys, - struct pipe_buffer *buf) -{ - driBOUnmap( dri_bo(buf) ); -} - - -static void -intel_buffer_destroy(struct pipe_winsys *winsys, - struct pipe_buffer *buf) -{ - driBOUnReference( dri_bo(buf) ); - FREE(buf); -} - - -/* Pipe has no concept of pools. We choose the tex/region pool - * for all buffers. - * Grabs the hardware lock! - */ -static struct pipe_buffer * -intel_buffer_create(struct pipe_winsys *winsys, - unsigned alignment, - unsigned usage, - unsigned size ) -{ - struct intel_buffer *buffer = CALLOC_STRUCT( intel_buffer ); - struct intel_pipe_winsys *iws = intel_pipe_winsys(winsys); - unsigned flags = 0; - - buffer->base.refcount = 1; - buffer->base.alignment = alignment; - buffer->base.usage = usage; - buffer->base.size = size; - - if (usage & (PIPE_BUFFER_USAGE_VERTEX /*| IWS_BUFFER_USAGE_LOCAL*/)) { - flags |= DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED; - } else { - flags |= DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MEM_TT; - } - - if (usage & PIPE_BUFFER_USAGE_GPU_READ) - flags |= DRM_BO_FLAG_READ; - - if (usage & PIPE_BUFFER_USAGE_GPU_WRITE) - flags |= DRM_BO_FLAG_WRITE; - - /* drm complains if we don't set any read/write flags. - */ - if ((flags & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE)) == 0) - flags |= DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE; - -#if 0 - if (flags & IWS_BUFFER_USAGE_EXE) - flags |= DRM_BO_FLAG_EXE; - - if (usage & IWS_BUFFER_USAGE_CACHED) - flags |= DRM_BO_FLAG_CACHED; -#endif - - driGenBuffers( iws->regionPool, - "pipe buffer", 1, &buffer->driBO, alignment, flags, 0 ); - - driBOData( buffer->driBO, size, NULL, iws->regionPool, 0 ); - - return &buffer->base; -} - - -static struct pipe_buffer * -intel_user_buffer_create(struct pipe_winsys *winsys, void *ptr, unsigned bytes) -{ - struct intel_buffer *buffer = CALLOC_STRUCT( intel_buffer ); - struct intel_pipe_winsys *iws = intel_pipe_winsys(winsys); - - driGenUserBuffer( iws->regionPool, - "pipe user buffer", &buffer->driBO, ptr, bytes ); - - buffer->base.refcount = 1; - - return &buffer->base; -} - - -/* The state tracker (should!) keep track of whether the fake - * frontbuffer has been touched by any rendering since the last time - * we copied its contents to the real frontbuffer. Our task is easy: - */ -static void -intel_flush_frontbuffer( struct pipe_winsys *winsys, - struct pipe_surface *surf, - void *context_private) -{ -#if 0 - struct intel_context *intel = (struct intel_context *) context_private; - __DRIdrawablePrivate *dPriv = intel->driDrawable; - - intelDisplaySurface(dPriv, surf, NULL); -#endif -} - - -static struct pipe_surface * -intel_i915_surface_alloc(struct pipe_winsys *winsys) -{ - struct pipe_surface *surf = CALLOC_STRUCT(pipe_surface); - if (surf) { - surf->refcount = 1; - surf->winsys = winsys; - } - return surf; -} - - -/** - * Round n up to next multiple. - */ -static INLINE unsigned -round_up(unsigned n, unsigned multiple) -{ - return (n + multiple - 1) & ~(multiple - 1); -} - -/** - * Copied from xm_winsys.c - */ -static int -intel_i915_surface_alloc_storage(struct pipe_winsys *winsys, - struct pipe_surface *surf, - unsigned width, unsigned height, - enum pipe_format format, - unsigned flags) -{ - const unsigned alignment = 64; - //int ret; - - surf->width = width; - surf->height = height; - surf->format = format; - surf->cpp = pf_get_size(format); - surf->pitch = round_up(width, alignment / surf->cpp); - - assert(!surf->buffer); - surf->buffer = winsys->buffer_create(winsys, alignment, - PIPE_BUFFER_USAGE_PIXEL, - surf->pitch * surf->cpp * height); - if(!surf->buffer) - return -1; - - return 0; -} - - -static void -intel_i915_surface_release(struct pipe_winsys *winsys, struct pipe_surface **s) -{ - struct pipe_surface *surf = *s; - surf->refcount--; - if (surf->refcount == 0) { - if (surf->buffer) - pipe_buffer_reference(winsys, &surf->buffer, NULL); - free(surf); - } - *s = NULL; -} - - - -static const char * -intel_get_name( struct pipe_winsys *winsys ) -{ - return "Intel/EGL/ttm"; -} - -static void -intel_fence_reference( struct pipe_winsys *sws, - struct pipe_fence_handle **ptr, - struct pipe_fence_handle *fence ) -{ - if (*ptr) - driFenceUnReference((struct _DriFenceObject **)ptr); - - if (fence) - *ptr = (struct pipe_fence_handle *)driFenceReference((struct _DriFenceObject *)fence); -} - -static int -intel_fence_signalled( struct pipe_winsys *sws, - struct pipe_fence_handle *fence, - unsigned flag ) -{ - return driFenceSignaled((struct _DriFenceObject *)fence, flag); -} - -static int -intel_fence_finish( struct pipe_winsys *sws, - struct pipe_fence_handle *fence, - unsigned flag ) -{ - /* JB: Lets allways lazy wait */ - return driFenceFinish((struct _DriFenceObject *)fence, flag, 1); -} - -struct pipe_winsys * -intel_create_pipe_winsys( int fd, struct _DriFreeSlabManager *fMan ) -{ - struct intel_pipe_winsys *iws = CALLOC_STRUCT( intel_pipe_winsys ); - - /* Fill in this struct with callbacks that pipe will need to - * communicate with the window system, buffer manager, etc. - * - * Pipe would be happy with a malloc based memory manager, but - * the SwapBuffers implementation in this winsys driver requires - * that rendering be done to an appropriate _DriBufferObject. - */ - iws->winsys.buffer_create = intel_buffer_create; - iws->winsys.user_buffer_create = intel_user_buffer_create; - iws->winsys.buffer_map = intel_buffer_map; - iws->winsys.buffer_unmap = intel_buffer_unmap; - iws->winsys.buffer_destroy = intel_buffer_destroy; - iws->winsys.flush_frontbuffer = intel_flush_frontbuffer; - iws->winsys.get_name = intel_get_name; - iws->winsys.surface_alloc = intel_i915_surface_alloc; - iws->winsys.surface_alloc_storage = intel_i915_surface_alloc_storage; - iws->winsys.surface_release = intel_i915_surface_release; - - iws->winsys.fence_reference = intel_fence_reference; - iws->winsys.fence_signalled = intel_fence_signalled; - iws->winsys.fence_finish = intel_fence_finish; - - if (fd) - iws->regionPool = driSlabPoolInit(fd, - DRM_BO_FLAG_READ | - DRM_BO_FLAG_WRITE | - DRM_BO_FLAG_MEM_TT, - DRM_BO_FLAG_READ | - DRM_BO_FLAG_WRITE | - DRM_BO_FLAG_MEM_TT, - 64, 6, 16, 4096, 0, - fMan); - - return &iws->winsys; -} - - -void -intel_destroy_pipe_winsys( struct pipe_winsys *winsys ) -{ - struct intel_pipe_winsys *iws = intel_pipe_winsys(winsys); - if (iws->regionPool) { - driPoolTakeDown(iws->regionPool); - } - free(iws); -} - diff --git a/src/gallium/winsys/egl_drm/intel/intel_winsys_softpipe.c b/src/gallium/winsys/egl_drm/intel/intel_winsys_softpipe.c deleted file mode 100644 index 0bc2dc4002..0000000000 --- a/src/gallium/winsys/egl_drm/intel/intel_winsys_softpipe.c +++ /dev/null @@ -1,82 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA - * 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, 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 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 - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS 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. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ -/* - * Authors: Keith Whitwell <keithw-at-tungstengraphics-dot-com> - */ - -#include "intel_context.h" -#include "intel_winsys.h" -#include "pipe/p_defines.h" -#include "pipe/p_util.h" -#include "pipe/p_format.h" -#include "softpipe/sp_winsys.h" - - -struct intel_softpipe_winsys { - struct softpipe_winsys sws; - struct intel_context *intel; -}; - -/** - * Return list of surface formats supported by this driver. - */ -static boolean -intel_is_format_supported(struct softpipe_winsys *sws, - enum pipe_format format) -{ - switch(format) { - case PIPE_FORMAT_A8R8G8B8_UNORM: - case PIPE_FORMAT_R5G6B5_UNORM: - case PIPE_FORMAT_S8Z24_UNORM: - return TRUE; - default: - return FALSE; - } -} - - -/** - * Create rendering context which uses software rendering. - */ -struct pipe_context * -intel_create_softpipe( struct intel_context *intel, - struct pipe_winsys *winsys ) -{ - struct intel_softpipe_winsys *isws = CALLOC_STRUCT( intel_softpipe_winsys ); - struct pipe_screen *screen = softpipe_create_screen(winsys); - - /* Fill in this struct with callbacks that softpipe will need to - * communicate with the window system, buffer manager, etc. - */ - isws->sws.is_format_supported = intel_is_format_supported; - isws->intel = intel; - - /* Create the softpipe context: - */ - return softpipe_create( screen, winsys, &isws->sws ); -} diff --git a/src/gallium/winsys/egl_drm/intel/ws_dri_bufmgr.h b/src/gallium/winsys/egl_drm/intel/ws_dri_bufmgr.h deleted file mode 100644 index fdaf5ee93a..0000000000 --- a/src/gallium/winsys/egl_drm/intel/ws_dri_bufmgr.h +++ /dev/null @@ -1,138 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA - * 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, 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 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 - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS 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. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ -/* - * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> - * Keith Whitwell <keithw-at-tungstengraphics-dot-com> - */ - -#ifndef _PSB_BUFMGR_H_ -#define _PSB_BUFMGR_H_ -#include <xf86mm.h> -#include "i915_drm.h" -#include "ws_dri_fencemgr.h" - -typedef struct _drmBONode -{ - drmMMListHead head; - drmBO *buf; - struct drm_i915_op_arg bo_arg; - uint64_t arg0; - uint64_t arg1; -} drmBONode; - -typedef struct _drmBOList { - unsigned numTarget; - unsigned numCurrent; - unsigned numOnList; - drmMMListHead list; - drmMMListHead free; -} drmBOList; - - -struct _DriFenceObject; -struct _DriBufferObject; -struct _DriBufferPool; -struct _DriBufferList; - -/* - * Return a pointer to the libdrm buffer object this DriBufferObject - * uses. - */ - -extern drmBO *driBOKernel(struct _DriBufferObject *buf); -extern void *driBOMap(struct _DriBufferObject *buf, unsigned flags, - unsigned hint); -extern void driBOUnmap(struct _DriBufferObject *buf); -extern unsigned long driBOOffset(struct _DriBufferObject *buf); -extern unsigned long driBOPoolOffset(struct _DriBufferObject *buf); - -extern uint64_t driBOFlags(struct _DriBufferObject *buf); -extern struct _DriBufferObject *driBOReference(struct _DriBufferObject *buf); -extern void driBOUnReference(struct _DriBufferObject *buf); - -extern int driBOData(struct _DriBufferObject *r_buf, - unsigned size, const void *data, - struct _DriBufferPool *pool, uint64_t flags); - -extern void driBOSubData(struct _DriBufferObject *buf, - unsigned long offset, unsigned long size, - const void *data); -extern void driBOGetSubData(struct _DriBufferObject *buf, - unsigned long offset, unsigned long size, - void *data); -extern int driGenBuffers(struct _DriBufferPool *pool, - const char *name, - unsigned n, - struct _DriBufferObject *buffers[], - unsigned alignment, uint64_t flags, unsigned hint); -extern void driGenUserBuffer(struct _DriBufferPool *pool, - const char *name, - struct _DriBufferObject *buffers[], - void *ptr, unsigned bytes); -extern void driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[]); -extern void driInitBufMgr(int fd); -extern struct _DriBufferList *driBOCreateList(int target); -extern int driBOResetList(struct _DriBufferList * list); -extern void driBOAddListItem(struct _DriBufferList * list, - struct _DriBufferObject *buf, - uint64_t flags, uint64_t mask, int *itemLoc, - struct _drmBONode **node); - -extern void driBOValidateList(int fd, struct _DriBufferList * list); -extern void driBOFreeList(struct _DriBufferList * list); -extern struct _DriFenceObject *driBOFenceUserList(struct _DriFenceMgr *mgr, - struct _DriBufferList *list, - const char *name, - drmFence *kFence); -extern void driBOUnrefUserList(struct _DriBufferList *list); -extern void driBOValidateUserList(struct _DriBufferList * list); -extern drmBOList *driGetdrmBOList(struct _DriBufferList *list); -extern void driPutdrmBOList(struct _DriBufferList *list); - -extern void driBOFence(struct _DriBufferObject *buf, - struct _DriFenceObject *fence); - -extern void driPoolTakeDown(struct _DriBufferPool *pool); -extern void driBOSetReferenced(struct _DriBufferObject *buf, - unsigned long handle); -unsigned long driBOSize(struct _DriBufferObject *buf); -extern void driBOWaitIdle(struct _DriBufferObject *buf, int lazy); -extern void driPoolTakeDown(struct _DriBufferPool *pool); - -extern void driReadLockKernelBO(void); -extern void driReadUnlockKernelBO(void); -extern void driWriteLockKernelBO(void); -extern void driWriteUnlockKernelBO(void); - -/* - * For debugging purposes. - */ - -extern drmBOList *driBOGetDRMBuffers(struct _DriBufferList *list); -extern drmBOList *driBOGetDRIBuffers(struct _DriBufferList *list); -#endif diff --git a/src/gallium/winsys/egl_drm/intel/ws_dri_fencemgr.c b/src/gallium/winsys/egl_drm/intel/ws_dri_fencemgr.c deleted file mode 100644 index 1f893b47ce..0000000000 --- a/src/gallium/winsys/egl_drm/intel/ws_dri_fencemgr.c +++ /dev/null @@ -1,377 +0,0 @@ -#include "ws_dri_fencemgr.h" -#include "glthread.h" -#include <xf86mm.h> -#include <string.h> -#include <unistd.h> - -/* - * Note: Locking order is - * _DriFenceObject::mutex - * _DriFenceMgr::mutex - */ - -struct _DriFenceMgr { - /* - * Constant members. Need no mutex protection. - */ - struct _DriFenceMgrCreateInfo info; - void *private; - - /* - * These members are protected by this->mutex - */ - _glthread_Mutex mutex; - int refCount; - drmMMListHead *heads; - int num_fences; -}; - -struct _DriFenceObject { - - /* - * These members are constant and need no mutex protection. - */ - struct _DriFenceMgr *mgr; - uint32_t fence_class; - uint32_t fence_type; - - /* - * These members are protected by mgr->mutex. - */ - drmMMListHead head; - int refCount; - - /* - * These members are protected by this->mutex. - */ - _glthread_Mutex mutex; - uint32_t signaled_type; - void *private; -}; - -uint32_t -driFenceType(struct _DriFenceObject *fence) -{ - return fence->fence_type; -} - -struct _DriFenceMgr * -driFenceMgrCreate(const struct _DriFenceMgrCreateInfo *info) -{ - struct _DriFenceMgr *tmp; - uint32_t i; - - tmp = calloc(1, sizeof(*tmp)); - if (!tmp) - return NULL; - - _glthread_INIT_MUTEX(tmp->mutex); - _glthread_LOCK_MUTEX(tmp->mutex); - tmp->refCount = 1; - tmp->info = *info; - tmp->num_fences = 0; - tmp->heads = calloc(tmp->info.num_classes, sizeof(*tmp->heads)); - if (!tmp->heads) - goto out_err; - - for (i=0; i<tmp->info.num_classes; ++i) { - DRMINITLISTHEAD(&tmp->heads[i]); - } - _glthread_UNLOCK_MUTEX(tmp->mutex); - return tmp; - - out_err: - if (tmp) - free(tmp); - return NULL; -} - -static void -driFenceMgrUnrefUnlock(struct _DriFenceMgr **pMgr) -{ - struct _DriFenceMgr *mgr = *pMgr; - - *pMgr = NULL; - if (--mgr->refCount == 0) - free(mgr); - else - _glthread_UNLOCK_MUTEX(mgr->mutex); -} - -void -driFenceMgrUnReference(struct _DriFenceMgr **pMgr) -{ - _glthread_LOCK_MUTEX((*pMgr)->mutex); - driFenceMgrUnrefUnlock(pMgr); -} - -static void -driFenceUnReferenceLocked(struct _DriFenceObject **pFence) -{ - struct _DriFenceObject *fence = *pFence; - struct _DriFenceMgr *mgr = fence->mgr; - - *pFence = NULL; - if (--fence->refCount == 0) { - DRMLISTDELINIT(&fence->head); - if (fence->private) - mgr->info.unreference(mgr, &fence->private); - --mgr->num_fences; - fence->mgr = NULL; - --mgr->refCount; - free(fence); - - } -} - - -static void -driSignalPreviousFencesLocked(struct _DriFenceMgr *mgr, - drmMMListHead *list, - uint32_t fence_class, - uint32_t fence_type) -{ - struct _DriFenceObject *entry; - drmMMListHead *prev; - - while(list != &mgr->heads[fence_class]) { - entry = DRMLISTENTRY(struct _DriFenceObject, list, head); - - /* - * Up refcount so that entry doesn't disappear from under us - * when we unlock-relock mgr to get the correct locking order. - */ - - ++entry->refCount; - _glthread_UNLOCK_MUTEX(mgr->mutex); - _glthread_LOCK_MUTEX(entry->mutex); - _glthread_LOCK_MUTEX(mgr->mutex); - - prev = list->prev; - - - - if (list->prev == list) { - - /* - * Somebody else removed the entry from the list. - */ - - _glthread_UNLOCK_MUTEX(entry->mutex); - driFenceUnReferenceLocked(&entry); - return; - } - - entry->signaled_type |= (fence_type & entry->fence_type); - if (entry->signaled_type == entry->fence_type) { - DRMLISTDELINIT(list); - mgr->info.unreference(mgr, &entry->private); - } - _glthread_UNLOCK_MUTEX(entry->mutex); - driFenceUnReferenceLocked(&entry); - list = prev; - } -} - - -int -driFenceFinish(struct _DriFenceObject *fence, uint32_t fence_type, - int lazy_hint) -{ - struct _DriFenceMgr *mgr = fence->mgr; - int ret = 0; - - _glthread_LOCK_MUTEX(fence->mutex); - - if ((fence->signaled_type & fence_type) == fence_type) - goto out0; - - ret = mgr->info.finish(mgr, fence->private, fence_type, lazy_hint); - if (ret) - goto out0; - - _glthread_LOCK_MUTEX(mgr->mutex); - _glthread_UNLOCK_MUTEX(fence->mutex); - - driSignalPreviousFencesLocked(mgr, &fence->head, fence->fence_class, - fence_type); - _glthread_UNLOCK_MUTEX(mgr->mutex); - return 0; - - out0: - _glthread_UNLOCK_MUTEX(fence->mutex); - return ret; -} - -uint32_t driFenceSignaledTypeCached(struct _DriFenceObject *fence) -{ - uint32_t ret; - - _glthread_LOCK_MUTEX(fence->mutex); - ret = fence->signaled_type; - _glthread_UNLOCK_MUTEX(fence->mutex); - - return ret; -} - -int -driFenceSignaledType(struct _DriFenceObject *fence, uint32_t flush_type, - uint32_t *signaled) -{ - int ret = 0; - struct _DriFenceMgr *mgr; - - _glthread_LOCK_MUTEX(fence->mutex); - mgr = fence->mgr; - *signaled = fence->signaled_type; - if ((fence->signaled_type & flush_type) == flush_type) - goto out0; - - ret = mgr->info.signaled(mgr, fence->private, flush_type, signaled); - if (ret) { - *signaled = fence->signaled_type; - goto out0; - } - - if ((fence->signaled_type | *signaled) == fence->signaled_type) - goto out0; - - _glthread_LOCK_MUTEX(mgr->mutex); - _glthread_UNLOCK_MUTEX(fence->mutex); - - driSignalPreviousFencesLocked(mgr, &fence->head, fence->fence_class, - *signaled); - - _glthread_UNLOCK_MUTEX(mgr->mutex); - return 0; - out0: - _glthread_UNLOCK_MUTEX(fence->mutex); - return ret; -} - -struct _DriFenceObject * -driFenceReference(struct _DriFenceObject *fence) -{ - _glthread_LOCK_MUTEX(fence->mgr->mutex); - ++fence->refCount; - _glthread_UNLOCK_MUTEX(fence->mgr->mutex); - return fence; -} - -void -driFenceUnReference(struct _DriFenceObject **pFence) -{ - struct _DriFenceMgr *mgr; - - if (*pFence == NULL) - return; - - mgr = (*pFence)->mgr; - _glthread_LOCK_MUTEX(mgr->mutex); - ++mgr->refCount; - driFenceUnReferenceLocked(pFence); - driFenceMgrUnrefUnlock(&mgr); -} - -struct _DriFenceObject -*driFenceCreate(struct _DriFenceMgr *mgr, uint32_t fence_class, - uint32_t fence_type, void *private, size_t private_size) -{ - struct _DriFenceObject *fence; - size_t fence_size = sizeof(*fence); - - if (private_size) - fence_size = ((fence_size + 15) & ~15); - - fence = calloc(1, fence_size + private_size); - - if (!fence) { - int ret = mgr->info.finish(mgr, private, fence_type, 0); - - if (ret) - usleep(10000000); - - return NULL; - } - - _glthread_INIT_MUTEX(fence->mutex); - _glthread_LOCK_MUTEX(fence->mutex); - _glthread_LOCK_MUTEX(mgr->mutex); - fence->refCount = 1; - DRMLISTADDTAIL(&fence->head, &mgr->heads[fence_class]); - fence->mgr = mgr; - ++mgr->refCount; - ++mgr->num_fences; - _glthread_UNLOCK_MUTEX(mgr->mutex); - fence->fence_class = fence_class; - fence->fence_type = fence_type; - fence->signaled_type = 0; - fence->private = private; - if (private_size) { - fence->private = (void *)(((uint8_t *) fence) + fence_size); - memcpy(fence->private, private, private_size); - } - - _glthread_UNLOCK_MUTEX(fence->mutex); - return fence; -} - - -static int -tSignaled(struct _DriFenceMgr *mgr, void *private, uint32_t flush_type, - uint32_t *signaled_type) -{ - long fd = (long) mgr->private; - int dummy; - drmFence *fence = (drmFence *) private; - int ret; - - *signaled_type = 0; - ret = drmFenceSignaled((int) fd, fence, flush_type, &dummy); - if (ret) - return ret; - - *signaled_type = fence->signaled; - - return 0; -} - -static int -tFinish(struct _DriFenceMgr *mgr, void *private, uint32_t fence_type, - int lazy_hint) -{ - long fd = (long) mgr->private; - unsigned flags = lazy_hint ? DRM_FENCE_FLAG_WAIT_LAZY : 0; - - return drmFenceWait((int)fd, flags, (drmFence *) private, fence_type); -} - -static int -tUnref(struct _DriFenceMgr *mgr, void **private) -{ - long fd = (long) mgr->private; - drmFence *fence = (drmFence *) *private; - *private = NULL; - - return drmFenceUnreference(fd, fence); -} - -struct _DriFenceMgr *driFenceMgrTTMInit(int fd) -{ - struct _DriFenceMgrCreateInfo info; - struct _DriFenceMgr *mgr; - - info.flags = DRI_FENCE_CLASS_ORDERED; - info.num_classes = 4; - info.signaled = tSignaled; - info.finish = tFinish; - info.unreference = tUnref; - - mgr = driFenceMgrCreate(&info); - if (mgr == NULL) - return NULL; - - mgr->private = (void *) (long) fd; - return mgr; -} - diff --git a/src/gallium/winsys/egl_drm/intel/ws_dri_fencemgr.h b/src/gallium/winsys/egl_drm/intel/ws_dri_fencemgr.h deleted file mode 100644 index 4ea58dfe18..0000000000 --- a/src/gallium/winsys/egl_drm/intel/ws_dri_fencemgr.h +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef DRI_FENCEMGR_H -#define DRI_FENCEMGR_H - -#include <stdint.h> -#include <stdlib.h> - -struct _DriFenceObject; -struct _DriFenceMgr; - -/* - * Do a quick check to see if the fence manager has registered the fence - * object as signaled. Note that this function may return a false negative - * answer. - */ -extern uint32_t driFenceSignaledTypeCached(struct _DriFenceObject *fence); - -/* - * Check if the fence object is signaled. This function can be substantially - * more expensive to call than the above function, but will not return a false - * negative answer. The argument "flush_type" sets the types that the - * underlying mechanism must make sure will eventually signal. - */ -extern int driFenceSignaledType(struct _DriFenceObject *fence, - uint32_t flush_type, uint32_t *signaled); - -/* - * Convenience functions. - */ - -static inline int driFenceSignaled(struct _DriFenceObject *fence, - uint32_t flush_type) -{ - uint32_t signaled_types; - int ret = driFenceSignaledType(fence, flush_type, &signaled_types); - if (ret) - return 0; - return ((signaled_types & flush_type) == flush_type); -} - -static inline int driFenceSignaledCached(struct _DriFenceObject *fence, - uint32_t flush_type) -{ - uint32_t signaled_types = - driFenceSignaledTypeCached(fence); - - return ((signaled_types & flush_type) == flush_type); -} - -/* - * Reference a fence object. - */ -extern struct _DriFenceObject *driFenceReference(struct _DriFenceObject *fence); - -/* - * Unreference a fence object. The fence object pointer will be reset to NULL. - */ - -extern void driFenceUnReference(struct _DriFenceObject **pFence); - - -/* - * Wait for a fence to signal the indicated fence_type. - * If "lazy_hint" is true, it indicates that the wait may sleep to avoid - * busy-wait polling. - */ -extern int driFenceFinish(struct _DriFenceObject *fence, uint32_t fence_type, - int lazy_hint); - -/* - * Create a DriFenceObject for manager "mgr". - * - * "private" is a pointer that should be used for the callbacks in - * struct _DriFenceMgrCreateInfo. - * - * if private_size is nonzero, then the info stored at *private, with size - * private size will be copied and the fence manager will instead use a - * pointer to the copied data for the callbacks in - * struct _DriFenceMgrCreateInfo. In that case, the object pointed to by - * "private" may be destroyed after the call to driFenceCreate. - */ -extern struct _DriFenceObject *driFenceCreate(struct _DriFenceMgr *mgr, - uint32_t fence_class, - uint32_t fence_type, - void *private, - size_t private_size); - -extern uint32_t driFenceType(struct _DriFenceObject *fence); - -/* - * Fence creations are ordered. If a fence signals a fence_type, - * it is safe to assume that all fences of the same class that was - * created before that fence has signaled the same type. - */ - -#define DRI_FENCE_CLASS_ORDERED (1 << 0) - -struct _DriFenceMgrCreateInfo { - uint32_t flags; - uint32_t num_classes; - int (*signaled) (struct _DriFenceMgr *mgr, void *private, uint32_t flush_type, - uint32_t *signaled_type); - int (*finish) (struct _DriFenceMgr *mgr, void *private, uint32_t fence_type, int lazy_hint); - int (*unreference) (struct _DriFenceMgr *mgr, void **private); -}; - -extern struct _DriFenceMgr * -driFenceMgrCreate(const struct _DriFenceMgrCreateInfo *info); - -void -driFenceMgrUnReference(struct _DriFenceMgr **pMgr); - -extern struct _DriFenceMgr * -driFenceMgrTTMInit(int fd); - -#endif diff --git a/src/gallium/winsys/egl_drm/intel/ws_dri_mallocpool.c b/src/gallium/winsys/egl_drm/intel/ws_dri_mallocpool.c deleted file mode 100644 index bf97d7e440..0000000000 --- a/src/gallium/winsys/egl_drm/intel/ws_dri_mallocpool.c +++ /dev/null @@ -1,162 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, TX., USA - * 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, 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 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 - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS 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. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ -/* - * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> - */ - -#include <xf86drm.h> -#include <stdlib.h> -#include <errno.h> -#include "imports.h" -#include "glthread.h" -#include "ws_dri_bufpool.h" -#include "ws_dri_bufmgr.h" -#include "intel_screen.h" - -static void * -pool_create(struct _DriBufferPool *pool, - unsigned long size, uint64_t flags, unsigned hint, - unsigned alignment) -{ - unsigned long *private = malloc(size + 2*sizeof(unsigned long)); - if ((flags & DRM_BO_MASK_MEM) != DRM_BO_FLAG_MEM_LOCAL) - abort(); - - *private = size; - return (void *)private; -} - - -static int -pool_destroy(struct _DriBufferPool *pool, void *private) -{ - free(private); - return 0; -} - -static int -pool_waitIdle(struct _DriBufferPool *pool, void *private, - _glthread_Mutex *mutex, int lazy) -{ - return 0; -} - -static int -pool_map(struct _DriBufferPool *pool, void *private, unsigned flags, - int hint, _glthread_Mutex *mutex, void **virtual) -{ - *virtual = (void *)((unsigned long *)private + 2); - return 0; -} - -static int -pool_unmap(struct _DriBufferPool *pool, void *private) -{ - return 0; -} - -static unsigned long -pool_offset(struct _DriBufferPool *pool, void *private) -{ - /* - * BUG - */ - abort(); - return 0UL; -} - -static unsigned long -pool_poolOffset(struct _DriBufferPool *pool, void *private) -{ - /* - * BUG - */ - abort(); -} - -static uint64_t -pool_flags(struct _DriBufferPool *pool, void *private) -{ - return DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED; -} - -static unsigned long -pool_size(struct _DriBufferPool *pool, void *private) -{ - return *(unsigned long *) private; -} - - -static int -pool_fence(struct _DriBufferPool *pool, void *private, - struct _DriFenceObject *fence) -{ - abort(); - return 0UL; -} - -static drmBO * -pool_kernel(struct _DriBufferPool *pool, void *private) -{ - abort(); - return NULL; -} - -static void -pool_takedown(struct _DriBufferPool *pool) -{ - free(pool); -} - - -struct _DriBufferPool * -driMallocPoolInit(void) -{ - struct _DriBufferPool *pool; - - pool = (struct _DriBufferPool *) malloc(sizeof(*pool)); - if (!pool) - return NULL; - - pool->data = NULL; - pool->fd = -1; - pool->map = &pool_map; - pool->unmap = &pool_unmap; - pool->destroy = &pool_destroy; - pool->offset = &pool_offset; - pool->poolOffset = &pool_poolOffset; - pool->flags = &pool_flags; - pool->size = &pool_size; - pool->create = &pool_create; - pool->fence = &pool_fence; - pool->kernel = &pool_kernel; - pool->validate = NULL; - pool->waitIdle = &pool_waitIdle; - pool->takeDown = &pool_takedown; - return pool; -} diff --git a/src/gallium/winsys/egl_drm/intel/ws_dri_slabpool.c b/src/gallium/winsys/egl_drm/intel/ws_dri_slabpool.c deleted file mode 100644 index e69519a01f..0000000000 --- a/src/gallium/winsys/egl_drm/intel/ws_dri_slabpool.c +++ /dev/null @@ -1,970 +0,0 @@ -/************************************************************************** - * - * Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA - * 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, 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 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 - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS 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. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ -/* - * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> - */ - -#include <stdint.h> -#include <sys/time.h> -#include <errno.h> -#include <unistd.h> -#include <assert.h> -#include "ws_dri_bufpool.h" -#include "ws_dri_fencemgr.h" -#include "ws_dri_bufmgr.h" -#include "glthread.h" - -#define DRI_SLABPOOL_ALLOC_RETRIES 100 - -struct _DriSlab; - -struct _DriSlabBuffer { - int isSlabBuffer; - drmBO *bo; - struct _DriFenceObject *fence; - struct _DriSlab *parent; - drmMMListHead head; - uint32_t mapCount; - uint32_t start; - uint32_t fenceType; - int unFenced; - _glthread_Cond event; -}; - -struct _DriKernelBO { - int fd; - drmBO bo; - drmMMListHead timeoutHead; - drmMMListHead head; - struct timeval timeFreed; - uint32_t pageAlignment; - void *virtual; -}; - -struct _DriSlab{ - drmMMListHead head; - drmMMListHead freeBuffers; - uint32_t numBuffers; - uint32_t numFree; - struct _DriSlabBuffer *buffers; - struct _DriSlabSizeHeader *header; - struct _DriKernelBO *kbo; -}; - - -struct _DriSlabSizeHeader { - drmMMListHead slabs; - drmMMListHead freeSlabs; - drmMMListHead delayedBuffers; - uint32_t numDelayed; - struct _DriSlabPool *slabPool; - uint32_t bufSize; - _glthread_Mutex mutex; -}; - -struct _DriFreeSlabManager { - struct timeval slabTimeout; - struct timeval checkInterval; - struct timeval nextCheck; - drmMMListHead timeoutList; - drmMMListHead unCached; - drmMMListHead cached; - _glthread_Mutex mutex; -}; - - -struct _DriSlabPool { - - /* - * The data of this structure remains constant after - * initialization and thus needs no mutex protection. - */ - - struct _DriFreeSlabManager *fMan; - uint64_t proposedFlags; - uint64_t validMask; - uint32_t *bucketSizes; - uint32_t numBuckets; - uint32_t pageSize; - int fd; - int pageAlignment; - int maxSlabSize; - int desiredNumBuffers; - struct _DriSlabSizeHeader *headers; -}; - -/* - * FIXME: Perhaps arrange timeout slabs in size buckets for fast - * retreival?? - */ - - -static inline int -driTimeAfterEq(struct timeval *arg1, struct timeval *arg2) -{ - return ((arg1->tv_sec > arg2->tv_sec) || - ((arg1->tv_sec == arg2->tv_sec) && - (arg1->tv_usec > arg2->tv_usec))); -} - -static inline void -driTimeAdd(struct timeval *arg, struct timeval *add) -{ - unsigned int sec; - - arg->tv_sec += add->tv_sec; - arg->tv_usec += add->tv_usec; - sec = arg->tv_usec / 1000000; - arg->tv_sec += sec; - arg->tv_usec -= sec*1000000; -} - -static void -driFreeKernelBO(struct _DriKernelBO *kbo) -{ - if (!kbo) - return; - - (void) drmBOUnreference(kbo->fd, &kbo->bo); - free(kbo); -} - - -static void -driFreeTimeoutKBOsLocked(struct _DriFreeSlabManager *fMan, - struct timeval *time) -{ - drmMMListHead *list, *next; - struct _DriKernelBO *kbo; - - if (!driTimeAfterEq(time, &fMan->nextCheck)) - return; - - for (list = fMan->timeoutList.next, next = list->next; - list != &fMan->timeoutList; - list = next, next = list->next) { - - kbo = DRMLISTENTRY(struct _DriKernelBO, list, timeoutHead); - - if (!driTimeAfterEq(time, &kbo->timeFreed)) - break; - - DRMLISTDELINIT(&kbo->timeoutHead); - DRMLISTDELINIT(&kbo->head); - driFreeKernelBO(kbo); - } - - fMan->nextCheck = *time; - driTimeAdd(&fMan->nextCheck, &fMan->checkInterval); -} - - -/* - * Add a _DriKernelBO to the free slab manager. - * This means that it is available for reuse, but if it's not - * reused in a while, it will be freed. - */ - -static void -driSetKernelBOFree(struct _DriFreeSlabManager *fMan, - struct _DriKernelBO *kbo) -{ - struct timeval time; - - _glthread_LOCK_MUTEX(fMan->mutex); - gettimeofday(&time, NULL); - driTimeAdd(&time, &fMan->slabTimeout); - - kbo->timeFreed = time; - - if (kbo->bo.flags & DRM_BO_FLAG_CACHED) - DRMLISTADD(&kbo->head, &fMan->cached); - else - DRMLISTADD(&kbo->head, &fMan->unCached); - - DRMLISTADDTAIL(&kbo->timeoutHead, &fMan->timeoutList); - driFreeTimeoutKBOsLocked(fMan, &time); - - _glthread_UNLOCK_MUTEX(fMan->mutex); -} - -/* - * Get a _DriKernelBO for us to use as storage for a slab. - * - */ - -static struct _DriKernelBO * -driAllocKernelBO(struct _DriSlabSizeHeader *header) - -{ - struct _DriSlabPool *slabPool = header->slabPool; - struct _DriFreeSlabManager *fMan = slabPool->fMan; - drmMMListHead *list, *next, *head; - uint32_t size = header->bufSize * slabPool->desiredNumBuffers; - struct _DriKernelBO *kbo; - struct _DriKernelBO *kboTmp; - int ret; - - /* - * FIXME: We should perhaps allow some variation in slabsize in order - * to efficiently reuse slabs. - */ - - size = (size <= slabPool->maxSlabSize) ? size : slabPool->maxSlabSize; - size = (size + slabPool->pageSize - 1) & ~(slabPool->pageSize - 1); - _glthread_LOCK_MUTEX(fMan->mutex); - - kbo = NULL; - - retry: - head = (slabPool->proposedFlags & DRM_BO_FLAG_CACHED) ? - &fMan->cached : &fMan->unCached; - - for (list = head->next, next = list->next; - list != head; - list = next, next = list->next) { - - kboTmp = DRMLISTENTRY(struct _DriKernelBO, list, head); - - if ((kboTmp->bo.size == size) && - (slabPool->pageAlignment == 0 || - (kboTmp->pageAlignment % slabPool->pageAlignment) == 0)) { - - if (!kbo) - kbo = kboTmp; - - if ((kbo->bo.proposedFlags ^ slabPool->proposedFlags) == 0) - break; - - } - } - - if (kbo) { - DRMLISTDELINIT(&kbo->head); - DRMLISTDELINIT(&kbo->timeoutHead); - } - - _glthread_UNLOCK_MUTEX(fMan->mutex); - - if (kbo) { - uint64_t new_mask = kbo->bo.proposedFlags ^ slabPool->proposedFlags; - - ret = 0; - if (new_mask) { - ret = drmBOSetStatus(kbo->fd, &kbo->bo, slabPool->proposedFlags, - new_mask, DRM_BO_HINT_DONT_FENCE, 0, 0); - } - if (ret == 0) - return kbo; - - driFreeKernelBO(kbo); - kbo = NULL; - goto retry; - } - - kbo = calloc(1, sizeof(struct _DriKernelBO)); - if (!kbo) - return NULL; - - kbo->fd = slabPool->fd; - DRMINITLISTHEAD(&kbo->head); - DRMINITLISTHEAD(&kbo->timeoutHead); - ret = drmBOCreate(kbo->fd, size, slabPool->pageAlignment, NULL, - slabPool->proposedFlags, - DRM_BO_HINT_DONT_FENCE, &kbo->bo); - if (ret) - goto out_err0; - - ret = drmBOMap(kbo->fd, &kbo->bo, - DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, - 0, &kbo->virtual); - - if (ret) - goto out_err1; - - ret = drmBOUnmap(kbo->fd, &kbo->bo); - if (ret) - goto out_err1; - - return kbo; - - out_err1: - drmBOUnreference(kbo->fd, &kbo->bo); - out_err0: - free(kbo); - return NULL; -} - - -static int -driAllocSlab(struct _DriSlabSizeHeader *header) -{ - struct _DriSlab *slab; - struct _DriSlabBuffer *buf; - uint32_t numBuffers; - int ret; - int i; - - slab = calloc(1, sizeof(*slab)); - if (!slab) - return -ENOMEM; - - slab->kbo = driAllocKernelBO(header); - if (!slab->kbo) { - ret = -ENOMEM; - goto out_err0; - } - - numBuffers = slab->kbo->bo.size / header->bufSize; - - slab->buffers = calloc(numBuffers, sizeof(*slab->buffers)); - if (!slab->buffers) { - ret = -ENOMEM; - goto out_err1; - } - - DRMINITLISTHEAD(&slab->head); - DRMINITLISTHEAD(&slab->freeBuffers); - slab->numBuffers = numBuffers; - slab->numFree = 0; - slab->header = header; - - buf = slab->buffers; - for (i=0; i < numBuffers; ++i) { - buf->parent = slab; - buf->start = i* header->bufSize; - buf->mapCount = 0; - buf->isSlabBuffer = 1; - _glthread_INIT_COND(buf->event); - DRMLISTADDTAIL(&buf->head, &slab->freeBuffers); - slab->numFree++; - buf++; - } - - DRMLISTADDTAIL(&slab->head, &header->slabs); - - return 0; - - out_err1: - driSetKernelBOFree(header->slabPool->fMan, slab->kbo); - free(slab->buffers); - out_err0: - free(slab); - return ret; -} - -/* - * Delete a buffer from the slab header delayed list and put - * it on the slab free list. - */ - -static void -driSlabFreeBufferLocked(struct _DriSlabBuffer *buf) -{ - struct _DriSlab *slab = buf->parent; - struct _DriSlabSizeHeader *header = slab->header; - drmMMListHead *list = &buf->head; - - DRMLISTDEL(list); - DRMLISTADDTAIL(list, &slab->freeBuffers); - slab->numFree++; - - if (slab->head.next == &slab->head) - DRMLISTADDTAIL(&slab->head, &header->slabs); - - if (slab->numFree == slab->numBuffers) { - list = &slab->head; - DRMLISTDEL(list); - DRMLISTADDTAIL(list, &header->freeSlabs); - } - - if (header->slabs.next == &header->slabs || - slab->numFree != slab->numBuffers) { - - drmMMListHead *next; - struct _DriFreeSlabManager *fMan = header->slabPool->fMan; - - for (list = header->freeSlabs.next, next = list->next; - list != &header->freeSlabs; - list = next, next = list->next) { - - slab = DRMLISTENTRY(struct _DriSlab, list, head); - - DRMLISTDELINIT(list); - driSetKernelBOFree(fMan, slab->kbo); - free(slab->buffers); - free(slab); - } - } -} - -static void -driSlabCheckFreeLocked(struct _DriSlabSizeHeader *header, int wait) -{ - drmMMListHead *list, *prev, *first; - struct _DriSlabBuffer *buf; - struct _DriSlab *slab; - int firstWasSignaled = 1; - int signaled; - int i; - int ret; - - /* - * Rerun the freeing test if the youngest tested buffer - * was signaled, since there might be more idle buffers - * in the delay list. - */ - - while (firstWasSignaled) { - firstWasSignaled = 0; - signaled = 0; - first = header->delayedBuffers.next; - - /* Only examine the oldest 1/3 of delayed buffers: - */ - if (header->numDelayed > 3) { - for (i = 0; i < header->numDelayed; i += 3) { - first = first->next; - } - } - - for (list = first, prev = list->prev; - list != &header->delayedBuffers; - list = prev, prev = list->prev) { - buf = DRMLISTENTRY(struct _DriSlabBuffer, list, head); - slab = buf->parent; - - if (!signaled) { - if (wait) { - ret = driFenceFinish(buf->fence, buf->fenceType, 0); - if (ret) - break; - signaled = 1; - wait = 0; - } else { - signaled = driFenceSignaled(buf->fence, buf->fenceType); - } - if (signaled) { - if (list == first) - firstWasSignaled = 1; - driFenceUnReference(&buf->fence); - header->numDelayed--; - driSlabFreeBufferLocked(buf); - } - } else if (driFenceSignaledCached(buf->fence, buf->fenceType)) { - driFenceUnReference(&buf->fence); - header->numDelayed--; - driSlabFreeBufferLocked(buf); - } - } - } -} - - -static struct _DriSlabBuffer * -driSlabAllocBuffer(struct _DriSlabSizeHeader *header) -{ - static struct _DriSlabBuffer *buf; - struct _DriSlab *slab; - drmMMListHead *list; - int count = DRI_SLABPOOL_ALLOC_RETRIES; - - _glthread_LOCK_MUTEX(header->mutex); - while(header->slabs.next == &header->slabs && count > 0) { - driSlabCheckFreeLocked(header, 0); - if (header->slabs.next != &header->slabs) - break; - - _glthread_UNLOCK_MUTEX(header->mutex); - if (count != DRI_SLABPOOL_ALLOC_RETRIES) - usleep(1); - _glthread_LOCK_MUTEX(header->mutex); - (void) driAllocSlab(header); - count--; - } - - list = header->slabs.next; - if (list == &header->slabs) { - _glthread_UNLOCK_MUTEX(header->mutex); - return NULL; - } - slab = DRMLISTENTRY(struct _DriSlab, list, head); - if (--slab->numFree == 0) - DRMLISTDELINIT(list); - - list = slab->freeBuffers.next; - DRMLISTDELINIT(list); - - _glthread_UNLOCK_MUTEX(header->mutex); - buf = DRMLISTENTRY(struct _DriSlabBuffer, list, head); - return buf; -} - -static void * -pool_create(struct _DriBufferPool *driPool, unsigned long size, - uint64_t flags, unsigned hint, unsigned alignment) -{ - struct _DriSlabPool *pool = (struct _DriSlabPool *) driPool->data; - struct _DriSlabSizeHeader *header; - struct _DriSlabBuffer *buf; - void *dummy; - int i; - int ret; - - /* - * FIXME: Check for compatibility. - */ - header = pool->headers; - for (i=0; i<pool->numBuckets; ++i) { - if (header->bufSize >= size) - break; - header++; - } - - if (i < pool->numBuckets) - return driSlabAllocBuffer(header); - - - /* - * Fall back to allocate a buffer object directly from DRM. - * and wrap it in a driBO structure. - */ - - - buf = calloc(1, sizeof(*buf)); - - if (!buf) - return NULL; - - buf->bo = calloc(1, sizeof(*buf->bo)); - if (!buf->bo) - goto out_err0; - - if (alignment) { - if ((alignment < pool->pageSize) && (pool->pageSize % alignment)) - goto out_err1; - if ((alignment > pool->pageSize) && (alignment % pool->pageSize)) - goto out_err1; - } - - ret = drmBOCreate(pool->fd, size, alignment / pool->pageSize, NULL, - flags, hint, buf->bo); - if (ret) - goto out_err1; - - ret = drmBOMap(pool->fd, buf->bo, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, - 0, &dummy); - if (ret) - goto out_err2; - - ret = drmBOUnmap(pool->fd, buf->bo); - if (ret) - goto out_err2; - - return buf; - out_err2: - drmBOUnreference(pool->fd, buf->bo); - out_err1: - free(buf->bo); - out_err0: - free(buf); - return NULL; -} - -static int -pool_destroy(struct _DriBufferPool *driPool, void *private) -{ - struct _DriSlabBuffer *buf = - (struct _DriSlabBuffer *) private; - struct _DriSlab *slab; - struct _DriSlabSizeHeader *header; - - if (!buf->isSlabBuffer) { - struct _DriSlabPool *pool = (struct _DriSlabPool *) driPool->data; - int ret; - - ret = drmBOUnreference(pool->fd, buf->bo); - free(buf->bo); - free(buf); - return ret; - } - - slab = buf->parent; - header = slab->header; - - _glthread_LOCK_MUTEX(header->mutex); - buf->unFenced = 0; - buf->mapCount = 0; - - if (buf->fence && !driFenceSignaledCached(buf->fence, buf->fenceType)) { - DRMLISTADDTAIL(&buf->head, &header->delayedBuffers); - header->numDelayed++; - } else { - if (buf->fence) - driFenceUnReference(&buf->fence); - driSlabFreeBufferLocked(buf); - } - - _glthread_UNLOCK_MUTEX(header->mutex); - return 0; -} - -static int -pool_waitIdle(struct _DriBufferPool *driPool, void *private, - _glthread_Mutex *mutex, int lazy) -{ - struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; - - while(buf->unFenced) - _glthread_COND_WAIT(buf->event, *mutex); - - if (!buf->fence) - return 0; - - driFenceFinish(buf->fence, buf->fenceType, lazy); - driFenceUnReference(&buf->fence); - - return 0; -} - -static int -pool_map(struct _DriBufferPool *pool, void *private, unsigned flags, - int hint, _glthread_Mutex *mutex, void **virtual) -{ - struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; - int busy; - - if (buf->isSlabBuffer) - busy = buf->unFenced || (buf->fence && !driFenceSignaledCached(buf->fence, buf->fenceType)); - else - busy = buf->fence && !driFenceSignaled(buf->fence, buf->fenceType); - - - if (busy) { - if (hint & DRM_BO_HINT_DONT_BLOCK) - return -EBUSY; - else { - (void) pool_waitIdle(pool, private, mutex, 0); - } - } - - ++buf->mapCount; - *virtual = (buf->isSlabBuffer) ? - (void *) ((uint8_t *) buf->parent->kbo->virtual + buf->start) : - (void *) buf->bo->virtual; - - return 0; -} - -static int -pool_unmap(struct _DriBufferPool *pool, void *private) -{ - struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; - - --buf->mapCount; - if (buf->mapCount == 0 && buf->isSlabBuffer) - _glthread_COND_BROADCAST(buf->event); - - return 0; -} - -static unsigned long -pool_offset(struct _DriBufferPool *pool, void *private) -{ - struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; - struct _DriSlab *slab; - struct _DriSlabSizeHeader *header; - - if (!buf->isSlabBuffer) { - assert(buf->bo->proposedFlags & DRM_BO_FLAG_NO_MOVE); - return buf->bo->offset; - } - - slab = buf->parent; - header = slab->header; - - (void) header; - assert(header->slabPool->proposedFlags & DRM_BO_FLAG_NO_MOVE); - return slab->kbo->bo.offset + buf->start; -} - -static unsigned long -pool_poolOffset(struct _DriBufferPool *pool, void *private) -{ - struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; - - return buf->start; -} - -static uint64_t -pool_flags(struct _DriBufferPool *pool, void *private) -{ - struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; - - if (!buf->isSlabBuffer) - return buf->bo->flags; - - return buf->parent->kbo->bo.flags; -} - -static unsigned long -pool_size(struct _DriBufferPool *pool, void *private) -{ - struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; - if (!buf->isSlabBuffer) - return buf->bo->size; - - return buf->parent->header->bufSize; -} - -static int -pool_fence(struct _DriBufferPool *pool, void *private, - struct _DriFenceObject *fence) -{ - struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; - drmBO *bo; - - if (buf->fence) - driFenceUnReference(&buf->fence); - - buf->fence = driFenceReference(fence); - bo = (buf->isSlabBuffer) ? - &buf->parent->kbo->bo: - buf->bo; - buf->fenceType = bo->fenceFlags; - - buf->unFenced = 0; - _glthread_COND_BROADCAST(buf->event); - - return 0; -} - -static drmBO * -pool_kernel(struct _DriBufferPool *pool, void *private) -{ - struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; - - if (!buf) - return NULL; - - return (buf->isSlabBuffer) ? &buf->parent->kbo->bo : buf->bo; -} - -static int -pool_validate(struct _DriBufferPool *pool, void *private, - _glthread_Mutex *mutex) -{ - struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; - - if (!buf->isSlabBuffer) - return 0; - - while(buf->mapCount != 0) - _glthread_COND_WAIT(buf->event, *mutex); - - buf->unFenced = 1; - return 0; -} - - -struct _DriFreeSlabManager * -driInitFreeSlabManager(uint32_t checkIntervalMsec, uint32_t slabTimeoutMsec) -{ - struct _DriFreeSlabManager *tmp; - - tmp = calloc(1, sizeof(*tmp)); - if (!tmp) - return NULL; - - _glthread_INIT_MUTEX(tmp->mutex); - _glthread_LOCK_MUTEX(tmp->mutex); - tmp->slabTimeout.tv_usec = slabTimeoutMsec*1000; - tmp->slabTimeout.tv_sec = tmp->slabTimeout.tv_usec / 1000000; - tmp->slabTimeout.tv_usec -= tmp->slabTimeout.tv_sec*1000000; - - tmp->checkInterval.tv_usec = checkIntervalMsec*1000; - tmp->checkInterval.tv_sec = tmp->checkInterval.tv_usec / 1000000; - tmp->checkInterval.tv_usec -= tmp->checkInterval.tv_sec*1000000; - - gettimeofday(&tmp->nextCheck, NULL); - driTimeAdd(&tmp->nextCheck, &tmp->checkInterval); - DRMINITLISTHEAD(&tmp->timeoutList); - DRMINITLISTHEAD(&tmp->unCached); - DRMINITLISTHEAD(&tmp->cached); - _glthread_UNLOCK_MUTEX(tmp->mutex); - - return tmp; -} - -void -driFinishFreeSlabManager(struct _DriFreeSlabManager *fMan) -{ - struct timeval time; - - time = fMan->nextCheck; - driTimeAdd(&time, &fMan->checkInterval); - - _glthread_LOCK_MUTEX(fMan->mutex); - driFreeTimeoutKBOsLocked(fMan, &time); - _glthread_UNLOCK_MUTEX(fMan->mutex); - - assert(fMan->timeoutList.next == &fMan->timeoutList); - assert(fMan->unCached.next == &fMan->unCached); - assert(fMan->cached.next == &fMan->cached); - - free(fMan); -} - -static void -driInitSizeHeader(struct _DriSlabPool *pool, uint32_t size, - struct _DriSlabSizeHeader *header) -{ - _glthread_INIT_MUTEX(header->mutex); - _glthread_LOCK_MUTEX(header->mutex); - - DRMINITLISTHEAD(&header->slabs); - DRMINITLISTHEAD(&header->freeSlabs); - DRMINITLISTHEAD(&header->delayedBuffers); - - header->numDelayed = 0; - header->slabPool = pool; - header->bufSize = size; - - _glthread_UNLOCK_MUTEX(header->mutex); -} - -static void -driFinishSizeHeader(struct _DriSlabSizeHeader *header) -{ - drmMMListHead *list, *next; - struct _DriSlabBuffer *buf; - - _glthread_LOCK_MUTEX(header->mutex); - for (list = header->delayedBuffers.next, next = list->next; - list != &header->delayedBuffers; - list = next, next = list->next) { - - buf = DRMLISTENTRY(struct _DriSlabBuffer, list , head); - if (buf->fence) { - (void) driFenceFinish(buf->fence, buf->fenceType, 0); - driFenceUnReference(&buf->fence); - } - header->numDelayed--; - driSlabFreeBufferLocked(buf); - } - _glthread_UNLOCK_MUTEX(header->mutex); -} - -static void -pool_takedown(struct _DriBufferPool *driPool) -{ - struct _DriSlabPool *pool = driPool->data; - int i; - - for (i=0; i<pool->numBuckets; ++i) { - driFinishSizeHeader(&pool->headers[i]); - } - - free(pool->headers); - free(pool->bucketSizes); - free(pool); - free(driPool); -} - -struct _DriBufferPool * -driSlabPoolInit(int fd, uint64_t flags, - uint64_t validMask, - uint32_t smallestSize, - uint32_t numSizes, - uint32_t desiredNumBuffers, - uint32_t maxSlabSize, - uint32_t pageAlignment, - struct _DriFreeSlabManager *fMan) -{ - struct _DriBufferPool *driPool; - struct _DriSlabPool *pool; - uint32_t i; - - driPool = calloc(1, sizeof(*driPool)); - if (!driPool) - return NULL; - - pool = calloc(1, sizeof(*pool)); - if (!pool) - goto out_err0; - - pool->bucketSizes = calloc(numSizes, sizeof(*pool->bucketSizes)); - if (!pool->bucketSizes) - goto out_err1; - - pool->headers = calloc(numSizes, sizeof(*pool->headers)); - if (!pool->headers) - goto out_err2; - - pool->fMan = fMan; - pool->proposedFlags = flags; - pool->validMask = validMask; - pool->numBuckets = numSizes; - pool->pageSize = getpagesize(); - pool->fd = fd; - pool->pageAlignment = pageAlignment; - pool->maxSlabSize = maxSlabSize; - pool->desiredNumBuffers = desiredNumBuffers; - - for (i=0; i<pool->numBuckets; ++i) { - pool->bucketSizes[i] = (smallestSize << i); - driInitSizeHeader(pool, pool->bucketSizes[i], - &pool->headers[i]); - } - - driPool->data = (void *) pool; - driPool->map = &pool_map; - driPool->unmap = &pool_unmap; - driPool->destroy = &pool_destroy; - driPool->offset = &pool_offset; - driPool->poolOffset = &pool_poolOffset; - driPool->flags = &pool_flags; - driPool->size = &pool_size; - driPool->create = &pool_create; - driPool->fence = &pool_fence; - driPool->kernel = &pool_kernel; - driPool->validate = &pool_validate; - driPool->waitIdle = &pool_waitIdle; - driPool->takeDown = &pool_takedown; - - return driPool; - - out_err2: - free(pool->bucketSizes); - out_err1: - free(pool); - out_err0: - free(driPool); - - return NULL; -} diff --git a/src/gallium/winsys/egl_xlib/Makefile b/src/gallium/winsys/egl_xlib/Makefile new file mode 100644 index 0000000000..76f1b56da4 --- /dev/null +++ b/src/gallium/winsys/egl_xlib/Makefile @@ -0,0 +1,89 @@ +# src/gallium/winsys/egl_xlib/Makefile + +# Build softpipe/xlib/EGL driver library/object: "egl_softpipe.so" + + +TOP = ../../../.. +include $(TOP)/configs/current + + +DRIVER_NAME = egl_softpipe.so + + +INCLUDE_DIRS = \ + -I$(TOP)/include \ + -I$(TOP)/src/egl/main \ + -I$(TOP)/src/mesa \ + -I$(TOP)/src/mesa/main \ + -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/drivers \ + -I$(TOP)/src/gallium/auxiliary + +WINSYS_SOURCES = \ + egl_xlib.c \ + sw_winsys.c + +WINSYS_OBJECTS = $(WINSYS_SOURCES:.c=.o) + + +LIBS = \ + $(GALLIUM_DRIVERS) \ + $(GALLIUM_AUXILIARIES) + +# XXX temporary (should create a separate lib with the GL API funcs and +# mesa code, as done for ES 1.x, 2.x, OpenVG, etc) +UNUSED_LIBS = \ + $(TOP)/src/mesa/libglapi.a \ + $(TOP)/src/mesa/libmesa.a \ + + +LOCAL_CFLAGS = -D_EGL_PLATFORM_X=1 + + +.c.o: + $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(LOCAL_CFLAGS) $< -o $@ + + +.PHONY: library + + +default: depend library Makefile + + +library: $(TOP)/$(LIB_DIR)/$(DRIVER_NAME) + + +# Make the egl_softpipe.so library +$(TOP)/$(LIB_DIR)/$(DRIVER_NAME): $(WINSYS_OBJECTS) $(LIBS) + $(TOP)/bin/mklib -o $(DRIVER_NAME) \ + -linker "$(CC)" \ + -noprefix \ + -install $(TOP)/$(LIB_DIR) \ + $(MKLIB_OPTIONS) $(WINSYS_OBJECTS) \ + --whole-archive $(LIBS) --no-whole-archive + + +depend: $(ALL_SOURCES) + @ echo "running $(MKDEP)" + @ rm -f depend # workaround oops on gutsy?!? + @ touch depend + @ $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) $(ALL_SOURCES) \ + > /dev/null 2>/dev/null + + +install: default + $(INSTALL) -d $(INSTALL_DIR)/$(LIB_DIR) + @if [ -e $(TOP)/$(LIB_DIR) ]; then \ + $(INSTALL) $(TOP)/$(LIB_DIR)/$(DRIVER_NAME) $(INSTALL_DIR)/$(LIB_DIR); \ + fi + + +# Emacs tags +tags: + etags `find . -name \*.[ch]` $(TOP)/include/GL/*.h + +clean: + -rm -f *.o *~ *.bak + + +include depend diff --git a/src/gallium/winsys/egl_xlib/egl_xlib.c b/src/gallium/winsys/egl_xlib/egl_xlib.c new file mode 100644 index 0000000000..eeb15e30a9 --- /dev/null +++ b/src/gallium/winsys/egl_xlib/egl_xlib.c @@ -0,0 +1,645 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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. + * + **************************************************************************/ + +/** + * EGL / softpipe / xlib winsys module + * + * Authors: Brian Paul + */ + + +#include <dlfcn.h> +#include <X11/Xutil.h> + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" +#include "pipe/p_state.h" +#include "pipe/p_util.h" +#include "pipe/p_winsys.h" +#include "softpipe/sp_winsys.h" + +#include "eglconfig.h" +#include "eglconfigutil.h" +#include "eglcontext.h" +#include "egldisplay.h" +#include "egldriver.h" +#include "eglglobals.h" +#include "egllog.h" +#include "eglsurface.h" + +#include "state_tracker/st_public.h" + +#include "sw_winsys.h" + + +/** subclass of _EGLDriver */ +struct xlib_egl_driver +{ + _EGLDriver Base; /**< base class */ + + struct pipe_winsys *winsys; + struct pipe_screen *screen; +}; + + +/** subclass of _EGLContext */ +struct xlib_egl_context +{ + _EGLContext Base; /**< base class */ + + struct pipe_context *pipe; /**< Gallium driver context */ + struct st_context *Context; /**< Mesa/gallium state tracker context */ +}; + + +/** subclass of _EGLSurface */ +struct xlib_egl_surface +{ + _EGLSurface Base; /**< base class */ + + Display *Dpy; /**< The X Display of the window */ + Window Win; /**< The user-created window ID */ + GC Gc; + XVisualInfo VisInfo; + + struct pipe_winsys *winsys; + + struct st_framebuffer *Framebuffer; +}; + + +/** cast wrapper */ +static INLINE struct xlib_egl_driver * +xlib_egl_driver(_EGLDriver *drv) +{ + return (struct xlib_egl_driver *) drv; +} + + +static struct xlib_egl_surface * +lookup_surface(EGLSurface surf) +{ + _EGLSurface *surface = _eglLookupSurface(surf); + return (struct xlib_egl_surface *) surface; +} + + +static struct xlib_egl_context * +lookup_context(EGLContext surf) +{ + _EGLContext *context = _eglLookupContext(surf); + return (struct xlib_egl_context *) context; +} + + +static unsigned int +bitcount(unsigned int n) +{ + unsigned int bits; + for (bits = 0; n > 0; n = n >> 1) { + bits += (n & 1); + } + return bits; +} + + +/** + * Create the EGLConfigs. (one per X visual) + */ +static void +create_configs(_EGLDriver *drv, EGLDisplay dpy) +{ + _EGLDisplay *disp = _eglLookupDisplay(dpy); + XVisualInfo *visInfo, visTemplate; + int num_visuals, i; + + /* get list of all X visuals, create an EGL config for each */ + visTemplate.screen = DefaultScreen(disp->Xdpy); + visInfo = XGetVisualInfo(disp->Xdpy, VisualScreenMask, + &visTemplate, &num_visuals); + if (!visInfo) { + printf("egl_xlib.c: couldn't get any X visuals\n"); + abort(); + } + + for (i = 0; i < num_visuals; i++) { + _EGLConfig *config = calloc(1, sizeof(_EGLConfig)); + int id = i + 1; + int rbits = bitcount(visInfo[i].red_mask); + int gbits = bitcount(visInfo[i].green_mask); + int bbits = bitcount(visInfo[i].blue_mask); + int abits = bbits == 8 ? 8 : 0; + int zbits = 24; + int sbits = 8; + int visid = visInfo[i].visualid; +#if defined(__cplusplus) || defined(c_plusplus) + int vistype = visInfo[i].c_class; +#else + int vistype = visInfo[i].class; +#endif + + _eglInitConfig(config, id); + SET_CONFIG_ATTRIB(config, EGL_BUFFER_SIZE, rbits + gbits + bbits + abits); + SET_CONFIG_ATTRIB(config, EGL_RED_SIZE, rbits); + SET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE, gbits); + SET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE, bbits); + SET_CONFIG_ATTRIB(config, EGL_ALPHA_SIZE, abits); + SET_CONFIG_ATTRIB(config, EGL_DEPTH_SIZE, zbits); + SET_CONFIG_ATTRIB(config, EGL_STENCIL_SIZE, sbits); + SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_ID, visid); + SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_TYPE, vistype); + + _eglAddConfig(disp, config); + } +} + + +/** + * Called via eglInitialize(), drv->API.Initialize(). + */ +static EGLBoolean +xlib_eglInitialize(_EGLDriver *drv, EGLDisplay dpy, + EGLint *minor, EGLint *major) +{ + create_configs(drv, dpy); + + drv->Initialized = EGL_TRUE; + + /* we're supporting EGL 1.4 */ + *minor = 1; + *major = 4; + + return EGL_TRUE; +} + + +/** + * Called via eglTerminate(), drv->API.Terminate(). + */ +static EGLBoolean +xlib_eglTerminate(_EGLDriver *drv, EGLDisplay dpy) +{ + return EGL_TRUE; +} + + +static _EGLProc +xlib_eglGetProcAddress(const char *procname) +{ + return (_EGLProc) st_get_proc_address(procname); +} + + +static void +get_drawable_visual_info(Display *dpy, Drawable d, XVisualInfo *visInfo) +{ + XWindowAttributes attr; + XVisualInfo visTemp, *vis; + int num_visuals; + + XGetWindowAttributes(dpy, d, &attr); + + visTemp.screen = DefaultScreen(dpy); + visTemp.visualid = attr.visual->visualid; + vis = XGetVisualInfo(dpy, + (VisualScreenMask | VisualIDMask), + &visTemp, &num_visuals); + if (vis) + *visInfo = *vis; + + XFree(vis); +} + + + +/** Get size of given window */ +static Status +get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height) +{ + Window root; + Status stat; + int xpos, ypos; + unsigned int w, h, bw, depth; + stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth); + *width = w; + *height = h; + return stat; +} + + +static void +check_and_update_buffer_size(struct xlib_egl_surface *surface) +{ + uint width, height; + get_drawable_size(surface->Dpy, surface->Win, &width, &height); + st_resize_framebuffer(surface->Framebuffer, width, height); + surface->Base.Width = width; + surface->Base.Height = height; +} + + + +static void +display_surface(struct pipe_winsys *pws, + struct pipe_surface *psurf, + struct xlib_egl_surface *xsurf) +{ + XImage *ximage; + void *data; + + ximage = XCreateImage(xsurf->Dpy, + xsurf->VisInfo.visual, + xsurf->VisInfo.depth, + ZPixmap, 0, /* format, offset */ + NULL, /* data */ + 0, 0, /* size */ + 32, /* bitmap_pad */ + 0); /* bytes_per_line */ + + + assert(ximage->format); + assert(ximage->bitmap_unit); + + data = pws->buffer_map(pws, psurf->buffer, 0); + + /* update XImage's fields */ + ximage->data = data; + ximage->width = psurf->width; + ximage->height = psurf->height; + ximage->bytes_per_line = psurf->pitch * psurf->cpp; + + XPutImage(xsurf->Dpy, xsurf->Win, xsurf->Gc, + ximage, 0, 0, 0, 0, psurf->width, psurf->height); + + XSync(xsurf->Dpy, 0); + + ximage->data = NULL; + XDestroyImage(ximage); + + pws->buffer_unmap(pws, psurf->buffer); +} + + + +/** Display gallium surface in X window */ +static void +flush_frontbuffer(struct pipe_winsys *pws, + struct pipe_surface *psurf, + void *context_private) +{ + struct xlib_egl_surface *xsurf = (struct xlib_egl_surface *) context_private; + display_surface(pws, psurf, xsurf); +} + + + +/** + * Called via eglCreateContext(), drv->API.CreateContext(). + */ +static EGLContext +xlib_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, + 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; + + /* let EGL lib init the common stuff */ + if (!_eglInitContext(drv, dpy, &ctx->Base, config, attrib_list)) { + free(ctx); + return EGL_NO_CONTEXT; + } + + /* API-dependent context creation */ + switch (ctx->Base.ClientAPI) { + case EGL_OPENGL_ES_API: + _eglLog(_EGL_DEBUG, "Create Context for ES version %d\n", + ctx->Base.ClientVersion); + /* fall-through */ + case EGL_OPENGL_API: + /* create a softpipe context */ + ctx->pipe = softpipe_create(xdrv->screen, xdrv->winsys, NULL); + /* Now do xlib / state tracker inits here */ + _eglConfigToContextModesRec(conf, &visual); + ctx->Context = st_create_context(ctx->pipe, &visual, share_ctx); + break; + default: + _eglError(EGL_BAD_MATCH, "eglCreateContext(unsupported API)"); + free(ctx); + return EGL_NO_CONTEXT; + } + + _eglSaveContext(&ctx->Base); + + return _eglGetContextHandle(&ctx->Base); +} + + +static EGLBoolean +xlib_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx) +{ + struct xlib_egl_context *context = lookup_context(ctx); + if (context) { + if (context->Base.IsBound) { + context->Base.DeletePending = EGL_TRUE; + } + else { + /* API-dependent clean-up */ + switch (context->Base.ClientAPI) { + case EGL_OPENGL_ES_API: + /* fall-through */ + case EGL_OPENGL_API: + st_destroy_context(context->Context); + break; + default: + assert(0); + } + free(context); + } + return EGL_TRUE; + } + else { + _eglError(EGL_BAD_CONTEXT, "eglDestroyContext"); + return EGL_TRUE; + } +} + + +/** + * Called via eglMakeCurrent(), drv->API.MakeCurrent(). + */ +static EGLBoolean +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); + + if (!_eglMakeCurrent(drv, dpy, draw, read, context)) + return EGL_FALSE; + + st_make_current((context ? context->Context : NULL), + (draw_surf ? draw_surf->Framebuffer : NULL), + (read_surf ? read_surf->Framebuffer : NULL)); + + if (draw_surf) + check_and_update_buffer_size(draw_surf); + if (read_surf && read_surf != draw_surf) + check_and_update_buffer_size(draw_surf); + + return EGL_TRUE; +} + + +static enum pipe_format +choose_color_format(const __GLcontextModes *visual) +{ + if (visual->redBits == 8 && + visual->greenBits == 8 && + visual->blueBits == 8 && + visual->alphaBits == 8) { + /* XXX this really also depends on the ordering of R,G,B,A */ + return PIPE_FORMAT_A8R8G8B8_UNORM; + } + else { + assert(0); + return PIPE_FORMAT_NONE; + } +} + + +static enum pipe_format +choose_depth_format(const __GLcontextModes *visual) +{ + if (visual->depthBits > 0) + return PIPE_FORMAT_S8Z24_UNORM; + else + return PIPE_FORMAT_NONE; +} + + +static enum pipe_format +choose_stencil_format(const __GLcontextModes *visual) +{ + if (visual->stencilBits > 0) + return PIPE_FORMAT_S8Z24_UNORM; + else + return PIPE_FORMAT_NONE; +} + + +/** + * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). + */ +static EGLSurface +xlib_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, + 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; + + /* Let EGL lib init the common stuff */ + if (!_eglInitSurface(drv, dpy, &surf->Base, EGL_WINDOW_BIT, + config, attrib_list)) { + free(surf); + return EGL_NO_SURFACE; + } + + _eglSaveSurface(&surf->Base); + + /* + * Now init the Xlib and gallium stuff + */ + surf->Win = (Window) window; /* The X window ID */ + surf->Dpy = disp->Xdpy; /* The X display */ + surf->Gc = XCreateGC(surf->Dpy, surf->Win, 0, NULL); + + surf->winsys = xdrv->winsys; + + _eglConfigToContextModesRec(conf, &visual); + get_drawable_size(surf->Dpy, surf->Win, &width, &height); + get_drawable_visual_info(surf->Dpy, surf->Win, &surf->VisInfo); + + surf->Base.Width = width; + surf->Base.Height = height; + + /* Create GL statetracker framebuffer */ + surf->Framebuffer = st_create_framebuffer(&visual, + choose_color_format(&visual), + choose_depth_format(&visual), + choose_stencil_format(&visual), + width, height, + (void *) surf); + + st_resize_framebuffer(surf->Framebuffer, width, height); + + return _eglGetSurfaceHandle(&surf->Base); +} + + +static EGLBoolean +xlib_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) +{ + struct xlib_egl_surface *surf = lookup_surface(surface); + if (surf) { + _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surface); + if (surf->Base.IsBound) { + surf->Base.DeletePending = EGL_TRUE; + } + else { + st_unreference_framebuffer(&surf->Framebuffer); + free(surf); + } + return EGL_TRUE; + } + else { + _eglError(EGL_BAD_SURFACE, "eglDestroySurface"); + return EGL_FALSE; + } +} + + +static EGLBoolean +xlib_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) +{ + /* error checking step: */ + if (!_eglSwapBuffers(drv, dpy, draw)) + return EGL_FALSE; + + { + struct xlib_egl_surface *xsurf = lookup_surface(draw); + struct pipe_winsys *pws = xsurf->winsys; + struct pipe_surface *psurf = + st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT); + + st_notify_swapbuffers(xsurf->Framebuffer); + + display_surface(pws, psurf, xsurf); + + check_and_update_buffer_size(xsurf); + } + + return EGL_TRUE; +} + + +/** + * Determine which API(s) is(are) present by looking for some specific + * global symbols. + */ +static EGLint +find_supported_apis(void) +{ + EGLint mask = 0; + void *handle; + + handle = dlopen(NULL, 0); + + if (dlsym(handle, "st_api_OpenGL_ES1")) + mask |= EGL_OPENGL_ES_BIT; + + if (dlsym(handle, "st_api_OpenGL_ES2")) + mask |= EGL_OPENGL_ES2_BIT; + + if (dlsym(handle, "st_api_OpenGL")) + mask |= EGL_OPENGL_BIT; + + if (dlsym(handle, "st_api_OpenVG")) + mask |= EGL_OPENVG_BIT; + + dlclose(handle); + + return mask; +} + + +/** + * This is the main entrypoint into the driver. + * Called by libEGL to instantiate an _EGLDriver object. + */ +_EGLDriver * +_eglMain(_EGLDisplay *dpy, const char *args) +{ + struct xlib_egl_driver *xdrv; + + _eglLog(_EGL_INFO, "Entering EGL/Xlib _eglMain(%s)", args); + + xdrv = CALLOC_STRUCT(xlib_egl_driver); + 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; + xdrv->Base.API.GetProcAddress = xlib_eglGetProcAddress; + xdrv->Base.API.CreateContext = xlib_eglCreateContext; + xdrv->Base.API.DestroyContext = xlib_eglDestroyContext; + xdrv->Base.API.CreateWindowSurface = xlib_eglCreateWindowSurface; + xdrv->Base.API.DestroySurface = xlib_eglDestroySurface; + xdrv->Base.API.MakeCurrent = xlib_eglMakeCurrent; + xdrv->Base.API.SwapBuffers = xlib_eglSwapBuffers; + + xdrv->Base.ClientAPIsMask = find_supported_apis(); + if (xdrv->Base.ClientAPIsMask == 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->Base.Name = "Xlib/softpipe"; + + /* create one winsys and use it for all contexts/surfaces */ + xdrv->winsys = create_sw_winsys(); + xdrv->winsys->flush_frontbuffer = flush_frontbuffer; + + xdrv->screen = softpipe_create_screen(xdrv->winsys); + + return &xdrv->Base; +} + diff --git a/src/gallium/winsys/egl_xlib/sw_winsys.c b/src/gallium/winsys/egl_xlib/sw_winsys.c new file mode 100644 index 0000000000..28cca9e581 --- /dev/null +++ b/src/gallium/winsys/egl_xlib/sw_winsys.c @@ -0,0 +1,283 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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, 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 TUNGSTEN GRAPHICS AND/OR ITS 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. + * + **************************************************************************/ + +/** + * Totally software-based winsys layer. + * Note that the one winsys function that we can't implement here + * is flush_frontbuffer(). + * Whoever uses this code will have to provide that. + * + * Authors: Brian Paul + */ + + +#include "pipe/p_winsys.h" +#include "pipe/p_state.h" +#include "pipe/p_util.h" +#include "pipe/p_inlines.h" + +#include "sw_winsys.h" + + + +/** Subclass of pipe_winsys */ +struct sw_pipe_winsys +{ + struct pipe_winsys Base; + /* no extra fields for now */ +}; + + +/** subclass of pipe_buffer */ +struct sw_pipe_buffer +{ + struct pipe_buffer Base; + boolean UserBuffer; /** Is this a user-space buffer? */ + void *Data; + void *Mapped; +}; + + +/** cast wrapper */ +static INLINE struct sw_pipe_buffer * +sw_pipe_buffer(struct pipe_buffer *b) +{ + return (struct sw_pipe_buffer *) b; +} + + +/** + * Round n up to next multiple. + */ +static INLINE unsigned +round_up(unsigned n, unsigned multiple) +{ + return (n + multiple - 1) & ~(multiple - 1); +} + + +static const char * +get_name(struct pipe_winsys *pws) +{ + return "software"; +} + + +/** Create new pipe_buffer and allocate storage of given size */ +static struct pipe_buffer * +buffer_create(struct pipe_winsys *pws, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer); + if (!buffer) + return NULL; + + buffer->Base.refcount = 1; + buffer->Base.alignment = alignment; + buffer->Base.usage = usage; + buffer->Base.size = size; + + /* align to 16-byte multiple for Cell */ + buffer->Data = align_malloc(size, MAX2(alignment, 16)); + + return &buffer->Base; +} + + +/** + * Create buffer which wraps user-space data. + */ +static struct pipe_buffer * +user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes) +{ + struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer); + if (!buffer) + return NULL; + + buffer->Base.refcount = 1; + buffer->Base.size = bytes; + buffer->UserBuffer = TRUE; + buffer->Data = ptr; + + return &buffer->Base; +} + + +static void * +buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf, unsigned flags) +{ + struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf); + buffer->Mapped = buffer->Data; + return buffer->Mapped; +} + + +static void +buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf) +{ + struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf); + buffer->Mapped = NULL; +} + + +static void +buffer_destroy(struct pipe_winsys *pws, struct pipe_buffer *buf) +{ + struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf); + + if (buffer->Data && !buffer->UserBuffer) { + align_free(buffer->Data); + buffer->Data = NULL; + } + + free(buffer); +} + + +/** + * Called via winsys->surface_alloc() to create new surfaces. + */ +static struct pipe_surface * +surface_alloc(struct pipe_winsys *ws) +{ + struct pipe_surface *surf = CALLOC_STRUCT(pipe_surface); + if (!surf) + return NULL; + + surf->refcount = 1; + surf->winsys = ws; + + return surf; +} + + +static int +surface_alloc_storage(struct pipe_winsys *winsys, + struct pipe_surface *surf, + unsigned width, unsigned height, + enum pipe_format format, + unsigned flags, + unsigned tex_usage) +{ + const unsigned alignment = 64; + + surf->width = width; + surf->height = height; + surf->format = format; + surf->cpp = pf_get_size(format); + surf->pitch = round_up(width, alignment / surf->cpp); + surf->usage = flags; + + assert(surf->cpp >= 1); + assert(surf->cpp <= 16); + assert(!surf->buffer); + surf->buffer = winsys->buffer_create(winsys, alignment, + PIPE_BUFFER_USAGE_PIXEL, + surf->pitch * surf->cpp * height); + if(!surf->buffer) + return -1; + + return 0; +} + + +static void +surface_release(struct pipe_winsys *winsys, struct pipe_surface **s) +{ + struct pipe_surface *surf = *s; + assert(!surf->texture); + surf->refcount--; + if (surf->refcount == 0) { + if (surf->buffer) + pipe_buffer_reference(winsys, &surf->buffer, NULL); + free(surf); + } + *s = NULL; +} + + +static void +fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence) +{ + /* no-op */ +} + + +static int +fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence, + unsigned flag) +{ + /* no-op */ + return 0; +} + + +static int +fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence, + unsigned flag) +{ + /* no-op */ + return 0; +} + + +/** + * Create/return a new pipe_winsys object. + */ +struct pipe_winsys * +create_sw_winsys(void) +{ + struct sw_pipe_winsys *ws = CALLOC_STRUCT(sw_pipe_winsys); + if (!ws) + return NULL; + + /* Fill in this struct with callbacks that pipe will need to + * communicate with the window system, buffer manager, etc. + */ + ws->Base.buffer_create = buffer_create; + ws->Base.user_buffer_create = user_buffer_create; + ws->Base.buffer_map = buffer_map; + ws->Base.buffer_unmap = buffer_unmap; + ws->Base.buffer_destroy = buffer_destroy; + + ws->Base.surface_alloc = surface_alloc; + ws->Base.surface_alloc_storage = surface_alloc_storage; + ws->Base.surface_release = surface_release; + + ws->Base.fence_reference = fence_reference; + ws->Base.fence_signalled = fence_signalled; + ws->Base.fence_finish = fence_finish; + + ws->Base.flush_frontbuffer = NULL; /* not implemented here! */ + + ws->Base.get_name = get_name; + + return &ws->Base; +} diff --git a/src/gallium/winsys/egl_drm/intel/intel_winsys.h b/src/gallium/winsys/egl_xlib/sw_winsys.h index d0a319f9a4..f96c5a14b0 100644 --- a/src/gallium/winsys/egl_drm/intel/intel_winsys.h +++ b/src/gallium/winsys/egl_xlib/sw_winsys.h @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -25,49 +25,16 @@ * **************************************************************************/ -#ifndef INTEL_WINSYS_H -#define INTEL_WINSYS_H -#include "pipe/p_state.h" +#ifndef SW_WINSYS_H +#define SW_WINSYS_H -struct intel_context; -struct pipe_context; -struct pipe_winsys; -struct pipe_buffer; -struct _DriBufferObject; - -struct pipe_winsys * -intel_create_pipe_winsys( int fd, struct _DriFreeSlabManager *fMan ); - -void -intel_destroy_pipe_winsys( struct pipe_winsys *winsys ); - -struct pipe_context * -intel_create_softpipe( struct intel_context *intel, - struct pipe_winsys *winsys ); -struct pipe_context * -intel_create_i915simple( struct intel_context *intel, - struct pipe_winsys *winsys ); - - -struct intel_buffer { - struct pipe_buffer base; - struct _DriBufferObject *driBO; -}; - -static INLINE struct intel_buffer * -intel_buffer( struct pipe_buffer *buf ) -{ - return (struct intel_buffer *)buf; -} +struct pipe_winsys; -static INLINE struct _DriBufferObject * -dri_bo( struct pipe_buffer *buf ) -{ - return intel_buffer(buf)->driBO; -} +extern struct pipe_winsys * +create_sw_winsys(void); -#endif +#endif /* SW_WINSYS_H */ diff --git a/src/gallium/winsys/gdi/SConscript b/src/gallium/winsys/gdi/SConscript new file mode 100644 index 0000000000..170fdf5127 --- /dev/null +++ b/src/gallium/winsys/gdi/SConscript @@ -0,0 +1,33 @@ +####################################################################### +# SConscript for gdi winsys + +Import('*') + +if env['platform'] == 'windows': + + env = env.Clone() + + env.Append(CPPPATH = [ + '#src/mesa/glapi', + '#src/mesa', + '#src/mesa/main', + ]) + + sources = [ + 'opengl32.def', + 'wgl.c', + 'wmesa.c', + ] + + drivers = [ + softpipe, + ] + + env.Append(LIBS = ['gdi32', 'user32']) + + # TODO: write a wrapper function http://www.scons.org/wiki/WrapperFunctions + env.SharedLibrary( + target ='opengl32', + source = sources, + LIBS = glapi + mesa + drivers + auxiliaries + env['LIBS'], + ) diff --git a/src/gallium/winsys/gdi/colors.h b/src/gallium/winsys/gdi/colors.h new file mode 100644 index 0000000000..03e512c1fa --- /dev/null +++ b/src/gallium/winsys/gdi/colors.h @@ -0,0 +1,29 @@ +/* Values for wmesa->pixelformat: */ + +#define PF_8A8B8G8R 3 /* 32-bit TrueColor: 8-A, 8-B, 8-G, 8-R */ +#define PF_8R8G8B 4 /* 32-bit TrueColor: 8-R, 8-G, 8-B */ +#define PF_5R6G5B 5 /* 16-bit TrueColor: 5-R, 6-G, 5-B bits */ +#define PF_DITHER8 6 /* Dithered RGB using a lookup table */ +#define PF_LOOKUP 7 /* Undithered RGB using a lookup table */ +#define PF_GRAYSCALE 10 /* Grayscale or StaticGray */ +#define PF_BADFORMAT 11 +#define PF_INDEX8 12 + + +#define BGR8(r,g,b) (unsigned)(((BYTE)((b & 0xc0) | ((g & 0xe0)>>2) | \ + ((r & 0xe0)>>5)))) + +/* Windows uses 5,5,5 for 16-bit */ +#define BGR16(r,g,b) ( (((unsigned short)b ) >> 3) | \ + (((unsigned short)g & 0xf8) << 2) | \ + (((unsigned short)r & 0xf8) << 7) ) + +#define BGR24(r,g,b) (unsigned long)((DWORD)(((BYTE)(b)| \ + ((WORD)((BYTE)(g))<<8))| \ + (((DWORD)(BYTE)(r))<<16))) + +#define BGR32(r,g,b) (unsigned long)((DWORD)(((BYTE)(b)| \ + ((WORD)((BYTE)(g))<<8))| \ + (((DWORD)(BYTE)(r))<<16))) + + diff --git a/src/gallium/winsys/gdi/opengl32.def b/src/gallium/winsys/gdi/opengl32.def new file mode 100644 index 0000000000..54e72f57b1 --- /dev/null +++ b/src/gallium/winsys/gdi/opengl32.def @@ -0,0 +1,859 @@ +; DO NOT EDIT - This file generated automatically by mesadef.py script +;DESCRIPTION 'Mesa (OpenGL work-alike) for Win32' +VERSION 6.5 +; +; Module definition file for Mesa (OPENGL32.DLL) +; +; Note: The OpenGL functions use the STDCALL +; function calling convention. Microsoft's +; OPENGL32 uses this convention and so must the +; Mesa OPENGL32 so that the Mesa DLL can be used +; as a drop-in replacement. +; +; The linker exports STDCALL entry points with +; 'decorated' names; e.g., _glBegin@0, where the +; trailing number is the number of bytes of +; parameter data pushed onto the stack. The +; callee is responsible for popping this data +; off the stack, usually via a RETF n instruction. +; +; However, the Microsoft OPENGL32.DLL does not export +; the decorated names, even though the calling convention +; is STDCALL. So, this module definition file is +; needed to force the Mesa OPENGL32.DLL to export the +; symbols in the same manner as the Microsoft DLL. +; Were it not for this problem, this file would not +; be needed (for the gl* functions) since the entry +; points are compiled with dllexport declspec. +; +; However, this file is still needed to export "internal" +; Mesa symbols for the benefit of the OSMESA32.DLL. +; +EXPORTS + glNewList + glEndList + glCallList + glCallLists + glDeleteLists + glGenLists + glListBase + glBegin + glBitmap + glColor3b + glColor3bv + glColor3d + glColor3dv + glColor3f + glColor3fv + glColor3i + glColor3iv + glColor3s + glColor3sv + glColor3ub + glColor3ubv + glColor3ui + glColor3uiv + glColor3us + glColor3usv + glColor4b + glColor4bv + glColor4d + glColor4dv + glColor4f + glColor4fv + glColor4i + glColor4iv + glColor4s + glColor4sv + glColor4ub + glColor4ubv + glColor4ui + glColor4uiv + glColor4us + glColor4usv + glEdgeFlag + glEdgeFlagv + glEnd + glIndexd + glIndexdv + glIndexf + glIndexfv + glIndexi + glIndexiv + glIndexs + glIndexsv + glNormal3b + glNormal3bv + glNormal3d + glNormal3dv + glNormal3f + glNormal3fv + glNormal3i + glNormal3iv + glNormal3s + glNormal3sv + glRasterPos2d + glRasterPos2dv + glRasterPos2f + glRasterPos2fv + glRasterPos2i + glRasterPos2iv + glRasterPos2s + glRasterPos2sv + glRasterPos3d + glRasterPos3dv + glRasterPos3f + glRasterPos3fv + glRasterPos3i + glRasterPos3iv + glRasterPos3s + glRasterPos3sv + glRasterPos4d + glRasterPos4dv + glRasterPos4f + glRasterPos4fv + glRasterPos4i + glRasterPos4iv + glRasterPos4s + glRasterPos4sv + glRectd + glRectdv + glRectf + glRectfv + glRecti + glRectiv + glRects + glRectsv + glTexCoord1d + glTexCoord1dv + glTexCoord1f + glTexCoord1fv + glTexCoord1i + glTexCoord1iv + glTexCoord1s + glTexCoord1sv + glTexCoord2d + glTexCoord2dv + glTexCoord2f + glTexCoord2fv + glTexCoord2i + glTexCoord2iv + glTexCoord2s + glTexCoord2sv + glTexCoord3d + glTexCoord3dv + glTexCoord3f + glTexCoord3fv + glTexCoord3i + glTexCoord3iv + glTexCoord3s + glTexCoord3sv + glTexCoord4d + glTexCoord4dv + glTexCoord4f + glTexCoord4fv + glTexCoord4i + glTexCoord4iv + glTexCoord4s + glTexCoord4sv + glVertex2d + glVertex2dv + glVertex2f + glVertex2fv + glVertex2i + glVertex2iv + glVertex2s + glVertex2sv + glVertex3d + glVertex3dv + glVertex3f + glVertex3fv + glVertex3i + glVertex3iv + glVertex3s + glVertex3sv + glVertex4d + glVertex4dv + glVertex4f + glVertex4fv + glVertex4i + glVertex4iv + glVertex4s + glVertex4sv + glClipPlane + glColorMaterial + glCullFace + glFogf + glFogfv + glFogi + glFogiv + glFrontFace + glHint + glLightf + glLightfv + glLighti + glLightiv + glLightModelf + glLightModelfv + glLightModeli + glLightModeliv + glLineStipple + glLineWidth + glMaterialf + glMaterialfv + glMateriali + glMaterialiv + glPointSize + glPolygonMode + glPolygonStipple + glScissor + glShadeModel + glTexParameterf + glTexParameterfv + glTexParameteri + glTexParameteriv + glTexImage1D + glTexImage2D + glTexEnvf + glTexEnvfv + glTexEnvi + glTexEnviv + glTexGend + glTexGendv + glTexGenf + glTexGenfv + glTexGeni + glTexGeniv + glFeedbackBuffer + glSelectBuffer + glRenderMode + glInitNames + glLoadName + glPassThrough + glPopName + glPushName + glDrawBuffer + glClear + glClearAccum + glClearIndex + glClearColor + glClearStencil + glClearDepth + glStencilMask + glColorMask + glDepthMask + glIndexMask + glAccum + glDisable + glEnable + glFinish + glFlush + glPopAttrib + glPushAttrib + glMap1d + glMap1f + glMap2d + glMap2f + glMapGrid1d + glMapGrid1f + glMapGrid2d + glMapGrid2f + glEvalCoord1d + glEvalCoord1dv + glEvalCoord1f + glEvalCoord1fv + glEvalCoord2d + glEvalCoord2dv + glEvalCoord2f + glEvalCoord2fv + glEvalMesh1 + glEvalPoint1 + glEvalMesh2 + glEvalPoint2 + glAlphaFunc + glBlendFunc + glLogicOp + glStencilFunc + glStencilOp + glDepthFunc + glPixelZoom + glPixelTransferf + glPixelTransferi + glPixelStoref + glPixelStorei + glPixelMapfv + glPixelMapuiv + glPixelMapusv + glReadBuffer + glCopyPixels + glReadPixels + glDrawPixels + glGetBooleanv + glGetClipPlane + glGetDoublev + glGetError + glGetFloatv + glGetIntegerv + glGetLightfv + glGetLightiv + glGetMapdv + glGetMapfv + glGetMapiv + glGetMaterialfv + glGetMaterialiv + glGetPixelMapfv + glGetPixelMapuiv + glGetPixelMapusv + glGetPolygonStipple + glGetString + glGetTexEnvfv + glGetTexEnviv + glGetTexGendv + glGetTexGenfv + glGetTexGeniv + glGetTexImage + glGetTexParameterfv + glGetTexParameteriv + glGetTexLevelParameterfv + glGetTexLevelParameteriv + glIsEnabled + glIsList + glDepthRange + glFrustum + glLoadIdentity + glLoadMatrixf + glLoadMatrixd + glMatrixMode + glMultMatrixf + glMultMatrixd + glOrtho + glPopMatrix + glPushMatrix + glRotated + glRotatef + glScaled + glScalef + glTranslated + glTranslatef + glViewport + glArrayElement + glColorPointer + glDisableClientState + glDrawArrays + glDrawElements + glEdgeFlagPointer + glEnableClientState + glGetPointerv + glIndexPointer + glInterleavedArrays + glNormalPointer + glTexCoordPointer + glVertexPointer + glPolygonOffset + glCopyTexImage1D + glCopyTexImage2D + glCopyTexSubImage1D + glCopyTexSubImage2D + glTexSubImage1D + glTexSubImage2D + glAreTexturesResident + glBindTexture + glDeleteTextures + glGenTextures + glIsTexture + glPrioritizeTextures + glIndexub + glIndexubv + glPopClientAttrib + glPushClientAttrib + glBlendColor + glBlendEquation + glDrawRangeElements + glColorTable + glColorTableParameterfv + glColorTableParameteriv + glCopyColorTable + glGetColorTable + glGetColorTableParameterfv + glGetColorTableParameteriv + glColorSubTable + glCopyColorSubTable + glConvolutionFilter1D + glConvolutionFilter2D + glConvolutionParameterf + glConvolutionParameterfv + glConvolutionParameteri + glConvolutionParameteriv + glCopyConvolutionFilter1D + glCopyConvolutionFilter2D + glGetConvolutionFilter + glGetConvolutionParameterfv + glGetConvolutionParameteriv + glGetSeparableFilter + glSeparableFilter2D + glGetHistogram + glGetHistogramParameterfv + glGetHistogramParameteriv + glGetMinmax + glGetMinmaxParameterfv + glGetMinmaxParameteriv + glHistogram + glMinmax + glResetHistogram + glResetMinmax + glTexImage3D + glTexSubImage3D + glCopyTexSubImage3D + glActiveTextureARB + glClientActiveTextureARB + glMultiTexCoord1dARB + glMultiTexCoord1dvARB + glMultiTexCoord1fARB + glMultiTexCoord1fvARB + glMultiTexCoord1iARB + glMultiTexCoord1ivARB + glMultiTexCoord1sARB + glMultiTexCoord1svARB + glMultiTexCoord2dARB + glMultiTexCoord2dvARB + glMultiTexCoord2fARB + glMultiTexCoord2fvARB + glMultiTexCoord2iARB + glMultiTexCoord2ivARB + glMultiTexCoord2sARB + glMultiTexCoord2svARB + glMultiTexCoord3dARB + glMultiTexCoord3dvARB + glMultiTexCoord3fARB + glMultiTexCoord3fvARB + glMultiTexCoord3iARB + glMultiTexCoord3ivARB + glMultiTexCoord3sARB + glMultiTexCoord3svARB + glMultiTexCoord4dARB + glMultiTexCoord4dvARB + glMultiTexCoord4fARB + glMultiTexCoord4fvARB + glMultiTexCoord4iARB + glMultiTexCoord4ivARB + glMultiTexCoord4sARB + glMultiTexCoord4svARB + glLoadTransposeMatrixfARB + glLoadTransposeMatrixdARB + glMultTransposeMatrixfARB + glMultTransposeMatrixdARB + glSampleCoverageARB + glCompressedTexImage3DARB + glCompressedTexImage2DARB + glCompressedTexImage1DARB + glCompressedTexSubImage3DARB + glCompressedTexSubImage2DARB + glCompressedTexSubImage1DARB + glGetCompressedTexImageARB + glActiveTexture + glClientActiveTexture + glMultiTexCoord1d + glMultiTexCoord1dv + glMultiTexCoord1f + glMultiTexCoord1fv + glMultiTexCoord1i + glMultiTexCoord1iv + glMultiTexCoord1s + glMultiTexCoord1sv + glMultiTexCoord2d + glMultiTexCoord2dv + glMultiTexCoord2f + glMultiTexCoord2fv + glMultiTexCoord2i + glMultiTexCoord2iv + glMultiTexCoord2s + glMultiTexCoord2sv + glMultiTexCoord3d + glMultiTexCoord3dv + glMultiTexCoord3f + glMultiTexCoord3fv + glMultiTexCoord3i + glMultiTexCoord3iv + glMultiTexCoord3s + glMultiTexCoord3sv + glMultiTexCoord4d + glMultiTexCoord4dv + glMultiTexCoord4f + glMultiTexCoord4fv + glMultiTexCoord4i + glMultiTexCoord4iv + glMultiTexCoord4s + glMultiTexCoord4sv + glLoadTransposeMatrixf + glLoadTransposeMatrixd + glMultTransposeMatrixf + glMultTransposeMatrixd + glSampleCoverage + glCompressedTexImage3D + glCompressedTexImage2D + glCompressedTexImage1D + glCompressedTexSubImage3D + glCompressedTexSubImage2D + glCompressedTexSubImage1D + glGetCompressedTexImage + glBlendColorEXT + glPolygonOffsetEXT + glTexImage3DEXT + glTexSubImage3DEXT + glTexSubImage1DEXT + glTexSubImage2DEXT + glCopyTexImage1DEXT + glCopyTexImage2DEXT + glCopyTexSubImage1DEXT + glCopyTexSubImage2DEXT + glCopyTexSubImage3DEXT + glAreTexturesResidentEXT + glBindTextureEXT + glDeleteTexturesEXT + glGenTexturesEXT + glIsTextureEXT + glPrioritizeTexturesEXT + glArrayElementEXT + glColorPointerEXT + glDrawArraysEXT + glEdgeFlagPointerEXT + glGetPointervEXT + glIndexPointerEXT + glNormalPointerEXT + glTexCoordPointerEXT + glVertexPointerEXT + glBlendEquationEXT + glPointParameterfEXT + glPointParameterfvEXT + glPointParameterfARB + glPointParameterfvARB + glColorTableEXT + glGetColorTableEXT + glGetColorTableParameterivEXT + glGetColorTableParameterfvEXT + glLockArraysEXT + glUnlockArraysEXT + glDrawRangeElementsEXT + glSecondaryColor3bEXT + glSecondaryColor3bvEXT + glSecondaryColor3dEXT + glSecondaryColor3dvEXT + glSecondaryColor3fEXT + glSecondaryColor3fvEXT + glSecondaryColor3iEXT + glSecondaryColor3ivEXT + glSecondaryColor3sEXT + glSecondaryColor3svEXT + glSecondaryColor3ubEXT + glSecondaryColor3ubvEXT + glSecondaryColor3uiEXT + glSecondaryColor3uivEXT + glSecondaryColor3usEXT + glSecondaryColor3usvEXT + glSecondaryColorPointerEXT + glMultiDrawArraysEXT + glMultiDrawElementsEXT + glFogCoordfEXT + glFogCoordfvEXT + glFogCoorddEXT + glFogCoorddvEXT + glFogCoordPointerEXT + glBlendFuncSeparateEXT + glFlushVertexArrayRangeNV + glVertexArrayRangeNV + glCombinerParameterfvNV + glCombinerParameterfNV + glCombinerParameterivNV + glCombinerParameteriNV + glCombinerInputNV + glCombinerOutputNV + glFinalCombinerInputNV + glGetCombinerInputParameterfvNV + glGetCombinerInputParameterivNV + glGetCombinerOutputParameterfvNV + glGetCombinerOutputParameterivNV + glGetFinalCombinerInputParameterfvNV + glGetFinalCombinerInputParameterivNV + glResizeBuffersMESA + glWindowPos2dMESA + glWindowPos2dvMESA + glWindowPos2fMESA + glWindowPos2fvMESA + glWindowPos2iMESA + glWindowPos2ivMESA + glWindowPos2sMESA + glWindowPos2svMESA + glWindowPos3dMESA + glWindowPos3dvMESA + glWindowPos3fMESA + glWindowPos3fvMESA + glWindowPos3iMESA + glWindowPos3ivMESA + glWindowPos3sMESA + glWindowPos3svMESA + glWindowPos4dMESA + glWindowPos4dvMESA + glWindowPos4fMESA + glWindowPos4fvMESA + glWindowPos4iMESA + glWindowPos4ivMESA + glWindowPos4sMESA + glWindowPos4svMESA + glWindowPos2dARB + glWindowPos2fARB + glWindowPos2iARB + glWindowPos2sARB + glWindowPos2dvARB + glWindowPos2fvARB + glWindowPos2ivARB + glWindowPos2svARB + glWindowPos3dARB + glWindowPos3fARB + glWindowPos3iARB + glWindowPos3sARB + glWindowPos3dvARB + glWindowPos3fvARB + glWindowPos3ivARB + glWindowPos3svARB + glAreProgramsResidentNV + glBindProgramNV + glDeleteProgramsNV + glExecuteProgramNV + glGenProgramsNV + glGetProgramParameterdvNV + glGetProgramParameterfvNV + glGetProgramivNV + glGetProgramStringNV + glGetTrackMatrixivNV + glGetVertexAttribdvNV + glGetVertexAttribfvNV + glGetVertexAttribivNV + glGetVertexAttribPointervNV + glIsProgramNV + glLoadProgramNV + glProgramParameter4dNV + glProgramParameter4dvNV + glProgramParameter4fNV + glProgramParameter4fvNV + glProgramParameters4dvNV + glProgramParameters4fvNV + glRequestResidentProgramsNV + glTrackMatrixNV + glVertexAttribPointerNV + glVertexAttrib1dNV + glVertexAttrib1dvNV + glVertexAttrib1fNV + glVertexAttrib1fvNV + glVertexAttrib1sNV + glVertexAttrib1svNV + glVertexAttrib2dNV + glVertexAttrib2dvNV + glVertexAttrib2fNV + glVertexAttrib2fvNV + glVertexAttrib2sNV + glVertexAttrib2svNV + glVertexAttrib3dNV + glVertexAttrib3dvNV + glVertexAttrib3fNV + glVertexAttrib3fvNV + glVertexAttrib3sNV + glVertexAttrib3svNV + glVertexAttrib4dNV + glVertexAttrib4dvNV + glVertexAttrib4fNV + glVertexAttrib4fvNV + glVertexAttrib4sNV + glVertexAttrib4svNV + glVertexAttrib4ubNV + glVertexAttrib4ubvNV + glVertexAttribs1dvNV + glVertexAttribs1fvNV + glVertexAttribs1svNV + glVertexAttribs2dvNV + glVertexAttribs2fvNV + glVertexAttribs2svNV + glVertexAttribs3dvNV + glVertexAttribs3fvNV + glVertexAttribs3svNV + glVertexAttribs4dvNV + glVertexAttribs4fvNV + glVertexAttribs4svNV + glVertexAttribs4ubvNV + glPointParameteriNV + glPointParameterivNV + glFogCoordf + glFogCoordfv + glFogCoordd + glFogCoorddv + glFogCoordPointer + glMultiDrawArrays + glMultiDrawElements + glPointParameterf + glPointParameterfv + glPointParameteri + glPointParameteriv + glSecondaryColor3b + glSecondaryColor3bv + glSecondaryColor3d + glSecondaryColor3dv + glSecondaryColor3f + glSecondaryColor3fv + glSecondaryColor3i + glSecondaryColor3iv + glSecondaryColor3s + glSecondaryColor3sv + glSecondaryColor3ub + glSecondaryColor3ubv + glSecondaryColor3ui + glSecondaryColor3uiv + glSecondaryColor3us + glSecondaryColor3usv + glSecondaryColorPointer + glWindowPos2d + glWindowPos2dv + glWindowPos2f + glWindowPos2fv + glWindowPos2i + glWindowPos2iv + glWindowPos2s + glWindowPos2sv + glWindowPos3d + glWindowPos3dv + glWindowPos3f + glWindowPos3fv + glWindowPos3i + glWindowPos3iv + glWindowPos3s + glWindowPos3sv + glVertexAttrib1sARB + glVertexAttrib1fARB + glVertexAttrib1dARB + glVertexAttrib2sARB + glVertexAttrib2fARB + glVertexAttrib2dARB + glVertexAttrib3sARB + glVertexAttrib3fARB + glVertexAttrib3dARB + glVertexAttrib4sARB + glVertexAttrib4fARB + glVertexAttrib4dARB + glVertexAttrib4NubARB + glVertexAttrib1svARB + glVertexAttrib1fvARB + glVertexAttrib1dvARB + glVertexAttrib2svARB + glVertexAttrib2fvARB + glVertexAttrib2dvARB + glVertexAttrib3svARB + glVertexAttrib3fvARB + glVertexAttrib3dvARB + glVertexAttrib4bvARB + glVertexAttrib4svARB + glVertexAttrib4ivARB + glVertexAttrib4ubvARB + glVertexAttrib4usvARB + glVertexAttrib4uivARB + glVertexAttrib4fvARB + glVertexAttrib4dvARB + glVertexAttrib4NbvARB + glVertexAttrib4NsvARB + glVertexAttrib4NivARB + glVertexAttrib4NubvARB + glVertexAttrib4NusvARB + glVertexAttrib4NuivARB + glVertexAttribPointerARB + glEnableVertexAttribArrayARB + glDisableVertexAttribArrayARB + glProgramStringARB + glBindProgramARB + glDeleteProgramsARB + glGenProgramsARB + glIsProgramARB + glProgramEnvParameter4dARB + glProgramEnvParameter4dvARB + glProgramEnvParameter4fARB + glProgramEnvParameter4fvARB + glProgramLocalParameter4dARB + glProgramLocalParameter4dvARB + glProgramLocalParameter4fARB + glProgramLocalParameter4fvARB + glGetProgramEnvParameterdvARB + glGetProgramEnvParameterfvARB + glGetProgramLocalParameterdvARB + glGetProgramLocalParameterfvARB + glGetProgramivARB + glGetProgramStringARB + glGetVertexAttribdvARB + glGetVertexAttribfvARB + glGetVertexAttribivARB + glGetVertexAttribPointervARB + glProgramNamedParameter4fNV + glProgramNamedParameter4dNV + glProgramNamedParameter4fvNV + glProgramNamedParameter4dvNV + glGetProgramNamedParameterfvNV + glGetProgramNamedParameterdvNV + glBindBufferARB + glBufferDataARB + glBufferSubDataARB + glDeleteBuffersARB + glGenBuffersARB + glGetBufferParameterivARB + glGetBufferPointervARB + glGetBufferSubDataARB + glIsBufferARB + glMapBufferARB + glUnmapBufferARB + glGenQueriesARB + glDeleteQueriesARB + glIsQueryARB + glBeginQueryARB + glEndQueryARB + glGetQueryivARB + glGetQueryObjectivARB + glGetQueryObjectuivARB + glBindBuffer + glBufferData + glBufferSubData + glDeleteBuffers + glGenBuffers + glGetBufferParameteriv + glGetBufferPointerv + glGetBufferSubData + glIsBuffer + glMapBuffer + glUnmapBuffer + glGenQueries + glDeleteQueries + glIsQuery + glBeginQuery + glEndQuery + glGetQueryiv + glGetQueryObjectiv + glGetQueryObjectuiv +; +; WGL API + wglChoosePixelFormat + wglCopyContext + wglCreateContext + wglCreateLayerContext + wglDeleteContext + wglDescribeLayerPlane + wglDescribePixelFormat + wglGetCurrentContext + wglGetCurrentDC + wglGetLayerPaletteEntries + wglGetPixelFormat + wglGetProcAddress + wglMakeCurrent + wglRealizeLayerPalette + wglSetLayerPaletteEntries + wglSetPixelFormat + wglShareLists + wglSwapBuffers + wglSwapLayerBuffers + wglUseFontBitmapsA + wglUseFontBitmapsW + wglUseFontOutlinesA + wglUseFontOutlinesW + wglGetExtensionsStringARB diff --git a/src/gallium/winsys/gdi/wgl.c b/src/gallium/winsys/gdi/wgl.c new file mode 100644 index 0000000000..50126014a8 --- /dev/null +++ b/src/gallium/winsys/gdi/wgl.c @@ -0,0 +1,703 @@ +/* $Id: wgl.c,v 1.12 2006/03/30 07:58:24 kschultz Exp $ */ + +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * File name : wgl.c + * WGL stuff. Added by Oleg Letsinsky, ajl@ultersys.ru + * Some things originated from the 3Dfx WGL functions + */ + +/* + * This file contains the implementation of the wgl* functions for + * Mesa on Windows. Since these functions are provided by Windows in + * GDI/OpenGL, we must supply our versions that work with Mesa here. + */ + + +/* We're essentially building part of GDI here, so define this so that + * we get the right export linkage. */ +#ifdef __MINGW32__ + +#include <stdarg.h> +#include <windef.h> +#include <wincon.h> +#include <winbase.h> + +# if defined(BUILD_GL32) +# define WINGDIAPI __declspec(dllexport) +# else +# define __W32API_USE_DLLIMPORT__ +# endif + +#include <wingdi.h> +#include "GL/mesa_wgl.h" +#include <stdlib.h> + +#else + +#define _GDI32_ +#include <windows.h> + +#endif + +#include "glapi.h" +#include "GL/wmesa.h" /* protos for wmesa* functions */ + +/* + * Pixel Format Descriptors + */ + +/* Extend the PFD to include DB flag */ +struct __pixelformat__ +{ + PIXELFORMATDESCRIPTOR pfd; + GLboolean doubleBuffered; +}; + +/* These are the PFD's supported by this driver. */ +struct __pixelformat__ pfd[] = +{ + /* Double Buffer, alpha */ + { + { + sizeof(PIXELFORMATDESCRIPTOR), 1, + PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| + PFD_GENERIC_FORMAT|PFD_DOUBLEBUFFER|PFD_SWAP_COPY, + PFD_TYPE_RGBA, + 24, + 8, 0, + 8, 8, + 8, 16, + 8, 24, + 0, 0, 0, 0, 0, + 16, 8, + 0, 0, 0, + 0, 0, 0 + }, + GL_TRUE + }, + /* Single Buffer, alpha */ + { + { + sizeof(PIXELFORMATDESCRIPTOR), 1, + PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| + PFD_GENERIC_FORMAT, + PFD_TYPE_RGBA, + 24, + 8, 0, + 8, 8, + 8, 16, + 8, 24, + 0, 0, 0, 0, 0, + 16, 8, + 0, 0, 0, + 0, 0, 0 + }, + GL_FALSE + }, + /* Double Buffer, no alpha */ + { + { + sizeof(PIXELFORMATDESCRIPTOR), 1, + PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| + PFD_GENERIC_FORMAT|PFD_DOUBLEBUFFER|PFD_SWAP_COPY, + PFD_TYPE_RGBA, + 24, + 8, 0, + 8, 8, + 8, 16, + 0, 0, + 0, 0, 0, 0, 0, + 16, 8, + 0, 0, 0, + 0, 0, 0 + }, + GL_TRUE + }, + /* Single Buffer, no alpha */ + { + { + sizeof(PIXELFORMATDESCRIPTOR), 1, + PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| + PFD_GENERIC_FORMAT, + PFD_TYPE_RGBA, + 24, + 8, 0, + 8, 8, + 8, 16, + 0, 0, + 0, 0, 0, 0, 0, + 16, 8, + 0, 0, 0, + 0, 0, 0 + }, + GL_FALSE + }, +}; + +int npfd = sizeof(pfd) / sizeof(pfd[0]); + + +/* + * Contexts + */ + +typedef struct { + WMesaContext ctx; +} MesaWglCtx; + +#define MESAWGL_CTX_MAX_COUNT 20 + +static MesaWglCtx wgl_ctx[MESAWGL_CTX_MAX_COUNT]; + +static unsigned ctx_count = 0; +static int ctx_current = -1; +static unsigned curPFD = 0; + +static HDC CurrentHDC = 0; + + +WINGDIAPI HGLRC GLAPIENTRY wglCreateContext(HDC hdc) +{ + int i = 0; + if (!ctx_count) { + for(i=0;i<MESAWGL_CTX_MAX_COUNT;i++) { + wgl_ctx[i].ctx = NULL; + } + } + for( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ ) { + if ( wgl_ctx[i].ctx == NULL ) { + wgl_ctx[i].ctx = + WMesaCreateContext(hdc, NULL, (GLboolean)GL_TRUE, + (GLboolean) (pfd[curPFD-1].doubleBuffered ? + GL_TRUE : GL_FALSE), + (GLboolean)(pfd[curPFD-1].pfd.cAlphaBits ? + GL_TRUE : GL_FALSE) ); + if (wgl_ctx[i].ctx == NULL) + break; + ctx_count++; + return ((HGLRC)wgl_ctx[i].ctx); + } + } + SetLastError(0); + return(NULL); +} + +WINGDIAPI BOOL GLAPIENTRY wglDeleteContext(HGLRC hglrc) +{ + int i; + for ( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ ) { + if ( wgl_ctx[i].ctx == (WMesaContext) hglrc ){ + WMesaMakeCurrent((WMesaContext) hglrc, NULL); + WMesaDestroyContext(wgl_ctx[i].ctx); + wgl_ctx[i].ctx = NULL; + ctx_count--; + return(TRUE); + } + } + SetLastError(0); + return(FALSE); +} + +WINGDIAPI HGLRC GLAPIENTRY wglGetCurrentContext(VOID) +{ + if (ctx_current < 0) + return 0; + else + return (HGLRC) wgl_ctx[ctx_current].ctx; +} + +WINGDIAPI HDC GLAPIENTRY wglGetCurrentDC(VOID) +{ + return CurrentHDC; +} + +WINGDIAPI BOOL GLAPIENTRY wglMakeCurrent(HDC hdc, HGLRC hglrc) +{ + int i; + + CurrentHDC = hdc; + + if (!hdc || !hglrc) { + WMesaMakeCurrent(NULL, NULL); + ctx_current = -1; + return TRUE; + } + + for ( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ ) { + if ( wgl_ctx[i].ctx == (WMesaContext) hglrc ) { + WMesaMakeCurrent( (WMesaContext) hglrc, hdc ); + ctx_current = i; + return TRUE; + } + } + return FALSE; +} + + +WINGDIAPI int GLAPIENTRY wglChoosePixelFormat(HDC hdc, + CONST + PIXELFORMATDESCRIPTOR *ppfd) +{ + int i,best = -1,bestdelta = 0x7FFFFFFF,delta; + (void) hdc; + + if(ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR) || ppfd->nVersion != 1) + { + SetLastError(0); + return(0); + } + for(i = 0; i < npfd;i++) + { + delta = 0; + if( + (ppfd->dwFlags & PFD_DRAW_TO_WINDOW) && + !(pfd[i].pfd.dwFlags & PFD_DRAW_TO_WINDOW)) + continue; + if( + (ppfd->dwFlags & PFD_DRAW_TO_BITMAP) && + !(pfd[i].pfd.dwFlags & PFD_DRAW_TO_BITMAP)) + continue; + if( + (ppfd->dwFlags & PFD_SUPPORT_GDI) && + !(pfd[i].pfd.dwFlags & PFD_SUPPORT_GDI)) + continue; + if( + (ppfd->dwFlags & PFD_SUPPORT_OPENGL) && + !(pfd[i].pfd.dwFlags & PFD_SUPPORT_OPENGL)) + continue; + if( + !(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) && + ((ppfd->dwFlags & PFD_DOUBLEBUFFER) != + (pfd[i].pfd.dwFlags & PFD_DOUBLEBUFFER))) + continue; + if( + !(ppfd->dwFlags & PFD_STEREO_DONTCARE) && + ((ppfd->dwFlags & PFD_STEREO) != + (pfd[i].pfd.dwFlags & PFD_STEREO))) + continue; + if(ppfd->iPixelType != pfd[i].pfd.iPixelType) + delta++; + if(ppfd->cAlphaBits != pfd[i].pfd.cAlphaBits) + delta++; + if(delta < bestdelta) + { + best = i + 1; + bestdelta = delta; + if(bestdelta == 0) + break; + } + } + if(best == -1) + { + SetLastError(0); + return(0); + } + return(best); +} + +WINGDIAPI int GLAPIENTRY wglDescribePixelFormat(HDC hdc, + int iPixelFormat, + UINT nBytes, + LPPIXELFORMATDESCRIPTOR ppfd) +{ + (void) hdc; + + if(ppfd == NULL) + return(npfd); + if(iPixelFormat < 1 || iPixelFormat > npfd || + nBytes != sizeof(PIXELFORMATDESCRIPTOR)) + { + SetLastError(0); + return(0); + } + *ppfd = pfd[iPixelFormat - 1].pfd; + return(npfd); +} + +WINGDIAPI PROC GLAPIENTRY wglGetProcAddress(LPCSTR lpszProc) +{ + PROC p = (PROC) _glapi_get_proc_address((const char *) lpszProc); + if (p) + return p; + + SetLastError(0); + return(NULL); +} + +WINGDIAPI int GLAPIENTRY wglGetPixelFormat(HDC hdc) +{ + (void) hdc; + if(curPFD == 0) { + SetLastError(0); + return(0); + } + return(curPFD); +} + +WINGDIAPI BOOL GLAPIENTRY wglSetPixelFormat(HDC hdc,int iPixelFormat, + const PIXELFORMATDESCRIPTOR *ppfd) +{ + (void) hdc; + + if(iPixelFormat < 1 || iPixelFormat > npfd || + ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR)) { + SetLastError(0); + return(FALSE); + } + curPFD = iPixelFormat; + return(TRUE); +} + +WINGDIAPI BOOL GLAPIENTRY wglSwapBuffers(HDC hdc) +{ + WMesaSwapBuffers(hdc); + return TRUE; +} + +static FIXED FixedFromDouble(double d) +{ + long l = (long) (d * 65536L); + return *(FIXED *) (void *) &l; +} + + +/* +** This is cribbed from FX/fxwgl.c, and seems to implement support +** for bitmap fonts where the wglUseFontBitmapsA() code implements +** support for outline fonts. In combination they hopefully give +** fairly generic support for fonts. +*/ +static BOOL wglUseFontBitmaps_FX(HDC fontDevice, DWORD firstChar, + DWORD numChars, DWORD listBase) +{ +#define VERIFY(a) a + + TEXTMETRIC metric; + BITMAPINFO *dibInfo; + HDC bitDevice; + COLORREF tempColor; + int i; + + VERIFY(GetTextMetrics(fontDevice, &metric)); + + dibInfo = (BITMAPINFO *) calloc(sizeof(BITMAPINFO) + sizeof(RGBQUAD), 1); + dibInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + dibInfo->bmiHeader.biPlanes = 1; + dibInfo->bmiHeader.biBitCount = 1; + dibInfo->bmiHeader.biCompression = BI_RGB; + + bitDevice = CreateCompatibleDC(fontDevice); + + /* Swap fore and back colors so the bitmap has the right polarity */ + tempColor = GetBkColor(bitDevice); + SetBkColor(bitDevice, GetTextColor(bitDevice)); + SetTextColor(bitDevice, tempColor); + + /* Place chars based on base line */ + VERIFY(SetTextAlign(bitDevice, TA_BASELINE) != GDI_ERROR ? 1 : 0); + + for(i = 0; i < (int)numChars; i++) { + SIZE size; + char curChar; + int charWidth,charHeight,bmapWidth,bmapHeight,numBytes,res; + HBITMAP bitObject; + HGDIOBJ origBmap; + unsigned char *bmap; + + curChar = (char)(i + firstChar); + + /* Find how high/wide this character is */ + VERIFY(GetTextExtentPoint32(bitDevice, (LPCWSTR)&curChar, 1, &size)); + + /* Create the output bitmap */ + charWidth = size.cx; + charHeight = size.cy; + /* Round up to the next multiple of 32 bits */ + bmapWidth = ((charWidth + 31) / 32) * 32; + bmapHeight = charHeight; + bitObject = CreateCompatibleBitmap(bitDevice, + bmapWidth, + bmapHeight); + /* VERIFY(bitObject); */ + + /* Assign the output bitmap to the device */ + origBmap = SelectObject(bitDevice, bitObject); + (void) VERIFY(origBmap); + + VERIFY( PatBlt( bitDevice, 0, 0, bmapWidth, bmapHeight,BLACKNESS ) ); + + /* Use our source font on the device */ + VERIFY(SelectObject(bitDevice, GetCurrentObject(fontDevice,OBJ_FONT))); + + /* Draw the character */ + VERIFY(TextOut(bitDevice, 0, metric.tmAscent, (LPCWSTR)&curChar, 1)); + + /* Unselect our bmap object */ + VERIFY(SelectObject(bitDevice, origBmap)); + + /* Convert the display dependant representation to a 1 bit deep DIB */ + numBytes = (bmapWidth * bmapHeight) / 8; + bmap = (unsigned char *)malloc(numBytes); + dibInfo->bmiHeader.biWidth = bmapWidth; + dibInfo->bmiHeader.biHeight = bmapHeight; + res = GetDIBits(bitDevice, bitObject, 0, bmapHeight, bmap, + dibInfo, + DIB_RGB_COLORS); + /* VERIFY(res); */ + + /* Create the GL object */ + glNewList(i + listBase, GL_COMPILE); + glBitmap(bmapWidth, bmapHeight, 0.0, (GLfloat)metric.tmDescent, + (GLfloat)charWidth, 0.0, + bmap); + glEndList(); + /* CheckGL(); */ + + /* Destroy the bmap object */ + DeleteObject(bitObject); + + /* Deallocate the bitmap data */ + free(bmap); + } + + /* Destroy the DC */ + VERIFY(DeleteDC(bitDevice)); + + free(dibInfo); + + return TRUE; +#undef VERIFY +} + +WINGDIAPI BOOL GLAPIENTRY wglUseFontBitmapsA(HDC hdc, DWORD first, + DWORD count, DWORD listBase) +{ + int i; + GLuint font_list; + DWORD size; + GLYPHMETRICS gm; + HANDLE hBits; + LPSTR lpBits; + MAT2 mat; + int success = TRUE; + + if (count == 0) + return FALSE; + + font_list = listBase; + + mat.eM11 = FixedFromDouble(1); + mat.eM12 = FixedFromDouble(0); + mat.eM21 = FixedFromDouble(0); + mat.eM22 = FixedFromDouble(-1); + + memset(&gm,0,sizeof(gm)); + + /* + ** If we can't get the glyph outline, it may be because this is a fixed + ** font. Try processing it that way. + */ + if( GetGlyphOutline(hdc, first, GGO_BITMAP, &gm, 0, NULL, &mat) + == GDI_ERROR ) { + return wglUseFontBitmaps_FX( hdc, first, count, listBase ); + } + + /* + ** Otherwise process all desired characters. + */ + for (i = 0; i < (int)count; i++) { + DWORD err; + + glNewList( font_list+i, GL_COMPILE ); + + /* allocate space for the bitmap/outline */ + size = GetGlyphOutline(hdc, first + i, GGO_BITMAP, + &gm, 0, NULL, &mat); + if (size == GDI_ERROR) { + glEndList( ); + err = GetLastError(); + success = FALSE; + continue; + } + + hBits = GlobalAlloc(GHND, size+1); + lpBits = GlobalLock(hBits); + + err = + GetGlyphOutline(hdc, /* handle to device context */ + first + i, /* character to query */ + GGO_BITMAP, /* format of data to return */ + &gm, /* ptr to structure for metrics*/ + size, /* size of buffer for data */ + lpBits, /* pointer to buffer for data */ + &mat /* pointer to transformation */ + /* matrix structure */ + ); + + if (err == GDI_ERROR) { + GlobalUnlock(hBits); + GlobalFree(hBits); + + glEndList( ); + err = GetLastError(); + success = FALSE; + continue; + } + + glBitmap(gm.gmBlackBoxX,gm.gmBlackBoxY, + (GLfloat)-gm.gmptGlyphOrigin.x, + (GLfloat)gm.gmptGlyphOrigin.y, + (GLfloat)gm.gmCellIncX, + (GLfloat)gm.gmCellIncY, + (const GLubyte * )lpBits); + + GlobalUnlock(hBits); + GlobalFree(hBits); + + glEndList( ); + } + + return success; +} + + + +/* NOT IMPLEMENTED YET */ +WINGDIAPI BOOL GLAPIENTRY wglCopyContext(HGLRC hglrcSrc, + HGLRC hglrcDst, + UINT mask) +{ + (void) hglrcSrc; (void) hglrcDst; (void) mask; + return(FALSE); +} + +WINGDIAPI HGLRC GLAPIENTRY wglCreateLayerContext(HDC hdc, + int iLayerPlane) +{ + (void) hdc; (void) iLayerPlane; + SetLastError(0); + return(NULL); +} + +WINGDIAPI BOOL GLAPIENTRY wglShareLists(HGLRC hglrc1, + HGLRC hglrc2) +{ + (void) hglrc1; (void) hglrc2; + return(TRUE); +} + + +WINGDIAPI BOOL GLAPIENTRY wglUseFontBitmapsW(HDC hdc, + DWORD first, + DWORD count, + DWORD listBase) +{ + (void) hdc; (void) first; (void) count; (void) listBase; + return FALSE; +} + +WINGDIAPI BOOL GLAPIENTRY wglUseFontOutlinesA(HDC hdc, + DWORD first, + DWORD count, + DWORD listBase, + FLOAT deviation, + FLOAT extrusion, + int format, + LPGLYPHMETRICSFLOAT lpgmf) +{ + (void) hdc; (void) first; (void) count; + (void) listBase; (void) deviation; (void) extrusion; (void) format; + (void) lpgmf; + SetLastError(0); + return(FALSE); +} + +WINGDIAPI BOOL GLAPIENTRY wglUseFontOutlinesW(HDC hdc, + DWORD first, + DWORD count, + DWORD listBase, + FLOAT deviation, + FLOAT extrusion, + int format, + LPGLYPHMETRICSFLOAT lpgmf) +{ + (void) hdc; (void) first; (void) count; + (void) listBase; (void) deviation; (void) extrusion; (void) format; + (void) lpgmf; + SetLastError(0); + return(FALSE); +} + +WINGDIAPI BOOL GLAPIENTRY wglDescribeLayerPlane(HDC hdc, + int iPixelFormat, + int iLayerPlane, + UINT nBytes, + LPLAYERPLANEDESCRIPTOR plpd) +{ + (void) hdc; (void) iPixelFormat; (void) iLayerPlane; + (void) nBytes; (void) plpd; + SetLastError(0); + return(FALSE); +} + +WINGDIAPI int GLAPIENTRY wglSetLayerPaletteEntries(HDC hdc, + int iLayerPlane, + int iStart, + int cEntries, + CONST COLORREF *pcr) +{ + (void) hdc; (void) iLayerPlane; (void) iStart; + (void) cEntries; (void) pcr; + SetLastError(0); + return(0); +} + +WINGDIAPI int GLAPIENTRY wglGetLayerPaletteEntries(HDC hdc, + int iLayerPlane, + int iStart, + int cEntries, + COLORREF *pcr) +{ + (void) hdc; (void) iLayerPlane; (void) iStart; (void) cEntries; (void) pcr; + SetLastError(0); + return(0); +} + +WINGDIAPI BOOL GLAPIENTRY wglRealizeLayerPalette(HDC hdc, + int iLayerPlane, + BOOL bRealize) +{ + (void) hdc; (void) iLayerPlane; (void) bRealize; + SetLastError(0); + return(FALSE); +} + +WINGDIAPI BOOL GLAPIENTRY wglSwapLayerBuffers(HDC hdc, + UINT fuPlanes) +{ + (void) hdc; (void) fuPlanes; + SetLastError(0); + return(FALSE); +} + +WINGDIAPI const char * GLAPIENTRY wglGetExtensionsStringARB(HDC hdc) +{ + return "WGL_ARB_extensions_string"; +} diff --git a/src/gallium/winsys/gdi/wmesa.c b/src/gallium/winsys/gdi/wmesa.c new file mode 100644 index 0000000000..74a8292352 --- /dev/null +++ b/src/gallium/winsys/gdi/wmesa.c @@ -0,0 +1,890 @@ +/* + * Windows (Win32/Win64) device driver for Mesa + * + */ + +#include "mtypes.h" +#include <GL/wmesa.h> +#include "wmesadef.h" + +#undef Elements + +#include "pipe/p_winsys.h" +#include "pipe/p_format.h" +#include "pipe/p_context.h" +#include "pipe/p_util.h" +#include "pipe/p_inlines.h" +#include "softpipe/sp_winsys.h" +#include "glapi/glapi.h" +#include "colors.h" + +extern GLvisual * +_mesa_create_visual( GLboolean rgbFlag, + GLboolean dbFlag, + GLboolean stereoFlag, + GLint redBits, + GLint greenBits, + GLint blueBits, + GLint alphaBits, + GLint indexBits, + GLint depthBits, + GLint stencilBits, + GLint accumRedBits, + GLint accumGreenBits, + GLint accumBlueBits, + GLint accumAlphaBits, + GLint numSamples ); + +/* linked list of our Framebuffers (windows) */ +WMesaFramebuffer FirstFramebuffer = NULL; + +struct wmesa_pipe_winsys +{ + struct pipe_winsys base; +}; + +/** + * Choose the pixel format for the given visual. + * This will tell the gallium driver how to pack pixel data into + * drawing surfaces. + */ +static GLuint +choose_pixel_format(GLvisual *v) +{ +#if 1 + return PIPE_FORMAT_A8R8G8B8_UNORM; +#else + if ( GET_REDMASK(v) == 0x0000ff + && GET_GREENMASK(v) == 0x00ff00 + && GET_BLUEMASK(v) == 0xff0000 + && v->BitsPerPixel == 32) { + if (CHECK_BYTE_ORDER(v)) { + /* no byteswapping needed */ + return 0 /* PIXEL_FORMAT_U_A8_B8_G8_R8 */; + } + else { + return PIPE_FORMAT_R8G8B8A8_UNORM; + } + } + else if ( GET_REDMASK(v) == 0xff0000 + && GET_GREENMASK(v) == 0x00ff00 + && GET_BLUEMASK(v) == 0x0000ff + && v->BitsPerPixel == 32) { + if (CHECK_BYTE_ORDER(v)) { + /* no byteswapping needed */ + return PIPE_FORMAT_A8R8G8B8_UNORM; + } + else { + return PIPE_FORMAT_B8G8R8A8_UNORM; + } + } + else if ( GET_REDMASK(v) == 0xf800 + && GET_GREENMASK(v) == 0x07e0 + && GET_BLUEMASK(v) == 0x001f + && CHECK_BYTE_ORDER(v) + && v->BitsPerPixel == 16) { + /* 5-6-5 RGB */ + return PIPE_FORMAT_R5G6B5_UNORM; + } + +printf("BITS %d\n",v->BitsPerPixel); + assert(0); + return 0; +#endif +} + +/* + * Determine the pixel format based on the pixel size. + */ +static void wmSetPixelFormat(WMesaFramebuffer pwfb, HDC hDC) +{ + /* Only 16 and 32 bit targets are supported now */ + assert(pwfb->cColorBits == 0 || + pwfb->cColorBits == 16 || + pwfb->cColorBits == 32); + + switch(pwfb->cColorBits){ + case 8: + pwfb->pixelformat = PF_INDEX8; + break; + case 16: + pwfb->pixelformat = PF_5R6G5B; + break; + case 32: + pwfb->pixelformat = PF_8R8G8B; + break; + default: + pwfb->pixelformat = PF_BADFORMAT; + } +} + + +/** + * Create DIB for back buffer. + * We write into this memory with the span routines and then blit it + * to the window on a buffer swap. + */ +BOOL wmCreateBackingStore(WMesaFramebuffer pwfb, long lxSize, long lySize) +{ + HDC hdc = pwfb->hDC; + BITMAPINFO bmi; + LPBITMAPINFO pbmi = &bmi; + HDC hic; + + pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + pbmi->bmiHeader.biWidth = lxSize; + pbmi->bmiHeader.biHeight= -lySize; + pbmi->bmiHeader.biPlanes = 1; + pbmi->bmiHeader.biBitCount = pwfb->cColorBits; + pbmi->bmiHeader.biCompression = BI_RGB; + pbmi->bmiHeader.biSizeImage = 0; + pbmi->bmiHeader.biXPelsPerMeter = 0; + pbmi->bmiHeader.biYPelsPerMeter = 0; + pbmi->bmiHeader.biClrUsed = 0; + pbmi->bmiHeader.biClrImportant = 0; + + hic = CreateIC("display", NULL, NULL, NULL); + pwfb->dib_hDC = CreateCompatibleDC(hic); + + pwfb->hbmDIB = CreateDIBSection(hic, + pbmi, + DIB_RGB_COLORS, + (void **)&(pwfb->pbPixels), + 0, + 0); + pwfb->hOldBitmap = SelectObject(pwfb->dib_hDC, pwfb->hbmDIB); + + DeleteDC(hic); + + wmSetPixelFormat(pwfb, pwfb->hDC); + return TRUE; +} + +/** + * Create a new WMesaFramebuffer object which will correspond to the + * given HDC (Window handle). + */ +WMesaFramebuffer +wmesa_new_framebuffer(HDC hdc, GLvisual *visual, GLuint width, GLuint height) +{ + WMesaFramebuffer pwfb + = (WMesaFramebuffer) malloc(sizeof(struct wmesa_framebuffer)); + if (pwfb) { + enum pipe_format colorFormat, depthFormat, stencilFormat; + + /* determine PIPE_FORMATs for buffers */ + colorFormat = choose_pixel_format(visual); + + if (visual->depthBits == 0) + depthFormat = PIPE_FORMAT_NONE; + else if (visual->depthBits <= 16) + depthFormat = PIPE_FORMAT_Z16_UNORM; + else if (visual->depthBits <= 24) + depthFormat = PIPE_FORMAT_S8Z24_UNORM; + else + depthFormat = PIPE_FORMAT_Z32_UNORM; + + if (visual->stencilBits == 8) { + if (depthFormat == PIPE_FORMAT_S8Z24_UNORM) + stencilFormat = depthFormat; + else + stencilFormat = PIPE_FORMAT_S8_UNORM; + } + else { + stencilFormat = PIPE_FORMAT_NONE; + } + + pwfb->stfb = st_create_framebuffer(visual, + colorFormat, depthFormat, stencilFormat, + width, height, + (void *) pwfb); + + pwfb->cColorBits = GetDeviceCaps(hdc, BITSPIXEL); + +#if 0 + wmCreateBackingStore(pwfb, width, height); +#endif + + pwfb->hDC = hdc; + /* insert at head of list */ + pwfb->next = FirstFramebuffer; + FirstFramebuffer = pwfb; + } + return pwfb; +} + +/** + * Given an hdc, free the corresponding WMesaFramebuffer + */ +void +wmesa_free_framebuffer(HDC hdc) +{ + WMesaFramebuffer pwfb, prev; + for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) { + if (pwfb->hDC == hdc) + break; + prev = pwfb; + } + if (pwfb) { + if (pwfb == FirstFramebuffer) + FirstFramebuffer = pwfb->next; + else + prev->next = pwfb->next; + free(pwfb); + } +} + +/** + * Given an hdc, return the corresponding WMesaFramebuffer + */ +WMesaFramebuffer +wmesa_lookup_framebuffer(HDC hdc) +{ + WMesaFramebuffer pwfb; + for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) { + if (pwfb->hDC == hdc) + return pwfb; + } + return NULL; +} + + +/** + * Given a GLframebuffer, return the corresponding WMesaFramebuffer. + */ +static WMesaFramebuffer wmesa_framebuffer(GLframebuffer *fb) +{ + return (WMesaFramebuffer) fb; +} + + +/** + * Given a GLcontext, return the corresponding WMesaContext. + */ +static WMesaContext wmesa_context(const GLcontext *ctx) +{ + return (WMesaContext) ctx; +} + +static wmDeleteBackingStore(WMesaFramebuffer pwfb) +{ + if (pwfb->hbmDIB) { + SelectObject(pwfb->dib_hDC, pwfb->hOldBitmap); + DeleteDC(pwfb->dib_hDC); + DeleteObject(pwfb->hbmDIB); + } +} + + +/** + * Find the width and height of the window named by hdc. + */ +static void +get_window_size(HDC hdc, GLuint *width, GLuint *height) +{ + if (WindowFromDC(hdc)) { + RECT rect; + GetClientRect(WindowFromDC(hdc), &rect); + *width = rect.right - rect.left; + *height = rect.bottom - rect.top; + } + else { /* Memory context */ + /* From contributed code - use the size of the desktop + * for the size of a memory context (?) */ + *width = GetDeviceCaps(hdc, HORZRES); + *height = GetDeviceCaps(hdc, VERTRES); + } +} + +/** + * Low-level OS/window system memory buffer + */ +struct wm_buffer +{ + struct pipe_buffer base; + boolean userBuffer; /** Is this a user-space buffer? */ + void *data; + void *mapped; +}; + +struct wmesa_surface +{ + struct pipe_surface surface; + + int no_swap; +}; + + +/** Cast wrapper */ +static INLINE struct wmesa_surface * +wmesa_surface(struct pipe_surface *ps) +{ +// assert(0); + return (struct wmesa_surface *) ps; +} + +/** + * Turn the softpipe opaque buffer pointer into a dri_bufmgr opaque + * buffer pointer... + */ +static INLINE struct wm_buffer * +wm_buffer( struct pipe_buffer *buf ) +{ + return (struct wm_buffer *)buf; +} + + + +/* Most callbacks map direcly onto dri_bufmgr operations: + */ +static void * +wm_buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf, + unsigned flags) +{ + struct wm_buffer *wm_buf = wm_buffer(buf); + wm_buf->mapped = wm_buf->data; + return wm_buf->mapped; +} + +static void +wm_buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf) +{ + struct wm_buffer *wm_buf = wm_buffer(buf); + wm_buf->mapped = NULL; +} + +static void +wm_buffer_destroy(struct pipe_winsys *pws, + struct pipe_buffer *buf) +{ + struct wm_buffer *oldBuf = wm_buffer(buf); + + if (oldBuf->data) { + { + if (!oldBuf->userBuffer) { + align_free(oldBuf->data); + } + } + + oldBuf->data = NULL; + } + + free(oldBuf); +} + + +static void +wm_flush_frontbuffer(struct pipe_winsys *pws, + struct pipe_surface *surf, + void *context_private) +{ + WMesaContext pwc = context_private; + WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(pwc->hDC); + struct wm_buffer *wm_buf; + BITMAPINFO bmi, *pbmi; + +#if 0 + if (pwfb) + BitBlt(pwfb->hDC, 0, 0, pwfb->stfb->Base.Width, pwfb->stfb->Base.Height, + pwfb->dib_hDC, 0, 0, SRCCOPY); +#else + wm_buf = wm_buffer(surf->buffer); + + pbmi = &bmi; + memset(pbmi, 0, sizeof(BITMAPINFO)); + pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + pbmi->bmiHeader.biWidth = pwfb->stfb->Base.Width; + pbmi->bmiHeader.biHeight= -((long)pwfb->stfb->Base.Height); + pbmi->bmiHeader.biPlanes = 1; + pbmi->bmiHeader.biBitCount = pwfb->cColorBits; + pbmi->bmiHeader.biCompression = BI_RGB; + pbmi->bmiHeader.biSizeImage = 0; + pbmi->bmiHeader.biXPelsPerMeter = 0; + pbmi->bmiHeader.biYPelsPerMeter = 0; + pbmi->bmiHeader.biClrUsed = 0; + pbmi->bmiHeader.biClrImportant = 0; + + StretchDIBits(pwfb->hDC, 0, 0, pwfb->stfb->Base.Width, pwfb->stfb->Base.Height, 0, 0, pwfb->stfb->Base.Width, pwfb->stfb->Base.Height, wm_buf->data, pbmi, 0, SRCCOPY); +#endif +} + + + +static const char * +wm_get_name(struct pipe_winsys *pws) +{ + return "gdi"; +} + +static struct pipe_buffer * +wm_buffer_create(struct pipe_winsys *pws, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct wm_buffer *buffer = CALLOC_STRUCT(wm_buffer); + + buffer->base.refcount = 1; + buffer->base.alignment = alignment; + buffer->base.usage = usage; + buffer->base.size = size; + + if (buffer->data == NULL) { + /* align to 16-byte multiple for Cell */ + buffer->data = align_malloc(size, max(alignment, 16)); + } + + return &buffer->base; +} + + +/** + * Create buffer which wraps user-space data. + */ +static struct pipe_buffer * +wm_user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes) +{ + struct wm_buffer *buffer = CALLOC_STRUCT(wm_buffer); + buffer->base.refcount = 1; + buffer->base.size = bytes; + buffer->userBuffer = TRUE; + buffer->data = ptr; + + return &buffer->base; +} + + + +/** + * Round n up to next multiple. + */ +static INLINE unsigned +round_up(unsigned n, unsigned multiple) +{ + return (n + multiple - 1) & ~(multiple - 1); +} + +static int +wm_surface_alloc_storage(struct pipe_winsys *winsys, + struct pipe_surface *surf, + unsigned width, unsigned height, + enum pipe_format format, + unsigned flags) +{ + const unsigned alignment = 64; + + surf->width = width; + surf->height = height; + surf->format = format; + surf->cpp = pf_get_size(format); + surf->pitch = round_up(width, alignment / surf->cpp); + + assert(!surf->buffer); + surf->buffer = winsys->buffer_create(winsys, alignment, + PIPE_BUFFER_USAGE_PIXEL, + surf->pitch * surf->cpp * height); + if(!surf->buffer) + return -1; + + return 0; +} + + +/** + * Called via winsys->surface_alloc() to create new surfaces. + */ +static struct pipe_surface * +wm_surface_alloc(struct pipe_winsys *ws) +{ + struct wmesa_surface *wms = CALLOC_STRUCT(wmesa_surface); + static boolean no_swap = 0; + static boolean firsttime = 1; + + if (firsttime) { + no_swap = getenv("SP_NO_RAST") != NULL; + firsttime = 0; + } + + assert(ws); + + wms->surface.refcount = 1; + wms->surface.winsys = ws; + + wms->no_swap = no_swap; + + return &wms->surface; +} + +static void +wm_surface_release(struct pipe_winsys *winsys, struct pipe_surface **s) +{ + struct pipe_surface *surf = *s; + surf->refcount--; + if (surf->refcount == 0) { + if (surf->buffer) + pipe_buffer_reference(winsys, &surf->buffer, NULL); + free(surf); + } + *s = NULL; +} + + +/* + * Fence functions - basically nothing to do, as we don't create any actual + * fence objects. + */ + +static void +wm_fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence) +{ +} + + +static int +wm_fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence, + unsigned flag) +{ + return 0; +} + + +static int +wm_fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence, + unsigned flag) +{ + return 0; +} + + + +struct pipe_winsys * +wmesa_get_pipe_winsys(GLvisual *visual) +{ + static struct wmesa_pipe_winsys *ws = NULL; + + if (!ws) { + ws = CALLOC_STRUCT(wmesa_pipe_winsys); + + /* Fill in this struct with callbacks that pipe will need to + * communicate with the window system, buffer manager, etc. + */ + ws->base.buffer_create = wm_buffer_create; + ws->base.user_buffer_create = wm_user_buffer_create; + ws->base.buffer_map = wm_buffer_map; + ws->base.buffer_unmap = wm_buffer_unmap; + ws->base.buffer_destroy = wm_buffer_destroy; + + ws->base.surface_alloc = wm_surface_alloc; + ws->base.surface_alloc_storage = wm_surface_alloc_storage; + ws->base.surface_release = wm_surface_release; + + ws->base.fence_reference = wm_fence_reference; + ws->base.fence_signalled = wm_fence_signalled; + ws->base.fence_finish = wm_fence_finish; + + ws->base.flush_frontbuffer = wm_flush_frontbuffer; + ws->base.get_name = wm_get_name; + } + + return &ws->base; +} + + + +/**********************************************************************/ +/***** WMESA Functions *****/ +/**********************************************************************/ + +WMesaContext WMesaCreateContext(HDC hDC, + HPALETTE* Pal, + GLboolean rgb_flag, + GLboolean db_flag, + GLboolean alpha_flag) +{ + WMesaContext c; + struct pipe_winsys *pws; + struct pipe_context *pipe; + struct pipe_screen *screen; + GLint red_bits, green_bits, blue_bits, alpha_bits; + GLvisual *visual; + + (void) Pal; + + /* Indexed mode not supported */ + if (!rgb_flag) + return NULL; + + /* Allocate wmesa context */ + c = CALLOC_STRUCT(wmesa_context); + if (!c) + return NULL; + + c->hDC = hDC; + + /* Get data for visual */ + /* Dealing with this is actually a bit of overkill because Mesa will end + * up treating all color component size requests less than 8 by using + * a single byte per channel. In addition, the interface to the span + * routines passes colors as an entire byte per channel anyway, so there + * is nothing to be saved by telling the visual to be 16 bits if the device + * is 16 bits. That is, Mesa is going to compute colors down to 8 bits per + * channel anyway. + * But we go through the motions here anyway. + */ + c->cColorBits = GetDeviceCaps(c->hDC, BITSPIXEL); + + switch (c->cColorBits) { + case 16: + red_bits = green_bits = blue_bits = 5; + alpha_bits = 0; + break; + default: + red_bits = green_bits = blue_bits = 8; + alpha_bits = 8; + break; + } + /* Create visual based on flags */ + visual = _mesa_create_visual(rgb_flag, + db_flag, /* db_flag */ + GL_FALSE, /* stereo */ + red_bits, green_bits, blue_bits, /* color RGB */ + alpha_flag ? alpha_bits : 0, /* color A */ + 0, /* index bits */ + DEFAULT_SOFTWARE_DEPTH_BITS, /* depth_bits */ + 8, /* stencil_bits */ + 16,16,16, /* accum RGB */ + alpha_flag ? 16 : 0, /* accum A */ + 1); /* num samples */ + + if (!visual) { + _mesa_free(c); + return NULL; + } + + pws = wmesa_get_pipe_winsys(visual); + + screen = softpipe_create_screen(pws); + + if (!screen) { + _mesa_free(c); + return NULL; + } + + pipe = softpipe_create(screen, pws, NULL); + + if (!pipe) { + /* FIXME - free screen */ + _mesa_free(c); + return NULL; + } + + pipe->priv = c; + + c->st = st_create_context(pipe, visual, NULL); + + c->st->ctx->DriverCtx = c; + + return c; +} + + +void WMesaDestroyContext( WMesaContext pwc ) +{ + GLcontext *ctx = pwc->st->ctx; + WMesaFramebuffer pwfb; + GET_CURRENT_CONTEXT(cur_ctx); + + if (cur_ctx == ctx) { + /* unbind current if deleting current context */ + WMesaMakeCurrent(NULL, NULL); + } + + /* clean up frame buffer resources */ + pwfb = wmesa_lookup_framebuffer(pwc->hDC); + if (pwfb) { +#if 0 + wmDeleteBackingStore(pwfb); +#endif + wmesa_free_framebuffer(pwc->hDC); + } + + /* Release for device, not memory contexts */ + if (WindowFromDC(pwc->hDC) != NULL) + { + ReleaseDC(WindowFromDC(pwc->hDC), pwc->hDC); + } + + st_destroy_context(pwc->st); + _mesa_free(pwc); +} + + +void WMesaMakeCurrent(WMesaContext c, HDC hdc) +{ + GLuint width = 0, height = 0; + WMesaFramebuffer pwfb; + + { + /* return if already current */ + GET_CURRENT_CONTEXT(ctx); + WMesaContext pwc = wmesa_context(ctx); + if (pwc && c == pwc && pwc->hDC == hdc) + return; + } + + pwfb = wmesa_lookup_framebuffer(hdc); + + if (hdc) { + get_window_size(hdc, &width, &height); + } + + /* Lazy creation of framebuffers */ + if (c && !pwfb && (hdc != 0)) { + GLvisual *visual = &c->st->ctx->Visual; + + pwfb = wmesa_new_framebuffer(hdc, visual, width, height); + } + + if (c && pwfb) { + st_make_current(c->st, pwfb->stfb, pwfb->stfb); + + st_resize_framebuffer(pwfb->stfb, width, height); + } + else { + /* Detach */ + st_make_current( NULL, NULL, NULL ); + } +} + + +void WMesaSwapBuffers( HDC hdc ) +{ + struct pipe_surface *surf; + struct wm_buffer *wm_buf; + WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(hdc); + BITMAPINFO bmi, *pbmi; + + if (!pwfb) { + _mesa_problem(NULL, "wmesa: swapbuffers on unknown hdc"); + return; + } + + + /* If we're swapping the buffer associated with the current context + * we have to flush any pending rendering commands first. + */ + st_notify_swapbuffers(pwfb->stfb); + +#if 0 + BitBlt(pwfb->hDC, 0, 0, pwfb->stfb->Base.Width, pwfb->stfb->Base.Height, + pwfb->dib_hDC, 0, 0, SRCCOPY); +#else + surf = st_get_framebuffer_surface(pwfb->stfb, ST_SURFACE_BACK_LEFT); + wm_buf = wm_buffer(surf->buffer); + + pbmi = &bmi; + memset(pbmi, 0, sizeof(BITMAPINFO)); + pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + pbmi->bmiHeader.biWidth = pwfb->stfb->Base.Width; + pbmi->bmiHeader.biHeight= -((long)pwfb->stfb->Base.Height); + pbmi->bmiHeader.biPlanes = 1; + pbmi->bmiHeader.biBitCount = pwfb->cColorBits; + pbmi->bmiHeader.biCompression = BI_RGB; + pbmi->bmiHeader.biSizeImage = 0; + pbmi->bmiHeader.biXPelsPerMeter = 0; + pbmi->bmiHeader.biYPelsPerMeter = 0; + pbmi->bmiHeader.biClrUsed = 0; + pbmi->bmiHeader.biClrImportant = 0; + + StretchDIBits(pwfb->hDC, 0, 0, pwfb->stfb->Base.Width, pwfb->stfb->Base.Height, 0, 0, pwfb->stfb->Base.Width, pwfb->stfb->Base.Height, wm_buf->data, pbmi, 0, SRCCOPY); + + { + GLuint width = 0, height = 0; + + get_window_size(pwfb->hDC, &width, &height); + + st_resize_framebuffer(pwfb->stfb, width, height); + } +#endif +} + +/* This is hopefully a temporary hack to define some needed dispatch + * table entries. Hopefully, I'll find a better solution. The + * dispatch table generation scripts ought to be making these dummy + * stubs as well. */ +#if !defined(__MINGW32__) || !defined(GL_NO_STDCALL) +void gl_dispatch_stub_543(void){} +void gl_dispatch_stub_544(void){} +void gl_dispatch_stub_545(void){} +void gl_dispatch_stub_546(void){} +void gl_dispatch_stub_547(void){} +void gl_dispatch_stub_548(void){} +void gl_dispatch_stub_549(void){} +void gl_dispatch_stub_550(void){} +void gl_dispatch_stub_551(void){} +void gl_dispatch_stub_552(void){} +void gl_dispatch_stub_553(void){} +void gl_dispatch_stub_554(void){} +void gl_dispatch_stub_555(void){} +void gl_dispatch_stub_556(void){} +void gl_dispatch_stub_557(void){} +void gl_dispatch_stub_558(void){} +void gl_dispatch_stub_559(void){} +void gl_dispatch_stub_560(void){} +void gl_dispatch_stub_561(void){} +void gl_dispatch_stub_565(void){} +void gl_dispatch_stub_566(void){} +void gl_dispatch_stub_577(void){} +void gl_dispatch_stub_578(void){} +void gl_dispatch_stub_603(void){} +void gl_dispatch_stub_645(void){} +void gl_dispatch_stub_646(void){} +void gl_dispatch_stub_647(void){} +void gl_dispatch_stub_648(void){} +void gl_dispatch_stub_649(void){} +void gl_dispatch_stub_650(void){} +void gl_dispatch_stub_651(void){} +void gl_dispatch_stub_652(void){} +void gl_dispatch_stub_653(void){} +void gl_dispatch_stub_733(void){} +void gl_dispatch_stub_734(void){} +void gl_dispatch_stub_735(void){} +void gl_dispatch_stub_736(void){} +void gl_dispatch_stub_737(void){} +void gl_dispatch_stub_738(void){} +void gl_dispatch_stub_744(void){} +void gl_dispatch_stub_745(void){} +void gl_dispatch_stub_746(void){} +void gl_dispatch_stub_760(void){} +void gl_dispatch_stub_761(void){} +void gl_dispatch_stub_763(void){} +void gl_dispatch_stub_765(void){} +void gl_dispatch_stub_766(void){} +void gl_dispatch_stub_767(void){} +void gl_dispatch_stub_768(void){} + +void gl_dispatch_stub_562(void){} +void gl_dispatch_stub_563(void){} +void gl_dispatch_stub_564(void){} +void gl_dispatch_stub_567(void){} +void gl_dispatch_stub_568(void){} +void gl_dispatch_stub_569(void){} +void gl_dispatch_stub_580(void){} +void gl_dispatch_stub_581(void){} +void gl_dispatch_stub_606(void){} +void gl_dispatch_stub_654(void){} +void gl_dispatch_stub_655(void){} +void gl_dispatch_stub_656(void){} +void gl_dispatch_stub_739(void){} +void gl_dispatch_stub_740(void){} +void gl_dispatch_stub_741(void){} +void gl_dispatch_stub_748(void){} +void gl_dispatch_stub_749(void){} +void gl_dispatch_stub_769(void){} +void gl_dispatch_stub_770(void){} +void gl_dispatch_stub_771(void){} +void gl_dispatch_stub_772(void){} +void gl_dispatch_stub_773(void){} + +#endif diff --git a/src/gallium/winsys/gdi/wmesadef.h b/src/gallium/winsys/gdi/wmesadef.h new file mode 100644 index 0000000000..fb8ce30a08 --- /dev/null +++ b/src/gallium/winsys/gdi/wmesadef.h @@ -0,0 +1,40 @@ +#ifndef WMESADEF_H +#define WMESADEF_H +#ifdef __MINGW32__ +#include <windows.h> +#endif +#if 0 +#include "context.h" +#endif +#include "state_tracker/st_context.h" +#include "state_tracker/st_public.h" + + +/** + * The Windows Mesa rendering context, derived from GLcontext. + */ +struct wmesa_context { + struct st_context *st; + HDC hDC; + BYTE cColorBits; +}; + +/** + * Windows framebuffer, derived from gl_framebuffer + */ +struct wmesa_framebuffer +{ + struct st_framebuffer *stfb; + HDC hDC; + int pixelformat; + BYTE cColorBits; + HDC dib_hDC; + HBITMAP hbmDIB; + HBITMAP hOldBitmap; + PBYTE pbPixels; + struct wmesa_framebuffer *next; +}; + +typedef struct wmesa_framebuffer *WMesaFramebuffer; + +#endif /* WMESADEF_H */ diff --git a/src/gallium/winsys/xlib/Makefile b/src/gallium/winsys/xlib/Makefile index c443330942..ec92c79068 100644 --- a/src/gallium/winsys/xlib/Makefile +++ b/src/gallium/winsys/xlib/Makefile @@ -1,5 +1,9 @@ # src/gallium/winsys/xlib/Makefile +# This makefile produces a "stand-alone" libGL.so which is based on +# Xlib (no DRI HW acceleration) + + TOP = ../../../.. include $(TOP)/configs/current diff --git a/src/gallium/winsys/xlib/SConscript b/src/gallium/winsys/xlib/SConscript index 218b89285f..5e98a36abc 100644 --- a/src/gallium/winsys/xlib/SConscript +++ b/src/gallium/winsys/xlib/SConscript @@ -3,30 +3,32 @@ Import('*') -env = env.Clone() +if env['platform'] == 'linux' and 'mesa' in env['statetrackers'] and not env['dri']: -env.Append(CPPPATH = [ - '#/src/mesa', - '#/src/mesa/main', -]) + env = env.Clone() -sources = [ - 'glxapi.c', - 'fakeglx.c', - 'xfonts.c', - 'xm_api.c', - 'xm_winsys.c', - 'xm_winsys_aub.c', - 'brw_aub.c', -] - -drivers = [ - softpipe, -] + env.Append(CPPPATH = [ + '#/src/mesa', + '#/src/mesa/main', + ]) -# TODO: write a wrapper function http://www.scons.org/wiki/WrapperFunctions -env.SharedLibrary( - target ='GL', - source = sources, - LIBS = glapi + mesa + drivers + auxiliaries + env['LIBS'], -) + sources = [ + 'glxapi.c', + 'fakeglx.c', + 'xfonts.c', + 'xm_api.c', + 'xm_winsys.c', + 'xm_winsys_aub.c', + 'brw_aub.c', + ] + + drivers = [ + softpipe, + ] + + # TODO: write a wrapper function http://www.scons.org/wiki/WrapperFunctions + env.SharedLibrary( + target ='GL', + source = sources, + LIBS = glapi + mesa + drivers + auxiliaries + env['LIBS'], + ) diff --git a/src/gallium/winsys/xlib/xm_api.c b/src/gallium/winsys/xlib/xm_api.c index 26b722f343..8a32c54349 100644 --- a/src/gallium/winsys/xlib/xm_api.c +++ b/src/gallium/winsys/xlib/xm_api.c @@ -797,8 +797,14 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) pipe = xmesa_create_i965simple(xmesa_get_pipe_winsys_aub(v)); } + if (pipe == NULL) + goto fail; + c->st = st_create_context(pipe, &v->mesa_visual, share_list ? share_list->st : NULL); + if (c->st == NULL) + goto fail; + mesaCtx = c->st->ctx; c->st->ctx->DriverCtx = c; @@ -818,6 +824,14 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) #endif return c; + + fail: + if (c->st) + st_destroy_context(c->st); + if (pipe) + pipe->destroy(pipe); + FREE(c); + return NULL; } |