aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_render.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_render.c')
-rw-r--r--nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_render.c726
1 files changed, 726 insertions, 0 deletions
diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_render.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_render.c
new file mode 100644
index 000000000..a0769e27f
--- /dev/null
+++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_render.c
@@ -0,0 +1,726 @@
+/**************************************************************************
+
+Copyright (C) 2004 Nicolai Haehnle.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Nicolai Haehnle <prefect_@gmx.net>
+ */
+
+#include "glheader.h"
+#include "state.h"
+#include "imports.h"
+#include "enums.h"
+#include "macros.h"
+#include "context.h"
+#include "dd.h"
+#include "simple_list.h"
+
+#include "api_arrayelt.h"
+#include "swrast/swrast.h"
+#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"
+#include "r300_ioctl.h"
+#include "r300_state.h"
+#include "r300_reg.h"
+#include "r300_program.h"
+#include "r300_tex.h"
+#include "r300_maos.h"
+#include "r300_emit.h"
+
+extern int future_hw_tcl_on;
+
+/**********************************************************************
+* Hardware rasterization
+*
+* When we fell back to software TCL, we still try to use the
+* rasterization hardware for rendering.
+**********************************************************************/
+
+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;
+
+ switch (prim & PRIM_MODE_MASK) {
+ case GL_POINTS:
+ type=R300_VAP_VF_CNTL__PRIM_POINTS;
+ break;
+ case GL_LINES:
+ type=R300_VAP_VF_CNTL__PRIM_LINES;
+ break;
+ case GL_LINE_STRIP:
+ type=R300_VAP_VF_CNTL__PRIM_LINE_STRIP;
+ break;
+ case GL_LINE_LOOP:
+ type=R300_VAP_VF_CNTL__PRIM_LINE_LOOP;
+ break;
+ case GL_TRIANGLES:
+ type=R300_VAP_VF_CNTL__PRIM_TRIANGLES;
+ break;
+ case GL_TRIANGLE_STRIP:
+ type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP;
+ break;
+ case GL_TRIANGLE_FAN:
+ type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN;
+ break;
+ case GL_QUADS:
+ type=R300_VAP_VF_CNTL__PRIM_QUADS;
+ break;
+ case GL_QUAD_STRIP:
+ type=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP;
+ break;
+ case GL_POLYGON:
+ type=R300_VAP_VF_CNTL__PRIM_POLYGON;
+ break;
+ default:
+ fprintf(stderr, "%s:%s Do not know how to handle primitive %02x - help me !\n",
+ __FILE__, __FUNCTION__,
+ prim & PRIM_MODE_MASK);
+ return -1;
+ break;
+ }
+ return type;
+}
+
+static int r300_get_num_verts(r300ContextPtr rmesa,
+ GLcontext *ctx,
+ 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";
+
+ switch (prim & PRIM_MODE_MASK) {
+ case GL_POINTS:
+ name="P";
+ verts_off = 0;
+ break;
+ case GL_LINES:
+ name="L";
+ verts_off = num_verts % 2;
+ break;
+ case GL_LINE_STRIP:
+ name="LS";
+ if(num_verts < 2)
+ verts_off = num_verts;
+ break;
+ case GL_LINE_LOOP:
+ name="LL";
+ if(num_verts < 2)
+ verts_off = num_verts;
+ break;
+ case GL_TRIANGLES:
+ name="T";
+ verts_off = num_verts % 3;
+ break;
+ case GL_TRIANGLE_STRIP:
+ name="TS";
+ if(num_verts < 3)
+ verts_off = num_verts;
+ break;
+ case GL_TRIANGLE_FAN:
+ name="TF";
+ if(num_verts < 3)
+ verts_off = num_verts;
+ break;
+ case GL_QUADS:
+ name="Q";
+ verts_off = num_verts % 4;
+ break;
+ case GL_QUAD_STRIP:
+ name="QS";
+ if(num_verts < 4)
+ verts_off = num_verts;
+ else
+ verts_off = num_verts % 2;
+ break;
+ case GL_POLYGON:
+ name="P";
+ if(num_verts < 3)
+ verts_off = num_verts;
+ break;
+ default:
+ fprintf(stderr, "%s:%s Do not know how to handle primitive %02x - help me !\n",
+ __FILE__, __FUNCTION__,
+ prim & PRIM_MODE_MASK);
+ return -1;
+ 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(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;
+}
+
+/* This function compiles GL context into state registers that
+ describe data routing inside of R300 pipeline.
+
+ In particular, it programs input_route, output_vtx_fmt, texture
+ unit configuration and gb_output_vtx_fmt
+
+ This function encompasses setup_AOS() from r300_lib.c
+*/
+
+
+
+
+/* Immediate implementation - vertex data is sent via command stream */
+
+static GLfloat default_vector[4]={0.0, 0.0, 0.0, 1.0};
+
+#define output_vector(v, i) { \
+ int _i; \
+ for(_i=0;_i<v->size;_i++){ \
+ if(VB->Elts){ \
+ efloat(VEC_ELT(v, GLfloat, VB->Elts[i])[_i]); \
+ }else{ \
+ 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 */
+
+static void r300_render_immediate_primitive(r300ContextPtr rmesa,
+ GLcontext *ctx,
+ int start,
+ int end,
+ int prim)
+{
+ 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;
+ }
+
+ //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;
+ }
+
+
+ start_immediate_packet(num_verts, type, 4*rmesa->state.aos_count);
+
+ for(i=start;i<start+num_verts;i++){
+#if 0
+ fprintf(stderr, "* (%f %f %f %f) (%f %f %f %f)\n",
+ VEC_ELT(VB->ObjPtr, 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<<k))
+ output_vector(VB->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);
+
+ }
+
+ r300EmitState(rmesa);
+
+/* 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;
+
+ if(addr & 1){
+ WARN_ONCE("Badly aligned buffer\n");
+ return ;
+ }
+ addr_a = 0; /*addr & 0x1c;*/
+
+ check_space(6);
+
+ start_packet3(RADEON_CP_PACKET3_3D_DRAW_INDX_2, 0);
+ /* TODO: R300_VAP_VF_CNTL__INDEX_SIZE_32bit . */
+ 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*/); /* Total number of dwords needed? */
+}
+
+static void r300_render_vb_primitive(r300ContextPtr rmesa,
+ GLcontext *ctx,
+ int start,
+ int end,
+ 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 0
+ start_index32_packet(num_verts, type);
+ for(i=0; i < num_verts; i++)
+ e32(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]);
+ return;
+ }
+
+ if(num_verts > 65535){ /* not implemented yet */
+ 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);
+#endif
+ }else{
+ r300EmitAOS(rmesa, rmesa->state.aos_count, start);
+ fire_AOS(PASS_PREFIX num_verts, type);
+ }
+}
+
+static 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
+
+ if (RADEON_DEBUG & DEBUG_PRIMS)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+
+ r300ReleaseArrays(ctx);
+ r300EmitArrays(ctx, GL_FALSE);
+
+// LOCK_HARDWARE(&(rmesa->radeon));
+
+ reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
+ e32(0x0000000a);
+
+ reg_start(0x4f18,0);
+ e32(0x00000003);
+ 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;
+ GLuint length = VB->Primitive[i].count;
+
+ r300_render_vb_primitive(rmesa, ctx, start, start + length, prim);
+ }
+
+ reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
+ e32(0x0000000a);
+
+ 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
+
+#if 0
+ return r300_run_immediate_render(ctx, stage);
+#else
+ return r300_run_vb_render(ctx, stage);
+#endif
+#else
+ return GL_TRUE;
+#endif
+}
+
+
+/**
+ * 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; \
+ } \
+} while(0)
+
+static void r300_check_render(GLcontext *ctx, struct tnl_pipeline_stage *stage)
+{
+ 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 */
+#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->RenderMode != GL_RENDER); // We do not do SELECT or FEEDBACK (yet ?)
+
+#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
+
+ /* HW doesnt appear to directly support these */
+ //FALLBACK_IF(ctx->Line.SmoothFlag); // GL_LINE_SMOOTH disabling to get blender going
+ 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
+}
+
+
+static void dtr(struct tnl_pipeline_stage *stage)
+{
+ (void)stage;
+}
+
+static GLboolean r300_create_render(GLcontext *ctx,
+ struct tnl_pipeline_stage *stage)
+{
+ return GL_TRUE;
+}
+
+
+const struct tnl_pipeline_stage _r300_render_stage = {
+ "r300 hw rasterize",
+ NULL,
+ r300_create_render,
+ dtr, /* destructor */
+ r300_check_render, /* check */
+ r300_run_render /* run */
+};
+
+static GLboolean r300_run_tcl_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;
+ 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(ctx->VertexProgram._Enabled == GL_FALSE){
+ _tnl_UpdateFixedFunctionProgram(ctx);
+ }
+ vp = (struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx);
+ if(vp->translated == GL_FALSE)
+ translate_vertex_shader(vp);
+ if(vp->translated == GL_FALSE){
+ fprintf(stderr, "Failing back to sw-tcl\n");
+ debug_vp(ctx, &vp->mesa_program);
+ hw_tcl_on=future_hw_tcl_on=0;
+ r300ResetHwState(rmesa);
+ return GL_TRUE;
+ }
+
+ r300_setup_textures(ctx);
+ r300_setup_rs_unit(ctx);
+
+ r300SetupVertexShader(rmesa);
+ r300SetupPixelShader(rmesa);
+
+ return r300_run_vb_render(ctx, stage);
+}
+
+static void r300_check_tcl_render(GLcontext *ctx, struct tnl_pipeline_stage *stage)
+{
+ 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;
+ }
+}
+
+const struct tnl_pipeline_stage _r300_tcl_stage = {
+ "r300 tcl",
+ NULL,
+ r300_create_render,
+ dtr, /* destructor */
+ r300_check_tcl_render, /* check */
+ r300_run_tcl_render /* run */
+};