Port viewport setting code from R200.
[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 * Authors:
30 * Nicolai Haehnle <prefect_@gmx.net>
31 */
32
33 #include "glheader.h"
34 #include "state.h"
35 #include "imports.h"
36 #include "enums.h"
37 #include "macros.h"
38 #include "context.h"
39 #include "dd.h"
40 #include "simple_list.h"
41
42 #include "api_arrayelt.h"
43 #include "swrast/swrast.h"
44 #include "swrast_setup/swrast_setup.h"
45 #include "array_cache/acache.h"
46 #include "tnl/tnl.h"
47
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"
53 #include "r300_reg.h"
54 #include "r300_program.h"
55
56 #include "r300_lib.h"
57
58
59 /**********************************************************************
60 * Hardware rasterization
61 *
62 * When we fell back to software TCL, we still try to use the
63 * rasterization hardware for rendering.
64 **********************************************************************/
65
66 static void r300_render_flat_primitive(r300ContextPtr rmesa,
67 GLcontext *ctx,
68 int start,
69 int end,
70 int type)
71 {
72 TNLcontext *tnl = TNL_CONTEXT(ctx);
73 struct vertex_buffer *VB = &tnl->vb;
74 GLuint i;
75 int k;
76 LOCAL_VARS
77
78 if(end<=start)return; /* do we need to watch for this ? */
79
80
81
82 start_immediate_packet(end-start, type, 8);
83
84 for(i=start;i<end;i++){
85 #if 0
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],
91
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]
96 );
97 #endif
98
99 /* coordinates */
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]);
103 #if 0
104 efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[3]);
105 #else
106 efloat(2.0);
107 #endif
108
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]);
113 #if 0
114 efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[3]);
115 #else
116 efloat(0.0);
117 #endif
118 }
119
120 }
121
122 static void r300_dispatch_flat_primitive(r300ContextPtr rmesa,
123 GLcontext *ctx,
124 int start,
125 int end,
126 int prim)
127 {
128 TNLcontext *tnl = TNL_CONTEXT(ctx);
129 struct vertex_buffer *VB = &tnl->vb;
130 GLuint i;
131 int type=-1;
132
133 if(end<=start)return; /* do we need to watch for this ? */
134
135 fprintf(stderr, "[%d-%d]", start, end);
136 switch (prim & PRIM_MODE_MASK) {
137 case GL_LINES:
138 fprintf(stderr, "L ");
139 type=R300_VAP_VF_CNTL__PRIM_LINES;
140 if(end<start+2){
141 fprintf(stderr, "Not enough vertices\n");
142 return; /* need enough vertices for Q */
143 }
144 break;
145 case GL_LINE_STRIP:
146 fprintf(stderr, "LS ");
147 type=R300_VAP_VF_CNTL__PRIM_LINE_STRIP;
148 if(end<start+2){
149 fprintf(stderr, "Not enough vertices\n");
150 return; /* need enough vertices for Q */
151 }
152 break;
153 case GL_LINE_LOOP:
154 fprintf(stderr, "LL ");
155 return;
156 if(end<start+2){
157 fprintf(stderr, "Not enough vertices\n");
158 return; /* need enough vertices for Q */
159 }
160 break;
161 case GL_TRIANGLES:
162 fprintf(stderr, "T ");
163 type=R300_VAP_VF_CNTL__PRIM_TRIANGLES;
164 if(end<start+3){
165 fprintf(stderr, "Not enough vertices\n");
166 return; /* need enough vertices for Q */
167 }
168 break;
169 case GL_TRIANGLE_STRIP:
170 fprintf(stderr, "TS ");
171 type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP;
172 if(end<start+3){
173 fprintf(stderr, "Not enough vertices\n");
174 return; /* need enough vertices for Q */
175 }
176 break;
177 case GL_TRIANGLE_FAN:
178 fprintf(stderr, "TF ");
179 type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN;
180 if(end<start+3){
181 fprintf(stderr, "Not enough vertices\n");
182 return; /* need enough vertices for Q */
183 }
184 break;
185 case GL_QUADS:
186 fprintf(stderr, "Q ");
187 type=R300_VAP_VF_CNTL__PRIM_QUADS;
188 if(end<start+4){
189 fprintf(stderr, "Not enough vertices\n");
190 return; /* need enough vertices for Q */
191 }
192 break;
193 case GL_QUAD_STRIP:
194 fprintf(stderr, "QS ");
195 type=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP;
196 if(end<start+4){
197 fprintf(stderr, "Not enough vertices\n");
198 return; /* need enough vertices for Q */
199 }
200 break;
201 default:
202 fprintf(stderr, "Cannot handle primitive %02x ", prim & PRIM_MODE_MASK);
203 return;
204 break;
205 }
206 r300_render_flat_primitive(rmesa, ctx, start, end, type);
207
208 }
209
210 static GLboolean r300_run_flat_render(GLcontext *ctx,
211 struct tnl_pipeline_stage *stage)
212 {
213 r300ContextPtr rmesa = R300_CONTEXT(ctx);
214 TNLcontext *tnl = TNL_CONTEXT(ctx);
215 struct vertex_buffer *VB = &tnl->vb;
216 GLuint i;
217 ADAPTOR adaptor;
218 AOS_DATA vb_arrays[2];
219 LOCAL_VARS
220
221 if (RADEON_DEBUG == DEBUG_PRIMS)
222 fprintf(stderr, "%s\n", __FUNCTION__);
223
224 /* setup array of structures data */
225
226 /* Note: immediate vertex data includes all coordinates.
227 To save bandwidth use either VBUF or state-based vertex generation */
228 /* xyz */
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;
234
235 /* color */
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;
241
242 adaptor=TWO_PIPE_ADAPTOR;
243
244 adaptor.color_offset[0]=rmesa->radeon.radeonScreen->backOffset+rmesa->radeon.radeonScreen->fbLocation;
245 adaptor.color_pitch[0]=(rmesa->radeon.radeonScreen->backPitch) | (0xc0<<16);
246
247 adaptor.depth_offset=rmesa->radeon.radeonScreen->depthOffset;
248 adaptor.depth_pitch=rmesa->radeon.radeonScreen->depthPitch | (0x2 << 16);
249
250 init_3d(PASS_PREFIX &adaptor);
251 init_flat_primitive(PASS_PREFIX &adaptor);
252
253 set_scissors(PASS_PREFIX 0, 0, 2647, 1941);
254
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);
259
260 reg_start(R300_RE_OCCLUSION_CNTL, 0);
261 e32(R300_OCCLUSION_ON);
262
263 set_quad0(PASS_PREFIX 1.0,1.0,1.0,1.0);
264 set_init21(PASS_PREFIX 0.0,1.0);
265
266 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
267 setup_AOS(PASS_PREFIX vb_arrays, 2);
268
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);
274 }
275
276 end_3d(PASS_PREFIX_VOID);
277
278 start_packet3(RADEON_CP_PACKET3_NOP, 0);
279 e32(0x0);
280
281 fprintf(stderr, "\n");
282 return GL_FALSE;
283 }
284
285 /**
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.
290 */
291 static GLboolean r300_run_render(GLcontext *ctx,
292 struct tnl_pipeline_stage *stage)
293 {
294 r300ContextPtr rmesa = R300_CONTEXT(ctx);
295 TNLcontext *tnl = TNL_CONTEXT(ctx);
296 struct vertex_buffer *VB = &tnl->vb;
297 GLuint i;
298
299 if (RADEON_DEBUG == DEBUG_PRIMS)
300 fprintf(stderr, "%s\n", __FUNCTION__);
301
302 return r300_run_flat_render(ctx, stage);
303 #if 0
304 return GL_TRUE;
305 #else
306 return GL_FALSE;
307 #endif
308
309 #if 0
310 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
311 TNLcontext *tnl = TNL_CONTEXT(ctx);
312 struct vertex_buffer *VB = &tnl->vb;
313 GLuint i;
314
315 /* Don't handle clipping or indexed vertices or vertex manipulations.
316 */
317 if (mmesa->RenderIndex != 0 ||
318 !mga_validate_render( ctx, VB )) {
319 return GL_TRUE;
320 }
321
322 tnl->Driver.Render.Start( ctx );
323 mmesa->SetupNewInputs = ~0;
324
325 for (i = 0 ; i < VB->PrimitiveCount ; i++)
326 {
327 GLuint prim = VB->Primitive[i].mode;
328 GLuint start = VB->Primitive[i].start;
329 GLuint length = VB->Primitive[i].count;
330
331 if (!length)
332 continue;
333
334 mga_render_tab_verts[prim & PRIM_MODE_MASK]( ctx, start, start + length,
335 prim);
336 }
337
338 tnl->Driver.Render.Finish( ctx );
339
340 return GL_FALSE; /* finished the pipe */
341 #endif
342 }
343
344
345 /**
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
350 */
351 #define FALLBACK_IF(expr) \
352 do { \
353 if (expr) { \
354 if (RADEON_DEBUG & DEBUG_FALLBACKS) \
355 fprintf(stderr, "%s: fallback:%s\n", \
356 __FUNCTION__, #expr); \
357 stage->active = GL_FALSE; \
358 return; \
359 } \
360 } while(0)
361
362 static void r300_check_render(GLcontext *ctx, struct tnl_pipeline_stage *stage)
363 {
364 r300ContextPtr r300 = R300_CONTEXT(ctx);
365 int i;
366
367 if (RADEON_DEBUG & DEBUG_STATE)
368 fprintf(stderr, "%s\n", __FUNCTION__);
369
370 /* We only support rendering in hardware for now */
371 if (ctx->RenderMode != GL_RENDER) {
372 stage->active = GL_FALSE;
373 return;
374 }
375
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);
379
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
396
397 for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
398 FALLBACK_IF(ctx->Texture.Unit[i].Enabled);
399
400
401 /* let r300_run_render do its job */
402 #if 0
403 stage->active = GL_FALSE;
404 #endif
405 }
406
407
408 static void dtr(struct tnl_pipeline_stage *stage)
409 {
410 (void)stage;
411 }
412
413 const struct tnl_pipeline_stage _r300_render_stage = {
414 "r300 hw rasterize",
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 */
423 };