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