Get textures to work with NeHe lesson06.
[mesa.git] / src / mesa / drivers / dri / r300 / r300_render.c
1 /**************************************************************************
2
3 Copyright (C) 2004 Nicolai Haehnle.
4
5 All Rights Reserved.
6
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
16 Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Nicolai Haehnle <prefect_@gmx.net>
31 */
32
33 #include "glheader.h"
34 #include "state.h"
35 #include "imports.h"
36 #include "enums.h"
37 #include "macros.h"
38 #include "context.h"
39 #include "dd.h"
40 #include "simple_list.h"
41
42 #include "api_arrayelt.h"
43 #include "swrast/swrast.h"
44 #include "swrast_setup/swrast_setup.h"
45 #include "array_cache/acache.h"
46 #include "tnl/tnl.h"
47
48 #include "radeon_ioctl.h"
49 #include "radeon_state.h"
50 #include "r300_context.h"
51 #include "r300_ioctl.h"
52 #include "r300_state.h"
53 #include "r300_reg.h"
54 #include "r300_program.h"
55
56 #include "r300_lib.h"
57
58
59 /**********************************************************************
60 * Hardware rasterization
61 *
62 * When we fell back to software TCL, we still try to use the
63 * rasterization hardware for rendering.
64 **********************************************************************/
65
66 static int r300_get_primitive_type(r300ContextPtr rmesa,
67 GLcontext *ctx,
68 int start,
69 int end,
70 int prim)
71 {
72 TNLcontext *tnl = TNL_CONTEXT(ctx);
73 struct vertex_buffer *VB = &tnl->vb;
74 GLuint i;
75 int type=-1, min_vertices=0;
76 char *name="UNKNOWN";
77
78 if(end<=start)return -1; /* do we need to watch for this ? */
79
80 switch (prim & PRIM_MODE_MASK) {
81 case GL_POINTS:
82 name="P";
83 type=R300_VAP_VF_CNTL__PRIM_POINTS;
84 min_vertices=1;
85 break;
86 case GL_LINES:
87 name="L";
88 type=R300_VAP_VF_CNTL__PRIM_LINES;
89 min_vertices=2;
90 break;
91 case GL_LINE_STRIP:
92 name="LS";
93 type=R300_VAP_VF_CNTL__PRIM_LINE_STRIP;
94 min_vertices=2;
95 break;
96 case GL_LINE_LOOP:
97 name="LL";
98 min_vertices=2;
99 return -1;
100 break;
101 case GL_TRIANGLES:
102 name="T";
103 type=R300_VAP_VF_CNTL__PRIM_TRIANGLES;
104 min_vertices=3;
105 break;
106 case GL_TRIANGLE_STRIP:
107 name="TS";
108 type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP;
109 min_vertices=3;
110 break;
111 case GL_TRIANGLE_FAN:
112 name="TF";
113 type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN;
114 min_vertices=3;
115 break;
116 case GL_QUADS:
117 name="Q";
118 type=R300_VAP_VF_CNTL__PRIM_QUADS;
119 min_vertices=4;
120 break;
121 case GL_QUAD_STRIP:
122 name="QS";
123 type=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP;
124 min_vertices=4;
125 break;
126 default:
127 fprintf(stderr, "Cannot handle primitive %02x ", prim & PRIM_MODE_MASK);
128 return -1;
129 break;
130 }
131 #if 0
132 fprintf(stderr, "[%d-%d]%s ", start, end, name);
133 #endif
134 if(start+min_vertices>=end){
135 fprintf(stderr, "Not enough vertices\n");
136 return -1;
137 }
138 return type;
139 }
140
141
142
143 /* Immediate implementation - vertex data is sent via command stream */
144
145 static GLfloat default_vector[4]={0.0, 0.0, 0.0, 1.0};
146
147 #define output_vector(v, i) \
148 { \
149 int _i; \
150 for(_i=0;_i<v->size;_i++){ \
151 efloat(VEC_ELT(v, GLfloat, i)[_i]); \
152 } \
153 for(_i=v->size;_i<4;_i++){ \
154 efloat(default_vector[_i]); \
155 } \
156 }
157
158 static void r300_render_flat_primitive(r300ContextPtr rmesa,
159 GLcontext *ctx,
160 int start,
161 int end,
162 int prim)
163 {
164 TNLcontext *tnl = TNL_CONTEXT(ctx);
165 struct vertex_buffer *VB = &tnl->vb;
166 GLuint i;
167 int k, type;
168 LOCAL_VARS
169
170 type=r300_get_primitive_type(rmesa, ctx, start, end, prim);
171
172 if(type<0)return;
173
174
175 start_immediate_packet(end-start, type, 8);
176
177 for(i=start;i<end;i++){
178 #if 0
179 fprintf(stderr, "* (%f %f %f %f) (%f %f %f %f)\n",
180 VEC_ELT(VB->ObjPtr, GLfloat, i)[0],
181 VEC_ELT(VB->ObjPtr, GLfloat, i)[1],
182 VEC_ELT(VB->ObjPtr, GLfloat, i)[2],
183 VEC_ELT(VB->ObjPtr, GLfloat, i)[3],
184
185 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[0],
186 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[1],
187 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[2],
188 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[3]
189 );
190 #endif
191
192
193 /* coordinates */
194 output_vector(VB->ObjPtr, i);
195
196 /* color components */
197 output_vector(VB->ColorPtr[0], i);
198 }
199
200 }
201
202 static GLboolean r300_run_flat_render(GLcontext *ctx,
203 struct tnl_pipeline_stage *stage)
204 {
205 r300ContextPtr rmesa = R300_CONTEXT(ctx);
206 TNLcontext *tnl = TNL_CONTEXT(ctx);
207 struct vertex_buffer *VB = &tnl->vb;
208 GLuint i;
209 AOS_DATA vb_arrays[2];
210 LOCAL_VARS
211
212 /* Flush state - make sure command buffer is nice and large */
213 r300Flush(ctx);
214
215 if (RADEON_DEBUG == DEBUG_PRIMS)
216 fprintf(stderr, "%s\n", __FUNCTION__);
217
218 /* setup array of structures data */
219
220 /* Note: immediate vertex data includes all coordinates.
221 To save bandwidth use either VBUF or state-based vertex generation */
222 /* xyz */
223 vb_arrays[0].element_size=4;
224 vb_arrays[0].stride=4;
225 vb_arrays[0].offset=0; /* Not used */
226 vb_arrays[0].format=AOS_FORMAT_FLOAT;
227 vb_arrays[0].ncomponents=4;
228 vb_arrays[0].reg=REG_COORDS;
229
230 /* color */
231 vb_arrays[1].element_size=4;
232 vb_arrays[1].stride=4;
233 vb_arrays[1].offset=0; /* Not used */
234 vb_arrays[1].format=AOS_FORMAT_FLOAT_COLOR;
235 vb_arrays[1].ncomponents=4;
236 vb_arrays[1].reg=REG_COLOR0;
237
238
239 /* needed before starting 3d operation .. */
240 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
241 e32(0x0000000a);
242
243 reg_start(0x4f18,0);
244 e32(0x00000003);
245
246 rmesa->hw.vte.cmd[1] = R300_VPORT_X_SCALE_ENA
247 | R300_VPORT_X_OFFSET_ENA
248 | R300_VPORT_Y_SCALE_ENA
249 | R300_VPORT_Y_OFFSET_ENA
250 | R300_VTX_W0_FMT;
251 R300_STATECHANGE(rmesa, vte);
252
253 r300EmitState(rmesa);
254
255 FLAT_COLOR_PIPELINE.vertex_shader.matrix[0].length=16;
256 memcpy(FLAT_COLOR_PIPELINE.vertex_shader.matrix[0].body.f, ctx->_ModelProjectMatrix.m, 16*4);
257
258 FLAT_COLOR_PIPELINE.vertex_shader.unknown2.length=4;
259 FLAT_COLOR_PIPELINE.vertex_shader.unknown2.body.f[0]=0.0;
260 FLAT_COLOR_PIPELINE.vertex_shader.unknown2.body.f[1]=0.0;
261 FLAT_COLOR_PIPELINE.vertex_shader.unknown2.body.f[2]=1.0;
262 FLAT_COLOR_PIPELINE.vertex_shader.unknown2.body.f[3]=0.0;
263
264 program_pipeline(PASS_PREFIX &FLAT_COLOR_PIPELINE);
265 cp_delay(PASS_PREFIX 15);
266
267 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
268 setup_AOS(PASS_PREFIX vb_arrays, 2);
269
270 for(i=0; i < VB->PrimitiveCount; i++){
271 GLuint prim = VB->Primitive[i].mode;
272 GLuint start = VB->Primitive[i].start;
273 GLuint length = VB->Primitive[i].count;
274 r300_render_flat_primitive(rmesa, ctx, start, start + length, prim);
275 }
276
277 sync_VAP(PASS_PREFIX_VOID);
278
279 end_3d(PASS_PREFIX_VOID);
280
281 /* Flush state - this reduces the chance that something else will mess with
282 the hardware in between */
283 r300Flush(ctx);
284 //fprintf(stderr, "\n");
285 return GL_FALSE;
286 }
287
288 /* vertex buffer implementation */
289
290 /* We use the start part of GART texture buffer for vertices */
291
292 /* 8 is somewhat bogus... it is probably something like 24 */
293 #define R300_MAX_AOS_ARRAYS 8
294
295 static void upload_vertex_buffer(r300ContextPtr rmesa,
296 GLcontext *ctx, AOS_DATA *array, int *n_arrays)
297 {
298 TNLcontext *tnl = TNL_CONTEXT(ctx);
299 struct vertex_buffer *VB = &tnl->vb;
300 int offset=0, idx=0;
301 int i,j;
302 radeonScreenPtr rsp=rmesa->radeon.radeonScreen;
303 /* Not the most efficient implementation, but, for now, I just want something that
304 works */
305 /* to do - make single memcpy per column (is it possible ?) */
306 /* to do - use dirty flags to avoid redundant copies */
307 #define UPLOAD_VECTOR(v, r, f)\
308 { \
309 /* Is the data dirty ? */ \
310 if (v->flags & ((1<<v->size)-1)) { \
311 fprintf(stderr, "size=%d vs stride=%d\n", v->size, v->stride); \
312 if(v->size*4==v->stride){\
313 /* fast path */ \
314 memcpy(rsp->gartTextures.map+offset, v->data, v->stride*VB->Count); \
315 } else { \
316 for(i=0;i<VB->Count;i++){ \
317 /* copy one vertex at a time*/ \
318 memcpy(rsp->gartTextures.map+offset+i*v->size*4, VEC_ELT(v, GLfloat, i), v->size*4); \
319 } \
320 } \
321 /* v->flags &= ~((1<<v->size)-1);*/ \
322 } \
323 array[idx].element_size=v->size; \
324 array[idx].stride=v->size; \
325 array[idx].format=(f); \
326 array[idx].ncomponents=v->size; \
327 array[idx].offset=rsp->gartTextures.handle+offset; \
328 array[idx].reg=r; \
329 offset+=v->size*4*VB->Count; \
330 idx++; \
331 }
332
333 UPLOAD_VECTOR(VB->ObjPtr, REG_COORDS, AOS_FORMAT_FLOAT);
334 UPLOAD_VECTOR(VB->ColorPtr[0], REG_COLOR0, AOS_FORMAT_FLOAT_COLOR);
335
336 *n_arrays=idx;
337 if(idx>=R300_MAX_AOS_ARRAYS){
338 fprintf(stderr, "Aieee ! Maximum AOS arrays count exceeded.. \n");
339 exit(-1);
340 }
341 }
342
343 static void r300_render_vb_flat_primitive(r300ContextPtr rmesa,
344 GLcontext *ctx,
345 int start,
346 int end,
347 int prim)
348 {
349 TNLcontext *tnl = TNL_CONTEXT(ctx);
350 struct vertex_buffer *VB = &tnl->vb;
351 GLuint i;
352 int k, type, n_arrays;
353 LOCAL_VARS
354
355 if(end<=start)return; /* do we need to watch for this ? */
356
357 type=r300_get_primitive_type(rmesa, ctx, start, end, prim);
358 if(type<0)return;
359
360 fire_AOS(PASS_PREFIX end-start, type);
361 }
362
363 static VERTEX_SHADER_FRAGMENT default_vector_vsf={
364 length: 4,
365 body: {
366 f: {0.0, 0.0, 0.0, 1.0}
367 }
368 };
369
370 static GLboolean r300_run_vb_flat_render(GLcontext *ctx,
371 struct tnl_pipeline_stage *stage)
372 {
373 r300ContextPtr rmesa = R300_CONTEXT(ctx);
374 TNLcontext *tnl = TNL_CONTEXT(ctx);
375 struct vertex_buffer *VB = &tnl->vb;
376 int i, j, n_arrays;
377 AOS_DATA vb_arrays[R300_MAX_AOS_ARRAYS];
378 AOS_DATA vb_arrays2[R300_MAX_AOS_ARRAYS];
379 LOCAL_VARS
380
381 if (RADEON_DEBUG == DEBUG_PRIMS)
382 fprintf(stderr, "%s\n", __FUNCTION__);
383
384 /* setup array of structures data */
385
386 upload_vertex_buffer(rmesa, ctx, vb_arrays, &n_arrays);
387 fprintf(stderr, "Using %d AOS arrays\n", n_arrays);
388
389 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
390 e32(0x0000000a);
391
392 reg_start(0x4f18,0);
393 e32(0x00000003);
394
395 r300EmitState(rmesa);
396
397 FLAT_COLOR_PIPELINE.vertex_shader.matrix[0].length=16;
398 memcpy(FLAT_COLOR_PIPELINE.vertex_shader.matrix[0].body.f, ctx->_ModelProjectMatrix.m, 16*4);
399
400 FLAT_COLOR_PIPELINE.vertex_shader.unknown2.length=4;
401 FLAT_COLOR_PIPELINE.vertex_shader.unknown2.body.f[0]=0.0;
402 FLAT_COLOR_PIPELINE.vertex_shader.unknown2.body.f[1]=0.0;
403 FLAT_COLOR_PIPELINE.vertex_shader.unknown2.body.f[2]=1.0;
404 FLAT_COLOR_PIPELINE.vertex_shader.unknown2.body.f[3]=0.0;
405
406 program_pipeline(PASS_PREFIX &FLAT_COLOR_PIPELINE);
407
408 set_quad0(PASS_PREFIX 1.0,1.0,1.0,1.0);
409 set_init21(PASS_PREFIX 0.0,1.0);
410
411 for(i=0; i < VB->PrimitiveCount; i++){
412 GLuint prim = VB->Primitive[i].mode;
413 GLuint start = VB->Primitive[i].start;
414 GLuint length = VB->Primitive[i].count;
415
416 /* copy arrays */
417 memcpy(vb_arrays2, vb_arrays, sizeof(AOS_DATA)*n_arrays);
418 for(j=0;j<n_arrays;j++){
419 vb_arrays2[j].offset+=vb_arrays2[j].stride*start*4;
420 }
421
422 setup_AOS(PASS_PREFIX vb_arrays2, n_arrays);
423
424 r300_render_vb_flat_primitive(rmesa, ctx, start, start + length, prim);
425 }
426
427 end_3d(PASS_PREFIX_VOID);
428
429 /* Flush state - we are done drawing.. */
430 r300Flush(ctx);
431 fprintf(stderr, "\n");
432 return GL_FALSE;
433 }
434
435 /* Textures... */
436
437 /* Immediate implementation - vertex data is sent via command stream */
438
439 static void r300_render_tex_primitive(r300ContextPtr rmesa,
440 GLcontext *ctx,
441 int start,
442 int end,
443 int prim)
444 {
445 TNLcontext *tnl = TNL_CONTEXT(ctx);
446 struct vertex_buffer *VB = &tnl->vb;
447 GLuint i;
448 int k, type;
449 LOCAL_VARS
450
451 type=r300_get_primitive_type(rmesa, ctx, start, end, prim);
452
453 fprintf(stderr,"ObjPtr: size=%d stride=%d\n",
454 VB->ObjPtr->size, VB->ObjPtr->stride);
455 fprintf(stderr,"ColorPtr[0]: size=%d stride=%d\n",
456 VB->ColorPtr[0]->size, VB->ColorPtr[0]->stride);
457
458 if(type<0)return;
459
460
461 start_immediate_packet(end-start, type, 12);
462
463 for(i=start;i<end;i++){
464 #if 0
465 fprintf(stderr, "* (%f %f %f %f) (%f %f %f %f)\n",
466 VEC_ELT(VB->ObjPtr, GLfloat, i)[0],
467 VEC_ELT(VB->ObjPtr, GLfloat, i)[1],
468 VEC_ELT(VB->ObjPtr, GLfloat, i)[2],
469 VEC_ELT(VB->ObjPtr, GLfloat, i)[3],
470
471 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[0],
472 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[1],
473 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[2],
474 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[3]
475 );
476 #endif
477
478
479 /* coordinates */
480 output_vector(VB->ObjPtr, i);
481
482 /* color components */
483 output_vector(VB->ColorPtr[0], i);
484
485 /* texture coordinates */
486 output_vector(VB->TexCoordPtr[0], i);
487 }
488
489 }
490
491 static GLboolean r300_run_tex_render(GLcontext *ctx,
492 struct tnl_pipeline_stage *stage)
493 {
494 r300ContextPtr rmesa = R300_CONTEXT(ctx);
495 TNLcontext *tnl = TNL_CONTEXT(ctx);
496 struct vertex_buffer *VB = &tnl->vb;
497 GLuint i;
498 AOS_DATA vb_arrays[3];
499 /* Only do 2d textures */
500 struct gl_texture_object *to=ctx->Texture.Unit[0].Current2D;
501 radeonScreenPtr rsp=rmesa->radeon.radeonScreen;
502 LOCAL_VARS
503
504
505 /* Flush state - make sure command buffer is nice and large */
506 r300Flush(ctx);
507
508 fprintf(stderr, "You can enable texture drawing in %s:%s \n", __FILE__, __FUNCTION__);
509 return GL_TRUE;
510
511 if (RADEON_DEBUG == DEBUG_PRIMS)
512 fprintf(stderr, "%s\n", __FUNCTION__);
513
514 /* setup array of structures data */
515
516 /* Note: immediate vertex data includes all coordinates.
517 To save bandwidth use either VBUF or state-based vertex generation */
518 /* xyzw */
519 vb_arrays[0].element_size=4;
520 vb_arrays[0].stride=4;
521 vb_arrays[0].offset=0; /* Not used */
522 vb_arrays[0].format=AOS_FORMAT_FLOAT;
523 vb_arrays[0].ncomponents=4;
524 vb_arrays[0].reg=REG_COORDS;
525
526 /* color */
527 vb_arrays[1].element_size=4;
528 vb_arrays[1].stride=4;
529 vb_arrays[1].offset=0; /* Not used */
530 vb_arrays[1].format=AOS_FORMAT_FLOAT_COLOR;
531 vb_arrays[1].ncomponents=4;
532 vb_arrays[1].reg=REG_COLOR0;
533
534 /* texture coordinates */
535 vb_arrays[2].element_size=4;
536 vb_arrays[2].stride=4;
537 vb_arrays[2].offset=0; /* Not used */
538 vb_arrays[2].format=AOS_FORMAT_FLOAT;
539 vb_arrays[2].ncomponents=4;
540 vb_arrays[2].reg=REG_TEX0;
541
542
543 /* needed before starting 3d operation .. */
544 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
545 e32(0x0000000a);
546
547 reg_start(0x4f18,0);
548 e32(0x00000003);
549
550
551 rmesa->hw.vte.cmd[1] = R300_VPORT_X_SCALE_ENA
552 | R300_VPORT_X_OFFSET_ENA
553 | R300_VPORT_Y_SCALE_ENA
554 | R300_VPORT_Y_OFFSET_ENA
555 | R300_VTX_W0_FMT;
556 R300_STATECHANGE(rmesa, vte);
557
558 r300EmitState(rmesa);
559
560 SINGLE_TEXTURE_PIPELINE.vertex_shader.matrix[0].length=16;
561 memcpy(SINGLE_TEXTURE_PIPELINE.vertex_shader.matrix[0].body.f, ctx->_ModelProjectMatrix.m, 16*4);
562
563 SINGLE_TEXTURE_PIPELINE.vertex_shader.unknown2.length=4;
564 SINGLE_TEXTURE_PIPELINE.vertex_shader.unknown2.body.f[0]=0.0;
565 SINGLE_TEXTURE_PIPELINE.vertex_shader.unknown2.body.f[1]=0.0;
566 SINGLE_TEXTURE_PIPELINE.vertex_shader.unknown2.body.f[2]=1.0;
567 SINGLE_TEXTURE_PIPELINE.vertex_shader.unknown2.body.f[3]=0.0;
568
569 /* Put it in the beginning of texture memory */
570 SINGLE_TEXTURE_PIPELINE.texture_unit[0].offset=rsp->gartTextures.handle;
571
572 /* Fill texture with some random data */
573 for(i=0;i<1000;i++)((int *)(rsp->gartTextures.map))[i]=rand();
574
575 /* Upload texture, a hack, really we can do a lot better */
576 #if 0
577 memcpy(rsp->gartTextures.map, to->Image[0][0]->Data, to->Image[0][0]->RowStride*to->Image[0][0]->Height*4);
578 #endif
579
580 /* Program RS unit. This needs to be moved into R300 pipeline */
581 reg_start(R300_RS_CNTL_0,1);
582 /* R300_RS_CNTL_0(4300) */
583 e32(0x00040084);
584 /* RS_INST_COUNT(4304) */
585 e32(0x000000c0);
586
587 reg_start(R300_RS_ROUTE_0,0);
588 e32(0x00024008);
589
590 reg_start(R300_RS_INTERP_0,7);
591 /* X_MEM0_0(4310) */
592 e32(0x00d10000);
593 /* X_MEM0_1(4314) */
594 e32(0x00d10044);
595 /* X_MEM0_2(4318) */
596 e32(0x00d10084);
597 /* X_MEM0_3(431c) */
598 e32(0x00d100c4);
599 /* X_MEM0_4(4320) */
600 e32(0x00d10004);
601 /* X_MEM0_5(4324) */
602 e32(0x00d10004);
603 /* X_MEM0_6(4328) */
604 e32(0x00d10004);
605 /* X_MEM0_7(432c) */
606 e32(0x00d10004);
607
608 reg_start(R300_RS_CNTL_0,0);
609 e32(0x00040084);
610
611 /* Magic register - note it is right after 20b0 */
612
613 reg_start(0x20b4,0);
614 e32(0x0000000c);
615
616 program_pipeline(PASS_PREFIX &SINGLE_TEXTURE_PIPELINE);
617
618 sync_VAP(PASS_PREFIX_VOID);
619 cp_delay(PASS_PREFIX 15);
620
621 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
622 setup_AOS(PASS_PREFIX vb_arrays, 3);
623
624 for(i=0; i < VB->PrimitiveCount; i++){
625 GLuint prim = VB->Primitive[i].mode;
626 GLuint start = VB->Primitive[i].start;
627 GLuint length = VB->Primitive[i].count;
628 r300_render_tex_primitive(rmesa, ctx, start, start + length, prim);
629 }
630
631 sync_VAP(PASS_PREFIX_VOID);
632
633 end_3d(PASS_PREFIX_VOID);
634
635 /* Flush state - this reduces the chance that something else will mess with
636 the hardware in between */
637 r300Flush(ctx);
638
639 fprintf(stderr, "\n");
640 return GL_FALSE;
641 }
642
643
644 /**
645 * Called by the pipeline manager to render a batch of primitives.
646 * We can return true to pass on to the next stage (i.e. software
647 * rasterization) or false to indicate that the pipeline has finished
648 * after we render something.
649 */
650 static GLboolean r300_run_render(GLcontext *ctx,
651 struct tnl_pipeline_stage *stage)
652 {
653 r300ContextPtr rmesa = R300_CONTEXT(ctx);
654 TNLcontext *tnl = TNL_CONTEXT(ctx);
655 struct vertex_buffer *VB = &tnl->vb;
656 GLuint i;
657
658 if (RADEON_DEBUG == DEBUG_PRIMS)
659 fprintf(stderr, "%s\n", __FUNCTION__);
660
661 #if 1
662 /* Just switch between pipelines.. We could possibly do better.. (?) */
663 if(ctx->Texture.Unit[0].Enabled)
664 return r300_run_tex_render(ctx, stage);
665 else
666 return r300_run_flat_render(ctx, stage);
667 #else
668 return GL_TRUE;
669 #endif
670
671 #if 0
672 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
673 TNLcontext *tnl = TNL_CONTEXT(ctx);
674 struct vertex_buffer *VB = &tnl->vb;
675 GLuint i;
676
677 /* Don't handle clipping or indexed vertices or vertex manipulations.
678 */
679 if (mmesa->RenderIndex != 0 ||
680 !mga_validate_render( ctx, VB )) {
681 return GL_TRUE;
682 }
683
684 tnl->Driver.Render.Start( ctx );
685 mmesa->SetupNewInputs = ~0;
686
687 for (i = 0 ; i < VB->PrimitiveCount ; i++)
688 {
689 GLuint prim = VB->Primitive[i].mode;
690 GLuint start = VB->Primitive[i].start;
691 GLuint length = VB->Primitive[i].count;
692
693 if (!length)
694 continue;
695
696 mga_render_tab_verts[prim & PRIM_MODE_MASK]( ctx, start, start + length,
697 prim);
698 }
699
700 tnl->Driver.Render.Finish( ctx );
701
702 return GL_FALSE; /* finished the pipe */
703 #endif
704 }
705
706
707 /**
708 * Called by the pipeline manager once before rendering.
709 * We check the GL state here to
710 * a) decide whether we can do the current state in hardware and
711 * b) update hardware registers
712 */
713 #define FALLBACK_IF(expr) \
714 do { \
715 if (expr) { \
716 if (RADEON_DEBUG & DEBUG_FALLBACKS) \
717 fprintf(stderr, "%s: fallback:%s\n", \
718 __FUNCTION__, #expr); \
719 stage->active = GL_FALSE; \
720 return; \
721 } \
722 } while(0)
723
724 static void r300_check_render(GLcontext *ctx, struct tnl_pipeline_stage *stage)
725 {
726 r300ContextPtr r300 = R300_CONTEXT(ctx);
727 int i;
728
729 if (RADEON_DEBUG & DEBUG_STATE)
730 fprintf(stderr, "%s\n", __FUNCTION__);
731
732 /* We only support rendering in hardware for now */
733 if (ctx->RenderMode != GL_RENDER) {
734 stage->active = GL_FALSE;
735 return;
736 }
737
738 // I failed to figure out how dither works in hardware,
739 // let's just ignore it for now
740 //FALLBACK_IF(ctx->Color.DitherFlag);
741
742 /* I'm almost certain I forgot something here */
743 FALLBACK_IF(ctx->Color.AlphaEnabled); // GL_ALPHA_TEST
744 FALLBACK_IF(ctx->Color.BlendEnabled); // GL_BLEND
745 FALLBACK_IF(ctx->Fog.Enabled); // GL_FOG
746 FALLBACK_IF(ctx->Line.SmoothFlag); // GL_LINE_SMOOTH
747 FALLBACK_IF(ctx->Line.StippleFlag); // GL_LINE_STIPPLE
748 FALLBACK_IF(ctx->Point.SmoothFlag); // GL_POINT_SMOOTH
749 if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite)
750 FALLBACK_IF(ctx->Point.PointSprite); // GL_POINT_SPRITE_NV
751 FALLBACK_IF(ctx->Polygon.OffsetPoint); // GL_POLYGON_OFFSET_POINT
752 FALLBACK_IF(ctx->Polygon.OffsetLine); // GL_POLYGON_OFFSET_LINE
753 FALLBACK_IF(ctx->Polygon.OffsetFill); // GL_POLYGON_OFFSET_FILL
754 FALLBACK_IF(ctx->Polygon.SmoothFlag); // GL_POLYGON_SMOOTH
755 FALLBACK_IF(ctx->Polygon.StippleFlag); // GL_POLYGON_STIPPLE
756 FALLBACK_IF(ctx->Stencil.Enabled); // GL_STENCIL_TEST
757 FALLBACK_IF(ctx->Multisample.Enabled); // GL_MULTISAMPLE_ARB
758
759 /* One step at a time - let one texture pass.. */
760 for (i = 1; i < ctx->Const.MaxTextureUnits; i++)
761 FALLBACK_IF(ctx->Texture.Unit[i].Enabled);
762
763
764 /* let r300_run_render do its job */
765 #if 0
766 stage->active = GL_FALSE;
767 #endif
768 }
769
770
771 static void dtr(struct tnl_pipeline_stage *stage)
772 {
773 (void)stage;
774 }
775
776 const struct tnl_pipeline_stage _r300_render_stage = {
777 "r300 hw rasterize",
778 _NEW_ALL, /* re-check (always re-check for now) */
779 0, /* re-run (always runs) */
780 GL_TRUE, /* active */
781 0, 0, /* inputs (set in check_render), outputs */
782 0, 0, /* changed_inputs, private */
783 dtr, /* destructor */
784 r300_check_render, /* check */
785 r300_run_render /* run */
786 };