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 **************************************************************************/
31 * \brief R300 Render (Vertex Buffer Implementation)
33 * The immediate implementation has been removed from CVS in favor of the vertex
34 * buffer implementation.
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.
41 * When falling back to software TCL still attempt to use hardware
44 * I am not sure that the cache related registers are setup correctly, but
45 * obviously this does work... Further investigation is needed.
47 * \author Nicolai Haehnle <prefect_@gmx.net>
49 * \todo Add immediate implementation back? Perhaps this is useful if there are
60 #include "simple_list.h"
61 #include "api_arrayelt.h"
62 #include "swrast/swrast.h"
63 #include "swrast_setup/swrast_setup.h"
66 #include "tnl/t_vp_build.h"
67 #include "radeon_reg.h"
68 #include "radeon_macros.h"
69 #include "radeon_ioctl.h"
70 #include "radeon_state.h"
71 #include "r300_context.h"
72 #include "r300_ioctl.h"
73 #include "r300_state.h"
76 #include "r300_emit.h"
77 extern int future_hw_tcl_on
;
80 * \brief Convert a OpenGL primitive type into a R300 primitive type.
82 static int r300PrimitiveType(r300ContextPtr rmesa
, GLcontext
* ctx
, int prim
)
84 switch (prim
& PRIM_MODE_MASK
) {
86 return R300_VAP_VF_CNTL__PRIM_POINTS
;
89 return R300_VAP_VF_CNTL__PRIM_LINES
;
92 return R300_VAP_VF_CNTL__PRIM_LINE_STRIP
;
95 return R300_VAP_VF_CNTL__PRIM_LINE_LOOP
;
98 return R300_VAP_VF_CNTL__PRIM_TRIANGLES
;
100 case GL_TRIANGLE_STRIP
:
101 return R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP
;
103 case GL_TRIANGLE_FAN
:
104 return R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN
;
107 return R300_VAP_VF_CNTL__PRIM_QUADS
;
110 return R300_VAP_VF_CNTL__PRIM_QUAD_STRIP
;
113 return R300_VAP_VF_CNTL__PRIM_POLYGON
;
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
;
171 return num_verts
- verts_off
;
174 static void r300EmitElts(GLcontext
* ctx
, void *elts
, unsigned long n_elts
)
176 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
177 struct r300_dma_region
*rvb
= &rmesa
->state
.elt_dma
;
180 if (r300IsGartMemory(rmesa
, elts
, n_elts
* 4)) {
181 rvb
->address
= rmesa
->radeon
.radeonScreen
->gartTextures
.map
;
182 rvb
->start
= ((char *)elts
) - rvb
->address
;
184 rmesa
->radeon
.radeonScreen
->gart_texture_offset
+
187 } else if (r300IsGartMemory(rmesa
, elts
, 1)) {
188 WARN_ONCE("Pointer not within GART memory!\n");
192 r300AllocDmaRegion(rmesa
, rvb
, n_elts
* 4, 4);
193 rvb
->aos_offset
= GET_START(rvb
);
195 out
= rvb
->address
+ rvb
->start
;
196 memcpy(out
, elts
, n_elts
* 4);
199 static void r300FireEB(r300ContextPtr rmesa
, unsigned long addr
,
200 int vertex_count
, int type
)
202 int cmd_reserved
= 0;
204 drm_radeon_cmd_header_t
*cmd
= NULL
;
206 start_packet3(CP_PACKET3(R300_PACKET3_3D_DRAW_INDX_2
, 0), 0);
207 e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES
| (vertex_count
<< 16) | type
| R300_VAP_VF_CNTL__INDEX_SIZE_32bit
);
209 start_packet3(CP_PACKET3(R300_PACKET3_INDX_BUFFER
, 2), 2);
210 e32(R300_EB_UNK1
| (0 << 16) | R300_EB_UNK2
);
215 static void r300EmitAOS(r300ContextPtr rmesa
, GLuint nr
, GLuint offset
)
217 int sz
= 1 + (nr
>> 1) * 3 + (nr
& 1) * 2;
219 int cmd_reserved
= 0;
221 drm_radeon_cmd_header_t
*cmd
= NULL
;
223 if (RADEON_DEBUG
& DEBUG_VERTS
)
224 fprintf(stderr
, "%s: nr=%d, ofs=0x%08x\n", __FUNCTION__
, nr
,
227 start_packet3(CP_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR
, sz
- 1), sz
- 1);
230 for (i
= 0; i
+ 1 < nr
; i
+= 2) {
231 e32((rmesa
->state
.aos
[i
].aos_size
<< 0) |
232 (rmesa
->state
.aos
[i
].aos_stride
<< 8) |
233 (rmesa
->state
.aos
[i
+ 1].aos_size
<< 16) |
234 (rmesa
->state
.aos
[i
+ 1].aos_stride
<< 24));
236 e32(rmesa
->state
.aos
[i
].aos_offset
+ offset
* 4 * rmesa
->state
.aos
[i
].aos_stride
);
237 e32(rmesa
->state
.aos
[i
+ 1].aos_offset
+ offset
* 4 * rmesa
->state
.aos
[i
+ 1].aos_stride
);
241 e32((rmesa
->state
.aos
[nr
- 1].aos_size
<< 0) |
242 (rmesa
->state
.aos
[nr
- 1].aos_stride
<< 8));
243 e32(rmesa
->state
.aos
[nr
- 1].aos_offset
+ offset
* 4 * rmesa
->state
.aos
[nr
- 1].aos_stride
);
247 static void r300FireAOS(r300ContextPtr rmesa
, int vertex_count
, int type
)
249 int cmd_reserved
= 0;
251 drm_radeon_cmd_header_t
*cmd
= NULL
;
253 start_packet3(CP_PACKET3(R300_PACKET3_3D_DRAW_VBUF_2
, 0), 0);
254 e32(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST
| (vertex_count
<< 16) | type
);
257 static void r300RunRenderPrimitive(r300ContextPtr rmesa
, GLcontext
* ctx
,
258 int start
, int end
, int prim
)
261 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
262 struct vertex_buffer
*vb
= &tnl
->vb
;
264 type
= r300PrimitiveType(rmesa
, ctx
, prim
);
265 num_verts
= r300NumVerts(rmesa
, end
- start
, prim
);
267 if (type
< 0 || num_verts
<= 0)
271 r300EmitAOS(rmesa
, rmesa
->state
.aos_count
, start
);
272 if (num_verts
> 65535) {
273 /* not implemented yet */
274 WARN_ONCE("Too many elts\n");
277 r300EmitElts(ctx
, vb
->Elts
, num_verts
);
278 r300FireEB(rmesa
, rmesa
->state
.elt_dma
.aos_offset
, num_verts
, type
);
280 r300EmitAOS(rmesa
, rmesa
->state
.aos_count
, start
);
281 r300FireAOS(rmesa
, num_verts
, type
);
285 static GLboolean
r300RunRender(GLcontext
* ctx
,
286 struct tnl_pipeline_stage
*stage
)
288 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
290 int cmd_reserved
= 0;
292 drm_radeon_cmd_header_t
*cmd
= NULL
;
293 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
294 struct vertex_buffer
*vb
= &tnl
->vb
;
296 if (RADEON_DEBUG
& DEBUG_PRIMS
)
297 fprintf(stderr
, "%s\n", __FUNCTION__
);
299 if (hw_tcl_on
== GL_FALSE
)
300 vb
->AttribPtr
[VERT_ATTRIB_POS
] = vb
->ClipPtr
;
301 r300UpdateShaders(rmesa
);
302 if (r300EmitArrays(ctx
))
305 r300UpdateShaderStates(rmesa
);
307 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
, 0);
308 e32(R300_RB3D_DSTCACHE_UNKNOWN_0A
);
310 reg_start(R300_RB3D_ZCACHE_CTLSTAT
, 0);
311 e32(R300_RB3D_ZCACHE_UNKNOWN_03
);
313 r300EmitState(rmesa
);
315 for (i
= 0; i
< vb
->PrimitiveCount
; i
++) {
316 GLuint prim
= _tnl_translate_prim(&vb
->Primitive
[i
]);
317 GLuint start
= vb
->Primitive
[i
].start
;
318 GLuint end
= vb
->Primitive
[i
].start
+ vb
->Primitive
[i
].count
;
319 r300RunRenderPrimitive(rmesa
, ctx
, start
, end
, prim
);
322 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
, 0);
323 e32(R300_RB3D_DSTCACHE_UNKNOWN_0A
);
325 reg_start(R300_RB3D_ZCACHE_CTLSTAT
, 0);
326 e32(R300_RB3D_ZCACHE_UNKNOWN_03
);
332 r300ReleaseArrays(ctx
);
337 #define FALLBACK_IF(expr) \
340 if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \
341 WARN_ONCE("Software fallback:%s\n", \
343 return R300_FALLBACK_RAST; \
347 static int r300Fallback(GLcontext
* ctx
)
349 r300ContextPtr r300
= R300_CONTEXT(ctx
);
350 struct r300_fragment_program
*fp
= (struct r300_fragment_program
*)
351 (char *)ctx
->FragmentProgram
._Current
;
355 r300TranslateFragmentShader(r300
, fp
);
356 FALLBACK_IF(!fp
->translated
);
359 FALLBACK_IF(ctx
->RenderMode
!= GL_RENDER
);
361 FALLBACK_IF(ctx
->Stencil
._TestTwoSide
362 && (ctx
->Stencil
.Ref
[0] != ctx
->Stencil
.Ref
[1]
363 || ctx
->Stencil
.ValueMask
[0] !=
364 ctx
->Stencil
.ValueMask
[1]
365 || ctx
->Stencil
.WriteMask
[0] !=
366 ctx
->Stencil
.WriteMask
[1]));
368 FALLBACK_IF(ctx
->Color
.ColorLogicOpEnabled
);
370 if (ctx
->Extensions
.NV_point_sprite
|| ctx
->Extensions
.ARB_point_sprite
)
371 FALLBACK_IF(ctx
->Point
.PointSprite
);
373 if (!r300
->disable_lowimpact_fallback
) {
374 FALLBACK_IF(ctx
->Polygon
.StippleFlag
);
375 FALLBACK_IF(ctx
->Multisample
.Enabled
);
376 FALLBACK_IF(ctx
->Line
.StippleFlag
);
377 FALLBACK_IF(ctx
->Line
.SmoothFlag
);
378 FALLBACK_IF(ctx
->Point
.SmoothFlag
);
381 return R300_FALLBACK_NONE
;
384 static GLboolean
r300RunNonTCLRender(GLcontext
* ctx
,
385 struct tnl_pipeline_stage
*stage
)
387 if (RADEON_DEBUG
& DEBUG_PRIMS
)
388 fprintf(stderr
, "%s\n", __FUNCTION__
);
390 if (r300Fallback(ctx
) >= R300_FALLBACK_RAST
)
393 return r300RunRender(ctx
, stage
);
396 static GLboolean
r300RunTCLRender(GLcontext
* ctx
,
397 struct tnl_pipeline_stage
*stage
)
399 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
400 struct r300_vertex_program
*vp
;
402 hw_tcl_on
= future_hw_tcl_on
;
404 if (RADEON_DEBUG
& DEBUG_PRIMS
)
405 fprintf(stderr
, "%s\n", __FUNCTION__
);
407 if (hw_tcl_on
== GL_FALSE
)
410 if (r300Fallback(ctx
) >= R300_FALLBACK_TCL
) {
411 hw_tcl_on
= GL_FALSE
;
415 r300UpdateShaders(rmesa
);
417 vp
= (struct r300_vertex_program
*)CURRENT_VERTEX_SHADER(ctx
);
418 if (vp
->native
== GL_FALSE
) {
419 hw_tcl_on
= GL_FALSE
;
423 return r300RunRender(ctx
, stage
);
426 const struct tnl_pipeline_stage _r300_render_stage
= {
427 "r300 Hardware Rasterization",
435 const struct tnl_pipeline_stage _r300_tcl_stage
= {
436 "r300 Hardware Transform, Clipping and Lighting",