Before calling _mesa_create_context(), initialize a dd_function_table struct
[mesa.git] / src / mesa / drivers / dri / i830 / i830_ioctl.c
1
2 /**************************************************************************
3
4 Copyright 2001 VA Linux Systems Inc., Fremont, California.
5
6 All Rights Reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the "Software"),
10 to deal in the Software without restriction, including without limitation
11 on the rights to use, copy, modify, merge, publish, distribute, sub
12 license, and/or sell copies of the Software, and to permit persons to whom
13 the Software is furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice (including the next
16 paragraph) shall be included in all copies or substantial portions of the
17 Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27 **************************************************************************/
28
29 /* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_ioctl.c,v 1.5 2002/12/10 01:26:53 dawes Exp $ */
30
31 /*
32 * Author:
33 * Jeff Hartmann <jhartmann@2d3d.com>
34 * Graeme Fisher <graeme@2d3d.co.za>
35 * Abraham vd Merwe <abraham@2d3d.co.za>
36 *
37 * Heavily based on the I810 driver, which was written by:
38 * Keith Whitwell <keith@tungstengraphics.com>
39 */
40
41 #include <stdio.h>
42 #include <unistd.h>
43 #include <errno.h>
44
45 #include "glheader.h"
46 #include "mtypes.h"
47 #include "macros.h"
48 #include "dd.h"
49 #include "swrast/swrast.h"
50
51 #include "mm.h"
52
53 #include "i830_screen.h"
54 #include "i830_dri.h"
55
56 #include "i830_context.h"
57 #include "i830_ioctl.h"
58 #include "i830_state.h"
59 #include "i830_debug.h"
60
61 #include "drm.h"
62
63 static drmBufPtr i830_get_buffer_ioctl( i830ContextPtr imesa )
64 {
65 drmI830DMA dma;
66 drmBufPtr buf;
67 int retcode,i = 0;
68 while (1) {
69 retcode = drmCommandWriteRead(imesa->driFd,
70 DRM_I830_GETBUF,
71 &dma,
72 sizeof(drmI830DMA));
73 if (dma.granted == 1 && retcode == 0)
74 break;
75
76 if (++i > 1000) {
77 imesa->sarea->perf_boxes |= I830_BOX_WAIT;
78 retcode = drmCommandNone(imesa->driFd, DRM_I830_FLUSH);
79 i = 0;
80 }
81 }
82
83 buf = &(imesa->i830Screen->bufs->list[dma.request_idx]);
84 buf->idx = dma.request_idx;
85 buf->used = 0;
86 buf->total = dma.request_size;
87 buf->address = (drmAddress)dma.virtual;
88
89 return buf;
90 }
91
92 static void i830ClearDrawQuad(i830ContextPtr imesa, float left,
93 float right,
94 float bottom, float top, GLubyte red,
95 GLubyte green, GLubyte blue, GLubyte alpha)
96 {
97 GLuint *vb = i830AllocDmaLowLocked( imesa, 128 );
98 i830Vertex tmp;
99 int i;
100
101 /* PRIM3D_TRIFAN */
102
103 /* initial vertex, left bottom */
104 tmp.v.x = left;
105 tmp.v.y = bottom;
106 tmp.v.z = 1.0;
107 tmp.v.w = 1.0;
108 tmp.v.color.red = red;
109 tmp.v.color.green = green;
110 tmp.v.color.blue = blue;
111 tmp.v.color.alpha = alpha;
112 tmp.v.specular.red = 0;
113 tmp.v.specular.green = 0;
114 tmp.v.specular.blue = 0;
115 tmp.v.specular.alpha = 0;
116 tmp.v.u0 = 0.0f;
117 tmp.v.v0 = 0.0f;
118 for (i = 0 ; i < 8 ; i++)
119 vb[i] = tmp.ui[i];
120
121 /* right bottom */
122 vb += 8;
123 tmp.v.x = right;
124 for (i = 0 ; i < 8 ; i++)
125 vb[i] = tmp.ui[i];
126
127 /* right top */
128 vb += 8;
129 tmp.v.y = top;
130 for (i = 0 ; i < 8 ; i++)
131 vb[i] = tmp.ui[i];
132
133 /* left top */
134 vb += 8;
135 tmp.v.x = left;
136 for (i = 0 ; i < 8 ; i++)
137 vb[i] = tmp.ui[i];
138 }
139
140 static void i830ClearWithTris(GLcontext *ctx, GLbitfield mask,
141 GLboolean all,
142 GLint cx, GLint cy, GLint cw, GLint ch)
143 {
144 i830ContextPtr imesa = I830_CONTEXT( ctx );
145 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
146 i830ScreenPrivate *i830Screen = imesa->i830Screen;
147 I830SAREAPtr sarea = imesa->sarea;
148 GLuint old_vertex_prim;
149 GLuint old_dirty;
150 int x0, y0, x1, y1;
151
152 if (I830_DEBUG & DEBUG_IOCTL)
153 fprintf(stderr, "Clearing with triangles\n");
154
155 old_dirty = imesa->dirty & ~I830_UPLOAD_CLIPRECTS;
156 /* Discard all the dirty flags except the cliprect one, reset later */
157 imesa->dirty &= I830_UPLOAD_CLIPRECTS;
158
159 if(!all) {
160 x0 = cx;
161 y0 = cy;
162 x1 = x0 + cw;
163 y1 = y0 + ch;
164 } else {
165 x0 = 0;
166 y0 = 0;
167 x1 = x0 + dPriv->w;
168 y1 = y0 + dPriv->h;
169 }
170
171 /* Clip to Screen */
172 if (x0 < 0) x0 = 0;
173 if (y0 < 0) y0 = 0;
174 if (x1 > i830Screen->width-1) x1 = i830Screen->width-1;
175 if (y1 > i830Screen->height-1) y1 = i830Screen->height-1;
176
177 LOCK_HARDWARE(imesa);
178 memcpy(sarea->ContextState,
179 imesa->Init_Setup,
180 sizeof(imesa->Setup) );
181 memcpy(sarea->BufferState,
182 imesa->BufferSetup,
183 sizeof(imesa->BufferSetup) );
184 sarea->StippleState[I830_STPREG_ST1] = 0;
185
186 old_vertex_prim = imesa->hw_primitive;
187 imesa->hw_primitive = PRIM3D_TRIFAN;
188
189 if(mask & DD_FRONT_LEFT_BIT) {
190 GLuint tmp = sarea->ContextState[I830_CTXREG_ENABLES_2];
191
192 sarea->dirty |= (I830_UPLOAD_CTX | I830_UPLOAD_BUFFERS |
193 I830_UPLOAD_TEXBLEND0);
194
195 sarea->TexBlendState[0][0] = (STATE3D_MAP_BLEND_OP_CMD(0) |
196 TEXPIPE_COLOR |
197 ENABLE_TEXOUTPUT_WRT_SEL |
198 TEXOP_OUTPUT_CURRENT |
199 DISABLE_TEX_CNTRL_STAGE |
200 TEXOP_SCALE_1X |
201 TEXOP_MODIFY_PARMS |
202 TEXOP_LAST_STAGE |
203 TEXBLENDOP_ARG1);
204 sarea->TexBlendState[0][1] = (STATE3D_MAP_BLEND_OP_CMD(0) |
205 TEXPIPE_ALPHA |
206 ENABLE_TEXOUTPUT_WRT_SEL |
207 TEXOP_OUTPUT_CURRENT |
208 TEXOP_SCALE_1X |
209 TEXOP_MODIFY_PARMS |
210 TEXBLENDOP_ARG1);
211 sarea->TexBlendState[0][2] = (STATE3D_MAP_BLEND_ARG_CMD(0) |
212 TEXPIPE_COLOR |
213 TEXBLEND_ARG1 |
214 TEXBLENDARG_MODIFY_PARMS |
215 TEXBLENDARG_CURRENT);
216 sarea->TexBlendState[0][3] = (STATE3D_MAP_BLEND_ARG_CMD(0) |
217 TEXPIPE_ALPHA |
218 TEXBLEND_ARG1 |
219 TEXBLENDARG_MODIFY_PARMS |
220 TEXBLENDARG_CURRENT);
221 sarea->TexBlendStateWordsUsed[0] = 4;
222
223 tmp &= ~(ENABLE_STENCIL_WRITE | ENABLE_DEPTH_WRITE);
224 tmp |= (DISABLE_STENCIL_WRITE |
225 DISABLE_DEPTH_WRITE |
226 (imesa->mask_red << WRITEMASK_RED_SHIFT) |
227 (imesa->mask_green << WRITEMASK_GREEN_SHIFT) |
228 (imesa->mask_blue << WRITEMASK_BLUE_SHIFT) |
229 (imesa->mask_alpha << WRITEMASK_ALPHA_SHIFT));
230 sarea->ContextState[I830_CTXREG_ENABLES_2] = tmp;
231
232 if(0)
233 fprintf(stderr, "fcdq : r_mask(%d) g_mask(%d) b_mask(%d) a_mask(%d)\n",
234 imesa->mask_red, imesa->mask_green, imesa->mask_blue,
235 imesa->mask_alpha);
236
237 sarea->BufferState[I830_DESTREG_CBUFADDR] = i830Screen->fbOffset;
238
239 if(0)
240 fprintf(stderr, "fcdq : x0(%d) x1(%d) y0(%d) y1(%d)\n"
241 "r(0x%x) g(0x%x) b(0x%x) a(0x%x)\n",
242 x0, x1, y0, y1, imesa->clear_red, imesa->clear_green,
243 imesa->clear_blue, imesa->clear_alpha);
244
245 i830ClearDrawQuad(imesa, (float)x0, (float)x1, (float)y0, (float)y1,
246 imesa->clear_red, imesa->clear_green,
247 imesa->clear_blue, imesa->clear_alpha);
248 i830FlushPrimsLocked( imesa );
249 }
250
251 if(mask & DD_BACK_LEFT_BIT) {
252 GLuint tmp = sarea->ContextState[I830_CTXREG_ENABLES_2];
253
254 sarea->dirty |= (I830_UPLOAD_CTX | I830_UPLOAD_BUFFERS |
255 I830_UPLOAD_TEXBLEND0);
256
257 sarea->TexBlendState[0][0] = (STATE3D_MAP_BLEND_OP_CMD(0) |
258 TEXPIPE_COLOR |
259 ENABLE_TEXOUTPUT_WRT_SEL |
260 TEXOP_OUTPUT_CURRENT |
261 DISABLE_TEX_CNTRL_STAGE |
262 TEXOP_SCALE_1X |
263 TEXOP_MODIFY_PARMS |
264 TEXOP_LAST_STAGE |
265 TEXBLENDOP_ARG1);
266 sarea->TexBlendState[0][1] = (STATE3D_MAP_BLEND_OP_CMD(0) |
267 TEXPIPE_ALPHA |
268 ENABLE_TEXOUTPUT_WRT_SEL |
269 TEXOP_OUTPUT_CURRENT |
270 TEXOP_SCALE_1X |
271 TEXOP_MODIFY_PARMS |
272 TEXBLENDOP_ARG1);
273 sarea->TexBlendState[0][2] = (STATE3D_MAP_BLEND_ARG_CMD(0) |
274 TEXPIPE_COLOR |
275 TEXBLEND_ARG1 |
276 TEXBLENDARG_MODIFY_PARMS |
277 TEXBLENDARG_CURRENT);
278 sarea->TexBlendState[0][3] = (STATE3D_MAP_BLEND_ARG_CMD(0) |
279 TEXPIPE_ALPHA |
280 TEXBLEND_ARG2 |
281 TEXBLENDARG_MODIFY_PARMS |
282 TEXBLENDARG_CURRENT);
283 sarea->TexBlendStateWordsUsed[0] = 4;
284
285 tmp &= ~(ENABLE_STENCIL_WRITE | ENABLE_DEPTH_WRITE);
286 tmp |= (DISABLE_STENCIL_WRITE |
287 DISABLE_DEPTH_WRITE |
288 (imesa->mask_red << WRITEMASK_RED_SHIFT) |
289 (imesa->mask_green << WRITEMASK_GREEN_SHIFT) |
290 (imesa->mask_blue << WRITEMASK_BLUE_SHIFT) |
291 (imesa->mask_alpha << WRITEMASK_ALPHA_SHIFT));
292
293 if(0)
294 fprintf(stderr, "bcdq : r_mask(%d) g_mask(%d) b_mask(%d) a_mask(%d)\n",
295 imesa->mask_red, imesa->mask_green, imesa->mask_blue,
296 imesa->mask_alpha);
297
298 sarea->ContextState[I830_CTXREG_ENABLES_2] = tmp;
299
300 sarea->BufferState[I830_DESTREG_CBUFADDR] = i830Screen->backOffset;
301
302 if(0)
303 fprintf(stderr, "bcdq : x0(%d) x1(%d) y0(%d) y1(%d)\n"
304 "r(0x%x) g(0x%x) b(0x%x) a(0x%x)\n",
305 x0, x1, y0, y1, imesa->clear_red, imesa->clear_green,
306 imesa->clear_blue, imesa->clear_alpha);
307
308 i830ClearDrawQuad(imesa, (float)x0, (float)x1, (float)y0, (float)y1,
309 imesa->clear_red, imesa->clear_green,
310 imesa->clear_blue, imesa->clear_alpha);
311 i830FlushPrimsLocked( imesa );
312 }
313
314 if(mask & DD_STENCIL_BIT) {
315 GLuint s_mask = ctx->Stencil.WriteMask[0];
316
317 sarea->dirty |= (I830_UPLOAD_CTX | I830_UPLOAD_BUFFERS |
318 I830_UPLOAD_TEXBLEND0);
319
320 sarea->TexBlendState[0][0] = (STATE3D_MAP_BLEND_OP_CMD(0) |
321 TEXPIPE_COLOR |
322 ENABLE_TEXOUTPUT_WRT_SEL |
323 TEXOP_OUTPUT_CURRENT |
324 DISABLE_TEX_CNTRL_STAGE |
325 TEXOP_SCALE_1X |
326 TEXOP_MODIFY_PARMS |
327 TEXOP_LAST_STAGE |
328 TEXBLENDOP_ARG1);
329 sarea->TexBlendState[0][1] = (STATE3D_MAP_BLEND_OP_CMD(0) |
330 TEXPIPE_ALPHA |
331 ENABLE_TEXOUTPUT_WRT_SEL |
332 TEXOP_OUTPUT_CURRENT |
333 TEXOP_SCALE_1X |
334 TEXOP_MODIFY_PARMS |
335 TEXBLENDOP_ARG1);
336 sarea->TexBlendState[0][2] = (STATE3D_MAP_BLEND_ARG_CMD(0) |
337 TEXPIPE_COLOR |
338 TEXBLEND_ARG1 |
339 TEXBLENDARG_MODIFY_PARMS |
340 TEXBLENDARG_CURRENT);
341 sarea->TexBlendState[0][3] = (STATE3D_MAP_BLEND_ARG_CMD(0) |
342 TEXPIPE_ALPHA |
343 TEXBLEND_ARG2 |
344 TEXBLENDARG_MODIFY_PARMS |
345 TEXBLENDARG_CURRENT);
346 sarea->TexBlendStateWordsUsed[0] = 4;
347
348 sarea->ContextState[I830_CTXREG_ENABLES_1] |= (ENABLE_STENCIL_TEST |
349 ENABLE_DEPTH_TEST);
350
351 sarea->ContextState[I830_CTXREG_ENABLES_2] &= ~(ENABLE_STENCIL_WRITE |
352 ENABLE_DEPTH_WRITE |
353 ENABLE_COLOR_WRITE);
354
355 sarea->ContextState[I830_CTXREG_ENABLES_2] |=
356 (ENABLE_STENCIL_WRITE |
357 DISABLE_DEPTH_WRITE |
358 (1 << WRITEMASK_RED_SHIFT) |
359 (1 << WRITEMASK_GREEN_SHIFT) |
360 (1 << WRITEMASK_BLUE_SHIFT) |
361 (1 << WRITEMASK_ALPHA_SHIFT) |
362 ENABLE_COLOR_WRITE);
363
364 sarea->ContextState[I830_CTXREG_STATE4] &=
365 ~MODE4_ENABLE_STENCIL_WRITE_MASK;
366
367 sarea->ContextState[I830_CTXREG_STATE4] |=
368 (ENABLE_STENCIL_WRITE_MASK |
369 STENCIL_WRITE_MASK(s_mask));
370
371 sarea->ContextState[I830_CTXREG_STENCILTST] &=
372 ~(STENCIL_OPS_MASK |
373 STENCIL_REF_VALUE_MASK |
374 ENABLE_STENCIL_TEST_FUNC_MASK);
375
376 sarea->ContextState[I830_CTXREG_STENCILTST] |=
377 (ENABLE_STENCIL_PARMS |
378 ENABLE_STENCIL_REF_VALUE |
379 ENABLE_STENCIL_TEST_FUNC |
380 STENCIL_FAIL_OP(STENCILOP_REPLACE) |
381 STENCIL_PASS_DEPTH_FAIL_OP(STENCILOP_REPLACE) |
382 STENCIL_PASS_DEPTH_PASS_OP(STENCILOP_REPLACE) |
383 STENCIL_REF_VALUE((ctx->Stencil.Clear & 0xff)) |
384 STENCIL_TEST_FUNC(COMPAREFUNC_ALWAYS));
385
386 if(0)
387 fprintf(stderr, "Enables_1 (0x%x) Enables_2 (0x%x) StenTst (0x%x)\n"
388 "Modes_4 (0x%x)\n",
389 sarea->ContextState[I830_CTXREG_ENABLES_1],
390 sarea->ContextState[I830_CTXREG_ENABLES_2],
391 sarea->ContextState[I830_CTXREG_STENCILTST],
392 sarea->ContextState[I830_CTXREG_STATE4]);
393
394 sarea->BufferState[I830_DESTREG_CBUFADDR] = i830Screen->fbOffset;
395
396 i830ClearDrawQuad(imesa, (float)x0, (float)x1, (float)y0, (float)y1,
397 255, 255, 255, 255);
398 i830FlushPrimsLocked( imesa );
399 }
400
401 UNLOCK_HARDWARE(imesa);
402 imesa->dirty = old_dirty;
403 imesa->dirty |= (I830_UPLOAD_CTX |
404 I830_UPLOAD_BUFFERS |
405 I830_UPLOAD_TEXBLEND0);
406
407 imesa->hw_primitive = old_vertex_prim;
408 }
409
410 static void i830Clear(GLcontext *ctx, GLbitfield mask, GLboolean all,
411 GLint cx1, GLint cy1, GLint cw, GLint ch)
412 {
413 i830ContextPtr imesa = I830_CONTEXT( ctx );
414 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
415 const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
416 drmI830Clear clear;
417 GLbitfield tri_mask = 0;
418 int i;
419 GLint cx, cy;
420
421 /* flip top to bottom */
422 cy = dPriv->h-cy1-ch;
423 cx = cx1 + imesa->drawX;
424 cy += imesa->drawY;
425
426 if(0) fprintf(stderr, "\nClearColor : 0x%08x\n", imesa->ClearColor);
427
428 clear.flags = 0;
429 clear.clear_color = imesa->ClearColor;
430 clear.clear_depth = 0;
431 clear.clear_colormask = 0;
432 clear.clear_depthmask = 0;
433
434 I830_FIREVERTICES( imesa );
435
436 if (mask & DD_FRONT_LEFT_BIT) {
437 if(colorMask == ~0) {
438 clear.flags |= I830_FRONT;
439 } else {
440 tri_mask |= DD_FRONT_LEFT_BIT;
441 }
442 mask &= ~DD_FRONT_LEFT_BIT;
443 }
444
445 if (mask & DD_BACK_LEFT_BIT) {
446 if(colorMask == ~0) {
447 clear.flags |= I830_BACK;
448 } else {
449 tri_mask |= DD_BACK_LEFT_BIT;
450 }
451 mask &= ~DD_BACK_LEFT_BIT;
452 }
453
454 if (mask & DD_DEPTH_BIT) {
455 clear.flags |= I830_DEPTH;
456 clear.clear_depthmask = imesa->depth_clear_mask;
457 clear.clear_depth = (GLuint)(ctx->Depth.Clear * imesa->ClearDepth);
458 mask &= ~DD_DEPTH_BIT;
459 }
460
461 if((mask & DD_STENCIL_BIT) && imesa->hw_stencil) {
462 if (ctx->Stencil.WriteMask[0] != 0xff) {
463 tri_mask |= DD_STENCIL_BIT;
464 } else {
465 clear.flags |= I830_DEPTH;
466 clear.clear_depthmask |= imesa->stencil_clear_mask;
467 clear.clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
468 }
469 mask &= ~DD_STENCIL_BIT;
470 }
471
472 /* First check for clears that need to happen with triangles */
473 if(tri_mask) {
474 i830ClearWithTris(ctx, tri_mask, all, cx, cy, cw, ch);
475 }
476
477 if (clear.flags) {
478 LOCK_HARDWARE( imesa );
479
480 for (i = 0 ; i < imesa->numClipRects ; )
481 {
482 int nr = MIN2(i + I830_NR_SAREA_CLIPRECTS, imesa->numClipRects);
483 XF86DRIClipRectRec *box = imesa->pClipRects;
484 drm_clip_rect_t *b = (drm_clip_rect_t *)imesa->sarea->boxes;
485 int n = 0;
486
487 if (!all) {
488 for ( ; i < nr ; i++) {
489 GLint x = box[i].x1;
490 GLint y = box[i].y1;
491 GLint w = box[i].x2 - x;
492 GLint h = box[i].y2 - y;
493
494 if (x < cx) w -= cx - x, x = cx;
495 if (y < cy) h -= cy - y, y = cy;
496 if (x + w > cx + cw) w = cx + cw - x;
497 if (y + h > cy + ch) h = cy + ch - y;
498 if (w <= 0) continue;
499 if (h <= 0) continue;
500
501 b->x1 = x;
502 b->y1 = y;
503 b->x2 = x + w;
504 b->y2 = y + h;
505 b++;
506 n++;
507 }
508 } else {
509 for ( ; i < nr ; i++) {
510 *b++ = *(drm_clip_rect_t *)&box[i];
511 n++;
512 }
513 }
514
515 imesa->sarea->nbox = n;
516 drmCommandWrite(imesa->driFd, DRM_I830_CLEAR,
517 &clear, sizeof(drmI830Clear));
518 }
519
520 UNLOCK_HARDWARE( imesa );
521 imesa->upload_cliprects = GL_TRUE;
522 }
523
524 if (mask)
525 _swrast_Clear( ctx, mask, all, cx1, cy1, cw, ch );
526 }
527
528
529
530 /*
531 * Copy the back buffer to the front buffer.
532 */
533 void i830CopyBuffer( const __DRIdrawablePrivate *dPriv )
534 {
535 i830ContextPtr imesa;
536 XF86DRIClipRectPtr pbox;
537 int nbox, i, tmp;
538
539 assert(dPriv);
540 assert(dPriv->driContextPriv);
541 assert(dPriv->driContextPriv->driverPrivate);
542
543 imesa = (i830ContextPtr) dPriv->driContextPriv->driverPrivate;
544
545 I830_FIREVERTICES( imesa );
546 LOCK_HARDWARE( imesa );
547
548 imesa->sarea->perf_boxes |= imesa->perf_boxes;
549 imesa->perf_boxes = 0;
550
551 pbox = dPriv->pClipRects;
552 nbox = dPriv->numClipRects;
553
554 for (i = 0 ; i < nbox ; )
555 {
556 int nr = MIN2(i + I830_NR_SAREA_CLIPRECTS, dPriv->numClipRects);
557 XF86DRIClipRectRec *b = (XF86DRIClipRectRec *)imesa->sarea->boxes;
558
559 imesa->sarea->nbox = nr - i;
560
561 for ( ; i < nr ; i++)
562 *b++ = pbox[i];
563 drmCommandNone(imesa->driFd, DRM_I830_SWAP);
564 }
565
566 tmp = GET_ENQUEUE_AGE(imesa);
567 UNLOCK_HARDWARE( imesa );
568
569 /* multiarb will suck the life out of the server without this throttle:
570 */
571 if (GET_DISPATCH_AGE(imesa) < imesa->lastSwap) {
572 i830WaitAge(imesa, imesa->lastSwap);
573 }
574
575 imesa->lastSwap = tmp;
576 imesa->upload_cliprects = GL_TRUE;
577 }
578
579 /* Flip the front & back buffes
580 */
581 void i830PageFlip( const __DRIdrawablePrivate *dPriv )
582 {
583 #if 0
584 i830ContextPtr imesa;
585 int tmp, ret;
586
587 if (I830_DEBUG & DEBUG_IOCTL)
588 fprintf(stderr, "%s\n", __FUNCTION__);
589
590 assert(dPriv);
591 assert(dPriv->driContextPriv);
592 assert(dPriv->driContextPriv->driverPrivate);
593
594 imesa = (i830ContextPtr) dPriv->driContextPriv->driverPrivate;
595
596 I830_FIREVERTICES( imesa );
597 LOCK_HARDWARE( imesa );
598
599 imesa->sarea->perf_boxes |= imesa->perf_boxes;
600 imesa->perf_boxes = 0;
601
602 if (dPriv->pClipRects) {
603 *(XF86DRIClipRectRec *)imesa->sarea->boxes = dPriv->pClipRects[0];
604 imesa->sarea->nbox = 1;
605 }
606
607 ret = drmCommandNone(imesa->driFd, DRM_I830_FLIP);
608 if (ret) {
609 fprintf(stderr, "%s: %d\n", __FUNCTION__, ret);
610 UNLOCK_HARDWARE( imesa );
611 exit(1);
612 }
613
614 tmp = GET_ENQUEUE_AGE(imesa);
615 UNLOCK_HARDWARE( imesa );
616
617 /* multiarb will suck the life out of the server without this throttle:
618 */
619 if (GET_DISPATCH_AGE(imesa) < imesa->lastSwap) {
620 i830WaitAge(imesa, imesa->lastSwap);
621 }
622
623 i830SetDrawBuffer( imesa->glCtx, imesa->glCtx->Color.DriverDrawBuffer );
624 imesa->upload_cliprects = GL_TRUE;
625 imesa->lastSwap = tmp;
626 #endif
627 }
628
629 /* This waits for *everybody* to finish rendering -- overkill.
630 */
631 void i830DmaFinish( i830ContextPtr imesa )
632 {
633 I830_FIREVERTICES( imesa );
634 LOCK_HARDWARE_QUIESCENT( imesa );
635 UNLOCK_HARDWARE( imesa );
636 }
637
638 void i830RegetLockQuiescent( i830ContextPtr imesa )
639 {
640 drmUnlock(imesa->driFd, imesa->hHWContext);
641 i830GetLock( imesa, DRM_LOCK_QUIESCENT );
642 }
643
644 void i830WaitAgeLocked( i830ContextPtr imesa, int age )
645 {
646 int i = 0;
647 while (++i < 5000) {
648 drmCommandNone(imesa->driFd, DRM_I830_GETAGE);
649 if (GET_DISPATCH_AGE(imesa) >= age) return;
650 imesa->sarea->perf_boxes |= I830_BOX_WAIT;
651 UNLOCK_HARDWARE( imesa );
652 if (I830_DEBUG & DEBUG_SLEEP) fprintf(stderr, ".");
653 usleep(1);
654 LOCK_HARDWARE( imesa );
655 }
656 /* If that didn't work, just do a flush:
657 */
658 drmCommandNone(imesa->driFd, DRM_I830_FLUSH);
659 }
660
661 void i830WaitAge( i830ContextPtr imesa, int age )
662 {
663 int i = 0;
664 if (GET_DISPATCH_AGE(imesa) >= age) return;
665
666 while (1) {
667 drmCommandNone(imesa->driFd, DRM_I830_GETAGE);
668 if (GET_DISPATCH_AGE(imesa) >= age) return;
669 imesa->perf_boxes |= I830_BOX_WAIT;
670
671 if (imesa->do_irqs) {
672 drmI830IrqEmit ie;
673 drmI830IrqWait iw;
674 int ret;
675
676 ie.irq_seq = &iw.irq_seq;
677
678 LOCK_HARDWARE( imesa );
679 ret = drmCommandWriteRead( imesa->driFd, DRM_I830_IRQ_EMIT, &ie, sizeof(ie) );
680 if ( ret ) {
681 fprintf( stderr, "%s: drmI830IrqEmit: %d\n", __FUNCTION__, ret );
682 exit(1);
683 }
684 UNLOCK_HARDWARE(imesa);
685
686 ret = drmCommandWrite( imesa->driFd, DRM_I830_IRQ_WAIT, &iw, sizeof(iw) );
687 if ( ret ) {
688 fprintf( stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, ret );
689 exit(1);
690 }
691 } else {
692 if (++i > 5000) usleep(1);
693 }
694 }
695 }
696
697 static void age_imesa( i830ContextPtr imesa, int age )
698 {
699 if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->base.timestamp = age;
700 if (imesa->CurrentTexObj[1]) imesa->CurrentTexObj[1]->base.timestamp = age;
701 }
702
703 void i830FlushPrimsLocked( i830ContextPtr imesa )
704 {
705 XF86DRIClipRectPtr pbox = (XF86DRIClipRectPtr)imesa->pClipRects;
706 int nbox = imesa->numClipRects;
707 drmBufPtr buffer = imesa->vertex_buffer;
708 I830SAREAPtr sarea = imesa->sarea;
709 drmI830Vertex vertex;
710 int i, nr;
711
712 if (I830_DEBUG & DEBUG_IOCTL)
713 fprintf(stderr, "%s dirty: %08x\n", __FUNCTION__, imesa->dirty);
714
715
716 vertex.idx = buffer->idx;
717 vertex.used = imesa->vertex_low;
718 vertex.discard = 0;
719 sarea->vertex_prim = imesa->hw_primitive;
720
721 /* Reset imesa vars:
722 */
723 imesa->vertex_buffer = 0;
724 imesa->vertex_addr = 0;
725 imesa->vertex_low = 0;
726 imesa->vertex_high = 0;
727 imesa->vertex_last_prim = 0;
728
729 if (imesa->dirty) {
730 if (I830_DEBUG & DEBUG_SANITY)
731 i830EmitHwStateLockedDebug(imesa);
732 else
733 i830EmitHwStateLocked(imesa);
734 }
735
736 if (I830_DEBUG & DEBUG_IOCTL)
737 fprintf(stderr,"%s: Vertex idx %d used %d discard %d\n",
738 __FUNCTION__, vertex.idx, vertex.used, vertex.discard);
739
740 if (!nbox) {
741 vertex.used = 0;
742 vertex.discard = 1;
743 if (drmCommandWrite (imesa->driFd, DRM_I830_VERTEX,
744 &vertex, sizeof(drmI830Vertex))) {
745 fprintf(stderr, "DRM_I830_VERTEX: %d\n", -errno);
746 UNLOCK_HARDWARE(imesa);
747 exit(1);
748 }
749 return;
750 }
751
752 for (i = 0 ; i < nbox ; i = nr ) {
753 XF86DRIClipRectPtr b = sarea->boxes;
754 int j;
755
756 nr = MIN2(i + I830_NR_SAREA_CLIPRECTS, nbox);
757 sarea->nbox = nr - i;
758
759 for ( j = i ; j < nr ; j++) {
760 b[j-i] = pbox[j];
761 }
762
763 /* Finished with the buffer?
764 */
765 if (nr == nbox)
766 vertex.discard = 1;
767
768 /* Do a bunch of sanity checks on the vertices sent to the hardware */
769 if (I830_DEBUG & DEBUG_SANITY) {
770 i830VertexSanity(imesa, vertex);
771
772 for ( j = 0 ; j < sarea->nbox ; j++) {
773 fprintf(stderr, "box %d/%d %d,%d %d,%d\n",
774 j, sarea->nbox, b[j].x1, b[j].y1, b[j].x2, b[j].y2);
775 }
776 }
777
778 drmCommandWrite (imesa->driFd, DRM_I830_VERTEX,
779 &vertex, sizeof(drmI830Vertex));
780 age_imesa(imesa, imesa->sarea->last_enqueue);
781 }
782
783 imesa->dirty = 0;
784 imesa->upload_cliprects = GL_FALSE;
785 }
786
787 void i830FlushPrimsGetBufferLocked( i830ContextPtr imesa )
788 {
789 if (imesa->vertex_buffer)
790 i830FlushPrimsLocked( imesa );
791 imesa->vertex_buffer = i830_get_buffer_ioctl( imesa );
792 imesa->vertex_addr = (char *)imesa->vertex_buffer->address;
793
794 /* leave room for instruction header & footer:
795 */
796 imesa->vertex_high = imesa->vertex_buffer->total - 4;
797 imesa->vertex_low = 4;
798 imesa->vertex_last_prim = imesa->vertex_low;
799 }
800
801 void i830FlushPrimsGetBuffer( i830ContextPtr imesa )
802 {
803 LOCK_HARDWARE(imesa);
804 i830FlushPrimsGetBufferLocked( imesa );
805 UNLOCK_HARDWARE(imesa);
806 }
807
808
809 void i830FlushPrims( i830ContextPtr imesa )
810 {
811 if (imesa->vertex_buffer) {
812 LOCK_HARDWARE( imesa );
813 i830FlushPrimsLocked( imesa );
814 UNLOCK_HARDWARE( imesa );
815 }
816 }
817
818 int i830_check_copy(int fd)
819 {
820 return drmCommandNone(fd, DRM_I830_DOCOPY);
821 }
822
823 static void i830Flush( GLcontext *ctx )
824 {
825 i830ContextPtr imesa = I830_CONTEXT( ctx );
826 I830_FIREVERTICES( imesa );
827 }
828
829 static void i830Finish( GLcontext *ctx )
830 {
831 i830ContextPtr imesa = I830_CONTEXT( ctx );
832 i830DmaFinish( imesa );
833 }
834
835 void i830InitIoctlFuncs( struct dd_function_table *functions )
836 {
837 functions->Flush = i830Flush;
838 functions->Clear = i830Clear;
839 functions->Finish = i830Finish;
840 }
841