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=cbd8f192a7aba28392668bad3dfd1efda6945178;hpb=b53030a94cf582da007f0ce3d427618989aa7dea;p=mesa.git diff --git a/src/mesa/drivers/dri/r300/r300_render.c b/src/mesa/drivers/dri/r300/r300_render.c index cbd8f192a7a..e6ed06a69d6 100644 --- a/src/mesa/drivers/dri/r300/r300_render.c +++ b/src/mesa/drivers/dri/r300/r300_render.c @@ -44,7 +44,10 @@ 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" #include "radeon_ioctl.h" #include "radeon_state.h" #include "r300_context.h" @@ -52,9 +55,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r300_state.h" #include "r300_reg.h" #include "r300_program.h" +#include "r300_tex.h" +#include "r300_maos.h" +#include "r300_emit.h" -#include "r300_lib.h" - +extern int future_hw_tcl_on; /********************************************************************** * Hardware rasterization @@ -63,409 +68,432 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * rasterization hardware for rendering. **********************************************************************/ -static int r300_get_primitive_type(r300ContextPtr rmesa, - GLcontext *ctx, - int start, - int end, - int prim) +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; - - if(end<=start)return -1; /* do we need to watch for this ? */ - - fprintf(stderr, "[%d-%d]", start, end); + int type=-1; + switch (prim & PRIM_MODE_MASK) { - case GL_LINES: - fprintf(stderr, "L "); + case GL_POINTS: + type=R300_VAP_VF_CNTL__PRIM_POINTS; + break; + case GL_LINES: type=R300_VAP_VF_CNTL__PRIM_LINES; - if(end 0) { + WARN_ONCE("user error: %d is not a valid number of vertices for primitive %s !\n", num_verts, name); + } + } -#define output_vector(v, i) \ - { \ - int _i; \ - for(_i=0;_isize;_i++){ \ - efloat(VEC_ELT(v, GLfloat, i)[_i]); \ - } \ - for(_i=v->size;_i<4;_i++){ \ - efloat(default_vector[_i]); \ - } \ + return num_verts - verts_off; +} + +/* Immediate implementation has been removed from CVS. */ + +/* vertex buffer implementation */ + +static void inline fire_EB(PREFIX unsigned long addr, int vertex_count, int type, int elt_size) +{ + 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 ; + } +#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); } -static void r300_render_flat_primitive(r300ContextPtr 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 + 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 +#else + (void)magic_2, (void)magic_1, (void)t_addr; + + addr_a = 0; + + 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); + } + + start_packet3(RADEON_CP_PACKET3_INDX_BUFFER, 2); + 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, GLcontext *ctx, int start, int end, int prim) { - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - GLuint i; - int k, type; - LOCAL_VARS - - type=r300_get_primitive_type(rmesa, ctx, start, end, prim); - if(type<0)return; - - - start_immediate_packet(end-start, type, 8); - - 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 1 - output_vector(VB->ObjPtr, i); - #else - efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[0]); - efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[1]); - efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[2]); - #if 0 - efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[3]); - #else - efloat(2.0); - #endif - #endif - - /* color components */ - #if 1 - output_vector(VB->ColorPtr[0], i); - #else - efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[0]); - efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[1]); - efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[2]); - #if 0 - efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[3]); - #else - efloat(0.0); - #endif - #endif - } + int type, num_verts; + 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.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(((unsigned long *)rmesa->state.VB.Elts)[i]/*rmesa->state.Elts[start+i]*/); /* start ? */ +#else + if(num_verts == 1){ + //start_index32_packet(num_verts, type); + //e32(rmesa->state.Elts[start]); + return; + } + + if(num_verts > 65535){ /* not implemented yet */ + WARN_ONCE("Too many elts\n"); + return; + } + + 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); + fire_AOS(PASS_PREFIX num_verts, type); + } } -static GLboolean r300_run_flat_render(GLcontext *ctx, - struct tnl_pipeline_stage *stage) +#if 0 +void dump_array(struct r300_dma_region *rvb, int count) { - r300ContextPtr rmesa = R300_CONTEXT(ctx); - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - GLuint i; - AOS_DATA vb_arrays[2]; - LOCAL_VARS + int *out = (int *)(rvb->address + rvb->start); + int i, ci; - if (RADEON_DEBUG == DEBUG_PRIMS) - fprintf(stderr, "%s\n", __FUNCTION__); + 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; + } - /* setup array of structures data */ - - /* Note: immediate vertex data includes all coordinates. - To save bandwidth use either VBUF or state-based vertex generation */ - /* xyz */ - vb_arrays[0].element_size=4; - vb_arrays[0].stride=4; - vb_arrays[0].offset=0; /* Not used */ - vb_arrays[0].format=AOS_FORMAT_FLOAT; - vb_arrays[0].ncomponents=4; - vb_arrays[0].reg=REG_COORDS; - - /* color */ - vb_arrays[1].element_size=4; - vb_arrays[1].stride=4; - vb_arrays[1].offset=0; /* Not used */ - vb_arrays[1].format=AOS_FORMAT_FLOAT_COLOR; - vb_arrays[1].ncomponents=4; - vb_arrays[1].reg=REG_COLOR0; - - r300EmitState(rmesa); - - /* needed before starting 3d operation .. */ - reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0); - e32(0x0000000a); - - reg_start(0x4f18,0); - e32(0x00000003); + fprintf(stderr, "\n"); +} + +void dump_dt(struct dt *dt, int count) +{ + int *out = dt->data; + int i, ci; + fprintf(stderr, "stride %d", dt->stride); - reg_start(0x20b0,0); - e32(0x0000043f); - - memcpy(FLAT_COLOR_PIPELINE.vertex_shader.parameters.body.f, ctx->_ModelProjectMatrix.m, 16*4); - - program_pipeline(PASS_PREFIX &FLAT_COLOR_PIPELINE); - - #if 0 /* Turn on for smooth color on teeth.. why ??.. */ - set_cull_cntl(PASS_PREFIX 0); - #endif - reg_start(R300_RE_OCCLUSION_CNTL, 0); - e32(R300_OCCLUSION_ON); - -// set_quad0(PASS_PREFIX 1.0,1.0,1.0,1.0); - set_init21(PASS_PREFIX 0.0,1.0); - - /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */ - setup_AOS(PASS_PREFIX vb_arrays, 2); - - 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_flat_primitive(rmesa, ctx, start, start + length, prim); - } + 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); + } - end_3d(PASS_PREFIX_VOID); - - fprintf(stderr, "\n"); - return GL_FALSE; + fprintf(stderr, "\n"); } +#endif -/* vertex buffer implementation */ - -/* We use the start part of GART texture buffer for vertices */ - -#define R300_MAX_AOS_ARRAYS 16 - -static void upload_vertex_buffer(r300ContextPtr rmesa, - GLcontext *ctx, AOS_DATA *array, int *n_arrays) +GLboolean r300_run_vb_render(GLcontext *ctx, + struct tnl_pipeline_stage *stage) { - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - int offset=0, idx=0; - int i,j; - radeonScreenPtr rsp=rmesa->radeon.radeonScreen; - /* Not the most efficient implementation, but, for now, I just want something that - works */ - /* to do - make single memcpy per column (is it possible ?) */ - /* to do - use dirty flags to avoid redundant copies */ -#define UPLOAD_VECTOR(v, r, f)\ - { \ - /* Is the data dirty ? */ \ - if (v->flags & ((1<size)-1)) { \ - fprintf(stderr, "size=%d vs stride=%d\n", v->size, v->stride); \ - if(v->size*4==v->stride){\ - /* fast path */ \ - memcpy(rsp->gartTextures.map+offset, v->data, v->stride*VB->Count); \ - } else { \ - for(i=0;iCount;i++){ \ - /* copy one vertex at a time*/ \ - memcpy(rsp->gartTextures.map+offset, VEC_ELT(v, GLfloat, i), v->size*4); \ - } \ - } \ - /* v->flags &= ~((1<size)-1);*/ \ - } \ - array[idx].element_size=v->size; \ - array[idx].stride=v->size; \ - array[idx].format=(f); \ - array[idx].ncomponents=v->size; \ - array[idx].offset=rsp->gartTextures.handle+offset; \ - array[idx].reg=r; \ - offset+=v->size*4*VB->Count; \ - idx++; \ - /* Fill in the rest with the components of default_vector */\ - /* \ - if(v->size<4){ \ - array[idx].element_size=4-v->size; \ - array[idx].stride=0; \ - array[idx].format=(f); \ - array[idx].ncomponents=4-v->size; \ - array[idx].offset=rsp->gartTextures.handle+v->size*4;\ - array[idx].reg=r; \ - idx++; \ - } \ - */\ + 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__); + + if (stage) { + TNLcontext *tnl = TNL_CONTEXT(ctx); + radeon_vb_to_rvb(rmesa, VB, &tnl->vb); } -/* Put a copy of default vector */ -memcpy(rsp->gartTextures.map, default_vector, 16); -offset+=16; + 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); -UPLOAD_VECTOR(VB->ObjPtr, REG_COORDS, AOS_FORMAT_FLOAT); -UPLOAD_VECTOR(VB->ColorPtr[0], REG_COLOR0, AOS_FORMAT_FLOAT_COLOR); +#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); -*n_arrays=idx; -if(idx>=R300_MAX_AOS_ARRAYS){ - fprintf(stderr, "Aieee ! Maximum AOS arrays count exceeded.. \n"); - exit(-1); + reg_start(0x4f18,0); + e32(0x00000003); +#if 0 + reg_start(R300_VAP_PVS_WAITIDLE,0); + e32(0x00000000); +#endif + r300EmitState(rmesa); + + 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_vb_primitive(rmesa, ctx, start, start + length, prim); } -} -static void r300_render_vb_flat_primitive(r300ContextPtr rmesa, - GLcontext *ctx, - int start, - int end, - int prim) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - GLuint i; - int k, type, n_arrays; - LOCAL_VARS - - if(end<=start)return; /* do we need to watch for this ? */ - - type=r300_get_primitive_type(rmesa, ctx, start, end, prim); - if(type<0)return; + reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0); + e32(0x0000000a/*0x2*/); + + reg_start(0x4f18,0); + e32(0x00000003/*0x1*/); - fire_AOS(PASS_PREFIX end-start, type); +#ifdef USER_BUFFERS + r300UseArrays(ctx); +#endif + r300ReleaseArrays(ctx); + return GL_FALSE; } -static VERTEX_SHADER_FRAGMENT default_vector_vsf={ - length: 4, - body: { - f: {0.0, 0.0, 0.0, 1.0} - } - }; +#define FALLBACK_IF(expr) \ +do { \ + if (expr) { \ + if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \ + WARN_ONCE("Software fallback:%s\n", #expr); \ + return R300_FALLBACK_RAST; \ + } \ +} while(0) -static GLboolean r300_run_vb_flat_render(GLcontext *ctx, - struct tnl_pipeline_stage *stage) +int r300Fallback(GLcontext *ctx) { - r300ContextPtr rmesa = R300_CONTEXT(ctx); - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - int i, j, n_arrays; - AOS_DATA vb_arrays[R300_MAX_AOS_ARRAYS]; - AOS_DATA vb_arrays2[R300_MAX_AOS_ARRAYS]; - LOCAL_VARS - - if (RADEON_DEBUG == DEBUG_PRIMS) - fprintf(stderr, "%s\n", __FUNCTION__); + int i; - /* setup array of structures data */ + //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->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 + + + FALLBACK_IF(ctx->Line.StippleFlag); + + /* HW doesnt appear to directly support these */ + 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 - upload_vertex_buffer(rmesa, ctx, vb_arrays, &n_arrays); - fprintf(stderr, "Using %d AOS arrays\n", n_arrays); - - r300EmitState(rmesa); - - reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0); - e32(0x0000000a); - - reg_start(0x4f18,0); - e32(0x00000003); - - reg_start(0x20b0,0); - e32(0x0000043f); - - program_pipeline(PASS_PREFIX &FLAT_COLOR_PIPELINE); - - //upload_vertex_shader_fragment(PASS_PREFIX VSF_DEST_UNKNOWN1, &default_vector_vsf); - - reg_start(R300_RE_OCCLUSION_CNTL, 0); - e32(R300_OCCLUSION_ON); - - set_quad0(PASS_PREFIX 1.0,1.0,1.0,1.0); - set_init21(PASS_PREFIX 0.0,1.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; - - /* copy arrays */ - memcpy(vb_arrays2, vb_arrays, sizeof(AOS_DATA)*n_arrays); - for(j=0;jConst.MaxTextureUnits; i++) + if (ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_RECT_BIT) + return R300_FALLBACK_TCL; - setup_AOS(PASS_PREFIX vb_arrays2, n_arrays); - - r300_render_vb_flat_primitive(rmesa, ctx, start, start + length, prim); - } - - end_3d(PASS_PREFIX_VOID); - - /* Flush state - we are done drawing.. */ - r300Flush(ctx); - fprintf(stderr, "\n"); - return GL_FALSE; + return R300_FALLBACK_NONE; } /** @@ -477,133 +505,186 @@ static GLboolean r300_run_vb_flat_render(GLcontext *ctx, 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__); - - return r300_run_flat_render(ctx, stage); - #if 0 - return GL_TRUE; - #else - return GL_FALSE; - #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; - } + if (RADEON_DEBUG & DEBUG_PRIMS) + fprintf(stderr, "%s\n", __FUNCTION__); - tnl->Driver.Render.Start( ctx ); - mmesa->SetupNewInputs = ~0; + if (r300Fallback(ctx) >= R300_FALLBACK_RAST) + return GL_TRUE; - 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; + return r300_run_vb_render(ctx, stage); +} - if (!length) - continue; +const struct tnl_pipeline_stage _r300_render_stage = { + "r300 hw rasterize", + NULL, + NULL, + NULL, + NULL, + r300_run_render /* run */ +}; - mga_render_tab_verts[prim & PRIM_MODE_MASK]( ctx, start, start + length, - prim); - } +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); - tnl->Driver.Render.Finish( ctx ); + 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 - return GL_FALSE; /* finished the pipe */ +#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 */ +}; -/** - * 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 +/* 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) */ -#define FALLBACK_IF(expr) \ -do { \ - if (expr) { \ - if (RADEON_DEBUG & DEBUG_FALLBACKS) \ - fprintf(stderr, "%s: fallback:%s\n", \ - __FUNCTION__, #expr); \ - stage->active = GL_FALSE; \ - return; \ - } \ -} while(0) +struct texrect_stage_data { + GLvector4f texcoord[MAX_TEXTURE_UNITS]; +}; + +#define TEXRECT_STAGE_DATA(stage) ((struct texrect_stage_data *)stage->privatePtr) -static void r300_check_render(GLcontext *ctx, struct tnl_pipeline_stage *stage) + +static GLboolean run_texrect_stage( GLcontext *ctx, + struct tnl_pipeline_stage *stage ) { - r300ContextPtr r300 = R300_CONTEXT(ctx); - int i; + 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_STATE) - fprintf(stderr, "%s\n", __FUNCTION__); + if (rmesa->radeon.Fallback) + return GL_TRUE; - /* We only support rendering in hardware for now */ - if (ctx->RenderMode != GL_RENDER) { - stage->active = GL_FALSE; - return; - } + 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]; + } + } - // I failed to figure out how dither works in hardware, - // let's just ignore it for now - //FALLBACK_IF(ctx->Color.DitherFlag); + return GL_TRUE; +} - /* I'm almost certain I forgot something here */ - FALLBACK_IF(ctx->Color.AlphaEnabled); // GL_ALPHA_TEST - FALLBACK_IF(ctx->Color.BlendEnabled); // GL_BLEND - FALLBACK_IF(ctx->Fog.Enabled); // GL_FOG - FALLBACK_IF(ctx->Line.SmoothFlag); // GL_LINE_SMOOTH - FALLBACK_IF(ctx->Line.StippleFlag); // GL_LINE_STIPPLE - FALLBACK_IF(ctx->Point.SmoothFlag); // GL_POINT_SMOOTH - if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite) - FALLBACK_IF(ctx->Point.PointSprite); // GL_POINT_SPRITE_NV - FALLBACK_IF(ctx->Polygon.OffsetPoint); // GL_POLYGON_OFFSET_POINT - FALLBACK_IF(ctx->Polygon.OffsetLine); // GL_POLYGON_OFFSET_LINE - FALLBACK_IF(ctx->Polygon.OffsetFill); // GL_POLYGON_OFFSET_FILL - FALLBACK_IF(ctx->Polygon.SmoothFlag); // GL_POLYGON_SMOOTH - FALLBACK_IF(ctx->Polygon.StippleFlag); // GL_POLYGON_STIPPLE - FALLBACK_IF(ctx->Stencil.Enabled); // GL_STENCIL_TEST - FALLBACK_IF(ctx->Multisample.Enabled); // GL_MULTISAMPLE_ARB - for (i = 0; i < ctx->Const.MaxTextureUnits; i++) - FALLBACK_IF(ctx->Texture.Unit[i].Enabled); +/* Called the first time stage->run() is invoked. + */ +static GLboolean alloc_texrect_data( GLcontext *ctx, + struct tnl_pipeline_stage *stage ) +{ + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + struct texrect_stage_data *store; + GLuint i; + stage->privatePtr = CALLOC(sizeof(*store)); + store = TEXRECT_STAGE_DATA(stage); + if (!store) + return GL_FALSE; - /* let r300_run_render do its job */ - #if 0 - stage->active = GL_FALSE; - #endif -} + for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) + _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 ); + return GL_TRUE; +} -static void dtr(struct tnl_pipeline_stage *stage) +static void free_texrect_data( struct tnl_pipeline_stage *stage ) { - (void)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_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 */ - r300_run_render /* run */ +const struct tnl_pipeline_stage _r300_texrect_stage = +{ + "r300 texrect stage", /* name */ + NULL, + alloc_texrect_data, + free_texrect_data, + NULL, + run_texrect_stage }; +