1 /**************************************************************************
3 Copyright (C) 2004 Nicolai Haehnle.
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:
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
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.
26 **************************************************************************/
30 * \brief R300 Render (Vertex Buffer Implementation)
32 * The immediate implementation has been removed from CVS in favor of the vertex
33 * buffer implementation.
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.
40 * When falling back to software TCL still attempt to use hardware
43 * I am not sure that the cache related registers are setup correctly, but
44 * obviously this does work... Further investigation is needed.
46 * \author Nicolai Haehnle <prefect_@gmx.net>
55 #include "simple_list.h"
56 #include "api_arrayelt.h"
57 #include "swrast/swrast.h"
58 #include "swrast_setup/swrast_setup.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"
70 #include "r300_program.h"
72 #include "r300_maos.h"
73 #include "r300_emit.h"
74 extern int future_hw_tcl_on
;
76 static int r300PrimitiveType(r300ContextPtr rmesa
, GLcontext
* ctx
,
81 switch (prim
& PRIM_MODE_MASK
) {
83 type
= R300_VAP_VF_CNTL__PRIM_POINTS
;
86 type
= R300_VAP_VF_CNTL__PRIM_LINES
;
89 type
= R300_VAP_VF_CNTL__PRIM_LINE_STRIP
;
92 type
= R300_VAP_VF_CNTL__PRIM_LINE_LOOP
;
95 type
= R300_VAP_VF_CNTL__PRIM_TRIANGLES
;
97 case GL_TRIANGLE_STRIP
:
98 type
= R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP
;
100 case GL_TRIANGLE_FAN
:
101 type
= R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN
;
104 type
= R300_VAP_VF_CNTL__PRIM_QUADS
;
107 type
= R300_VAP_VF_CNTL__PRIM_QUAD_STRIP
;
110 type
= R300_VAP_VF_CNTL__PRIM_POLYGON
;
114 "%s:%s Do not know how to handle primitive 0x%04x - help me !\n",
115 __FILE__
, __FUNCTION__
, prim
& PRIM_MODE_MASK
);
122 static int r300NumVerts(r300ContextPtr rmesa
, int num_verts
, int prim
)
126 switch (prim
& PRIM_MODE_MASK
) {
131 verts_off
= num_verts
% 2;
135 verts_off
= num_verts
;
139 verts_off
= num_verts
;
142 verts_off
= num_verts
% 3;
144 case GL_TRIANGLE_STRIP
:
146 verts_off
= num_verts
;
148 case GL_TRIANGLE_FAN
:
150 verts_off
= num_verts
;
153 verts_off
= num_verts
% 4;
157 verts_off
= num_verts
;
159 verts_off
= num_verts
% 2;
163 verts_off
= num_verts
;
167 "%s:%s Do not know how to handle primitive 0x%04x - help me !\n",
168 __FILE__
, __FUNCTION__
, prim
& PRIM_MODE_MASK
);
173 if (RADEON_DEBUG
& DEBUG_VERTS
) {
174 if (num_verts
- verts_off
== 0) {
176 ("user error: Need more than %d vertices to draw primitive 0x%04x !\n",
177 num_verts
, prim
& PRIM_MODE_MASK
);
183 ("user error: %d is not a valid number of vertices for primitive 0x%04x !\n",
184 num_verts
, prim
& PRIM_MODE_MASK
);
188 return num_verts
- verts_off
;
191 static void inline r300FireEB(r300ContextPtr rmesa
, unsigned long addr
,
192 int vertex_count
, int type
, int elt_size
)
194 int cmd_reserved
= 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
;
201 assert(elt_size
== 2 || elt_size
== 4);
203 if (addr
& (elt_size
- 1)) {
204 WARN_ONCE("Badly aligned buffer\n");
208 magic_1
= (addr
% 32) / 4;
209 t_addr
= addr
& ~0x1d;
210 magic_2
= (vertex_count
+ 1 + (t_addr
& 0x2)) / 2 + magic_1
;
214 start_packet3(RADEON_CP_PACKET3_3D_DRAW_INDX_2
, 0);
216 e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES
|
217 (vertex_count
<< 16) | type
|
218 R300_VAP_VF_CNTL__INDEX_SIZE_32bit
);
220 e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES
|
221 (vertex_count
<< 16) | type
);
224 start_packet3(RADEON_CP_PACKET3_INDX_BUFFER
, 2);
227 e32(R300_EB_UNK1
| (0 << 16) | R300_EB_UNK2
);
230 e32(R300_EB_UNK1
| (magic_1
<< 16) | R300_EB_UNK2
);
234 e32(R300_EB_UNK1
| (0 << 16) | R300_EB_UNK2
);
244 e32((vertex_count
+ 1) / 2);
249 static void r300RunRenderPrimitive(r300ContextPtr rmesa
, GLcontext
* ctx
,
250 int start
, int end
, int prim
)
254 type
= r300PrimitiveType(rmesa
, ctx
, prim
);
255 num_verts
= r300NumVerts(rmesa
, end
- start
, prim
);
257 if (type
< 0 || num_verts
<= 0)
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");
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
);
271 r300EmitAOS(rmesa
, rmesa
->state
.aos_count
, start
);
272 fire_AOS(rmesa
, num_verts
, type
);
276 static GLboolean
r300RunRender(GLcontext
* ctx
,
277 struct tnl_pipeline_stage
*stage
)
279 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
280 struct radeon_vertex_buffer
*VB
= &rmesa
->state
.VB
;
282 int cmd_reserved
= 0;
284 drm_radeon_cmd_header_t
*cmd
= NULL
;
286 if (RADEON_DEBUG
& DEBUG_PRIMS
)
287 fprintf(stderr
, "%s\n", __FUNCTION__
);
290 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
291 radeon_vb_to_rvb(rmesa
, VB
, &tnl
->vb
);
294 r300UpdateShaders(rmesa
);
295 if (r300EmitArrays(ctx
))
298 r300UpdateShaderStates(rmesa
);
300 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
, 0);
301 e32(R300_RB3D_DSTCACHE_UNKNOWN_0A
);
303 reg_start(R300_RB3D_ZCACHE_CTLSTAT
, 0);
304 e32(R300_RB3D_ZCACHE_UNKNOWN_03
);
306 r300EmitState(rmesa
);
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
;
313 r300RunRenderPrimitive(rmesa
, ctx
, start
, start
+ length
,
317 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
, 0);
318 e32(R300_RB3D_DSTCACHE_UNKNOWN_0A
);
320 reg_start(R300_RB3D_ZCACHE_CTLSTAT
, 0);
321 e32(R300_RB3D_ZCACHE_UNKNOWN_03
);
326 r300ReleaseArrays(ctx
);
330 #define FALLBACK_IF(expr) \
333 if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \
334 WARN_ONCE("Software fallback:%s\n", \
336 return R300_FALLBACK_RAST; \
340 int r300Fallback(GLcontext
* ctx
)
342 r300ContextPtr r300
= R300_CONTEXT(ctx
);
343 struct r300_fragment_program
*fp
= (struct r300_fragment_program
*)
344 (char *)ctx
->FragmentProgram
._Current
;
348 r300_translate_fragment_shader(r300
, fp
);
349 FALLBACK_IF(!fp
->translated
);
352 FALLBACK_IF(ctx
->RenderMode
!= GL_RENDER
);
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]));
361 FALLBACK_IF(ctx
->Color
.ColorLogicOpEnabled
);
363 if (ctx
->Extensions
.NV_point_sprite
364 || ctx
->Extensions
.ARB_point_sprite
)
365 FALLBACK_IF(ctx
->Point
.PointSprite
);
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
);
377 return R300_FALLBACK_NONE
;
380 static GLboolean
r300RunNonTNLRender(GLcontext
* ctx
,
381 struct tnl_pipeline_stage
*stage
)
383 if (RADEON_DEBUG
& DEBUG_PRIMS
)
384 fprintf(stderr
, "%s\n", __FUNCTION__
);
386 if (r300Fallback(ctx
) >= R300_FALLBACK_RAST
)
389 return r300RunRender(ctx
, stage
);
392 static GLboolean
r300RunTCLRender(GLcontext
* ctx
,
393 struct tnl_pipeline_stage
*stage
)
395 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
396 struct r300_vertex_program
*vp
;
398 hw_tcl_on
= future_hw_tcl_on
;
400 if (RADEON_DEBUG
& DEBUG_PRIMS
)
401 fprintf(stderr
, "%s\n", __FUNCTION__
);
403 if (hw_tcl_on
== GL_FALSE
)
406 if (r300Fallback(ctx
) >= R300_FALLBACK_TCL
) {
407 hw_tcl_on
= GL_FALSE
;
411 r300UpdateShaders(rmesa
);
413 vp
= (struct r300_vertex_program
*)CURRENT_VERTEX_SHADER(ctx
);
414 if (vp
->native
== GL_FALSE
) {
415 hw_tcl_on
= GL_FALSE
;
419 return r300RunRender(ctx
, stage
);
422 const struct tnl_pipeline_stage _r300_render_stage
= {
423 "r300 Hardware Rasterization",
431 const struct tnl_pipeline_stage _r300_tcl_stage
= {
432 "r300 Hardware Transform, Clipping and Lighting",