fix some signed vs unsigned warnings
[mesa.git] / src / mesa / drivers / dri / i810 / i810ioctl.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/i810/i810ioctl.c,v 1.7 2002/10/30 12:51:33 alanh Exp $ */
2
3 #include <unistd.h> /* for usleep() */
4
5 #include "glheader.h"
6 #include "mtypes.h"
7 #include "macros.h"
8 #include "dd.h"
9 #include "swrast/swrast.h"
10 #include "mm.h"
11
12 #include "i810screen.h"
13 #include "i810_dri.h"
14
15 #include "i810context.h"
16 #include "i810ioctl.h"
17 #include "i810state.h"
18
19 static drmBufPtr i810_get_buffer_ioctl( i810ContextPtr imesa )
20 {
21 drmI810DMA dma;
22 drmBufPtr buf;
23 int retcode, i = 0;
24
25 while (1) {
26 retcode = drmCommandWriteRead(imesa->driFd, DRM_I810_GETBUF,
27 &dma, sizeof(drmI810DMA));
28
29 if (dma.granted == 1 && retcode == 0)
30 break;
31
32 if (++i > 1000) {
33 drmCommandNone(imesa->driFd, DRM_I810_FLUSH);
34 i = 0;
35 }
36 }
37
38 buf = &(imesa->i810Screen->bufs->list[dma.request_idx]);
39 buf->idx = dma.request_idx;
40 buf->used = 0;
41 buf->total = dma.request_size;
42 buf->address = (drmAddress)dma.virtual;
43
44 return buf;
45 }
46
47
48
49 #define DEPTH_SCALE ((1<<16)-1)
50
51 static void i810Clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
52 GLint cx, GLint cy, GLint cw, GLint ch )
53 {
54 i810ContextPtr imesa = I810_CONTEXT( ctx );
55 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
56 const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
57 drmI810Clear clear;
58 unsigned int i;
59
60 clear.flags = 0;
61 clear.clear_color = imesa->ClearColor;
62 clear.clear_depth = (GLuint) (ctx->Depth.Clear * DEPTH_SCALE);
63
64 I810_FIREVERTICES( imesa );
65
66 if ((mask & DD_FRONT_LEFT_BIT) && colorMask == ~0U) {
67 clear.flags |= I810_FRONT;
68 mask &= ~DD_FRONT_LEFT_BIT;
69 }
70
71 if ((mask & DD_BACK_LEFT_BIT) && colorMask == ~0U) {
72 clear.flags |= I810_BACK;
73 mask &= ~DD_BACK_LEFT_BIT;
74 }
75
76 if (mask & DD_DEPTH_BIT) {
77 if (ctx->Depth.Mask)
78 clear.flags |= I810_DEPTH;
79 mask &= ~DD_DEPTH_BIT;
80 }
81
82 if (clear.flags) {
83 LOCK_HARDWARE( imesa );
84
85 /* flip top to bottom */
86 cy = dPriv->h-cy-ch;
87 cx += imesa->drawX;
88 cy += imesa->drawY;
89
90 for (i = 0 ; i < imesa->numClipRects ; )
91 {
92 unsigned int nr = MIN2(i + I810_NR_SAREA_CLIPRECTS, imesa->numClipRects);
93 drm_clip_rect_t *box = imesa->pClipRects;
94 drm_clip_rect_t *b = (drm_clip_rect_t *)imesa->sarea->boxes;
95 int n = 0;
96
97 if (!all) {
98 for ( ; i < nr ; i++) {
99 GLint x = box[i].x1;
100 GLint y = box[i].y1;
101 GLint w = box[i].x2 - x;
102 GLint h = box[i].y2 - y;
103
104 if (x < cx) w -= cx - x, x = cx;
105 if (y < cy) h -= cy - y, y = cy;
106 if (x + w > cx + cw) w = cx + cw - x;
107 if (y + h > cy + ch) h = cy + ch - y;
108 if (w <= 0) continue;
109 if (h <= 0) continue;
110
111 b->x1 = x;
112 b->y1 = y;
113 b->x2 = x + w;
114 b->y2 = y + h;
115 b++;
116 n++;
117 }
118 } else {
119 for ( ; i < nr ; i++) {
120 *b++ = box[i];
121 n++;
122 }
123 }
124
125 imesa->sarea->nbox = n;
126 drmCommandWrite(imesa->driFd, DRM_I810_CLEAR,
127 &clear, sizeof(drmI810Clear));
128 }
129
130 UNLOCK_HARDWARE( imesa );
131 imesa->upload_cliprects = GL_TRUE;
132 }
133
134 if (mask)
135 _swrast_Clear( ctx, mask, all, cx, cy, cw, ch );
136 }
137
138
139
140
141 /*
142 * Copy the back buffer to the front buffer.
143 */
144 void i810CopyBuffer( const __DRIdrawablePrivate *dPriv )
145 {
146 i810ContextPtr imesa;
147 drm_clip_rect_t *pbox;
148 int nbox, i, tmp;
149
150 assert(dPriv);
151 assert(dPriv->driContextPriv);
152 assert(dPriv->driContextPriv->driverPrivate);
153
154 imesa = (i810ContextPtr) dPriv->driContextPriv->driverPrivate;
155
156 I810_FIREVERTICES( imesa );
157 LOCK_HARDWARE( imesa );
158
159 pbox = (drm_clip_rect_t *)dPriv->pClipRects;
160 nbox = dPriv->numClipRects;
161
162 for (i = 0 ; i < nbox ; )
163 {
164 int nr = MIN2(i + I810_NR_SAREA_CLIPRECTS, dPriv->numClipRects);
165 drm_clip_rect_t *b = (drm_clip_rect_t *)imesa->sarea->boxes;
166
167 imesa->sarea->nbox = nr - i;
168
169 for ( ; i < nr ; i++)
170 *b++ = pbox[i];
171
172 drmCommandNone(imesa->driFd, DRM_I810_SWAP);
173 }
174
175 tmp = GET_ENQUEUE_AGE(imesa);
176 UNLOCK_HARDWARE( imesa );
177
178 /* multiarb will suck the life out of the server without this throttle:
179 */
180 if (GET_DISPATCH_AGE(imesa) < imesa->lastSwap) {
181 i810WaitAge(imesa, imesa->lastSwap);
182 }
183
184 imesa->lastSwap = tmp;
185 imesa->upload_cliprects = GL_TRUE;
186 }
187
188
189 /*
190 * XXX implement when full-screen extension is done.
191 */
192 void i810PageFlip( const __DRIdrawablePrivate *dPriv )
193 {
194 i810ContextPtr imesa;
195 int tmp, ret;
196
197 assert(dPriv);
198 assert(dPriv->driContextPriv);
199 assert(dPriv->driContextPriv->driverPrivate);
200
201 imesa = (i810ContextPtr) dPriv->driContextPriv->driverPrivate;
202
203 I810_FIREVERTICES( imesa );
204 LOCK_HARDWARE( imesa );
205
206 if (dPriv->pClipRects) {
207 memcpy(&(imesa->sarea->boxes[0]), &(dPriv->pClipRects[0]),
208 sizeof(drm_clip_rect_t));
209 imesa->sarea->nbox = 1;
210 }
211 ret = drmCommandNone(imesa->driFd, DRM_I810_FLIP);
212 if (ret) {
213 fprintf(stderr, "%s: %d\n", __FUNCTION__, ret);
214 UNLOCK_HARDWARE( imesa );
215 exit(1);
216 }
217
218 tmp = GET_ENQUEUE_AGE(imesa);
219 UNLOCK_HARDWARE( imesa );
220
221 /* multiarb will suck the life out of the server without this throttle:
222 */
223 if (GET_DISPATCH_AGE(imesa) < imesa->lastSwap) {
224 i810WaitAge(imesa, imesa->lastSwap);
225 }
226
227 /* i810SetDrawBuffer( imesa->glCtx, imesa->glCtx->Color.DriverDrawBuffer );*/
228 i810DrawBuffer( imesa->glCtx, imesa->glCtx->Color.DrawBuffer[0] );
229 imesa->upload_cliprects = GL_TRUE;
230 imesa->lastSwap = tmp;
231 return;
232 }
233
234
235 /* This waits for *everybody* to finish rendering -- overkill.
236 */
237 void i810DmaFinish( i810ContextPtr imesa )
238 {
239 I810_FIREVERTICES( imesa );
240
241 LOCK_HARDWARE( imesa );
242 i810RegetLockQuiescent( imesa );
243 UNLOCK_HARDWARE( imesa );
244 }
245
246
247 void i810RegetLockQuiescent( i810ContextPtr imesa )
248 {
249 drmUnlock(imesa->driFd, imesa->hHWContext);
250 i810GetLock( imesa, DRM_LOCK_QUIESCENT );
251 }
252
253 void i810WaitAgeLocked( i810ContextPtr imesa, int age )
254 {
255 int i = 0, j;
256
257 while (++i < 5000) {
258 drmCommandNone(imesa->driFd, DRM_I810_GETAGE);
259 if (GET_DISPATCH_AGE(imesa) >= age)
260 return;
261 for (j = 0 ; j < 1000 ; j++)
262 ;
263 }
264
265 drmCommandNone(imesa->driFd, DRM_I810_FLUSH);
266 }
267
268
269 void i810WaitAge( i810ContextPtr imesa, int age )
270 {
271 int i = 0, j;
272
273 while (++i < 5000) {
274 drmCommandNone(imesa->driFd, DRM_I810_GETAGE);
275 if (GET_DISPATCH_AGE(imesa) >= age)
276 return;
277 for (j = 0 ; j < 1000 ; j++)
278 ;
279 }
280
281 i = 0;
282 while (++i < 1000) {
283 drmCommandNone(imesa->driFd, DRM_I810_GETAGE);
284 if (GET_DISPATCH_AGE(imesa) >= age)
285 return;
286 usleep(1000);
287 }
288
289 LOCK_HARDWARE(imesa);
290 drmCommandNone(imesa->driFd, DRM_I810_FLUSH);
291 UNLOCK_HARDWARE(imesa);
292 }
293
294
295
296
297 static int intersect_rect( drm_clip_rect_t *out,
298 drm_clip_rect_t *a,
299 drm_clip_rect_t *b )
300 {
301 *out = *a;
302 if (b->x1 > out->x1) out->x1 = b->x1;
303 if (b->x2 < out->x2) out->x2 = b->x2;
304 if (out->x1 >= out->x2) return 0;
305
306 if (b->y1 > out->y1) out->y1 = b->y1;
307 if (b->y2 < out->y2) out->y2 = b->y2;
308 if (out->y1 >= out->y2) return 0;
309 return 1;
310 }
311
312
313 static void emit_state( i810ContextPtr imesa )
314 {
315 GLuint dirty = imesa->dirty;
316 I810SAREAPtr sarea = imesa->sarea;
317
318 if (dirty & I810_UPLOAD_BUFFERS) {
319 memcpy( sarea->BufferState, imesa->BufferSetup,
320 sizeof(imesa->BufferSetup) );
321 }
322
323 if (dirty & I810_UPLOAD_CTX) {
324 memcpy( sarea->ContextState, imesa->Setup,
325 sizeof(imesa->Setup) );
326 }
327
328 if (dirty & I810_UPLOAD_TEX0) {
329 memcpy(sarea->TexState[0],
330 imesa->CurrentTexObj[0]->Setup,
331 sizeof(imesa->CurrentTexObj[0]->Setup));
332 }
333
334 if (dirty & I810_UPLOAD_TEX1) {
335 GLuint *setup = sarea->TexState[1];
336
337 memcpy( setup,
338 imesa->CurrentTexObj[1]->Setup,
339 sizeof(imesa->CurrentTexObj[1]->Setup));
340
341 /* Need this for the case where both units are bound to the same
342 * texobj.
343 */
344 setup[I810_TEXREG_MI1] ^= (MI1_MAP_0 ^ MI1_MAP_1);
345 setup[I810_TEXREG_MLC] ^= (MLC_MAP_0 ^ MLC_MAP_1);
346 setup[I810_TEXREG_MLL] ^= (MLL_MAP_0 ^ MLL_MAP_1);
347 setup[I810_TEXREG_MCS] ^= (MCS_COORD_0 ^ MCS_COORD_1);
348 setup[I810_TEXREG_MF] ^= (MF_MAP_0 ^ MF_MAP_1);
349 }
350
351 sarea->dirty = dirty;
352 imesa->dirty = 0;
353 }
354
355
356 static void age_imesa( i810ContextPtr imesa, int age )
357 {
358 if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->base.timestamp = age;
359 if (imesa->CurrentTexObj[1]) imesa->CurrentTexObj[1]->base.timestamp = age;
360 }
361
362
363 void i810FlushPrimsLocked( i810ContextPtr imesa )
364 {
365 drm_clip_rect_t *pbox = imesa->pClipRects;
366 int nbox = imesa->numClipRects;
367 drmBufPtr buffer = imesa->vertex_buffer;
368 I810SAREAPtr sarea = imesa->sarea;
369 drmI810Vertex vertex;
370 int i;
371
372 if (I810_DEBUG & DEBUG_STATE)
373 i810PrintDirty( __FUNCTION__, imesa->dirty );
374
375 if (imesa->dirty)
376 emit_state( imesa );
377
378 vertex.idx = buffer->idx;
379 vertex.used = imesa->vertex_low;
380 vertex.discard = 0;
381 sarea->vertex_prim = imesa->hw_primitive;
382
383 if (!nbox) {
384 vertex.used = 0;
385 }
386 else if (nbox > I810_NR_SAREA_CLIPRECTS) {
387 imesa->upload_cliprects = GL_TRUE;
388 }
389
390 if (!nbox || !imesa->upload_cliprects)
391 {
392 if (nbox == 1)
393 sarea->nbox = 0;
394 else
395 sarea->nbox = nbox;
396
397 vertex.discard = 1;
398 drmCommandWrite(imesa->driFd, DRM_I810_VERTEX,
399 &vertex, sizeof(drmI810Vertex));
400 age_imesa(imesa, sarea->last_enqueue);
401 }
402 else
403 {
404 for (i = 0 ; i < nbox ; )
405 {
406 int nr = MIN2(i + I810_NR_SAREA_CLIPRECTS, nbox);
407 drm_clip_rect_t *b = (drm_clip_rect_t *)sarea->boxes;
408
409 if (imesa->scissor) {
410 sarea->nbox = 0;
411
412 for ( ; i < nr ; i++) {
413 b->x1 = pbox[i].x1 - imesa->drawX;
414 b->y1 = pbox[i].y1 - imesa->drawY;
415 b->x2 = pbox[i].x2 - imesa->drawX;
416 b->y2 = pbox[i].y2 - imesa->drawY;
417
418 if (intersect_rect(b, b, &imesa->scissor_rect)) {
419 sarea->nbox++;
420 b++;
421 }
422 }
423
424 /* Culled?
425 */
426 if (!sarea->nbox) {
427 if (nr < nbox) continue;
428 vertex.used = 0;
429 }
430 } else {
431 sarea->nbox = nr - i;
432 for ( ; i < nr ; i++, b++) {
433 b->x1 = pbox[i].x1 - imesa->drawX;
434 b->y1 = pbox[i].y1 - imesa->drawY;
435 b->x2 = pbox[i].x2 - imesa->drawX;
436 b->y2 = pbox[i].y2 - imesa->drawY;
437 }
438 }
439
440 /* Finished with the buffer?
441 */
442 if (nr == nbox)
443 vertex.discard = 1;
444
445 drmCommandWrite(imesa->driFd, DRM_I810_VERTEX,
446 &vertex, sizeof(drmI810Vertex));
447 age_imesa(imesa, imesa->sarea->last_enqueue);
448 }
449 }
450
451 /* Reset imesa vars:
452 */
453 imesa->vertex_buffer = 0;
454 imesa->vertex_addr = 0;
455 imesa->vertex_low = 0;
456 imesa->vertex_high = 0;
457 imesa->vertex_last_prim = 0;
458 imesa->dirty = 0;
459 imesa->upload_cliprects = GL_FALSE;
460 }
461
462 void i810FlushPrimsGetBuffer( i810ContextPtr imesa )
463 {
464 LOCK_HARDWARE(imesa);
465
466 if (imesa->vertex_buffer)
467 i810FlushPrimsLocked( imesa );
468
469 imesa->vertex_buffer = i810_get_buffer_ioctl( imesa );
470 imesa->vertex_high = imesa->vertex_buffer->total;
471 imesa->vertex_addr = (char *)imesa->vertex_buffer->address;
472 imesa->vertex_low = 4; /* leave room for instruction header */
473 imesa->vertex_last_prim = imesa->vertex_low;
474 UNLOCK_HARDWARE(imesa);
475 }
476
477
478 void i810FlushPrims( i810ContextPtr imesa )
479 {
480 if (imesa->vertex_buffer) {
481 LOCK_HARDWARE( imesa );
482 i810FlushPrimsLocked( imesa );
483 UNLOCK_HARDWARE( imesa );
484 }
485 }
486
487
488
489 int i810_check_copy(int fd)
490 {
491 return(drmCommandNone(fd, DRM_I810_DOCOPY));
492 }
493
494 static void i810Flush( GLcontext *ctx )
495 {
496 i810ContextPtr imesa = I810_CONTEXT( ctx );
497 I810_FIREVERTICES( imesa );
498 }
499
500 static void i810Finish( GLcontext *ctx )
501 {
502 i810ContextPtr imesa = I810_CONTEXT( ctx );
503 i810DmaFinish( imesa );
504 }
505
506 void i810InitIoctlFuncs( struct dd_function_table *functions )
507 {
508 functions->Flush = i810Flush;
509 functions->Clear = i810Clear;
510 functions->Finish = i810Finish;
511 }