(Stephane Marchesin, me) add hyperz support to radeon and r200 drivers. Only fast...
[mesa.git] / src / mesa / drivers / dri / savage / savageioctl.c
1 /*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <sys/mman.h>
29
30 #include "mtypes.h"
31 #include "macros.h"
32 #include "dd.h"
33 #include "context.h"
34 #include "swrast/swrast.h"
35
36 #include "mm.h"
37 #include "savagecontext.h"
38 #include "savageioctl.h"
39 #include "savage_bci.h"
40 #include "savagedma.h"
41
42 #include "drm.h"
43 #include <sys/ioctl.h>
44 #include <sys/timeb.h>
45
46 extern GLuint bcicount;
47 #define DEPTH_SCALE_16 ((1<<16)-1)
48 #define DEPTH_SCALE_24 ((1<<24)-1)
49
50 static void savage_BCI_clear(GLcontext *ctx, drm_savage_clear_t *pclear)
51 {
52 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
53 int nbox = imesa->sarea->nbox;
54 drm_clip_rect_t *pbox = imesa->sarea->boxes;
55 int i;
56
57
58 if (nbox > SAVAGE_NR_SAREA_CLIPRECTS)
59 nbox = SAVAGE_NR_SAREA_CLIPRECTS;
60
61 for (i = 0 ; i < nbox ; i++, pbox++) {
62 unsigned int x = pbox->x1;
63 unsigned int y = pbox->y1;
64 unsigned int width = pbox->x2 - x;
65 unsigned int height = pbox->y2 - y;
66 uint32_t *bciptr;
67
68 if (pbox->x1 > pbox->x2 ||
69 pbox->y1 > pbox->y2 ||
70 pbox->x2 > imesa->savageScreen->width ||
71 pbox->y2 > imesa->savageScreen->height)
72 continue;
73
74 if ( pclear->flags & SAVAGE_FRONT ) {
75 bciptr = savageDMAAlloc (imesa, 8);
76 WRITE_CMD((bciptr) , 0x4BCC8C00,uint32_t);
77 WRITE_CMD((bciptr) , imesa->savageScreen->frontOffset,uint32_t);
78 WRITE_CMD((bciptr) , imesa->savageScreen->frontBitmapDesc,uint32_t);
79 WRITE_CMD((bciptr) , pclear->clear_color,uint32_t);
80 WRITE_CMD((bciptr) , (y <<16) | x,uint32_t);
81 WRITE_CMD((bciptr) , (height << 16) | width,uint32_t);
82 savageDMACommit (imesa, bciptr);
83 }
84 if ( pclear->flags & SAVAGE_BACK ) {
85 bciptr = savageDMAAlloc (imesa, 8);
86 WRITE_CMD((bciptr) , 0x4BCC8C00,uint32_t);
87 WRITE_CMD((bciptr) , imesa->savageScreen->backOffset,uint32_t);
88 WRITE_CMD((bciptr) , imesa->savageScreen->backBitmapDesc,uint32_t);
89 WRITE_CMD((bciptr) , pclear->clear_color,uint32_t);
90 WRITE_CMD((bciptr) , (y <<16) | x,uint32_t);
91 WRITE_CMD((bciptr) , (height << 16) | width,uint32_t);
92 savageDMACommit (imesa, bciptr);
93 }
94
95 if ( pclear->flags & (SAVAGE_DEPTH |SAVAGE_STENCIL) ) {
96 uint32_t writeMask = 0x0;
97 if(imesa->hw_stencil)
98 {
99 if(pclear->flags & SAVAGE_STENCIL)
100 {
101
102 writeMask |= 0xFF000000;
103 }
104 if(pclear->flags & SAVAGE_DEPTH)
105 {
106 writeMask |= 0x00FFFFFF;
107 }
108 }
109 if(imesa->IsFullScreen && imesa->NotFirstFrame &&
110 imesa->savageScreen->chipset >= S3_SAVAGE4)
111 {
112 imesa->regs.s4.zBufCtrl.ni.autoZEnable = GL_TRUE;
113 imesa->regs.s4.zBufCtrl.ni.frameID =
114 ~imesa->regs.s4.zBufCtrl.ni.frameID;
115
116 imesa->dirty |= SAVAGE_UPLOAD_CTX;
117 }
118 else
119 {
120 if(imesa->IsFullScreen)
121 imesa->NotFirstFrame = GL_TRUE;
122
123 if(imesa->hw_stencil)
124 {
125 bciptr = savageDMAAlloc (imesa, 10);
126 if(writeMask != 0xFFFFFFFF)
127 {
128 WRITE_CMD((bciptr) , 0x960100D7,uint32_t);
129 WRITE_CMD((bciptr) , writeMask,uint32_t);
130 }
131 }
132 else
133 {
134 bciptr = savageDMAAlloc (imesa, 6);
135 }
136
137 WRITE_CMD((bciptr) , 0x4BCC8C00,uint32_t);
138 WRITE_CMD((bciptr) , imesa->savageScreen->depthOffset,uint32_t);
139 WRITE_CMD((bciptr) , imesa->savageScreen->depthBitmapDesc,uint32_t);
140 WRITE_CMD((bciptr) , pclear->clear_depth,uint32_t);
141 WRITE_CMD((bciptr) , (y <<16) | x,uint32_t);
142 WRITE_CMD((bciptr) , (height << 16) | width,uint32_t);
143 if(imesa->hw_stencil)
144 {
145 if(writeMask != 0xFFFFFFFF)
146 {
147 WRITE_CMD((bciptr) , 0x960100D7,uint32_t);
148 WRITE_CMD((bciptr) , 0xFFFFFFFF,uint32_t);
149 }
150 }
151 savageDMACommit (imesa, bciptr);
152 }
153 }
154 }
155 /* FK: Make sure that the clear stuff is emitted. Otherwise a
156 software fallback may get overwritten by a delayed clear. */
157 savageDMAFlush (imesa);
158 }
159
160 struct timeb a,b;
161
162 static void savage_BCI_swap(savageContextPtr imesa)
163 {
164 int nbox = imesa->sarea->nbox;
165 drm_clip_rect_t *pbox = imesa->sarea->boxes;
166 int i;
167 volatile uint32_t *bciptr;
168
169 if (nbox > SAVAGE_NR_SAREA_CLIPRECTS)
170 nbox = SAVAGE_NR_SAREA_CLIPRECTS;
171 savageDMAFlush (imesa);
172
173 if(imesa->IsFullScreen)
174 { /* full screen*/
175 unsigned int tmp0;
176 tmp0 = imesa->savageScreen->frontOffset;
177 imesa->savageScreen->frontOffset = imesa->savageScreen->backOffset;
178 imesa->savageScreen->backOffset = tmp0;
179
180 if(imesa->toggle == TARGET_BACK)
181 imesa->toggle = TARGET_FRONT;
182 else
183 imesa->toggle = TARGET_BACK;
184
185 imesa->drawMap = (char *)imesa->apertureBase[imesa->toggle];
186 imesa->readMap = (char *)imesa->apertureBase[imesa->toggle];
187
188 imesa->regs.s4.destCtrl.ni.offset = imesa->savageScreen->backOffset>>11;
189 imesa->dirty |= SAVAGE_UPLOAD_CTX;
190 bciptr = SAVAGE_GET_BCI_POINTER(imesa,3);
191 *(bciptr) = 0x960100B0;
192 *(bciptr) = (imesa->savageScreen->frontOffset);
193 *(bciptr) = 0xA0000000;
194 }
195
196 else
197 { /* Use bitblt copy from back to front buffer*/
198
199 for (i = 0 ; i < nbox; i++, pbox++)
200 {
201 unsigned int w = pbox->x2 - pbox->x1;
202 unsigned int h = pbox->y2 - pbox->y1;
203
204 if (pbox->x1 > pbox->x2 ||
205 pbox->y1 > pbox->y2 ||
206 pbox->x2 > imesa->savageScreen->width ||
207 pbox->y2 > imesa->savageScreen->height)
208 continue;
209
210 bciptr = SAVAGE_GET_BCI_POINTER(imesa,6);
211
212 *(bciptr) = 0x4BCC00C0;
213
214 *(bciptr) = imesa->savageScreen->backOffset;
215 *(bciptr) = imesa->savageScreen->backBitmapDesc;
216 *(bciptr) = (pbox->y1 <<16) | pbox->x1; /*x0, y0*/
217 *(bciptr) = (pbox->y1 <<16) | pbox->x1;
218 *(bciptr) = (h << 16) | w;
219 }
220
221 }
222 }
223
224
225 static void savageDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
226 GLint cx, GLint cy, GLint cw, GLint ch )
227 {
228 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
229 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
230 const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
231 drm_savage_clear_t clear;
232 int i;
233
234 clear.flags = 0;
235 clear.clear_color = imesa->ClearColor;
236
237 if(imesa->savageScreen->zpp == 2)
238 clear.clear_depth = (GLuint) (ctx->Depth.Clear * DEPTH_SCALE_16);
239 else
240 clear.clear_depth = (GLuint) (ctx->Depth.Clear * DEPTH_SCALE_24);
241
242 FLUSH_BATCH( imesa );
243
244 if ((mask & DD_FRONT_LEFT_BIT) && ((colorMask&0xffffffUL)==0xffffffUL) ){
245 clear.flags |= SAVAGE_FRONT;
246 mask &= ~DD_FRONT_LEFT_BIT;
247 }
248
249 if ((mask & DD_BACK_LEFT_BIT) && ((colorMask&0xffffffUL)==0xffffffUL) ) {
250 clear.flags |= SAVAGE_BACK;
251 mask &= ~DD_BACK_LEFT_BIT;
252 }
253
254 if ((mask & DD_DEPTH_BIT) && ctx->Depth.Mask) {
255 clear.flags |= SAVAGE_DEPTH;
256 mask &= ~DD_DEPTH_BIT;
257 }
258
259 if((mask & DD_STENCIL_BIT) && imesa->hw_stencil)
260 {
261 clear.flags |= SAVAGE_STENCIL;
262 mask &= ~DD_STENCIL_BIT;
263 }
264
265 if (clear.flags) {
266 LOCK_HARDWARE( imesa );
267
268 /* flip top to bottom */
269 cy = dPriv->h-cy-ch;
270 cx += imesa->drawX;
271 cy += imesa->drawY;
272
273 for (i = 0 ; i < imesa->numClipRects ; ) {
274 int nr = MIN2(i + SAVAGE_NR_SAREA_CLIPRECTS, imesa->numClipRects);
275 drm_clip_rect_t *box = imesa->pClipRects;
276 drm_clip_rect_t *b = imesa->sarea->boxes;
277 int n = 0;
278
279 if (!all) {
280 for ( ; i < nr ; i++) {
281 GLint x = box[i].x1;
282 GLint y = box[i].y1;
283 GLint w = box[i].x2 - x;
284 GLint h = box[i].y2 - y;
285
286 if (x < cx) w -= cx - x, x = cx;
287 if (y < cy) h -= cy - y, y = cy;
288 if (x + w > cx + cw) w = cx + cw - x;
289 if (y + h > cy + ch) h = cy + ch - y;
290 if (w <= 0) continue;
291 if (h <= 0) continue;
292
293 b->x1 = x;
294 b->y1 = y;
295 b->x2 = x + w;
296 b->y2 = y + h;
297 b++;
298 n++;
299 }
300 } else {
301 for ( ; i < nr ; i++) {
302 *b++ = *(drm_clip_rect_t *)&box[i];
303 n++;
304 }
305 }
306
307 imesa->sarea->nbox = n;
308
309 savage_BCI_clear(ctx,&clear);
310 }
311
312 UNLOCK_HARDWARE( imesa );
313 imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS|SAVAGE_UPLOAD_CTX;
314 }
315
316 if (mask)
317 _swrast_Clear( ctx, mask, all, cx, cy, cw, ch );
318 }
319
320
321
322
323 /*
324 * Copy the back buffer to the front buffer.
325 */
326 void savageSwapBuffers( __DRIdrawablePrivate *dPriv )
327 {
328 savageContextPtr imesa;
329 drm_clip_rect_t *pbox;
330 int nbox;
331 int i;
332
333 GLboolean pending;
334
335 assert(dPriv);
336 assert(dPriv->driContextPriv);
337 assert(dPriv->driContextPriv->driverPrivate);
338
339 imesa = (savageContextPtr) dPriv->driContextPriv->driverPrivate;
340 if (imesa->IsDouble)
341 _mesa_notifySwapBuffers( imesa->glCtx );
342
343 FLUSH_BATCH(imesa);
344
345 LOCK_HARDWARE( imesa );
346 WAIT_IDLE_EMPTY;
347 PAGE_PENDING(pending);
348
349 if(!pending)
350 {
351 pbox = dPriv->pClipRects;
352 nbox = dPriv->numClipRects;
353
354 for (i = 0 ; i < nbox ; )
355 {
356 int nr = MIN2(i + SAVAGE_NR_SAREA_CLIPRECTS, dPriv->numClipRects);
357 drm_clip_rect_t *b = (drm_clip_rect_t *)imesa->sarea->boxes;
358
359 imesa->sarea->nbox = nr - i;
360
361 for ( ; i < nr ; i++)
362 *b++ = pbox[i];
363 savage_BCI_swap(imesa) ;
364 }
365 }
366 UNLOCK_HARDWARE( imesa );
367
368
369 }
370
371 /* This waits for *everybody* to finish rendering -- overkill.
372 */
373 void savageDmaFinish( savageContextPtr imesa )
374 {
375 savageDMAFlush(imesa);
376 WAIT_IDLE_EMPTY;
377 }
378
379
380 void savageRegetLockQuiescent( savageContextPtr imesa )
381 {
382
383
384 }
385
386 void savageWaitAgeLocked( savageContextPtr imesa, int age )
387 {
388 }
389
390
391 void savageWaitAge( savageContextPtr imesa, int age )
392 {
393 }
394
395
396
397 void savageFlushVerticesLocked( savageContextPtr imesa )
398 {
399 drmBufPtr buffer = imesa->vertex_dma_buffer;
400
401 if (!buffer)
402 return;
403
404 imesa->vertex_dma_buffer = NULL;
405
406 /* Lot's of stuff to do here. For now there is a fake DMA implementation
407 * in savagedma.c that emits drawing commands. Cliprects are not handled
408 * yet. */
409 if (buffer->used) {
410 /* State must be updated "per primitive" because hardware
411 * culling must be disabled for unfilled primitives, points
412 * and lines. */
413 savageEmitHwStateLocked (imesa);
414 savageFakeVertices (imesa, buffer);
415 }
416 }
417
418
419 void savageFlushVertices( savageContextPtr imesa )
420 {
421 LOCK_HARDWARE(imesa);
422 savageFlushVerticesLocked (imesa);
423 UNLOCK_HARDWARE(imesa);
424 }
425
426
427 int savage_check_copy(int fd)
428 {
429 return 0;
430 }
431
432 static void savageDDFlush( GLcontext *ctx )
433 {
434 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
435 LOCK_HARDWARE(imesa);
436 savageFlushVerticesLocked (imesa);
437 savageDMAFlush (imesa);
438 UNLOCK_HARDWARE(imesa);
439 }
440
441 static void savageDDFinish( GLcontext *ctx )
442 {
443 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
444 LOCK_HARDWARE(imesa);
445 savageFlushVerticesLocked (imesa);
446 savageDmaFinish (imesa);
447 UNLOCK_HARDWARE(imesa);
448 }
449
450 #define ALT_STATUS_WORD0 (* (volatile GLuint *)(imesa->MMIO_BASE+0x48c60))
451 #define STATUS_WORD0 (* (volatile GLuint *)(imesa->MMIO_BASE+0x48c00))
452 #define MAXFIFO_S4 0x7F00
453 #define MAXFIFO_S3D 0x7F00
454
455 static GLboolean savagePagePending_s4( savageContextPtr imesa ) {
456 return (ALT_STATUS_WORD0 & 0x08000000) ? GL_TRUE : GL_FALSE;
457 }
458 static GLboolean savagePagePending_s3d( savageContextPtr imesa ) {
459 return GL_FALSE;
460 }
461 static void savageWaitForFIFO_s4( savageContextPtr imesa, unsigned count ) {
462 int loop = 0;
463 int slots = MAXFIFO_S4-count;
464 while((ALT_STATUS_WORD0 & 0x001fffff) > slots && loop++ < MAXLOOP);
465 }
466 static void savageWaitForFIFO_s3d( savageContextPtr imesa, unsigned count ) {
467 int loop = 0;
468 int slots = MAXFIFO_S3D-count;
469 while((STATUS_WORD0 & 0x0001ffff) > slots && loop++ < MAXLOOP);
470 }
471 static void savageWaitIdleEmpty_s4( savageContextPtr imesa ) {
472 int loop = 0;
473 while((ALT_STATUS_WORD0 & 0x00ffffff) != 0x00E00000L && loop++ < MAXLOOP);
474 }
475 static void savageWaitIdleEmpty_s3d( savageContextPtr imesa ) {
476 int loop = 0;
477 while((STATUS_WORD0 & 0x000fffff) != 0x000E0000L && loop++ < MAXLOOP);
478 }
479
480 GLboolean (*savagePagePending)( savageContextPtr imesa ) = NULL;
481 void (*savageWaitForFIFO)( savageContextPtr imesa, unsigned count ) = NULL;
482 void (*savageWaitIdleEmpty)( savageContextPtr imesa ) = NULL;
483
484
485 void savageDDInitIoctlFuncs( GLcontext *ctx )
486 {
487 ctx->Driver.Clear = savageDDClear;
488 ctx->Driver.Flush = savageDDFlush;
489 ctx->Driver.Finish = savageDDFinish;
490 if (SAVAGE_CONTEXT( ctx )->savageScreen->chipset >= S3_SAVAGE4) {
491 savagePagePending = savagePagePending_s4;
492 savageWaitForFIFO = savageWaitForFIFO_s4;
493 savageWaitIdleEmpty = savageWaitIdleEmpty_s4;
494 } else {
495 savagePagePending = savagePagePending_s3d;
496 savageWaitForFIFO = savageWaitForFIFO_s3d;
497 savageWaitIdleEmpty = savageWaitIdleEmpty_s3d;
498 }
499 }
500
501 #if SAVAGE_CMD_DMA
502 /* Alloc a continuous memory */
503 /* return: 0 error when kernel alloc pages(can try a half memory size)
504 >0 sucess
505 <0 Other error*/
506 int savageAllocDMABuffer(savageContextPtr imesa, drm_savage_alloc_cont_mem_t *req)
507 {
508 int ret;
509 if (req ==NULL)
510 return 0;
511
512 if ((ret=ioctl(imesa->driFd, DRM_IOCTL_SAVAGE_ALLOC_CONTINUOUS_MEM, req)) <=0)
513 return ret;
514
515 return 1;
516
517 }
518
519 /* get the physics address*/
520 GLuint savageGetPhyAddress(savageContextPtr imesa,void * pointer)
521 {
522
523 drm_savage_get_physcis_address_t req;
524 int ret;
525
526 req.v_address = (GLuint )pointer;
527 ret = ioctl(imesa->driFd, DRM_IOCTL_SAVAGE_GET_PHYSICS_ADDRESS,&req);
528
529 return req.p_address;
530 }
531
532 /* free the buffer got by savageAllocDMABuffe*/
533 int savageFreeDMABuffer(savageContextPtr imesa, drm_savage_alloc_cont_mem_t *req)
534 {
535 GLuint ret;
536 if (req ==NULL)
537 return 0;
538
539 if ((ret=ioctl(imesa->driFd, DRM_IOCTL_SAVAGE_FREE_CONTINUOUS_MEM, req)) <=0)
540 return ret;
541 return 1;
542
543 }
544 #endif