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 * Nicolai Haehnle <prefect_@gmx.net>
40 #include "simple_list.h"
42 #include "api_arrayelt.h"
43 #include "swrast/swrast.h"
44 #include "swrast_setup/swrast_setup.h"
45 #include "array_cache/acache.h"
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"
54 #include "r300_program.h"
59 /**********************************************************************
60 * Hardware rasterization
62 * When we fell back to software TCL, we still try to use the
63 * rasterization hardware for rendering.
64 **********************************************************************/
66 static void r300_render_flat_primitive(r300ContextPtr rmesa
,
72 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
73 struct vertex_buffer
*VB
= &tnl
->vb
;
78 if(end
<=start
)return; /* do we need to watch for this ? */
82 start_immediate_packet(end
-start
, type
, 8);
84 for(i
=start
;i
<end
;i
++){
86 fprintf(stderr
, "* (%f %f %f %f) (%f %f %f %f)\n",
87 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[0],
88 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[1],
89 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[2],
90 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[3],
92 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[0],
93 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[1],
94 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[2],
95 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[3]
100 efloat(VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[0]);
101 efloat(VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[1]);
102 efloat(VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[2]);
104 efloat(VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[3]);
109 /* color components */
110 efloat(VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[0]);
111 efloat(VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[1]);
112 efloat(VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[2]);
114 efloat(VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[3]);
122 static void r300_dispatch_flat_primitive(r300ContextPtr rmesa
,
128 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
129 struct vertex_buffer
*VB
= &tnl
->vb
;
133 if(end
<=start
)return; /* do we need to watch for this ? */
135 fprintf(stderr
, "[%d-%d]", start
, end
);
136 switch (prim
& PRIM_MODE_MASK
) {
138 fprintf(stderr
, "L ");
139 type
=R300_VAP_VF_CNTL__PRIM_LINES
;
141 fprintf(stderr
, "Not enough vertices\n");
142 return; /* need enough vertices for Q */
146 fprintf(stderr
, "LS ");
147 type
=R300_VAP_VF_CNTL__PRIM_LINE_STRIP
;
149 fprintf(stderr
, "Not enough vertices\n");
150 return; /* need enough vertices for Q */
154 fprintf(stderr
, "LL ");
157 fprintf(stderr
, "Not enough vertices\n");
158 return; /* need enough vertices for Q */
162 fprintf(stderr
, "T ");
163 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLES
;
165 fprintf(stderr
, "Not enough vertices\n");
166 return; /* need enough vertices for Q */
169 case GL_TRIANGLE_STRIP
:
170 fprintf(stderr
, "TS ");
171 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP
;
173 fprintf(stderr
, "Not enough vertices\n");
174 return; /* need enough vertices for Q */
177 case GL_TRIANGLE_FAN
:
178 fprintf(stderr
, "TF ");
179 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN
;
181 fprintf(stderr
, "Not enough vertices\n");
182 return; /* need enough vertices for Q */
186 fprintf(stderr
, "Q ");
187 type
=R300_VAP_VF_CNTL__PRIM_QUADS
;
189 fprintf(stderr
, "Not enough vertices\n");
190 return; /* need enough vertices for Q */
194 fprintf(stderr
, "QS ");
195 type
=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP
;
197 fprintf(stderr
, "Not enough vertices\n");
198 return; /* need enough vertices for Q */
202 fprintf(stderr
, "Cannot handle primitive %02x ", prim
& PRIM_MODE_MASK
);
206 r300_render_flat_primitive(rmesa
, ctx
, start
, end
, type
);
210 static GLboolean
r300_run_flat_render(GLcontext
*ctx
,
211 struct tnl_pipeline_stage
*stage
)
213 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
214 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
215 struct vertex_buffer
*VB
= &tnl
->vb
;
218 AOS_DATA vb_arrays
[2];
221 if (RADEON_DEBUG
== DEBUG_PRIMS
)
222 fprintf(stderr
, "%s\n", __FUNCTION__
);
224 /* setup array of structures data */
226 /* Note: immediate vertex data includes all coordinates.
227 To save bandwidth use either VBUF or state-based vertex generation */
229 vb_arrays
[0].element_size
=4;
230 vb_arrays
[0].stride
=4;
231 vb_arrays
[0].offset
=0; /* Not used */
232 vb_arrays
[0].format
=AOS_FORMAT_FLOAT
;
233 vb_arrays
[0].ncomponents
=4;
236 vb_arrays
[1].element_size
=4;
237 vb_arrays
[1].stride
=4;
238 vb_arrays
[1].offset
=0; /* Not used */
239 vb_arrays
[1].format
=AOS_FORMAT_FLOAT_COLOR
;
240 vb_arrays
[1].ncomponents
=4;
242 adaptor
=TWO_PIPE_ADAPTOR
;
244 adaptor
.color_offset
[0]=rmesa
->radeon
.radeonScreen
->backOffset
+rmesa
->radeon
.radeonScreen
->fbLocation
;
245 adaptor
.color_pitch
[0]=(rmesa
->radeon
.radeonScreen
->backPitch
) | (0xc0<<16);
247 adaptor
.depth_offset
=rmesa
->radeon
.radeonScreen
->depthOffset
;
248 adaptor
.depth_pitch
=rmesa
->radeon
.radeonScreen
->depthPitch
| (0x2 << 16);
250 init_3d(PASS_PREFIX
&adaptor
);
251 init_flat_primitive(PASS_PREFIX
&adaptor
);
253 set_scissors(PASS_PREFIX
0, 0, 2647, 1941);
255 set_cliprect(PASS_PREFIX
0, 0, 0, 2647,1941);
256 set_cliprect(PASS_PREFIX
1, 0, 0, 2647,1941);
257 set_cliprect(PASS_PREFIX
2, 0, 0, 2647,1941);
258 set_cliprect(PASS_PREFIX
3, 0, 0, 2647,1941);
260 reg_start(R300_RE_OCCLUSION_CNTL
, 0);
261 e32(R300_OCCLUSION_ON
);
263 set_quad0(PASS_PREFIX
1.0,1.0,1.0,1.0);
264 set_init21(PASS_PREFIX
0.0,1.0);
266 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
267 setup_AOS(PASS_PREFIX vb_arrays
, 2);
269 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
270 GLuint prim
= VB
->Primitive
[i
].mode
;
271 GLuint start
= VB
->Primitive
[i
].start
;
272 GLuint length
= VB
->Primitive
[i
].count
;
273 r300_dispatch_flat_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
276 end_3d(PASS_PREFIX_VOID
);
278 start_packet3(RADEON_CP_PACKET3_NOP
, 0);
281 fprintf(stderr
, "\n");
286 * Called by the pipeline manager to render a batch of primitives.
287 * We can return true to pass on to the next stage (i.e. software
288 * rasterization) or false to indicate that the pipeline has finished
289 * after we render something.
291 static GLboolean
r300_run_render(GLcontext
*ctx
,
292 struct tnl_pipeline_stage
*stage
)
294 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
295 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
296 struct vertex_buffer
*VB
= &tnl
->vb
;
299 if (RADEON_DEBUG
== DEBUG_PRIMS
)
300 fprintf(stderr
, "%s\n", __FUNCTION__
);
302 return r300_run_flat_render(ctx
, stage
);
310 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
311 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
312 struct vertex_buffer
*VB
= &tnl
->vb
;
315 /* Don't handle clipping or indexed vertices or vertex manipulations.
317 if (mmesa
->RenderIndex
!= 0 ||
318 !mga_validate_render( ctx
, VB
)) {
322 tnl
->Driver
.Render
.Start( ctx
);
323 mmesa
->SetupNewInputs
= ~0;
325 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++)
327 GLuint prim
= VB
->Primitive
[i
].mode
;
328 GLuint start
= VB
->Primitive
[i
].start
;
329 GLuint length
= VB
->Primitive
[i
].count
;
334 mga_render_tab_verts
[prim
& PRIM_MODE_MASK
]( ctx
, start
, start
+ length
,
338 tnl
->Driver
.Render
.Finish( ctx
);
340 return GL_FALSE
; /* finished the pipe */
346 * Called by the pipeline manager once before rendering.
347 * We check the GL state here to
348 * a) decide whether we can do the current state in hardware and
349 * b) update hardware registers
351 #define FALLBACK_IF(expr) \
354 if (RADEON_DEBUG & DEBUG_FALLBACKS) \
355 fprintf(stderr, "%s: fallback:%s\n", \
356 __FUNCTION__, #expr); \
357 stage->active = GL_FALSE; \
362 static void r300_check_render(GLcontext
*ctx
, struct tnl_pipeline_stage
*stage
)
364 r300ContextPtr r300
= R300_CONTEXT(ctx
);
367 if (RADEON_DEBUG
& DEBUG_STATE
)
368 fprintf(stderr
, "%s\n", __FUNCTION__
);
370 /* We only support rendering in hardware for now */
371 if (ctx
->RenderMode
!= GL_RENDER
) {
372 stage
->active
= GL_FALSE
;
376 // I failed to figure out how dither works in hardware,
377 // let's just ignore it for now
378 //FALLBACK_IF(ctx->Color.DitherFlag);
380 /* I'm almost certain I forgot something here */
381 FALLBACK_IF(ctx
->Color
.AlphaEnabled
); // GL_ALPHA_TEST
382 FALLBACK_IF(ctx
->Color
.BlendEnabled
); // GL_BLEND
383 FALLBACK_IF(ctx
->Fog
.Enabled
); // GL_FOG
384 FALLBACK_IF(ctx
->Line
.SmoothFlag
); // GL_LINE_SMOOTH
385 FALLBACK_IF(ctx
->Line
.StippleFlag
); // GL_LINE_STIPPLE
386 FALLBACK_IF(ctx
->Point
.SmoothFlag
); // GL_POINT_SMOOTH
387 if (ctx
->Extensions
.NV_point_sprite
|| ctx
->Extensions
.ARB_point_sprite
)
388 FALLBACK_IF(ctx
->Point
.PointSprite
); // GL_POINT_SPRITE_NV
389 FALLBACK_IF(ctx
->Polygon
.OffsetPoint
); // GL_POLYGON_OFFSET_POINT
390 FALLBACK_IF(ctx
->Polygon
.OffsetLine
); // GL_POLYGON_OFFSET_LINE
391 FALLBACK_IF(ctx
->Polygon
.OffsetFill
); // GL_POLYGON_OFFSET_FILL
392 FALLBACK_IF(ctx
->Polygon
.SmoothFlag
); // GL_POLYGON_SMOOTH
393 FALLBACK_IF(ctx
->Polygon
.StippleFlag
); // GL_POLYGON_STIPPLE
394 FALLBACK_IF(ctx
->Stencil
.Enabled
); // GL_STENCIL_TEST
395 FALLBACK_IF(ctx
->Multisample
.Enabled
); // GL_MULTISAMPLE_ARB
397 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++)
398 FALLBACK_IF(ctx
->Texture
.Unit
[i
].Enabled
);
401 /* let r300_run_render do its job */
403 stage
->active
= GL_FALSE
;
408 static void dtr(struct tnl_pipeline_stage
*stage
)
413 const struct tnl_pipeline_stage _r300_render_stage
= {
415 _NEW_ALL
, /* re-check (always re-check for now) */
416 0, /* re-run (always runs) */
417 GL_TRUE
, /* active */
418 0, 0, /* inputs (set in check_render), outputs */
419 0, 0, /* changed_inputs, private */
420 dtr
, /* destructor */
421 r300_check_render
, /* check */
422 r300_run_render
/* run */