r300: Added some more Doxygen documentation and made some functions static.
[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 * \file
30 *
31 * \brief R300 Render (Vertex Buffer Implementation)
32 *
33 * The immediate implementation has been removed from CVS in favor of the vertex
34 * buffer implementation.
35 *
36 * The render functions are called by the pipeline manager to render a batch of
37 * primitives. They return TRUE to pass on to the next stage (i.e. software
38 * rasterization) or FALSE to indicate that the pipeline has finished after
39 * rendering something.
40 *
41 * When falling back to software TCL still attempt to use hardware
42 * rasterization.
43 *
44 * I am not sure that the cache related registers are setup correctly, but
45 * obviously this does work... Further investigation is needed.
46 *
47 * \author Nicolai Haehnle <prefect_@gmx.net>
48 */
49
50 #include "glheader.h"
51 #include "state.h"
52 #include "imports.h"
53 #include "enums.h"
54 #include "macros.h"
55 #include "context.h"
56 #include "dd.h"
57 #include "simple_list.h"
58 #include "api_arrayelt.h"
59 #include "swrast/swrast.h"
60 #include "swrast_setup/swrast_setup.h"
61 #include "vbo/vbo.h"
62 #include "tnl/tnl.h"
63 #include "tnl/t_vp_build.h"
64 #include "radeon_reg.h"
65 #include "radeon_macros.h"
66 #include "radeon_ioctl.h"
67 #include "radeon_state.h"
68 #include "r300_context.h"
69 #include "r300_ioctl.h"
70 #include "r300_state.h"
71 #include "r300_reg.h"
72 #include "r300_tex.h"
73 #include "r300_maos.h"
74 #include "r300_emit.h"
75 extern int future_hw_tcl_on;
76
77 /**
78 * \brief Convert a OpenGL primitive type into a R300 primitive type.
79 */
80 static int r300PrimitiveType(r300ContextPtr rmesa, GLcontext * ctx, int prim)
81 {
82 int type = -1;
83
84 switch (prim & PRIM_MODE_MASK) {
85 case GL_POINTS:
86 type = R300_VAP_VF_CNTL__PRIM_POINTS;
87 break;
88 case GL_LINES:
89 type = R300_VAP_VF_CNTL__PRIM_LINES;
90 break;
91 case GL_LINE_STRIP:
92 type = R300_VAP_VF_CNTL__PRIM_LINE_STRIP;
93 break;
94 case GL_LINE_LOOP:
95 type = R300_VAP_VF_CNTL__PRIM_LINE_LOOP;
96 break;
97 case GL_TRIANGLES:
98 type = R300_VAP_VF_CNTL__PRIM_TRIANGLES;
99 break;
100 case GL_TRIANGLE_STRIP:
101 type = R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP;
102 break;
103 case GL_TRIANGLE_FAN:
104 type = R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN;
105 break;
106 case GL_QUADS:
107 type = R300_VAP_VF_CNTL__PRIM_QUADS;
108 break;
109 case GL_QUAD_STRIP:
110 type = R300_VAP_VF_CNTL__PRIM_QUAD_STRIP;
111 break;
112 case GL_POLYGON:
113 type = R300_VAP_VF_CNTL__PRIM_POLYGON;
114 break;
115 default:
116 fprintf(stderr,
117 "%s:%s Do not know how to handle primitive 0x%04x - help me !\n",
118 __FILE__, __FUNCTION__, prim & PRIM_MODE_MASK);
119 return -1;
120 break;
121 }
122 return type;
123 }
124
125 static int r300NumVerts(r300ContextPtr rmesa, int num_verts, int prim)
126 {
127 int verts_off = 0;
128
129 switch (prim & PRIM_MODE_MASK) {
130 case GL_POINTS:
131 verts_off = 0;
132 break;
133 case GL_LINES:
134 verts_off = num_verts % 2;
135 break;
136 case GL_LINE_STRIP:
137 if (num_verts < 2)
138 verts_off = num_verts;
139 break;
140 case GL_LINE_LOOP:
141 if (num_verts < 2)
142 verts_off = num_verts;
143 break;
144 case GL_TRIANGLES:
145 verts_off = num_verts % 3;
146 break;
147 case GL_TRIANGLE_STRIP:
148 if (num_verts < 3)
149 verts_off = num_verts;
150 break;
151 case GL_TRIANGLE_FAN:
152 if (num_verts < 3)
153 verts_off = num_verts;
154 break;
155 case GL_QUADS:
156 verts_off = num_verts % 4;
157 break;
158 case GL_QUAD_STRIP:
159 if (num_verts < 4)
160 verts_off = num_verts;
161 else
162 verts_off = num_verts % 2;
163 break;
164 case GL_POLYGON:
165 if (num_verts < 3)
166 verts_off = num_verts;
167 break;
168 default:
169 fprintf(stderr,
170 "%s:%s Do not know how to handle primitive 0x%04x - help me !\n",
171 __FILE__, __FUNCTION__, prim & PRIM_MODE_MASK);
172 return -1;
173 break;
174 }
175
176 if (RADEON_DEBUG & DEBUG_VERTS) {
177 if (num_verts - verts_off == 0) {
178 WARN_ONCE
179 ("user error: Need more than %d vertices to draw primitive 0x%04x !\n",
180 num_verts, prim & PRIM_MODE_MASK);
181 return 0;
182 }
183
184 if (verts_off > 0) {
185 WARN_ONCE
186 ("user error: %d is not a valid number of vertices for primitive 0x%04x !\n",
187 num_verts, prim & PRIM_MODE_MASK);
188 }
189 }
190
191 return num_verts - verts_off;
192 }
193
194 static void inline r300FireEB(r300ContextPtr rmesa, unsigned long addr,
195 int vertex_count, int type, int elt_size)
196 {
197 int cmd_reserved = 0;
198 int cmd_written = 0;
199 drm_radeon_cmd_header_t *cmd = NULL;
200 unsigned long t_addr;
201 unsigned long magic_1, magic_2;
202
203 assert(elt_size == 2 || elt_size == 4);
204
205 if (addr & (elt_size - 1)) {
206 WARN_ONCE("Badly aligned buffer\n");
207 return;
208 }
209
210 magic_1 = (addr % 32) / 4;
211 t_addr = addr & ~0x1d;
212 magic_2 = (vertex_count + 1 + (t_addr & 0x2)) / 2 + magic_1;
213
214 start_packet3(RADEON_CP_PACKET3_3D_DRAW_INDX_2, 0);
215 if (elt_size == 4) {
216 e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES |
217 (vertex_count << 16) | type |
218 R300_VAP_VF_CNTL__INDEX_SIZE_32bit);
219 } else {
220 e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES |
221 (vertex_count << 16) | type);
222 }
223
224 start_packet3(RADEON_CP_PACKET3_INDX_BUFFER, 2);
225 #ifdef OPTIMIZE_ELTS
226 if (elt_size == 4) {
227 e32(R300_EB_UNK1 | (0 << 16) | R300_EB_UNK2);
228 e32(addr);
229 } else {
230 e32(R300_EB_UNK1 | (magic_1 << 16) | R300_EB_UNK2);
231 e32(t_addr);
232 }
233 #else
234 e32(R300_EB_UNK1 | (0 << 16) | R300_EB_UNK2);
235 e32(addr);
236 #endif
237
238 if (elt_size == 4) {
239 e32(vertex_count);
240 } else {
241 #ifdef OPTIMIZE_ELTS
242 e32(magic_2);
243 #else
244 e32((vertex_count + 1) / 2);
245 #endif
246 }
247 }
248
249 static void r300RunRenderPrimitive(r300ContextPtr rmesa, GLcontext * ctx,
250 int start, int end, int prim)
251 {
252 int type, num_verts;
253
254 type = r300PrimitiveType(rmesa, ctx, prim);
255 num_verts = r300NumVerts(rmesa, end - start, prim);
256
257 if (type < 0 || num_verts <= 0)
258 return;
259
260 if (rmesa->state.VB.Elts) {
261 r300EmitAOS(rmesa, rmesa->state.aos_count, start);
262 if (num_verts > 65535) {
263 /* not implemented yet */
264 WARN_ONCE("Too many elts\n");
265 return;
266 }
267 r300EmitElts(ctx, rmesa->state.VB.Elts, num_verts,
268 rmesa->state.VB.elt_size);
269 r300FireEB(rmesa, rmesa->state.elt_dma.aos_offset,
270 num_verts, type, rmesa->state.VB.elt_size);
271 } else {
272 r300EmitAOS(rmesa, rmesa->state.aos_count, start);
273 fire_AOS(rmesa, num_verts, type);
274 }
275 }
276
277 #define CONV_VB(a, b) rvb->AttribPtr[(a)].size = vb->b->size, \
278 rvb->AttribPtr[(a)].type = GL_FLOAT, \
279 rvb->AttribPtr[(a)].stride = vb->b->stride, \
280 rvb->AttribPtr[(a)].data = vb->b->data
281
282 static void radeon_vb_to_rvb(r300ContextPtr rmesa,
283 struct radeon_vertex_buffer *rvb,
284 struct vertex_buffer *vb)
285 {
286 int i;
287 GLcontext *ctx;
288 ctx = rmesa->radeon.glCtx;
289
290 memset(rvb, 0, sizeof(*rvb));
291
292 rvb->Elts = vb->Elts;
293 rvb->elt_size = 4;
294 rvb->elt_min = 0;
295 rvb->elt_max = vb->Count;
296
297 rvb->Count = vb->Count;
298
299 if (hw_tcl_on) {
300 CONV_VB(VERT_ATTRIB_POS, ObjPtr);
301 } else {
302 assert(vb->ClipPtr);
303 CONV_VB(VERT_ATTRIB_POS, ClipPtr);
304 }
305
306 CONV_VB(VERT_ATTRIB_NORMAL, NormalPtr);
307 CONV_VB(VERT_ATTRIB_COLOR0, ColorPtr[0]);
308 CONV_VB(VERT_ATTRIB_COLOR1, SecondaryColorPtr[0]);
309 CONV_VB(VERT_ATTRIB_FOG, FogCoordPtr);
310
311 for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++)
312 CONV_VB(VERT_ATTRIB_TEX0 + i, TexCoordPtr[i]);
313
314 for (i = 0; i < MAX_VERTEX_PROGRAM_ATTRIBS; i++)
315 CONV_VB(VERT_ATTRIB_GENERIC0 + i,
316 AttribPtr[VERT_ATTRIB_GENERIC0 + i]);
317
318 rvb->Primitive = vb->Primitive;
319 rvb->PrimitiveCount = vb->PrimitiveCount;
320 rvb->LockFirst = rvb->LockCount = 0;
321 rvb->lock_uptodate = GL_FALSE;
322 }
323
324 static GLboolean r300RunRender(GLcontext * ctx,
325 struct tnl_pipeline_stage *stage)
326 {
327 r300ContextPtr rmesa = R300_CONTEXT(ctx);
328 struct radeon_vertex_buffer *VB = &rmesa->state.VB;
329 int i;
330 int cmd_reserved = 0;
331 int cmd_written = 0;
332 drm_radeon_cmd_header_t *cmd = NULL;
333
334 if (RADEON_DEBUG & DEBUG_PRIMS)
335 fprintf(stderr, "%s\n", __FUNCTION__);
336
337 if (stage) {
338 TNLcontext *tnl = TNL_CONTEXT(ctx);
339 radeon_vb_to_rvb(rmesa, VB, &tnl->vb);
340 }
341
342 r300UpdateShaders(rmesa);
343 if (r300EmitArrays(ctx))
344 return GL_TRUE;
345
346 r300UpdateShaderStates(rmesa);
347
348 reg_start(R300_RB3D_DSTCACHE_CTLSTAT, 0);
349 e32(R300_RB3D_DSTCACHE_UNKNOWN_0A);
350
351 reg_start(R300_RB3D_ZCACHE_CTLSTAT, 0);
352 e32(R300_RB3D_ZCACHE_UNKNOWN_03);
353
354 r300EmitState(rmesa);
355
356 for (i = 0; i < VB->PrimitiveCount; i++) {
357 GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
358 GLuint start = VB->Primitive[i].start;
359 GLuint length = VB->Primitive[i].count;
360 GLuint end = VB->Primitive[i].start + VB->Primitive[i].count;
361 r300RunRenderPrimitive(rmesa, ctx, start, end, prim);
362 }
363
364 reg_start(R300_RB3D_DSTCACHE_CTLSTAT, 0);
365 e32(R300_RB3D_DSTCACHE_UNKNOWN_0A);
366
367 reg_start(R300_RB3D_ZCACHE_CTLSTAT, 0);
368 e32(R300_RB3D_ZCACHE_UNKNOWN_03);
369
370 #ifdef USER_BUFFERS
371 r300UseArrays(ctx);
372 #endif
373
374 r300ReleaseArrays(ctx);
375
376 return GL_FALSE;
377 }
378
379 #define FALLBACK_IF(expr) \
380 do { \
381 if (expr) { \
382 if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \
383 WARN_ONCE("Software fallback:%s\n", \
384 #expr); \
385 return R300_FALLBACK_RAST; \
386 } \
387 } while(0)
388
389 static int r300Fallback(GLcontext * ctx)
390 {
391 r300ContextPtr r300 = R300_CONTEXT(ctx);
392 struct r300_fragment_program *fp = (struct r300_fragment_program *)
393 (char *)ctx->FragmentProgram._Current;
394
395 if (fp) {
396 if (!fp->translated)
397 r300TranslateFragmentShader(r300, fp);
398 FALLBACK_IF(!fp->translated);
399 }
400
401 FALLBACK_IF(ctx->RenderMode != GL_RENDER);
402
403 FALLBACK_IF(ctx->Stencil._TestTwoSide
404 && (ctx->Stencil.Ref[0] != ctx->Stencil.Ref[1]
405 || ctx->Stencil.ValueMask[0] !=
406 ctx->Stencil.ValueMask[1]
407 || ctx->Stencil.WriteMask[0] !=
408 ctx->Stencil.WriteMask[1]));
409
410 FALLBACK_IF(ctx->Color.ColorLogicOpEnabled);
411
412 if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite)
413 FALLBACK_IF(ctx->Point.PointSprite);
414
415 if (!r300->disable_lowimpact_fallback) {
416 FALLBACK_IF(ctx->Polygon.OffsetPoint);
417 FALLBACK_IF(ctx->Polygon.OffsetLine);
418 FALLBACK_IF(ctx->Polygon.StippleFlag);
419 FALLBACK_IF(ctx->Multisample.Enabled);
420 FALLBACK_IF(ctx->Line.StippleFlag);
421 FALLBACK_IF(ctx->Line.SmoothFlag);
422 FALLBACK_IF(ctx->Point.SmoothFlag);
423 }
424
425 return R300_FALLBACK_NONE;
426 }
427
428 static GLboolean r300RunNonTNLRender(GLcontext * ctx,
429 struct tnl_pipeline_stage *stage)
430 {
431 if (RADEON_DEBUG & DEBUG_PRIMS)
432 fprintf(stderr, "%s\n", __FUNCTION__);
433
434 if (r300Fallback(ctx) >= R300_FALLBACK_RAST)
435 return GL_TRUE;
436
437 return r300RunRender(ctx, stage);
438 }
439
440 static GLboolean r300RunTCLRender(GLcontext * ctx,
441 struct tnl_pipeline_stage *stage)
442 {
443 r300ContextPtr rmesa = R300_CONTEXT(ctx);
444 struct r300_vertex_program *vp;
445
446 hw_tcl_on = future_hw_tcl_on;
447
448 if (RADEON_DEBUG & DEBUG_PRIMS)
449 fprintf(stderr, "%s\n", __FUNCTION__);
450
451 if (hw_tcl_on == GL_FALSE)
452 return GL_TRUE;
453
454 if (r300Fallback(ctx) >= R300_FALLBACK_TCL) {
455 hw_tcl_on = GL_FALSE;
456 return GL_TRUE;
457 }
458
459 r300UpdateShaders(rmesa);
460
461 vp = (struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx);
462 if (vp->native == GL_FALSE) {
463 hw_tcl_on = GL_FALSE;
464 return GL_TRUE;
465 }
466
467 return r300RunRender(ctx, stage);
468 }
469
470 const struct tnl_pipeline_stage _r300_render_stage = {
471 "r300 Hardware Rasterization",
472 NULL,
473 NULL,
474 NULL,
475 NULL,
476 r300RunNonTNLRender
477 };
478
479 const struct tnl_pipeline_stage _r300_tcl_stage = {
480 "r300 Hardware Transform, Clipping and Lighting",
481 NULL,
482 NULL,
483 NULL,
484 NULL,
485 r300RunTCLRender
486 };