Properly input stencil info contributed by Wladimir.
[profile/ivi/mesa.git] / src / mesa / drivers / dri / r300 / r300_ioctl.c
1 /*
2 Copyright (C) The Weather Channel, Inc.  2002.
3 Copyright (C) 2004 Nicolai Haehnle.
4 All Rights Reserved.
5
6 The Weather Channel (TM) funded Tungsten Graphics to develop the
7 initial release of the Radeon 8500 driver under the XFree86 license.
8 This notice must be preserved.
9
10 Permission is hereby granted, free of charge, to any person obtaining
11 a copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sublicense, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial
20 portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 **************************************************************************/
31
32 /*
33  * Authors:
34  *   Keith Whitwell <keith@tungstengraphics.com>
35  *   Nicolai Haehnle <prefect_@gmx.net>
36  */
37
38 #include <sched.h>
39 #include <errno.h>
40
41 #include "glheader.h"
42 #include "imports.h"
43 #include "macros.h"
44 #include "context.h"
45 #include "swrast/swrast.h"
46
47 #include "r300_context.h"
48 #include "radeon_ioctl.h"
49 #include "r300_ioctl.h"
50 #include "r300_cmdbuf.h"
51 #include "r300_state.h"
52 #include "r300_program.h"
53 #include "radeon_reg.h"
54
55 #include "vblank.h"
56
57
58 #define CLEARBUFFER_COLOR       0x1
59 #define CLEARBUFFER_DEPTH       0x2
60
61 static void r300ClearBuffer(r300ContextPtr r300, int flags, int buffer)
62 {
63         GLcontext* ctx = r300->radeon.glCtx;
64         __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
65         int i;
66         GLuint cboffset, cbpitch;
67         drm_r300_cmd_header_t* cmd;
68
69         if (RADEON_DEBUG & DEBUG_IOCTL)
70                 fprintf(stderr, "%s: %s buffer (%i,%i %ix%i)\n",
71                         __FUNCTION__, buffer ? "back" : "front",
72                         dPriv->x, dPriv->y, dPriv->w, dPriv->h);
73
74         if (buffer) {
75                 cboffset = r300->radeon.radeonScreen->backOffset;
76                 cbpitch = r300->radeon.radeonScreen->backPitch;
77         } else {
78                 cboffset = r300->radeon.radeonScreen->frontOffset;
79                 cbpitch = r300->radeon.radeonScreen->frontPitch;
80         }
81
82         cboffset += r300->radeon.radeonScreen->fbLocation;
83
84         R300_STATECHANGE(r300, vir[0]);
85         ((drm_r300_cmd_header_t*)r300->hw.vir[0].cmd)->unchecked_state.count = 1;
86         r300->hw.vir[0].cmd[1] = 0x21030003;
87
88         R300_STATECHANGE(r300, vir[1]);
89         ((drm_r300_cmd_header_t*)r300->hw.vir[1].cmd)->unchecked_state.count = 1;
90         r300->hw.vir[1].cmd[1] = 0xF688F688;
91
92         R300_STATECHANGE(r300, vic);
93         r300->hw.vic.cmd[R300_VIC_CNTL_0] = 0x00000001;
94         r300->hw.vic.cmd[R300_VIC_CNTL_1] = 0x00000405;
95         
96         R300_STATECHANGE(r300, vof);
97         r300->hw.vof.cmd[R300_VOF_CNTL_0] = R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT
98                                 | R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT;
99         r300->hw.vof.cmd[R300_VOF_CNTL_1] = 0; /* no textures */
100         
101         R300_STATECHANGE(r300, txe);
102         r300->hw.txe.cmd[R300_TXE_ENABLE] = 0;
103         
104         R300_STATECHANGE(r300, vpt);
105         r300->hw.vpt.cmd[R300_VPT_XSCALE] = r300PackFloat32(1.0);
106         r300->hw.vpt.cmd[R300_VPT_XOFFSET] = r300PackFloat32(dPriv->x);
107         r300->hw.vpt.cmd[R300_VPT_YSCALE] = r300PackFloat32(1.0);
108         r300->hw.vpt.cmd[R300_VPT_YOFFSET] = r300PackFloat32(dPriv->y);
109         r300->hw.vpt.cmd[R300_VPT_ZSCALE] = r300PackFloat32(1.0);
110         r300->hw.vpt.cmd[R300_VPT_ZOFFSET] = r300PackFloat32(0.0);
111
112         R300_STATECHANGE(r300, at);
113         r300->hw.at.cmd[R300_AT_ALPHA_TEST] = 0;
114         
115         R300_STATECHANGE(r300, bld);
116         r300->hw.bld.cmd[R300_BLD_CBLEND] = 0;
117         r300->hw.bld.cmd[R300_BLD_ABLEND] = 0;
118         
119         R300_STATECHANGE(r300, cb);
120         r300->hw.cb.cmd[R300_CB_OFFSET] = cboffset;
121         r300->hw.cb.cmd[R300_CB_PITCH] = cbpitch | R300_COLOR_UNKNOWN_22_23;
122
123         R300_STATECHANGE(r300, unk221C);
124         r300->hw.unk221C.cmd[1] = R300_221C_CLEAR;
125
126         R300_STATECHANGE(r300, ps);
127         r300->hw.ps.cmd[R300_PS_POINTSIZE] =
128                 ((dPriv->w * 6) << R300_POINTSIZE_X_SHIFT) |
129                 ((dPriv->h * 6) << R300_POINTSIZE_Y_SHIFT);
130
131         R300_STATECHANGE(r300, ri);
132         for(i = 1; i <= 8; ++i)
133                 r300->hw.ri.cmd[i] = R300_RS_INTERP_USED;
134
135         R300_STATECHANGE(r300, rc);
136         /* The second constant is needed to get glxgears display anything .. */
137         r300->hw.rc.cmd[1] = R300_RS_CNTL_0_UNKNOWN_7 | R300_RS_CNTL_0_UNKNOWN_18;
138         r300->hw.rc.cmd[2] = 0;
139         
140         R300_STATECHANGE(r300, rr);
141         ((drm_r300_cmd_header_t*)r300->hw.rr.cmd)->unchecked_state.count = 1;
142         r300->hw.rr.cmd[1] = 0x00004000;
143
144         R300_STATECHANGE(r300, cmk);
145         if (flags & CLEARBUFFER_COLOR) {
146                 r300->hw.cmk.cmd[R300_CMK_COLORMASK] =
147                         (ctx->Color.ColorMask[BCOMP] ? R300_COLORMASK0_B : 0) |
148                         (ctx->Color.ColorMask[GCOMP] ? R300_COLORMASK0_G : 0) |
149                         (ctx->Color.ColorMask[RCOMP] ? R300_COLORMASK0_R : 0) |
150                         (ctx->Color.ColorMask[ACOMP] ? R300_COLORMASK0_A : 0);
151         } else {
152                 r300->hw.cmk.cmd[R300_CMK_COLORMASK] = 0;
153         }
154
155         R300_STATECHANGE(r300, fp);
156         r300->hw.fp.cmd[R300_FP_CNTL0] = 0; /* 1 pass, no textures */
157         r300->hw.fp.cmd[R300_FP_CNTL1] = 0; /* no temporaries */
158         r300->hw.fp.cmd[R300_FP_CNTL2] = 0; /* no offset, one ALU instr */
159         r300->hw.fp.cmd[R300_FP_NODE0] = 0;
160         r300->hw.fp.cmd[R300_FP_NODE1] = 0;
161         r300->hw.fp.cmd[R300_FP_NODE2] = 0;
162         r300->hw.fp.cmd[R300_FP_NODE3] = R300_PFS_NODE_LAST_NODE;
163
164         R300_STATECHANGE(r300, fpi[0]);
165         R300_STATECHANGE(r300, fpi[1]);
166         R300_STATECHANGE(r300, fpi[2]);
167         R300_STATECHANGE(r300, fpi[3]);
168         ((drm_r300_cmd_header_t*)r300->hw.fpi[0].cmd)->unchecked_state.count = 1;
169         ((drm_r300_cmd_header_t*)r300->hw.fpi[1].cmd)->unchecked_state.count = 1;
170         ((drm_r300_cmd_header_t*)r300->hw.fpi[2].cmd)->unchecked_state.count = 1;
171         ((drm_r300_cmd_header_t*)r300->hw.fpi[3].cmd)->unchecked_state.count = 1;
172
173         /* MOV o0, t0 */
174         r300->hw.fpi[0].cmd[1] = FP_INSTRC(MAD, FP_ARGC(SRC0C_XYZ), FP_ARGC(ONE), FP_ARGC(ZERO));
175         r300->hw.fpi[1].cmd[1] = FP_SELC(0,NO,XYZ,FP_TMP(0),0,0);
176         r300->hw.fpi[2].cmd[1] = FP_INSTRA(MAD, FP_ARGA(SRC0A), FP_ARGA(ONE), FP_ARGA(ZERO));
177         r300->hw.fpi[3].cmd[1] = FP_SELA(0,NO,W,FP_TMP(0),0,0);
178
179         R300_STATECHANGE(r300, pvs);
180         r300->hw.pvs.cmd[R300_PVS_CNTL_1] =
181                 (0 << R300_PVS_CNTL_1_PROGRAM_START_SHIFT) |
182                 (0 << R300_PVS_CNTL_1_UNKNOWN_SHIFT) |
183                 (1 << R300_PVS_CNTL_1_PROGRAM_END_SHIFT);
184         r300->hw.pvs.cmd[R300_PVS_CNTL_2] = 0; /* no parameters */
185         r300->hw.pvs.cmd[R300_PVS_CNTL_3] =
186                 (1 << R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT);
187
188         R300_STATECHANGE(r300, vpi);
189         ((drm_r300_cmd_header_t*)r300->hw.vpi.cmd)->unchecked_state.count = 8;
190
191         /* MOV o0, i0; */
192         r300->hw.vpi.cmd[1] = VP_OUT(ADD,OUT,0,XYZW);
193         r300->hw.vpi.cmd[2] = VP_IN(IN,0);
194         r300->hw.vpi.cmd[3] = VP_ZERO();
195         r300->hw.vpi.cmd[4] = 0;
196
197         /* MOV o1, i1; */
198         r300->hw.vpi.cmd[5] = VP_OUT(ADD,OUT,1,XYZW);
199         r300->hw.vpi.cmd[6] = VP_IN(IN,1);
200         r300->hw.vpi.cmd[7] = VP_ZERO();
201         r300->hw.vpi.cmd[8] = 0;
202
203         R300_STATECHANGE(r300, zs);
204         if (flags & CLEARBUFFER_DEPTH) {
205                 r300->hw.zs.cmd[R300_ZS_CNTL_0] = 0x6; // test and write
206                 r300->hw.zs.cmd[R300_ZS_CNTL_1] = (R300_ZS_ALWAYS<<R300_RB3D_ZS1_DEPTH_FUNC_SHIFT);
207 /*
208                 R300_STATECHANGE(r300, zb);
209                 r300->hw.zb.cmd[R300_ZB_OFFSET] =
210                         1024*4*300 +
211                         r300->radeon.radeonScreen->frontOffset +
212                         r300->radeon.radeonScreen->fbLocation;
213                 r300->hw.zb.cmd[R300_ZB_PITCH] =
214                         r300->radeon.radeonScreen->depthPitch;
215 */
216         } else {
217                 r300->hw.zs.cmd[R300_ZS_CNTL_0] = 0; // disable
218                 r300->hw.zs.cmd[R300_ZS_CNTL_1] = 0;
219         }
220
221         /* Make sure we have enough space */
222         r300EnsureCmdBufSpace(r300, r300->hw.max_state_size + 9, __FUNCTION__);
223
224         r300EmitState(r300);
225
226         cmd = (drm_r300_cmd_header_t*)r300AllocCmdBuf(r300, 9, __FUNCTION__);
227         cmd[0].packet3.cmd_type = R300_CMD_PACKET3;
228         cmd[0].packet3.packet = R300_CMD_PACKET3_CLEAR;
229         cmd[1].u = r300PackFloat32(dPriv->w / 2.0);
230         cmd[2].u = r300PackFloat32(dPriv->h / 2.0);
231         cmd[3].u = r300PackFloat32(ctx->Depth.Clear);
232         cmd[4].u = r300PackFloat32(1.0);
233         cmd[5].u = r300PackFloat32(ctx->Color.ClearColor[0]);
234         cmd[6].u = r300PackFloat32(ctx->Color.ClearColor[1]);
235         cmd[7].u = r300PackFloat32(ctx->Color.ClearColor[2]);
236         cmd[8].u = r300PackFloat32(ctx->Color.ClearColor[3]);
237 }
238
239
240 /**
241  * Buffer clear
242  */
243 static void r300Clear(GLcontext * ctx, GLbitfield mask, GLboolean all,
244                       GLint cx, GLint cy, GLint cw, GLint ch)
245 {
246         r300ContextPtr r300 = R300_CONTEXT(ctx);
247         __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
248         int flags = 0;
249         int bits = 0;
250         int swapped;
251
252         if (RADEON_DEBUG & DEBUG_IOCTL)
253                 fprintf(stderr, "%s:  all=%d cx=%d cy=%d cw=%d ch=%d\n",
254                         __FUNCTION__, all, cx, cy, cw, ch);
255
256         {
257                 LOCK_HARDWARE(&r300->radeon);
258                 UNLOCK_HARDWARE(&r300->radeon);
259                 if (dPriv->numClipRects == 0)
260                         return;
261         }
262
263         if (mask & DD_FRONT_LEFT_BIT) {
264                 flags |= DD_FRONT_LEFT_BIT;
265                 mask &= ~DD_FRONT_LEFT_BIT;
266         }
267
268         if (mask & DD_BACK_LEFT_BIT) {
269                 flags |= DD_BACK_LEFT_BIT;
270                 mask &= ~DD_BACK_LEFT_BIT;
271         }
272
273         if (mask & DD_DEPTH_BIT) {
274                 bits |= CLEARBUFFER_DEPTH;
275                 mask &= ~DD_DEPTH_BIT;
276         }
277
278         if (mask) {
279                 if (RADEON_DEBUG & DEBUG_FALLBACKS)
280                         fprintf(stderr, "%s: swrast clear, mask: %x\n",
281                                 __FUNCTION__, mask);
282                 _swrast_Clear(ctx, mask, all, cx, cy, cw, ch);
283         }
284
285         swapped = r300->radeon.doPageFlip && (r300->radeon.sarea->pfCurrentPage == 1);
286
287         if (flags & DD_FRONT_LEFT_BIT) {
288                 r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, swapped);
289                 bits = 0;
290         }
291
292         if (flags & DD_BACK_LEFT_BIT) {
293                 r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, swapped ^ 1);
294                 bits = 0;
295         }
296
297         if (bits)
298                 r300ClearBuffer(r300, bits, 0);
299
300         /* Recalculate the hardware state. This could be done more efficiently,
301          * but do keep it like this for now.
302          */
303         r300ResetHwState(r300);
304         /* r300ClearBuffer has trampled all over the hardware state.. */
305         r300->hw.all_dirty=GL_TRUE;
306 }
307
308 void r300Flush(GLcontext * ctx)
309 {
310         r300ContextPtr r300 = R300_CONTEXT(ctx);
311
312         if (RADEON_DEBUG & DEBUG_IOCTL)
313                 fprintf(stderr, "%s\n", __FUNCTION__);
314
315         if (r300->cmdbuf.count_used > r300->cmdbuf.count_reemit)
316                 r300FlushCmdBuf(r300, __FUNCTION__);
317 }
318
319 void r300RefillCurrentDmaRegion(r300ContextPtr rmesa)
320 {
321         struct r200_dma_buffer *dmabuf;
322         int fd = rmesa->radeon.dri.fd;
323         int index = 0;
324         int size = 0;
325         drmDMAReq dma;
326         int ret;
327
328         if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
329                 fprintf(stderr, "%s\n", __FUNCTION__);
330
331         if (rmesa->dma.flush) {
332                 rmesa->dma.flush(rmesa);
333         }
334
335         if (rmesa->dma.current.buf)
336                 r300ReleaseDmaRegion(rmesa, &rmesa->dma.current, __FUNCTION__);
337
338         if (rmesa->dma.nr_released_bufs > 4)
339                 r300FlushCmdBuf(rmesa, __FUNCTION__);
340
341         dma.context = rmesa->radeon.dri.hwContext;
342         dma.send_count = 0;
343         dma.send_list = NULL;
344         dma.send_sizes = NULL;
345         dma.flags = 0;
346         dma.request_count = 1;
347         dma.request_size = RADEON_BUFFER_SIZE;
348         dma.request_list = &index;
349         dma.request_sizes = &size;
350         dma.granted_count = 0;
351
352         LOCK_HARDWARE(&rmesa->radeon);  /* no need to validate */
353
354         while (1) {
355                 ret = drmDMA(fd, &dma);
356                 if (ret == 0)
357                         break;
358
359                 if (rmesa->dma.nr_released_bufs) {
360                         r200FlushCmdBufLocked(rmesa, __FUNCTION__);
361                 }
362
363                 if (rmesa->radeon.do_usleeps) {
364                         UNLOCK_HARDWARE(&rmesa->radeon);
365                         DO_USLEEP(1);
366                         LOCK_HARDWARE(&rmesa->radeon);
367                 }
368         }
369
370         UNLOCK_HARDWARE(&rmesa->radeon);
371
372         if (RADEON_DEBUG & DEBUG_DMA)
373                 fprintf(stderr, "Allocated buffer %d\n", index);
374
375         dmabuf = CALLOC_STRUCT(r300_dma_buffer);
376         dmabuf->buf = &rmesa->radeon.radeonScreen->buffers->list[index];
377         dmabuf->refcount = 1;
378
379         rmesa->dma.current.buf = dmabuf;
380         rmesa->dma.current.address = dmabuf->buf->address;
381         rmesa->dma.current.end = dmabuf->buf->total;
382         rmesa->dma.current.start = 0;
383         rmesa->dma.current.ptr = 0;
384 }
385
386 void r300ReleaseDmaRegion(r300ContextPtr rmesa,
387                           struct r300_dma_region *region, const char *caller)
388 {
389         if (RADEON_DEBUG & DEBUG_IOCTL)
390                 fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
391
392         if (!region->buf)
393                 return;
394
395         if (rmesa->dma.flush)
396                 rmesa->dma.flush(rmesa);
397
398         if (--region->buf->refcount == 0) {
399                 drm_radeon_cmd_header_t *cmd;
400
401                 if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
402                         fprintf(stderr, "%s -- DISCARD BUF %d\n", __FUNCTION__,
403                                 region->buf->buf->idx);
404
405                 cmd =
406                     (drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa,
407                                                                 sizeof(*cmd),
408                                                                 __FUNCTION__);
409                 cmd->dma.cmd_type = RADEON_CMD_DMA_DISCARD;
410                 cmd->dma.buf_idx = region->buf->buf->idx;
411                 FREE(region->buf);
412                 rmesa->dma.nr_released_bufs++;
413         }
414
415         region->buf = 0;
416         region->start = 0;
417 }
418
419 /* Allocates a region from rmesa->dma.current.  If there isn't enough
420  * space in current, grab a new buffer (and discard what was left of current)
421  */
422 void r300AllocDmaRegion(r300ContextPtr rmesa,
423                         struct r300_dma_region *region,
424                         int bytes, int alignment)
425 {
426         if (RADEON_DEBUG & DEBUG_IOCTL)
427                 fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
428
429         if (rmesa->dma.flush)
430                 rmesa->dma.flush(rmesa);
431
432         if (region->buf)
433                 r300ReleaseDmaRegion(rmesa, region, __FUNCTION__);
434
435         alignment--;
436         rmesa->dma.current.start = rmesa->dma.current.ptr =
437             (rmesa->dma.current.ptr + alignment) & ~alignment;
438
439         if (rmesa->dma.current.ptr + bytes > rmesa->dma.current.end)
440                 r300RefillCurrentDmaRegion(rmesa);
441
442         region->start = rmesa->dma.current.start;
443         region->ptr = rmesa->dma.current.start;
444         region->end = rmesa->dma.current.start + bytes;
445         region->address = rmesa->dma.current.address;
446         region->buf = rmesa->dma.current.buf;
447         region->buf->refcount++;
448
449         rmesa->dma.current.ptr += bytes;        /* bug - if alignment > 7 */
450         rmesa->dma.current.start =
451             rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
452
453         assert(rmesa->dma.current.ptr <= rmesa->dma.current.end);
454 }
455
456 /* Called via glXGetMemoryOffsetMESA() */
457 GLuint r300GetMemoryOffsetMESA(__DRInativeDisplay * dpy, int scrn,
458                                const GLvoid * pointer)
459 {
460         GET_CURRENT_CONTEXT(ctx);
461         r300ContextPtr rmesa;
462         GLuint card_offset;
463
464         if (!ctx || !(rmesa = R300_CONTEXT(ctx))) {
465                 fprintf(stderr, "%s: no context\n", __FUNCTION__);
466                 return ~0;
467         }
468
469         if (!r300IsGartMemory(rmesa, pointer, 0))
470                 return ~0;
471
472         if (rmesa->radeon.dri.drmMinor < 6)
473                 return ~0;
474
475         card_offset = r300GartOffsetFromVirtual(rmesa, pointer);
476
477         return card_offset - rmesa->radeon.radeonScreen->gart_base;
478 }
479
480 GLboolean r300IsGartMemory(r300ContextPtr rmesa, const GLvoid * pointer,
481                            GLint size)
482 {
483         int offset =
484             (char *)pointer - (char *)rmesa->radeon.radeonScreen->gartTextures.map;
485         int valid = (size >= 0 && offset >= 0
486                      && offset + size < rmesa->radeon.radeonScreen->gartTextures.size);
487
488         if (RADEON_DEBUG & DEBUG_IOCTL)
489                 fprintf(stderr, "r300IsGartMemory( %p ) : %d\n", pointer,
490                         valid);
491
492         return valid;
493 }
494
495 GLuint r300GartOffsetFromVirtual(r300ContextPtr rmesa, const GLvoid * pointer)
496 {
497         int offset =
498             (char *)pointer - (char *)rmesa->radeon.radeonScreen->gartTextures.map;
499
500         fprintf(stderr, "offset=%08x\n", offset);
501
502         if (offset < 0 || offset > rmesa->radeon.radeonScreen->gartTextures.size)
503                 return ~0;
504         else
505                 return rmesa->radeon.radeonScreen->gart_texture_offset + offset;
506 }
507
508 void r300InitIoctlFuncs(struct dd_function_table *functions)
509 {
510         functions->Clear = r300Clear;
511         functions->Finish = radeonFinish;
512         functions->Flush = r300Flush;
513 }