Restructure code.
[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;
76
77 if(end<=start)return -1; /* do we need to watch for this ? */
78
79 fprintf(stderr, "[%d-%d]", start, end);
80 switch (prim & PRIM_MODE_MASK) {
81 case GL_LINES:
82 fprintf(stderr, "L ");
83 type=R300_VAP_VF_CNTL__PRIM_LINES;
84 if(end<start+2){
85 fprintf(stderr, "Not enough vertices\n");
86 return -1; /* need enough vertices for Q */
87 }
88 break;
89 case GL_LINE_STRIP:
90 fprintf(stderr, "LS ");
91 type=R300_VAP_VF_CNTL__PRIM_LINE_STRIP;
92 if(end<start+2){
93 fprintf(stderr, "Not enough vertices\n");
94 return -1; /* need enough vertices for Q */
95 }
96 break;
97 case GL_LINE_LOOP:
98 fprintf(stderr, "LL ");
99 return -1;
100 if(end<start+2){
101 fprintf(stderr, "Not enough vertices\n");
102 return -1; /* need enough vertices for Q */
103 }
104 break;
105 case GL_TRIANGLES:
106 fprintf(stderr, "T ");
107 type=R300_VAP_VF_CNTL__PRIM_TRIANGLES;
108 if(end<start+3){
109 fprintf(stderr, "Not enough vertices\n");
110 return -1; /* need enough vertices for Q */
111 }
112 break;
113 case GL_TRIANGLE_STRIP:
114 fprintf(stderr, "TS ");
115 type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP;
116 if(end<start+3){
117 fprintf(stderr, "Not enough vertices\n");
118 return -1; /* need enough vertices for Q */
119 }
120 break;
121 case GL_TRIANGLE_FAN:
122 fprintf(stderr, "TF ");
123 type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN;
124 if(end<start+3){
125 fprintf(stderr, "Not enough vertices\n");
126 return -1; /* need enough vertices for Q */
127 }
128 break;
129 case GL_QUADS:
130 fprintf(stderr, "Q ");
131 type=R300_VAP_VF_CNTL__PRIM_QUADS;
132 if(end<start+4){
133 fprintf(stderr, "Not enough vertices\n");
134 return -1; /* need enough vertices for Q */
135 }
136 break;
137 case GL_QUAD_STRIP:
138 fprintf(stderr, "QS ");
139 type=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP;
140 if(end<start+4){
141 fprintf(stderr, "Not enough vertices\n");
142 return -1; /* need enough vertices for Q */
143 }
144 break;
145 default:
146 fprintf(stderr, "Cannot handle primitive %02x ", prim & PRIM_MODE_MASK);
147 return -1;
148 break;
149 }
150 return type;
151 }
152
153
154
155 /* Immediate implementation - vertex data is sent via command stream */
156
157 static GLfloat default_vector[4]={0.0, 0.0, 0.0, 1.0};
158
159 #define output_vector(v, i) \
160 { \
161 int _i; \
162 for(_i=0;_i<v->size;_i++){ \
163 efloat(VEC_ELT(v, GLfloat, i)[_i]); \
164 } \
165 for(_i=v->size;_i<4;_i++){ \
166 efloat(default_vector[_i]); \
167 } \
168 }
169
170 static void r300_render_flat_primitive(r300ContextPtr rmesa,
171 GLcontext *ctx,
172 int start,
173 int end,
174 int prim)
175 {
176 TNLcontext *tnl = TNL_CONTEXT(ctx);
177 struct vertex_buffer *VB = &tnl->vb;
178 GLuint i;
179 int k, type;
180 LOCAL_VARS
181
182 type=r300_get_primitive_type(rmesa, ctx, start, end, prim);
183 if(type<0)return;
184
185
186 start_immediate_packet(end-start, type, 8);
187
188 for(i=start;i<end;i++){
189 #if 0
190 fprintf(stderr, "* (%f %f %f %f) (%f %f %f %f)\n",
191 VEC_ELT(VB->ObjPtr, GLfloat, i)[0],
192 VEC_ELT(VB->ObjPtr, GLfloat, i)[1],
193 VEC_ELT(VB->ObjPtr, GLfloat, i)[2],
194 VEC_ELT(VB->ObjPtr, GLfloat, i)[3],
195
196 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[0],
197 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[1],
198 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[2],
199 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[3]
200 );
201 #endif
202
203
204 /* coordinates */
205 #if 1
206 output_vector(VB->ObjPtr, i);
207 #else
208 efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[0]);
209 efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[1]);
210 efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[2]);
211 #if 0
212 efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[3]);
213 #else
214 efloat(2.0);
215 #endif
216 #endif
217
218 /* color components */
219 #if 1
220 output_vector(VB->ColorPtr[0], i);
221 #else
222 efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[0]);
223 efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[1]);
224 efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[2]);
225 #if 0
226 efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[3]);
227 #else
228 efloat(0.0);
229 #endif
230 #endif
231 }
232
233 }
234
235 static GLboolean r300_run_flat_render(GLcontext *ctx,
236 struct tnl_pipeline_stage *stage)
237 {
238 r300ContextPtr rmesa = R300_CONTEXT(ctx);
239 TNLcontext *tnl = TNL_CONTEXT(ctx);
240 struct vertex_buffer *VB = &tnl->vb;
241 GLuint i;
242 AOS_DATA vb_arrays[2];
243 LOCAL_VARS
244
245 if (RADEON_DEBUG == DEBUG_PRIMS)
246 fprintf(stderr, "%s\n", __FUNCTION__);
247
248 /* setup array of structures data */
249
250 /* Note: immediate vertex data includes all coordinates.
251 To save bandwidth use either VBUF or state-based vertex generation */
252 /* xyz */
253 vb_arrays[0].element_size=4;
254 vb_arrays[0].stride=4;
255 vb_arrays[0].offset=0; /* Not used */
256 vb_arrays[0].format=AOS_FORMAT_FLOAT;
257 vb_arrays[0].ncomponents=4;
258 vb_arrays[0].reg=REG_COORDS;
259
260 /* color */
261 vb_arrays[1].element_size=4;
262 vb_arrays[1].stride=4;
263 vb_arrays[1].offset=0; /* Not used */
264 vb_arrays[1].format=AOS_FORMAT_FLOAT_COLOR;
265 vb_arrays[1].ncomponents=4;
266 vb_arrays[1].reg=REG_COLOR0;
267
268 r300EmitState(rmesa);
269
270 /* needed before starting 3d operation .. */
271 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
272 e32(0x0000000a);
273
274 reg_start(0x4f18,0);
275 e32(0x00000003);
276
277
278 reg_start(0x20b0,0);
279 e32(0x0000043f);
280
281 program_pipeline(PASS_PREFIX &FLAT_COLOR_PIPELINE);
282
283 #if 0 /* Turn on for smooth color on teeth.. why ??.. */
284 set_cull_cntl(PASS_PREFIX 0);
285 #endif
286 reg_start(R300_RE_OCCLUSION_CNTL, 0);
287 e32(R300_OCCLUSION_ON);
288
289 // set_quad0(PASS_PREFIX 1.0,1.0,1.0,1.0);
290 set_init21(PASS_PREFIX 0.0,1.0);
291
292 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
293 setup_AOS(PASS_PREFIX vb_arrays, 2);
294
295 for(i=0; i < VB->PrimitiveCount; i++){
296 GLuint prim = VB->Primitive[i].mode;
297 GLuint start = VB->Primitive[i].start;
298 GLuint length = VB->Primitive[i].count;
299 r300_render_flat_primitive(rmesa, ctx, start, start + length, prim);
300 }
301
302 end_3d(PASS_PREFIX_VOID);
303
304 fprintf(stderr, "\n");
305 return GL_FALSE;
306 }
307
308 /* vertex buffer implementation */
309
310 /* We use the start part of GART texture buffer for vertices */
311
312 #define R300_MAX_AOS_ARRAYS 16
313
314 static void upload_vertex_buffer(r300ContextPtr rmesa,
315 GLcontext *ctx, AOS_DATA *array, int *n_arrays)
316 {
317 TNLcontext *tnl = TNL_CONTEXT(ctx);
318 struct vertex_buffer *VB = &tnl->vb;
319 int offset=0, idx=0;
320 int i,j;
321 radeonScreenPtr rsp=rmesa->radeon.radeonScreen;
322 /* Not the most efficient implementation, but, for now, I just want something that
323 works */
324 /* to do - make single memcpy per column (is it possible ?) */
325 /* to do - use dirty flags to avoid redundant copies */
326 #define UPLOAD_VECTOR(v, r, f)\
327 { \
328 /* Is the data dirty ? */ \
329 if (v->flags & ((1<<v->size)-1)) { \
330 fprintf(stderr, "size=%d vs stride=%d\n", v->size, v->stride); \
331 if(v->size*4==v->stride){\
332 /* fast path */ \
333 memcpy(rsp->gartTextures.map+offset, v->data, v->stride*VB->Count); \
334 } else { \
335 for(i=0;i<VB->Count;i++){ \
336 /* copy one vertex at a time*/ \
337 memcpy(rsp->gartTextures.map+offset, VEC_ELT(v, GLfloat, i), v->size*4); \
338 } \
339 } \
340 /* v->flags &= ~((1<<v->size)-1);*/ \
341 } \
342 array[idx].element_size=v->size; \
343 array[idx].stride=v->size; \
344 array[idx].format=(f); \
345 array[idx].ncomponents=v->size; \
346 array[idx].offset=rsp->gartTextures.handle+offset; \
347 array[idx].reg=r; \
348 offset+=v->size*4*VB->Count; \
349 idx++; \
350 /* Fill in the rest with the components of default_vector */\
351 /* \
352 if(v->size<4){ \
353 array[idx].element_size=4-v->size; \
354 array[idx].stride=0; \
355 array[idx].format=(f); \
356 array[idx].ncomponents=4-v->size; \
357 array[idx].offset=rsp->gartTextures.handle+v->size*4;\
358 array[idx].reg=r; \
359 idx++; \
360 } \
361 */\
362 }
363
364 /* Put a copy of default vector */
365 memcpy(rsp->gartTextures.map, default_vector, 16);
366 offset+=16;
367
368 UPLOAD_VECTOR(VB->ObjPtr, REG_COORDS, AOS_FORMAT_FLOAT);
369 UPLOAD_VECTOR(VB->ColorPtr[0], REG_COLOR0, AOS_FORMAT_FLOAT_COLOR);
370
371 *n_arrays=idx;
372 if(idx>=R300_MAX_AOS_ARRAYS){
373 fprintf(stderr, "Aieee ! Maximum AOS arrays count exceeded.. \n");
374 exit(-1);
375 }
376 }
377
378 static void r300_render_vb_flat_primitive(r300ContextPtr rmesa,
379 GLcontext *ctx,
380 int start,
381 int end,
382 int prim)
383 {
384 TNLcontext *tnl = TNL_CONTEXT(ctx);
385 struct vertex_buffer *VB = &tnl->vb;
386 GLuint i;
387 int k, type, n_arrays;
388 LOCAL_VARS
389
390 if(end<=start)return; /* do we need to watch for this ? */
391
392 type=r300_get_primitive_type(rmesa, ctx, start, end, prim);
393 if(type<0)return;
394
395 fire_AOS(PASS_PREFIX end-start, type);
396 }
397
398 static VERTEX_SHADER_FRAGMENT default_vector_vsf={
399 length: 4,
400 body: {
401 f: {0.0, 0.0, 0.0, 1.0}
402 }
403 };
404
405 static GLboolean r300_run_vb_flat_render(GLcontext *ctx,
406 struct tnl_pipeline_stage *stage)
407 {
408 r300ContextPtr rmesa = R300_CONTEXT(ctx);
409 TNLcontext *tnl = TNL_CONTEXT(ctx);
410 struct vertex_buffer *VB = &tnl->vb;
411 int i, j, n_arrays;
412 AOS_DATA vb_arrays[R300_MAX_AOS_ARRAYS];
413 AOS_DATA vb_arrays2[R300_MAX_AOS_ARRAYS];
414 LOCAL_VARS
415
416 if (RADEON_DEBUG == DEBUG_PRIMS)
417 fprintf(stderr, "%s\n", __FUNCTION__);
418
419 /* setup array of structures data */
420
421 upload_vertex_buffer(rmesa, ctx, vb_arrays, &n_arrays);
422 fprintf(stderr, "Using %d AOS arrays\n", n_arrays);
423
424 r300EmitState(rmesa);
425
426 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
427 e32(0x0000000a);
428
429 reg_start(0x4f18,0);
430 e32(0x00000003);
431
432 reg_start(0x20b0,0);
433 e32(0x0000043f);
434
435 program_pipeline(PASS_PREFIX &FLAT_COLOR_PIPELINE);
436
437 //upload_vertex_shader_fragment(PASS_PREFIX VSF_DEST_UNKNOWN1, &default_vector_vsf);
438
439 reg_start(R300_RE_OCCLUSION_CNTL, 0);
440 e32(R300_OCCLUSION_ON);
441
442 set_quad0(PASS_PREFIX 1.0,1.0,1.0,1.0);
443 set_init21(PASS_PREFIX 0.0,1.0);
444
445 for(i=0; i < VB->PrimitiveCount; i++){
446 GLuint prim = VB->Primitive[i].mode;
447 GLuint start = VB->Primitive[i].start;
448 GLuint length = VB->Primitive[i].count;
449
450 /* copy arrays */
451 memcpy(vb_arrays2, vb_arrays, sizeof(AOS_DATA)*n_arrays);
452 for(j=0;j<n_arrays;j++){
453 vb_arrays2[j].offset+=vb_arrays2[j].stride*start;
454 }
455
456 setup_AOS(PASS_PREFIX vb_arrays2, n_arrays);
457
458 r300_render_vb_flat_primitive(rmesa, ctx, start, start + length, prim);
459 }
460
461 end_3d(PASS_PREFIX_VOID);
462
463 /* Flush state - we are done drawing.. */
464 r300Flush(ctx);
465 fprintf(stderr, "\n");
466 return GL_FALSE;
467 }
468
469 /**
470 * Called by the pipeline manager to render a batch of primitives.
471 * We can return true to pass on to the next stage (i.e. software
472 * rasterization) or false to indicate that the pipeline has finished
473 * after we render something.
474 */
475 static GLboolean r300_run_render(GLcontext *ctx,
476 struct tnl_pipeline_stage *stage)
477 {
478 r300ContextPtr rmesa = R300_CONTEXT(ctx);
479 TNLcontext *tnl = TNL_CONTEXT(ctx);
480 struct vertex_buffer *VB = &tnl->vb;
481 GLuint i;
482
483 if (RADEON_DEBUG == DEBUG_PRIMS)
484 fprintf(stderr, "%s\n", __FUNCTION__);
485
486 return r300_run_flat_render(ctx, stage);
487 #if 0
488 return GL_TRUE;
489 #else
490 return GL_FALSE;
491 #endif
492
493 #if 0
494 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
495 TNLcontext *tnl = TNL_CONTEXT(ctx);
496 struct vertex_buffer *VB = &tnl->vb;
497 GLuint i;
498
499 /* Don't handle clipping or indexed vertices or vertex manipulations.
500 */
501 if (mmesa->RenderIndex != 0 ||
502 !mga_validate_render( ctx, VB )) {
503 return GL_TRUE;
504 }
505
506 tnl->Driver.Render.Start( ctx );
507 mmesa->SetupNewInputs = ~0;
508
509 for (i = 0 ; i < VB->PrimitiveCount ; i++)
510 {
511 GLuint prim = VB->Primitive[i].mode;
512 GLuint start = VB->Primitive[i].start;
513 GLuint length = VB->Primitive[i].count;
514
515 if (!length)
516 continue;
517
518 mga_render_tab_verts[prim & PRIM_MODE_MASK]( ctx, start, start + length,
519 prim);
520 }
521
522 tnl->Driver.Render.Finish( ctx );
523
524 return GL_FALSE; /* finished the pipe */
525 #endif
526 }
527
528
529 /**
530 * Called by the pipeline manager once before rendering.
531 * We check the GL state here to
532 * a) decide whether we can do the current state in hardware and
533 * b) update hardware registers
534 */
535 #define FALLBACK_IF(expr) \
536 do { \
537 if (expr) { \
538 if (RADEON_DEBUG & DEBUG_FALLBACKS) \
539 fprintf(stderr, "%s: fallback:%s\n", \
540 __FUNCTION__, #expr); \
541 stage->active = GL_FALSE; \
542 return; \
543 } \
544 } while(0)
545
546 static void r300_check_render(GLcontext *ctx, struct tnl_pipeline_stage *stage)
547 {
548 r300ContextPtr r300 = R300_CONTEXT(ctx);
549 int i;
550
551 if (RADEON_DEBUG & DEBUG_STATE)
552 fprintf(stderr, "%s\n", __FUNCTION__);
553
554 /* We only support rendering in hardware for now */
555 if (ctx->RenderMode != GL_RENDER) {
556 stage->active = GL_FALSE;
557 return;
558 }
559
560 // I failed to figure out how dither works in hardware,
561 // let's just ignore it for now
562 //FALLBACK_IF(ctx->Color.DitherFlag);
563
564 /* I'm almost certain I forgot something here */
565 FALLBACK_IF(ctx->Color.AlphaEnabled); // GL_ALPHA_TEST
566 FALLBACK_IF(ctx->Color.BlendEnabled); // GL_BLEND
567 FALLBACK_IF(ctx->Fog.Enabled); // GL_FOG
568 FALLBACK_IF(ctx->Line.SmoothFlag); // GL_LINE_SMOOTH
569 FALLBACK_IF(ctx->Line.StippleFlag); // GL_LINE_STIPPLE
570 FALLBACK_IF(ctx->Point.SmoothFlag); // GL_POINT_SMOOTH
571 if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite)
572 FALLBACK_IF(ctx->Point.PointSprite); // GL_POINT_SPRITE_NV
573 FALLBACK_IF(ctx->Polygon.OffsetPoint); // GL_POLYGON_OFFSET_POINT
574 FALLBACK_IF(ctx->Polygon.OffsetLine); // GL_POLYGON_OFFSET_LINE
575 FALLBACK_IF(ctx->Polygon.OffsetFill); // GL_POLYGON_OFFSET_FILL
576 FALLBACK_IF(ctx->Polygon.SmoothFlag); // GL_POLYGON_SMOOTH
577 FALLBACK_IF(ctx->Polygon.StippleFlag); // GL_POLYGON_STIPPLE
578 FALLBACK_IF(ctx->Stencil.Enabled); // GL_STENCIL_TEST
579 FALLBACK_IF(ctx->Multisample.Enabled); // GL_MULTISAMPLE_ARB
580
581 for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
582 FALLBACK_IF(ctx->Texture.Unit[i].Enabled);
583
584
585 /* let r300_run_render do its job */
586 #if 0
587 stage->active = GL_FALSE;
588 #endif
589 }
590
591
592 static void dtr(struct tnl_pipeline_stage *stage)
593 {
594 (void)stage;
595 }
596
597 const struct tnl_pipeline_stage _r300_render_stage = {
598 "r300 hw rasterize",
599 _NEW_ALL, /* re-check (always re-check for now) */
600 0, /* re-run (always runs) */
601 GL_TRUE, /* active */
602 0, 0, /* inputs (set in check_render), outputs */
603 0, 0, /* changed_inputs, private */
604 dtr, /* destructor */
605 r300_check_render, /* check */
606 r300_run_render /* run */
607 };