add support for user-configurable brilinear filtering on r200
[mesa.git] / src / mesa / drivers / dri / r200 / r200_cmdbuf.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_cmdbuf.c,v 1.1 2002/10/30 12:51:51 alanh Exp $ */
2 /*
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
8
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 */
29
30 /*
31 * Authors:
32 * Keith Whitwell <keith@tungstengraphics.com>
33 */
34
35 #include "glheader.h"
36 #include "imports.h"
37 #include "macros.h"
38 #include "context.h"
39 #include "swrast/swrast.h"
40 #include "simple_list.h"
41
42 #include "r200_context.h"
43 #include "r200_state.h"
44 #include "r200_ioctl.h"
45 #include "r200_tcl.h"
46 #include "r200_sanity.h"
47 #include "radeon_reg.h"
48
49 static void print_state_atom( struct r200_state_atom *state )
50 {
51 int i;
52
53 fprintf(stderr, "emit %s/%d\n", state->name, state->cmd_size);
54
55 if (0 & R200_DEBUG & DEBUG_VERBOSE)
56 for (i = 0 ; i < state->cmd_size ; i++)
57 fprintf(stderr, "\t%s[%d]: %x\n", state->name, i, state->cmd[i]);
58
59 }
60
61 /* The state atoms will be emitted in the order they appear in the atom list,
62 * so this step is important.
63 */
64 void r200SetUpAtomList( r200ContextPtr rmesa )
65 {
66 int i, mtu;
67
68 mtu = rmesa->glCtx->Const.MaxTextureUnits;
69
70 make_empty_list(&rmesa->hw.atomlist);
71 rmesa->hw.atomlist.name = "atom-list";
72
73 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.ctx );
74 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.set );
75 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.lin );
76 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.msk );
77 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vpt );
78 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vtx );
79 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vap );
80 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vte );
81 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.msc );
82 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.cst );
83 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.zbs );
84 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tcl );
85 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.msl );
86 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tcg );
87 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.grd );
88 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.fog );
89 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tam );
90 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tf );
91 for (i = 0; i < mtu; ++i)
92 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tex[i] );
93 for (i = 0; i < mtu; ++i)
94 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.cube[i] );
95 for (i = 0; i < 6; ++i)
96 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.pix[i] );
97
98 for (i = 0; i < 8; ++i)
99 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.lit[i] );
100 for (i = 0; i < 3 + mtu; ++i)
101 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.mat[i] );
102 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.eye );
103 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.glt );
104 for (i = 0; i < 2; ++i)
105 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.mtl[i] );
106 for (i = 0; i < 6; ++i)
107 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.ucp[i] );
108 /* FIXME: is this a good place to insert that atom ? */
109 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.prf );
110 }
111
112 static void r200SaveHwState( r200ContextPtr rmesa )
113 {
114 struct r200_state_atom *atom;
115 char * dest = rmesa->backup_store.cmd_buf;
116
117 if (R200_DEBUG & DEBUG_STATE)
118 fprintf(stderr, "%s\n", __FUNCTION__);
119
120 rmesa->backup_store.cmd_used = 0;
121
122 foreach( atom, &rmesa->hw.atomlist ) {
123 if ( atom->check( rmesa->glCtx, atom->idx ) ) {
124 int size = atom->cmd_size * 4;
125 memcpy( dest, atom->cmd, size);
126 dest += size;
127 rmesa->backup_store.cmd_used += size;
128 if (R200_DEBUG & DEBUG_STATE)
129 print_state_atom( atom );
130 }
131 }
132
133 assert( rmesa->backup_store.cmd_used <= R200_CMD_BUF_SZ );
134 if (R200_DEBUG & DEBUG_STATE)
135 fprintf(stderr, "Returning to r200EmitState\n");
136 }
137
138 void r200EmitState( r200ContextPtr rmesa )
139 {
140 char *dest;
141 int mtu;
142 struct r200_state_atom *atom;
143
144 if (R200_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
145 fprintf(stderr, "%s\n", __FUNCTION__);
146
147 if (rmesa->save_on_next_emit) {
148 r200SaveHwState(rmesa);
149 rmesa->save_on_next_emit = GL_FALSE;
150 }
151
152 if (!rmesa->hw.is_dirty && !rmesa->hw.all_dirty)
153 return;
154
155 mtu = rmesa->glCtx->Const.MaxTextureUnits;
156
157 /* To avoid going across the entire set of states multiple times, just check
158 * for enough space for the case of emitting all state, and inline the
159 * r200AllocCmdBuf code here without all the checks.
160 */
161 r200EnsureCmdBufSpace( rmesa, rmesa->hw.max_state_size );
162
163 /* we need to calculate dest after EnsureCmdBufSpace
164 as we may flush the buffer - airlied */
165 dest = rmesa->store.cmd_buf + rmesa->store.cmd_used;
166 if (R200_DEBUG & DEBUG_STATE) {
167 foreach( atom, &rmesa->hw.atomlist ) {
168 if ( atom->dirty || rmesa->hw.all_dirty ) {
169 if ( atom->check( rmesa->glCtx, atom->idx ) )
170 print_state_atom( atom );
171 else
172 fprintf(stderr, "skip state %s\n", atom->name);
173 }
174 }
175 }
176
177 foreach( atom, &rmesa->hw.atomlist ) {
178 if ( rmesa->hw.all_dirty )
179 atom->dirty = GL_TRUE;
180 if ( atom->dirty ) {
181 if ( atom->check( rmesa->glCtx, atom->idx ) ) {
182 int size = atom->cmd_size * 4;
183 memcpy( dest, atom->cmd, size);
184 dest += size;
185 rmesa->store.cmd_used += size;
186 atom->dirty = GL_FALSE;
187 }
188 }
189 }
190
191 assert( rmesa->store.cmd_used <= R200_CMD_BUF_SZ );
192
193 rmesa->hw.is_dirty = GL_FALSE;
194 rmesa->hw.all_dirty = GL_FALSE;
195 }
196
197 /* Fire a section of the retained (indexed_verts) buffer as a regular
198 * primtive.
199 */
200 void r200EmitVbufPrim( r200ContextPtr rmesa,
201 GLuint primitive,
202 GLuint vertex_nr )
203 {
204 drm_radeon_cmd_header_t *cmd;
205
206 assert(!(primitive & R200_VF_PRIM_WALK_IND));
207
208 r200EmitState( rmesa );
209
210 if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS))
211 fprintf(stderr, "%s cmd_used/4: %d prim %x nr %d\n", __FUNCTION__,
212 rmesa->store.cmd_used/4, primitive, vertex_nr);
213
214 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, VBUF_BUFSZ,
215 __FUNCTION__ );
216 cmd[0].i = 0;
217 cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
218 cmd[1].i = R200_CP_CMD_3D_DRAW_VBUF_2;
219 cmd[2].i = (primitive |
220 R200_VF_PRIM_WALK_LIST |
221 R200_VF_COLOR_ORDER_RGBA |
222 (vertex_nr << R200_VF_VERTEX_NUMBER_SHIFT));
223 }
224
225
226 void r200FlushElts( r200ContextPtr rmesa )
227 {
228 int *cmd = (int *)(rmesa->store.cmd_buf + rmesa->store.elts_start);
229 int dwords;
230 int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 12)) / 2;
231
232 if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS))
233 fprintf(stderr, "%s\n", __FUNCTION__);
234
235 assert( rmesa->dma.flush == r200FlushElts );
236 rmesa->dma.flush = NULL;
237
238 /* Cope with odd number of elts:
239 */
240 rmesa->store.cmd_used = (rmesa->store.cmd_used + 2) & ~2;
241 dwords = (rmesa->store.cmd_used - rmesa->store.elts_start) / 4;
242
243 cmd[1] |= (dwords - 3) << 16;
244 cmd[2] |= nr << R200_VF_VERTEX_NUMBER_SHIFT;
245
246 if (R200_DEBUG & DEBUG_SYNC) {
247 fprintf(stderr, "%s: Syncing\n", __FUNCTION__);
248 r200Finish( rmesa->glCtx );
249 }
250 }
251
252
253 GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa,
254 GLuint primitive,
255 GLuint min_nr )
256 {
257 drm_radeon_cmd_header_t *cmd;
258 GLushort *retval;
259
260 if (R200_DEBUG & DEBUG_IOCTL)
261 fprintf(stderr, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive);
262
263 assert((primitive & R200_VF_PRIM_WALK_IND));
264
265 r200EmitState( rmesa );
266
267 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, ELTS_BUFSZ(min_nr),
268 __FUNCTION__ );
269 cmd[0].i = 0;
270 cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
271 cmd[1].i = R200_CP_CMD_3D_DRAW_INDX_2;
272 cmd[2].i = (primitive |
273 R200_VF_PRIM_WALK_IND |
274 R200_VF_COLOR_ORDER_RGBA);
275
276
277 retval = (GLushort *)(cmd+3);
278
279 if (R200_DEBUG & DEBUG_PRIMS)
280 fprintf(stderr, "%s: header 0x%x prim %x \n",
281 __FUNCTION__,
282 cmd[1].i, primitive);
283
284 assert(!rmesa->dma.flush);
285 rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
286 rmesa->dma.flush = r200FlushElts;
287
288 rmesa->store.elts_start = ((char *)cmd) - rmesa->store.cmd_buf;
289
290 return retval;
291 }
292
293
294
295 void r200EmitVertexAOS( r200ContextPtr rmesa,
296 GLuint vertex_size,
297 GLuint offset )
298 {
299 drm_radeon_cmd_header_t *cmd;
300
301 if (R200_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL))
302 fprintf(stderr, "%s: vertex_size 0x%x offset 0x%x \n",
303 __FUNCTION__, vertex_size, offset);
304
305 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, VERT_AOS_BUFSZ,
306 __FUNCTION__ );
307
308 cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
309 cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | (2 << 16);
310 cmd[2].i = 1;
311 cmd[3].i = vertex_size | (vertex_size << 8);
312 cmd[4].i = offset;
313 }
314
315
316 void r200EmitAOS( r200ContextPtr rmesa,
317 struct r200_dma_region **component,
318 GLuint nr,
319 GLuint offset )
320 {
321 drm_radeon_cmd_header_t *cmd;
322 int sz = AOS_BUFSZ(nr);
323 int i;
324 int *tmp;
325
326 if (R200_DEBUG & DEBUG_IOCTL)
327 fprintf(stderr, "%s nr arrays: %d\n", __FUNCTION__, nr);
328
329 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, sz, __FUNCTION__ );
330 cmd[0].i = 0;
331 cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
332 cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | (((sz / sizeof(int)) - 3) << 16);
333 cmd[2].i = nr;
334 tmp = &cmd[0].i;
335 cmd += 3;
336
337 for (i = 0 ; i < nr ; i++) {
338 if (i & 1) {
339 cmd[0].i |= ((component[i]->aos_stride << 24) |
340 (component[i]->aos_size << 16));
341 cmd[2].i = (component[i]->aos_start +
342 offset * component[i]->aos_stride * 4);
343 cmd += 3;
344 }
345 else {
346 cmd[0].i = ((component[i]->aos_stride << 8) |
347 (component[i]->aos_size << 0));
348 cmd[1].i = (component[i]->aos_start +
349 offset * component[i]->aos_stride * 4);
350 }
351 }
352
353 if (R200_DEBUG & DEBUG_VERTS) {
354 fprintf(stderr, "%s:\n", __FUNCTION__);
355 for (i = 0 ; i < sz ; i++)
356 fprintf(stderr, " %d: %x\n", i, tmp[i]);
357 }
358 }
359
360 void r200EmitBlit( r200ContextPtr rmesa,
361 GLuint color_fmt,
362 GLuint src_pitch,
363 GLuint src_offset,
364 GLuint dst_pitch,
365 GLuint dst_offset,
366 GLint srcx, GLint srcy,
367 GLint dstx, GLint dsty,
368 GLuint w, GLuint h )
369 {
370 drm_radeon_cmd_header_t *cmd;
371
372 if (R200_DEBUG & DEBUG_IOCTL)
373 fprintf(stderr, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
374 __FUNCTION__,
375 src_pitch, src_offset, srcx, srcy,
376 dst_pitch, dst_offset, dstx, dsty,
377 w, h);
378
379 assert( (src_pitch & 63) == 0 );
380 assert( (dst_pitch & 63) == 0 );
381 assert( (src_offset & 1023) == 0 );
382 assert( (dst_offset & 1023) == 0 );
383 assert( w < (1<<16) );
384 assert( h < (1<<16) );
385
386 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, 8 * sizeof(int),
387 __FUNCTION__ );
388
389
390 cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
391 cmd[1].i = R200_CP_CMD_BITBLT_MULTI | (5 << 16);
392 cmd[2].i = (RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
393 RADEON_GMC_DST_PITCH_OFFSET_CNTL |
394 RADEON_GMC_BRUSH_NONE |
395 (color_fmt << 8) |
396 RADEON_GMC_SRC_DATATYPE_COLOR |
397 RADEON_ROP3_S |
398 RADEON_DP_SRC_SOURCE_MEMORY |
399 RADEON_GMC_CLR_CMP_CNTL_DIS |
400 RADEON_GMC_WR_MSK_DIS );
401
402 cmd[3].i = ((src_pitch/64)<<22) | (src_offset >> 10);
403 cmd[4].i = ((dst_pitch/64)<<22) | (dst_offset >> 10);
404 cmd[5].i = (srcx << 16) | srcy;
405 cmd[6].i = (dstx << 16) | dsty; /* dst */
406 cmd[7].i = (w << 16) | h;
407 }
408
409
410 void r200EmitWait( r200ContextPtr rmesa, GLuint flags )
411 {
412 if (rmesa->dri.drmMinor >= 6) {
413 drm_radeon_cmd_header_t *cmd;
414
415 assert( !(flags & ~(RADEON_WAIT_2D|RADEON_WAIT_3D)) );
416
417 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, 1 * sizeof(int),
418 __FUNCTION__ );
419 cmd[0].i = 0;
420 cmd[0].wait.cmd_type = RADEON_CMD_WAIT;
421 cmd[0].wait.flags = flags;
422 }
423 }