GL_(UN)PACK_SKIP_IMAGES should only be applied to 3D texture pack/unpacking
[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 }
109
110 static void r200SaveHwState( r200ContextPtr rmesa )
111 {
112 struct r200_state_atom *atom;
113 char * dest = rmesa->backup_store.cmd_buf;
114
115 if (R200_DEBUG & DEBUG_STATE)
116 fprintf(stderr, "%s\n", __FUNCTION__);
117
118 rmesa->backup_store.cmd_used = 0;
119
120 foreach( atom, &rmesa->hw.atomlist ) {
121 if ( atom->check( rmesa->glCtx, atom->idx ) ) {
122 int size = atom->cmd_size * 4;
123 memcpy( dest, atom->cmd, size);
124 dest += size;
125 rmesa->backup_store.cmd_used += size;
126 if (R200_DEBUG & DEBUG_STATE)
127 print_state_atom( atom );
128 }
129 }
130
131 assert( rmesa->backup_store.cmd_used <= R200_CMD_BUF_SZ );
132 if (R200_DEBUG & DEBUG_STATE)
133 fprintf(stderr, "Returning to r200EmitState\n");
134 }
135
136 void r200EmitState( r200ContextPtr rmesa )
137 {
138 char *dest;
139 int mtu;
140 struct r200_state_atom *atom;
141
142 if (R200_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
143 fprintf(stderr, "%s\n", __FUNCTION__);
144
145 if (rmesa->save_on_next_emit) {
146 r200SaveHwState(rmesa);
147 rmesa->save_on_next_emit = GL_FALSE;
148 }
149
150 if (!rmesa->hw.is_dirty && !rmesa->hw.all_dirty)
151 return;
152
153 mtu = rmesa->glCtx->Const.MaxTextureUnits;
154
155 /* To avoid going across the entire set of states multiple times, just check
156 * for enough space for the case of emitting all state, and inline the
157 * r200AllocCmdBuf code here without all the checks.
158 */
159 r200EnsureCmdBufSpace( rmesa, rmesa->hw.max_state_size );
160
161 /* we need to calculate dest after EnsureCmdBufSpace
162 as we may flush the buffer - airlied */
163 dest = rmesa->store.cmd_buf + rmesa->store.cmd_used;
164 if (R200_DEBUG & DEBUG_STATE) {
165 foreach( atom, &rmesa->hw.atomlist ) {
166 if ( atom->dirty || rmesa->hw.all_dirty ) {
167 if ( atom->check( rmesa->glCtx, atom->idx ) )
168 print_state_atom( atom );
169 else
170 fprintf(stderr, "skip state %s\n", atom->name);
171 }
172 }
173 }
174
175 foreach( atom, &rmesa->hw.atomlist ) {
176 if ( rmesa->hw.all_dirty )
177 atom->dirty = GL_TRUE;
178 if ( atom->dirty ) {
179 if ( atom->check( rmesa->glCtx, atom->idx ) ) {
180 int size = atom->cmd_size * 4;
181 memcpy( dest, atom->cmd, size);
182 dest += size;
183 rmesa->store.cmd_used += size;
184 atom->dirty = GL_FALSE;
185 }
186 }
187 }
188
189 assert( rmesa->store.cmd_used <= R200_CMD_BUF_SZ );
190
191 rmesa->hw.is_dirty = GL_FALSE;
192 rmesa->hw.all_dirty = GL_FALSE;
193 }
194
195 /* Fire a section of the retained (indexed_verts) buffer as a regular
196 * primtive.
197 */
198 extern void r200EmitVbufPrim( r200ContextPtr rmesa,
199 GLuint primitive,
200 GLuint vertex_nr )
201 {
202 drm_radeon_cmd_header_t *cmd;
203
204 assert(!(primitive & R200_VF_PRIM_WALK_IND));
205
206 r200EmitState( rmesa );
207
208 if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS))
209 fprintf(stderr, "%s cmd_used/4: %d prim %x nr %d\n", __FUNCTION__,
210 rmesa->store.cmd_used/4, primitive, vertex_nr);
211
212 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, VBUF_BUFSZ,
213 __FUNCTION__ );
214 cmd[0].i = 0;
215 cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
216 cmd[1].i = R200_CP_CMD_3D_DRAW_VBUF_2;
217 cmd[2].i = (primitive |
218 R200_VF_PRIM_WALK_LIST |
219 R200_VF_COLOR_ORDER_RGBA |
220 (vertex_nr << R200_VF_VERTEX_NUMBER_SHIFT));
221 }
222
223
224 void r200FlushElts( r200ContextPtr rmesa )
225 {
226 int *cmd = (int *)(rmesa->store.cmd_buf + rmesa->store.elts_start);
227 int dwords;
228 int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 12)) / 2;
229
230 if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS))
231 fprintf(stderr, "%s\n", __FUNCTION__);
232
233 assert( rmesa->dma.flush == r200FlushElts );
234 rmesa->dma.flush = 0;
235
236 /* Cope with odd number of elts:
237 */
238 rmesa->store.cmd_used = (rmesa->store.cmd_used + 2) & ~2;
239 dwords = (rmesa->store.cmd_used - rmesa->store.elts_start) / 4;
240
241 cmd[1] |= (dwords - 3) << 16;
242 cmd[2] |= nr << R200_VF_VERTEX_NUMBER_SHIFT;
243
244 if (R200_DEBUG & DEBUG_SYNC) {
245 fprintf(stderr, "%s: Syncing\n", __FUNCTION__);
246 r200Finish( rmesa->glCtx );
247 }
248 }
249
250
251 GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa,
252 GLuint primitive,
253 GLuint min_nr )
254 {
255 drm_radeon_cmd_header_t *cmd;
256 GLushort *retval;
257
258 if (R200_DEBUG & DEBUG_IOCTL)
259 fprintf(stderr, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive);
260
261 assert((primitive & R200_VF_PRIM_WALK_IND));
262
263 r200EmitState( rmesa );
264
265 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, ELTS_BUFSZ(min_nr),
266 __FUNCTION__ );
267 cmd[0].i = 0;
268 cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
269 cmd[1].i = R200_CP_CMD_3D_DRAW_INDX_2;
270 cmd[2].i = (primitive |
271 R200_VF_PRIM_WALK_IND |
272 R200_VF_COLOR_ORDER_RGBA);
273
274
275 retval = (GLushort *)(cmd+3);
276
277 if (R200_DEBUG & DEBUG_PRIMS)
278 fprintf(stderr, "%s: header 0x%x prim %x \n",
279 __FUNCTION__,
280 cmd[1].i, primitive);
281
282 assert(!rmesa->dma.flush);
283 rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
284 rmesa->dma.flush = r200FlushElts;
285
286 rmesa->store.elts_start = ((char *)cmd) - rmesa->store.cmd_buf;
287
288 return retval;
289 }
290
291
292
293 void r200EmitVertexAOS( r200ContextPtr rmesa,
294 GLuint vertex_size,
295 GLuint offset )
296 {
297 drm_radeon_cmd_header_t *cmd;
298
299 if (R200_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL))
300 fprintf(stderr, "%s: vertex_size 0x%x offset 0x%x \n",
301 __FUNCTION__, vertex_size, offset);
302
303 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, VERT_AOS_BUFSZ,
304 __FUNCTION__ );
305
306 cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
307 cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | (2 << 16);
308 cmd[2].i = 1;
309 cmd[3].i = vertex_size | (vertex_size << 8);
310 cmd[4].i = offset;
311 }
312
313
314 void r200EmitAOS( r200ContextPtr rmesa,
315 struct r200_dma_region **component,
316 GLuint nr,
317 GLuint offset )
318 {
319 drm_radeon_cmd_header_t *cmd;
320 int sz = AOS_BUFSZ(nr);
321 int i;
322 int *tmp;
323
324 if (R200_DEBUG & DEBUG_IOCTL)
325 fprintf(stderr, "%s nr arrays: %d\n", __FUNCTION__, nr);
326
327 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, sz, __FUNCTION__ );
328 cmd[0].i = 0;
329 cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
330 cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | (((sz / sizeof(int)) - 3) << 16);
331 cmd[2].i = nr;
332 tmp = &cmd[0].i;
333 cmd += 3;
334
335 for (i = 0 ; i < nr ; i++) {
336 if (i & 1) {
337 cmd[0].i |= ((component[i]->aos_stride << 24) |
338 (component[i]->aos_size << 16));
339 cmd[2].i = (component[i]->aos_start +
340 offset * component[i]->aos_stride * 4);
341 cmd += 3;
342 }
343 else {
344 cmd[0].i = ((component[i]->aos_stride << 8) |
345 (component[i]->aos_size << 0));
346 cmd[1].i = (component[i]->aos_start +
347 offset * component[i]->aos_stride * 4);
348 }
349 }
350
351 if (R200_DEBUG & DEBUG_VERTS) {
352 fprintf(stderr, "%s:\n", __FUNCTION__);
353 for (i = 0 ; i < sz ; i++)
354 fprintf(stderr, " %d: %x\n", i, tmp[i]);
355 }
356 }
357
358 void r200EmitBlit( r200ContextPtr rmesa,
359 GLuint color_fmt,
360 GLuint src_pitch,
361 GLuint src_offset,
362 GLuint dst_pitch,
363 GLuint dst_offset,
364 GLint srcx, GLint srcy,
365 GLint dstx, GLint dsty,
366 GLuint w, GLuint h )
367 {
368 drm_radeon_cmd_header_t *cmd;
369
370 if (R200_DEBUG & DEBUG_IOCTL)
371 fprintf(stderr, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
372 __FUNCTION__,
373 src_pitch, src_offset, srcx, srcy,
374 dst_pitch, dst_offset, dstx, dsty,
375 w, h);
376
377 assert( (src_pitch & 63) == 0 );
378 assert( (dst_pitch & 63) == 0 );
379 assert( (src_offset & 1023) == 0 );
380 assert( (dst_offset & 1023) == 0 );
381 assert( w < (1<<16) );
382 assert( h < (1<<16) );
383
384 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, 8 * sizeof(int),
385 __FUNCTION__ );
386
387
388 cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
389 cmd[1].i = R200_CP_CMD_BITBLT_MULTI | (5 << 16);
390 cmd[2].i = (RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
391 RADEON_GMC_DST_PITCH_OFFSET_CNTL |
392 RADEON_GMC_BRUSH_NONE |
393 (color_fmt << 8) |
394 RADEON_GMC_SRC_DATATYPE_COLOR |
395 RADEON_ROP3_S |
396 RADEON_DP_SRC_SOURCE_MEMORY |
397 RADEON_GMC_CLR_CMP_CNTL_DIS |
398 RADEON_GMC_WR_MSK_DIS );
399
400 cmd[3].i = ((src_pitch/64)<<22) | (src_offset >> 10);
401 cmd[4].i = ((dst_pitch/64)<<22) | (dst_offset >> 10);
402 cmd[5].i = (srcx << 16) | srcy;
403 cmd[6].i = (dstx << 16) | dsty; /* dst */
404 cmd[7].i = (w << 16) | h;
405 }
406
407
408 void r200EmitWait( r200ContextPtr rmesa, GLuint flags )
409 {
410 if (rmesa->dri.drmMinor >= 6) {
411 drm_radeon_cmd_header_t *cmd;
412
413 assert( !(flags & ~(RADEON_WAIT_2D|RADEON_WAIT_3D)) );
414
415 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, 1 * sizeof(int),
416 __FUNCTION__ );
417 cmd[0].i = 0;
418 cmd[0].wait.cmd_type = RADEON_CMD_WAIT;
419 cmd[0].wait.flags = flags;
420 }
421 }