X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fr300%2Fr300_render.c;h=e6ed06a69d6b6e2096637b0ab33ba3df4cccda22;hb=83a43aca233cfdf8f8cac26895ef4ea4105d96af;hp=894d3d1b904eece06c6c819b9a98c994ccb2ce5b;hpb=6bd390743da6e01410f3fc124d79956629e2a6f2;p=mesa.git diff --git a/src/mesa/drivers/dri/r300/r300_render.c b/src/mesa/drivers/dri/r300/r300_render.c index 894d3d1b904..e6ed06a69d6 100644 --- a/src/mesa/drivers/dri/r300/r300_render.c +++ b/src/mesa/drivers/dri/r300/r300_render.c @@ -44,6 +44,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "swrast_setup/swrast_setup.h" #include "array_cache/acache.h" #include "tnl/tnl.h" +#include "tnl/t_vp_build.h" #include "radeon_reg.h" #include "radeon_macros.h" @@ -58,6 +59,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r300_maos.h" #include "r300_emit.h" +extern int future_hw_tcl_on; + /********************************************************************** * Hardware rasterization * @@ -67,10 +70,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. static int r300_get_primitive_type(r300ContextPtr rmesa, GLcontext *ctx, int prim) { - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - GLuint i; - int type=-1; + int type=-1; switch (prim & PRIM_MODE_MASK) { case GL_POINTS: @@ -118,11 +118,8 @@ static int r300_get_num_verts(r300ContextPtr rmesa, int num_verts, int prim) { - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - GLuint i; - int type=-1, verts_off=0; - char *name="UNKNOWN"; + int verts_off=0; + char *name="UNKNOWN"; switch (prim & PRIM_MODE_MASK) { case GL_POINTS: @@ -181,303 +178,101 @@ static int r300_get_num_verts(r300ContextPtr rmesa, break; } - if(num_verts - verts_off == 0){ - WARN_ONCE("user error: Need more than %d vertices to draw primitive %s !\n", num_verts, name); - return 0; - } + if (RADEON_DEBUG & DEBUG_VERTS) { + if (num_verts - verts_off == 0) { + WARN_ONCE("user error: Need more than %d vertices to draw primitive %s !\n", num_verts, name); + return 0; + } - if(verts_off > 0){ - WARN_ONCE("user error: %d is not a valid number of vertices for primitive %s !\n", num_verts, name); + if (verts_off > 0) { + WARN_ONCE("user error: %d is not a valid number of vertices for primitive %s !\n", num_verts, name); + } } return num_verts - verts_off; } -void dump_inputs(GLcontext *ctx, int render_inputs) -{ - int k; - fprintf(stderr, "inputs:"); - fprintf(stderr, "%08x ", render_inputs); - - if(render_inputs & _TNL_BIT_POS) - fprintf(stderr, "_TNL_BIT_POS "); - if(render_inputs & _TNL_BIT_NORMAL) - fprintf(stderr, "_TNL_BIT_NORMAL "); - - /* color components */ - if(render_inputs & _TNL_BIT_COLOR0) - fprintf(stderr, "_TNL_BIT_COLOR0 "); - if(render_inputs & _TNL_BIT_COLOR1) - fprintf(stderr, "_TNL_BIT_COLOR1 "); - - if(render_inputs & _TNL_BIT_FOG) - fprintf(stderr, "_TNL_BIT_FOG "); - - /* texture coordinates */ - for(k=0;k < ctx->Const.MaxTextureUnits;k++) - if(render_inputs & (_TNL_BIT_TEX0<size;_i++){ \ - efloat(VEC_ELT(v, GLfloat, i)[_i]); \ - } \ - for(_i=v->size;_i<4;_i++){ \ - efloat(default_vector[_i]); \ - } \ - } - -/* Immediate implementation - vertex data is sent via command stream */ +/* vertex buffer implementation */ -static void r300_render_immediate_primitive(r300ContextPtr rmesa, - GLcontext *ctx, - int start, - int end, - int prim) +static void inline fire_EB(PREFIX unsigned long addr, int vertex_count, int type, int elt_size) { - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - GLuint i, render_inputs; - int k, type, num_verts; - LOCAL_VARS - - type=r300_get_primitive_type(rmesa, ctx, prim); - num_verts=r300_get_num_verts(rmesa, ctx, end-start, prim); - -#if 0 - fprintf(stderr,"ObjPtr: size=%d stride=%d\n", - VB->ObjPtr->size, VB->ObjPtr->stride); - fprintf(stderr,"ColorPtr[0]: size=%d stride=%d\n", - VB->ColorPtr[0]->size, VB->ColorPtr[0]->stride); - fprintf(stderr,"TexCoordPtr[0]: size=%d stride=%d\n", - VB->TexCoordPtr[0]->size, VB->TexCoordPtr[0]->stride); -#endif - - if(type<0 || num_verts <= 0)return; - - if(!VB->ObjPtr){ - WARN_ONCE("FIXME: Don't know how to handle GL_ARB_vertex_buffer_object correctly\n"); - return; - } - /* A packet cannot have more than 16383 data words.. */ - if((num_verts*4*rmesa->state.aos_count)>16380){ - WARN_ONCE("Too many vertices to paint. Fix me !\n"); - return; + LOCAL_VARS + unsigned long addr_a; + unsigned long t_addr; + unsigned long magic_1, magic_2; + GLcontext *ctx; + ctx = rmesa->radeon.glCtx; + + assert(elt_size == 2 || elt_size == 4); + + if(addr & (elt_size-1)){ + WARN_ONCE("Badly aligned buffer\n"); + return ; } - - //fprintf(stderr, "aos_count=%d start=%d end=%d\n", rmesa->state.aos_count, start, end); - - if(rmesa->state.aos_count==0){ - WARN_ONCE("Aeiee ! aos_count==0, while it shouldn't. Skipping rendering\n"); - return; - } - - render_inputs = rmesa->state.render_inputs; - - if(!render_inputs){ - WARN_ONCE("Aeiee ! render_inputs==0. Skipping rendering.\n"); - return; - } - - //dump_inputs(ctx, render_inputs); return ; - - start_immediate_packet(num_verts, type, 4*rmesa->state.aos_count); - - for(i=start;iObjPtr, GLfloat, i)[0], - VEC_ELT(VB->ObjPtr, GLfloat, i)[1], - VEC_ELT(VB->ObjPtr, GLfloat, i)[2], - VEC_ELT(VB->ObjPtr, GLfloat, i)[3], - - VEC_ELT(VB->ColorPtr[0], GLfloat, i)[0], - VEC_ELT(VB->ColorPtr[0], GLfloat, i)[1], - VEC_ELT(VB->ColorPtr[0], GLfloat, i)[2], - VEC_ELT(VB->ColorPtr[0], GLfloat, i)[3] - ); -#endif - - - /* coordinates */ - if(render_inputs & _TNL_BIT_POS) - output_vector(VB->ObjPtr, i); - if(render_inputs & _TNL_BIT_NORMAL) - output_vector(VB->NormalPtr, i); - - /* color components */ - if(render_inputs & _TNL_BIT_COLOR0) - output_vector(VB->ColorPtr[0], i); - if(render_inputs & _TNL_BIT_COLOR1) - output_vector(VB->SecondaryColorPtr[0], i); - -/* if(render_inputs & _TNL_BIT_FOG) // Causes lock ups when immediate mode is on - output_vector(VB->FogCoordPtr, i);*/ - - /* texture coordinates */ - for(k=0;k < ctx->Const.MaxTextureUnits;k++) - if(render_inputs & (_TNL_BIT_TEX0<TexCoordPtr[k], i); - - if(render_inputs & _TNL_BIT_INDEX) - output_vector(VB->IndexPtr[0], i); - if(render_inputs & _TNL_BIT_POINTSIZE) - output_vector(VB->PointSizePtr, i); - } - -} - - -static GLboolean r300_run_immediate_render(GLcontext *ctx, - struct tnl_pipeline_stage *stage) -{ - r300ContextPtr rmesa = R300_CONTEXT(ctx); - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - GLuint i; - /* Only do 2d textures */ - struct gl_texture_object *to=ctx->Texture.Unit[0].Current2D; - r300TexObjPtr t=to->DriverData; - LOCAL_VARS - - - /* Update texture state - needs to be done only when actually changed.. - All the time for now.. */ - - - if (RADEON_DEBUG == DEBUG_PRIMS) - fprintf(stderr, "%s\n", __FUNCTION__); - -#if 1 /* we need this, somehow */ - /* Flush state - make sure command buffer is nice and large */ - r300Flush(ctx); - /* Make sure we have enough space */ -#else - /* Count is very imprecize, but should be good upper bound */ - r300EnsureCmdBufSpace(rmesa, rmesa->hw.max_state_size + 4+2+30 - +VB->PrimitiveCount*(1+8)+VB->Count*4*rmesa->state.texture.tc_count+4, __FUNCTION__); -#endif - - /* needed before starting 3d operation .. */ - reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0); - e32(0x0000000a); - - reg_start(0x4f18,0); - e32(0x00000003); - - -#if 0 /* looks like the Z offset issue got fixed */ - rmesa->hw.vte.cmd[1] = R300_VPORT_X_SCALE_ENA - | R300_VPORT_X_OFFSET_ENA - | R300_VPORT_Y_SCALE_ENA - | R300_VPORT_Y_OFFSET_ENA - | R300_VTX_W0_FMT; - R300_STATECHANGE(rmesa, vte); -#endif - - - - /* Magic register - note it is right after 20b0 */ - - - if(rmesa->state.texture.tc_count>0){ - reg_start(0x20b4,0); - e32(0x0000000c); - +#ifdef OPTIMIZE_ELTS + addr_a = 0; + + magic_1 = (addr % 32) / 4; + t_addr = addr & (~0x1d); + magic_2 = (vertex_count + 1 + (t_addr & 0x2)) / 2 + magic_1; + + check_space(6); + + start_packet3(RADEON_CP_PACKET3_3D_DRAW_INDX_2, 0); + if(elt_size == 4){ + e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (vertex_count<<16) | type | R300_VAP_VF_CNTL__INDEX_SIZE_32bit); + } else { + e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (vertex_count<<16) | type); } - r300EmitState(rmesa); - + start_packet3(RADEON_CP_PACKET3_INDX_BUFFER, 2); + if(elt_size == 4){ + e32(R300_EB_UNK1 | (0 << 16) | R300_EB_UNK2); + e32(addr /*& 0xffffffe3*/); + } else { + e32(R300_EB_UNK1 | (magic_1 << 16) | R300_EB_UNK2); + e32(t_addr); + } + + if(elt_size == 4){ + e32(vertex_count /*+ addr_a/4*/); /* Total number of dwords needed? */ + } else { + e32(magic_2); /* Total number of dwords needed? */ + } + //cp_delay(PASS_PREFIX 1); #if 0 - reg_start(R300_RB3D_COLORMASK, 0); - e32(0xf); - - vsf_start_fragment(0x406, 4); - efloat(0.0); - efloat(0.0); - efloat(0.0); - efloat(1.0); - - vsf_start_fragment(0x400, 4); - efloat(0.0); - efloat(0.0); - efloat(0.0); - efloat(1.0); + fprintf(stderr, "magic_1 %d\n", magic_1); + fprintf(stderr, "t_addr %x\n", t_addr); + fprintf(stderr, "magic_2 %d\n", magic_2); + exit(1); #endif - -/* Setup INPUT_ROUTE and INPUT_CNTL */ - r300EmitArrays(ctx, GL_TRUE); - -/* Why do we need this for immediate mode?? Vertex processor needs it to know proper regs */ -// r300EmitLOAD_VBPNTR(rmesa, 0); -/* Okay, it seems I misunderstood something, EmitAOS does the same thing */ - r300EmitAOS(rmesa, rmesa->state.aos_count, 0); - - for(i=0; i < VB->PrimitiveCount; i++){ - GLuint prim = VB->Primitive[i].mode; - GLuint start = VB->Primitive[i].start; - GLuint length = VB->Primitive[i].count; - - r300_render_immediate_primitive(rmesa, ctx, start, start + length, prim); - } - - /* This sequence is required after any 3d drawing packet - I suspect it work arounds a bug (or deficiency) in hardware */ - - reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0); - e32(0x0000000a); - - reg_start(0x4f18,0); - e32(0x00000003); - - return GL_FALSE; -} - -/* vertex buffer implementation */ - -static void inline fire_EB(PREFIX unsigned long addr, int vertex_count, int type) -{ - LOCAL_VARS - unsigned long addr_a; +#else + (void)magic_2, (void)magic_1, (void)t_addr; - addr_a = addr & 0x1c; + addr_a = 0; check_space(6); start_packet3(RADEON_CP_PACKET3_3D_DRAW_INDX_2, 0); - /* TODO: Check if R300_VAP_VF_CNTL__INDEX_SIZE_32bit works. */ - e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (vertex_count<<16) | type); + if(elt_size == 4){ + e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (vertex_count<<16) | type | R300_VAP_VF_CNTL__INDEX_SIZE_32bit); + } else { + e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (vertex_count<<16) | type); + } start_packet3(RADEON_CP_PACKET3_INDX_BUFFER, 2); - e32(R300_EB_UNK1 | (addr_a << 16) | R300_EB_UNK2); - e32(addr & 0xffffffe3); - e32((vertex_count+1)/2 + addr_a/4); + e32(R300_EB_UNK1 | (0 << 16) | R300_EB_UNK2); + e32(addr /*& 0xffffffe3*/); + + if(elt_size == 4){ + e32(vertex_count /*+ addr_a/4*/); /* Total number of dwords needed? */ + } else { + e32((vertex_count+1)/2 /*+ addr_a/4*/); /* Total number of dwords needed? */ + } + //cp_delay(PASS_PREFIX 1); +#endif } static void r300_render_vb_primitive(r300ContextPtr rmesa, @@ -487,28 +282,24 @@ static void r300_render_vb_primitive(r300ContextPtr rmesa, int prim) { int type, num_verts; - radeonScreenPtr rsp=rmesa->radeon.radeonScreen; - LOCAL_VARS - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - int i; type=r300_get_primitive_type(rmesa, ctx, prim); num_verts=r300_get_num_verts(rmesa, ctx, end-start, prim); if(type<0 || num_verts <= 0)return; - if(rmesa->state.Elts){ - r300EmitAOS(rmesa, rmesa->state.aos_count, 0); -#if 1 + if(rmesa->state.VB.Elts){ + r300EmitAOS(rmesa, rmesa->state.aos_count, /*0*/start); +#if 0 + LOCAL_VARS + int i; start_index32_packet(num_verts, type); for(i=0; i < num_verts; i++) - e32(rmesa->state.Elts[start+i]); /* start ? */ + e32(((unsigned long *)rmesa->state.VB.Elts)[i]/*rmesa->state.Elts[start+i]*/); /* start ? */ #else - WARN_ONCE("Rendering with elt buffers\n"); if(num_verts == 1){ - start_index32_packet(num_verts, type); - e32(rmesa->state.Elts[start]); + //start_index32_packet(num_verts, type); + //e32(rmesa->state.Elts[start]); return; } @@ -516,8 +307,9 @@ static void r300_render_vb_primitive(r300ContextPtr rmesa, WARN_ONCE("Too many elts\n"); return; } - r300EmitElts(ctx, rmesa->state.Elts+start, num_verts); - fire_EB(PASS_PREFIX GET_START(&(rmesa->state.elt_dma)), num_verts, type); + + r300EmitElts(ctx, rmesa->state.VB.Elts, num_verts, rmesa->state.VB.elt_size); + fire_EB(PASS_PREFIX rmesa->state.elt_dma.aos_offset, num_verts, type, rmesa->state.VB.elt_size); #endif }else{ r300EmitAOS(rmesa, rmesa->state.aos_count, start); @@ -525,34 +317,117 @@ static void r300_render_vb_primitive(r300ContextPtr rmesa, } } -static GLboolean r300_run_vb_render(GLcontext *ctx, +#if 0 +void dump_array(struct r300_dma_region *rvb, int count) +{ + int *out = (int *)(rvb->address + rvb->start); + int i, ci; + + fprintf(stderr, "stride %d:", rvb->aos_stride); + for (i=0; i < count; i++) { + fprintf(stderr, "{"); + if (rvb->aos_format == AOS_FORMAT_FLOAT) + for (ci=0; ci < rvb->aos_size; ci++) + fprintf(stderr, "%f ", ((float *)out)[ci]); + else + for (ci=0; ci < rvb->aos_size; ci++) + fprintf(stderr, "%d ", ((unsigned char *)out)[ci]); + fprintf(stderr, "}"); + + out += rvb->aos_stride; + } + + fprintf(stderr, "\n"); +} + +void dump_dt(struct dt *dt, int count) +{ + int *out = dt->data; + int i, ci; + + fprintf(stderr, "stride %d", dt->stride); + + for (i=0; i < count; i++){ + fprintf(stderr, "{"); + if (dt->type == GL_FLOAT) + for (ci=0; ci < dt->size; ci++) + fprintf(stderr, "%f ", ((float *)out)[ci]); + else + for (ci=0; ci < dt->size; ci++) + fprintf(stderr, "%d ", ((unsigned char *)out)[ci]); + fprintf(stderr, "}"); + + out = (int *)((char *)out + dt->stride); + } + + fprintf(stderr, "\n"); +} +#endif + +GLboolean r300_run_vb_render(GLcontext *ctx, struct tnl_pipeline_stage *stage) { - r300ContextPtr rmesa = R300_CONTEXT(ctx); - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - int i, j; - LOCAL_VARS + r300ContextPtr rmesa = R300_CONTEXT(ctx); + struct radeon_vertex_buffer *VB = &rmesa->state.VB; + int i; + LOCAL_VARS if (RADEON_DEBUG & DEBUG_PRIMS) fprintf(stderr, "%s\n", __FUNCTION__); - - - r300ReleaseArrays(ctx); - r300EmitArrays(ctx, GL_FALSE); - //dump_inputs(ctx, rmesa->state.render_inputs); -// LOCK_HARDWARE(&(rmesa->radeon)); + if (stage) { + TNLcontext *tnl = TNL_CONTEXT(ctx); + radeon_vb_to_rvb(rmesa, VB, &tnl->vb); + } + + r300UpdateShaders(rmesa); + if (rmesa->state.VB.LockCount == 0 || 1) { + r300EmitArrays(ctx, GL_FALSE); + r300UpdateShaderStates(rmesa); + } else { + /* TODO: Figure out why do we need these. */ + R300_STATECHANGE(rmesa, vir[0]); + R300_STATECHANGE(rmesa, vir[1]); + R300_STATECHANGE(rmesa, vic); + R300_STATECHANGE(rmesa, vof); + +#if 0 + fprintf(stderr, "dt:\n"); + for(i=0; i < VERT_ATTRIB_MAX; i++){ + fprintf(stderr, "dt %d:", i); + dump_dt(&rmesa->state.VB.AttribPtr[i], VB->Count); + } + + fprintf(stderr, "before:\n"); + for(i=0; i < rmesa->state.aos_count; i++){ + fprintf(stderr, "aos %d:", i); + dump_array(&rmesa->state.aos[i], VB->Count); + } +#endif +#if 0 + r300ReleaseArrays(ctx); + r300EmitArrays(ctx, GL_FALSE); + + fprintf(stderr, "after:\n"); + for(i=0; i < rmesa->state.aos_count; i++){ + fprintf(stderr, "aos %d:", i); + dump_array(&rmesa->state.aos[i], VB->Count); + } +#endif + } + reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0); e32(0x0000000a); reg_start(0x4f18,0); e32(0x00000003); +#if 0 + reg_start(R300_VAP_PVS_WAITIDLE,0); + e32(0x00000000); +#endif r300EmitState(rmesa); - - rmesa->state.Elts = VB->Elts; - + for(i=0; i < VB->PrimitiveCount; i++){ GLuint prim = VB->Primitive[i].mode; GLuint start = VB->Primitive[i].start; @@ -562,219 +437,254 @@ static GLboolean r300_run_vb_render(GLcontext *ctx, } reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0); - e32(0x0000000a); + e32(0x0000000a/*0x2*/); reg_start(0x4f18,0); - e32(0x00000003); - -// end_3d(PASS_PREFIX_VOID); - - /* Flush state - we are done drawing.. */ -// r300FlushCmdBufLocked(rmesa, __FUNCTION__); -// radeonWaitForIdleLocked(&(rmesa->radeon)); - -// UNLOCK_HARDWARE(&(rmesa->radeon)); - return GL_FALSE; -} - -/** - * Called by the pipeline manager to render a batch of primitives. - * We can return true to pass on to the next stage (i.e. software - * rasterization) or false to indicate that the pipeline has finished - * after we render something. - */ -static GLboolean r300_run_render(GLcontext *ctx, - struct tnl_pipeline_stage *stage) -{ - r300ContextPtr rmesa = R300_CONTEXT(ctx); - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - GLuint i; - - if (RADEON_DEBUG & DEBUG_PRIMS) - fprintf(stderr, "%s\n", __FUNCTION__); - - -#if 1 + e32(0x00000003/*0x1*/); -#if 0 - return r300_run_immediate_render(ctx, stage); -#else - return r300_run_vb_render(ctx, stage); -#endif -#else - return GL_TRUE; -#endif - -#if 0 - mgaContextPtr mmesa = MGA_CONTEXT(ctx); - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - GLuint i; - - /* Don't handle clipping or indexed vertices or vertex manipulations. - */ - if (mmesa->RenderIndex != 0 || - !mga_validate_render( ctx, VB )) { - return GL_TRUE; - } - - tnl->Driver.Render.Start( ctx ); - mmesa->SetupNewInputs = ~0; - - for (i = 0 ; i < VB->PrimitiveCount ; i++) - { - GLuint prim = VB->Primitive[i].mode; - GLuint start = VB->Primitive[i].start; - GLuint length = VB->Primitive[i].count; - - if (!length) - continue; - - mga_render_tab_verts[prim & PRIM_MODE_MASK]( ctx, start, start + length, - prim); - } - - tnl->Driver.Render.Finish( ctx ); - - return GL_FALSE; /* finished the pipe */ +#ifdef USER_BUFFERS + r300UseArrays(ctx); #endif + r300ReleaseArrays(ctx); + return GL_FALSE; } - -/** - * Called by the pipeline manager once before rendering. - * We check the GL state here to - * a) decide whether we can do the current state in hardware and - * b) update hardware registers - */ #define FALLBACK_IF(expr) \ do { \ if (expr) { \ - if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \ - fprintf(stderr, "%s: fallback:%s\n", \ - __FUNCTION__, #expr); \ - stage->active = GL_FALSE; \ - return; \ + if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \ + WARN_ONCE("Software fallback:%s\n", #expr); \ + return R300_FALLBACK_RAST; \ } \ } while(0) -static void r300_check_render(GLcontext *ctx, struct tnl_pipeline_stage *stage) +int r300Fallback(GLcontext *ctx) { - r300ContextPtr r300 = R300_CONTEXT(ctx); int i; - if (RADEON_DEBUG & DEBUG_STATE) - fprintf(stderr, "%s\n", __FUNCTION__); - - /* We only support rendering in hardware for now */ - if (ctx->RenderMode != GL_RENDER) { - stage->active = GL_FALSE; - return; - } - - - /* I'm almost certain I forgot something here */ + //FALLBACK_IF(ctx->RenderMode != GL_RENDER); // We do not do SELECT or FEEDBACK (yet ?) + #if 0 /* These should work now.. */ FALLBACK_IF(ctx->Color.DitherFlag); FALLBACK_IF(ctx->Color.AlphaEnabled); // GL_ALPHA_TEST FALLBACK_IF(ctx->Color.BlendEnabled); // GL_BLEND FALLBACK_IF(ctx->Polygon.OffsetFill); // GL_POLYGON_OFFSET_FILL #endif - //FALLBACK_IF(ctx->Polygon.OffsetPoint); // GL_POLYGON_OFFSET_POINT - //FALLBACK_IF(ctx->Polygon.OffsetLine); // GL_POLYGON_OFFSET_LINE + FALLBACK_IF(ctx->Polygon.OffsetPoint); // GL_POLYGON_OFFSET_POINT + FALLBACK_IF(ctx->Polygon.OffsetLine); // GL_POLYGON_OFFSET_LINE //FALLBACK_IF(ctx->Stencil.Enabled); // GL_STENCIL_TEST //FALLBACK_IF(ctx->Fog.Enabled); // GL_FOG disable as swtcl doesnt seem to support this //FALLBACK_IF(ctx->Polygon.SmoothFlag); // GL_POLYGON_SMOOTH disabling to get blender going FALLBACK_IF(ctx->Polygon.StippleFlag); // GL_POLYGON_STIPPLE FALLBACK_IF(ctx->Multisample.Enabled); // GL_MULTISAMPLE_ARB - -#if 0 /* ut2k3 fails to start if this is on */ - /* One step at a time - let one texture pass.. */ - for (i = 1; i < ctx->Const.MaxTextureUnits; i++) - FALLBACK_IF(ctx->Texture.Unit[i].Enabled); -#endif - /* Assumed factor reg is found but pattern is still missing */ - //FALLBACK_IF(ctx->Line.StippleFlag); // GL_LINE_STIPPLE disabling to get blender going + + FALLBACK_IF(ctx->Line.StippleFlag); /* HW doesnt appear to directly support these */ - //FALLBACK_IF(ctx->Line.SmoothFlag); // GL_LINE_SMOOTH disabling to get blender going + FALLBACK_IF(ctx->Line.SmoothFlag); // GL_LINE_SMOOTH FALLBACK_IF(ctx->Point.SmoothFlag); // GL_POINT_SMOOTH /* Rest could be done with vertex fragments */ if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite) FALLBACK_IF(ctx->Point.PointSprite); // GL_POINT_SPRITE_NV - //GL_POINT_DISTANCE_ATTENUATION_ARB - //GL_POINT_FADE_THRESHOLD_SIZE_ARB - - /* let r300_run_render do its job */ -#if 0 - stage->active = GL_FALSE; -#endif -} + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) + if (ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_RECT_BIT) + return R300_FALLBACK_TCL; + + return R300_FALLBACK_NONE; +} -static void dtr(struct tnl_pipeline_stage *stage) +/** + * Called by the pipeline manager to render a batch of primitives. + * We can return true to pass on to the next stage (i.e. software + * rasterization) or false to indicate that the pipeline has finished + * after we render something. + */ +static GLboolean r300_run_render(GLcontext *ctx, + struct tnl_pipeline_stage *stage) { - (void)stage; + + if (RADEON_DEBUG & DEBUG_PRIMS) + fprintf(stderr, "%s\n", __FUNCTION__); + + if (r300Fallback(ctx) >= R300_FALLBACK_RAST) + return GL_TRUE; + + return r300_run_vb_render(ctx, stage); } const struct tnl_pipeline_stage _r300_render_stage = { "r300 hw rasterize", - _NEW_ALL, /* re-check (always re-check for now) */ - 0, /* re-run (always runs) */ - GL_TRUE, /* active */ - 0, 0, /* inputs (set in check_render), outputs */ - 0, 0, /* changed_inputs, private */ - dtr, /* destructor */ - r300_check_render, /* check */ + NULL, + NULL, + NULL, + NULL, r300_run_render /* run */ }; - + static GLboolean r300_run_tcl_render(GLcontext *ctx, struct tnl_pipeline_stage *stage) { + r300ContextPtr rmesa = R300_CONTEXT(ctx); + struct r300_vertex_program *vp; + + hw_tcl_on=future_hw_tcl_on; + + if (RADEON_DEBUG & DEBUG_PRIMS) + fprintf(stderr, "%s\n", __FUNCTION__); + if(hw_tcl_on == GL_FALSE) + return GL_TRUE; + + if (r300Fallback(ctx) >= R300_FALLBACK_TCL) { + hw_tcl_on = GL_FALSE; + return GL_TRUE; + } + + r300UpdateShaders(rmesa); + + vp = (struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx); +#if 0 /* Draw every second request with software arb vp */ + vp->native++; + vp->native &= 1; + //vp->native = GL_FALSE; +#endif + +#if 0 /* You dont want to know what this does... */ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct tnl_cache *cache; + struct tnl_cache_item *c; + + cache = tnl->vp_cache; + c = cache->items[0xc000cc0e % cache->size]; + + if(c && c->data == vp) + vp->native = GL_FALSE; + +#endif +#if 0 + vp->native = GL_FALSE; +#endif + if (vp->native == GL_FALSE) { + hw_tcl_on = GL_FALSE; + return GL_TRUE; + } + //r300UpdateShaderStates(rmesa); + + return r300_run_vb_render(ctx, stage); +} + +const struct tnl_pipeline_stage _r300_tcl_stage = { + "r300 tcl", + NULL, + NULL, + NULL, + NULL, + r300_run_tcl_render /* run */ +}; + +/* R300 texture rectangle expects coords in 0..1 range, not 0..dimension + * as in the extension spec. Need to translate here. + * + * Note that swrast expects 0..dimension, so if a fallback is active, + * don't do anything. (Maybe need to configure swrast to match hw) + */ +struct texrect_stage_data { + GLvector4f texcoord[MAX_TEXTURE_UNITS]; +}; + +#define TEXRECT_STAGE_DATA(stage) ((struct texrect_stage_data *)stage->privatePtr) + + +static GLboolean run_texrect_stage( GLcontext *ctx, + struct tnl_pipeline_stage *stage ) +{ + struct texrect_stage_data *store = TEXRECT_STAGE_DATA(stage); r300ContextPtr rmesa = R300_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; GLuint i; - if (RADEON_DEBUG & DEBUG_PRIMS) - fprintf(stderr, "%s\n", __FUNCTION__); + if (rmesa->radeon.Fallback) + return GL_TRUE; - return r300_run_vb_render(ctx, stage); + for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) { + if (ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_RECT_BIT) { + struct gl_texture_object *texObj = ctx->Texture.Unit[i].CurrentRect; + struct gl_texture_image *texImage = texObj->Image[0][texObj->BaseLevel]; + const GLfloat iw = 1.0/texImage->Width; + const GLfloat ih = 1.0/texImage->Height; + GLfloat *in = (GLfloat *)VB->TexCoordPtr[i]->data; + GLint instride = VB->TexCoordPtr[i]->stride; + GLfloat (*out)[4] = store->texcoord[i].data; + GLint j; + + store->texcoord[i].size = VB->TexCoordPtr[i]->size; + for (j = 0 ; j < VB->Count ; j++) { + switch (VB->TexCoordPtr[i]->size) { + case 4: + out[j][3] = in[3]; + /* fallthrough */ + case 3: + out[j][2] = in[2]; + /* fallthrough */ + default: + out[j][0] = in[0] * iw; + out[j][1] = in[1] * ih; + } + in = (GLfloat *)((GLubyte *)in + instride); + } + + VB->AttribPtr[VERT_ATTRIB_TEX0+i] = VB->TexCoordPtr[i] = &store->texcoord[i]; + } + } + + return GL_TRUE; } -static void r300_check_tcl_render(GLcontext *ctx, struct tnl_pipeline_stage *stage) + +/* Called the first time stage->run() is invoked. + */ +static GLboolean alloc_texrect_data( GLcontext *ctx, + struct tnl_pipeline_stage *stage ) { - r300ContextPtr r300 = R300_CONTEXT(ctx); - int i; + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + struct texrect_stage_data *store; + GLuint i; - if (RADEON_DEBUG & DEBUG_STATE) - fprintf(stderr, "%s\n", __FUNCTION__); + stage->privatePtr = CALLOC(sizeof(*store)); + store = TEXRECT_STAGE_DATA(stage); + if (!store) + return GL_FALSE; - /* We only support rendering in hardware for now */ - if (ctx->RenderMode != GL_RENDER) { - stage->active = GL_FALSE; - return; - } - if(VERTPROG_ACTIVE(ctx)) { - stage->active = GL_TRUE; - stage->inputs = ctx->VertexProgram.Current->InputsRead; - } else { - stage->active = GL_FALSE; - } + for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) + _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 ); + + return GL_TRUE; } -const struct tnl_pipeline_stage _r300_tcl_stage = { - "r300 tcl", - _NEW_ALL, /* re-check (always re-check for now) */ - 0, /* re-run (always runs) */ - GL_TRUE, /* active */ - 0, 0, /* inputs (set in check_render), outputs */ - 0, 0, /* changed_inputs, private */ - dtr, /* destructor */ - r300_check_tcl_render, /* check */ - r300_run_tcl_render /* run */ +static void free_texrect_data( struct tnl_pipeline_stage *stage ) +{ + struct texrect_stage_data *store = TEXRECT_STAGE_DATA(stage); + GLuint i; + + if (store) { + for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) + if (store->texcoord[i].data) + _mesa_vector4f_free( &store->texcoord[i] ); + FREE( store ); + stage->privatePtr = NULL; + } +} + +const struct tnl_pipeline_stage _r300_texrect_stage = +{ + "r300 texrect stage", /* name */ + NULL, + alloc_texrect_data, + free_texrect_data, + NULL, + run_texrect_stage }; +