32 and z24s8 softpipe buffers
[mesa.git] / src / mesa / drivers / dri / i915tex / intel_buffers.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "intel_screen.h"
29 #include "intel_context.h"
30 #include "intel_blit.h"
31 #include "intel_buffers.h"
32 #include "intel_depthstencil.h"
33 #include "intel_fbo.h"
34 #include "intel_tris.h"
35 #include "intel_regions.h"
36 #include "intel_batchbuffer.h"
37 #include "intel_reg.h"
38 #include "context.h"
39 #include "utils.h"
40 #include "drirenderbuffer.h"
41 #include "framebuffer.h"
42 #include "swrast/swrast.h"
43 #include "vblank.h"
44
45
46 /* This block can be removed when libdrm >= 2.3.1 is required */
47
48 #ifndef DRM_VBLANK_FLIP
49
50 #define DRM_VBLANK_FLIP 0x8000000
51
52 typedef struct drm_i915_flip {
53 int pipes;
54 } drm_i915_flip_t;
55
56 #undef DRM_IOCTL_I915_FLIP
57 #define DRM_IOCTL_I915_FLIP DRM_IOW(DRM_COMMAND_BASE + DRM_I915_FLIP, \
58 drm_i915_flip_t)
59
60 #endif
61
62
63 /**
64 * XXX move this into a new dri/common/cliprects.c file.
65 */
66 GLboolean
67 intel_intersect_cliprects(drm_clip_rect_t * dst,
68 const drm_clip_rect_t * a,
69 const drm_clip_rect_t * b)
70 {
71 GLint bx = b->x1;
72 GLint by = b->y1;
73 GLint bw = b->x2 - bx;
74 GLint bh = b->y2 - by;
75
76 if (bx < a->x1)
77 bw -= a->x1 - bx, bx = a->x1;
78 if (by < a->y1)
79 bh -= a->y1 - by, by = a->y1;
80 if (bx + bw > a->x2)
81 bw = a->x2 - bx;
82 if (by + bh > a->y2)
83 bh = a->y2 - by;
84 if (bw <= 0)
85 return GL_FALSE;
86 if (bh <= 0)
87 return GL_FALSE;
88
89 dst->x1 = bx;
90 dst->y1 = by;
91 dst->x2 = bx + bw;
92 dst->y2 = by + bh;
93
94 return GL_TRUE;
95 }
96
97 /**
98 * Return pointer to current color drawing region, or NULL.
99 */
100 struct intel_region *
101 intel_drawbuf_region(struct intel_context *intel)
102 {
103 struct intel_renderbuffer *irbColor =
104 intel_renderbuffer(intel->ctx.DrawBuffer->_ColorDrawBuffers[0][0]);
105 if (irbColor)
106 return irbColor->region;
107 else
108 return NULL;
109 }
110
111 /**
112 * Return pointer to current color reading region, or NULL.
113 */
114 struct intel_region *
115 intel_readbuf_region(struct intel_context *intel)
116 {
117 struct intel_renderbuffer *irb
118 = intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer);
119 if (irb)
120 return irb->region;
121 else
122 return NULL;
123 }
124
125
126
127 /**
128 * Update the following fields for rendering to a user-created FBO:
129 * intel->numClipRects
130 * intel->pClipRects
131 * intel->drawX
132 * intel->drawY
133 */
134 static void
135 intelSetRenderbufferClipRects(struct intel_context *intel)
136 {
137 assert(intel->ctx.DrawBuffer->Width > 0);
138 assert(intel->ctx.DrawBuffer->Height > 0);
139 intel->fboRect.x1 = 0;
140 intel->fboRect.y1 = 0;
141 intel->fboRect.x2 = intel->ctx.DrawBuffer->Width;
142 intel->fboRect.y2 = intel->ctx.DrawBuffer->Height;
143 intel->numClipRects = 1;
144 intel->pClipRects = &intel->fboRect;
145 intel->drawX = 0;
146 intel->drawY = 0;
147 }
148
149 /**
150 * As above, but for rendering private front/back buffer of a window.
151 * \sa intelSetPrivbufClipRects
152 */
153
154 static void
155 intelSetPrivbufClipRects(struct intel_context *intel)
156 {
157 __DRIdrawablePrivate *dPriv = intel->driDrawable;
158 if (!dPriv)
159 return;
160
161 intel->fakeClipRect.x1 = 0;
162 intel->fakeClipRect.y1 = 0;
163 intel->fakeClipRect.x2 = dPriv->w;
164 intel->fakeClipRect.y2 = dPriv->h;
165 intel->numClipRects = 1;
166 intel->pClipRects = &intel->fakeClipRect;
167 intel->drawX = 0;
168 intel->drawY = 0;
169 }
170
171
172
173 /**
174 * This will be called whenever the currently bound window is moved/resized.
175 * XXX: actually, it seems to NOT be called when the window is only moved (BP).
176 */
177 void
178 intelWindowMoved(struct intel_context *intel)
179 {
180 GLcontext *ctx = &intel->ctx;
181 __DRIdrawablePrivate *dPriv = intel->driDrawable;
182 struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
183
184 if (!intel->ctx.DrawBuffer) {
185 /* when would this happen? -BP */
186 intel->numClipRects = 0;
187 }
188
189
190 if (intel->intelScreen->driScrnPriv->ddxMinor >= 7) {
191 drmI830Sarea *sarea = intel->sarea;
192 drm_clip_rect_t drw_rect = { .x1 = dPriv->x, .x2 = dPriv->x + dPriv->w,
193 .y1 = dPriv->y, .y2 = dPriv->y + dPriv->h };
194 drm_clip_rect_t pipeA_rect = { .x1 = sarea->pipeA_x, .y1 = sarea->pipeA_y,
195 .x2 = sarea->pipeA_x + sarea->pipeA_w,
196 .y2 = sarea->pipeA_y + sarea->pipeA_h };
197 drm_clip_rect_t pipeB_rect = { .x1 = sarea->pipeB_x, .y1 = sarea->pipeB_y,
198 .x2 = sarea->pipeB_x + sarea->pipeB_w,
199 .y2 = sarea->pipeB_y + sarea->pipeB_h };
200 GLint areaA = driIntersectArea( drw_rect, pipeA_rect );
201 GLint areaB = driIntersectArea( drw_rect, pipeB_rect );
202 GLuint flags = intel_fb->vblank_flags;
203 GLboolean pf_active;
204 GLint pf_pipes;
205
206 /* Update page flipping info
207 */
208 pf_pipes = 0;
209
210 if (areaA > 0)
211 pf_pipes |= 1;
212
213 if (areaB > 0)
214 pf_pipes |= 2;
215
216 intel_fb->pf_current_page = (intel->sarea->pf_current_page >>
217 (intel_fb->pf_pipes & 0x2)) & 0x3;
218
219 intel_fb->pf_num_pages = intel->intelScreen->third.handle ? 3 : 2;
220
221 pf_active = pf_pipes && (pf_pipes & intel->sarea->pf_active) == pf_pipes;
222
223 if (INTEL_DEBUG & DEBUG_LOCK)
224 if (pf_active != intel_fb->pf_active)
225 _mesa_printf("%s - Page flipping %sactive\n", __progname,
226 pf_active ? "" : "in");
227
228 if (pf_active) {
229 /* Sync pages between pipes if we're flipping on both at the same time */
230 if (pf_pipes == 0x3 && pf_pipes != intel_fb->pf_pipes &&
231 (intel->sarea->pf_current_page & 0x3) !=
232 (((intel->sarea->pf_current_page) >> 2) & 0x3)) {
233 drm_i915_flip_t flip;
234
235 if (intel_fb->pf_current_page ==
236 (intel->sarea->pf_current_page & 0x3)) {
237 /* XXX: This is ugly, but emitting two flips 'in a row' can cause
238 * lockups for unknown reasons.
239 */
240 intel->sarea->pf_current_page =
241 intel->sarea->pf_current_page & 0x3;
242 intel->sarea->pf_current_page |=
243 ((intel_fb->pf_current_page + intel_fb->pf_num_pages - 1) %
244 intel_fb->pf_num_pages) << 2;
245
246 flip.pipes = 0x2;
247 } else {
248 intel->sarea->pf_current_page =
249 intel->sarea->pf_current_page & (0x3 << 2);
250 intel->sarea->pf_current_page |=
251 (intel_fb->pf_current_page + intel_fb->pf_num_pages - 1) %
252 intel_fb->pf_num_pages;
253
254 flip.pipes = 0x1;
255 }
256
257 drmCommandWrite(intel->driFd, DRM_I915_FLIP, &flip, sizeof(flip));
258 }
259
260 intel_fb->pf_pipes = pf_pipes;
261 }
262
263 intel_fb->pf_active = pf_active;
264 intel_flip_renderbuffers(intel_fb);
265 intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer);
266
267 /* Update vblank info
268 */
269 if (areaB > areaA || (areaA == areaB && areaB > 0)) {
270 flags = intel_fb->vblank_flags | VBLANK_FLAG_SECONDARY;
271 } else {
272 flags = intel_fb->vblank_flags & ~VBLANK_FLAG_SECONDARY;
273 }
274
275 if (flags != intel_fb->vblank_flags && intel_fb->vblank_flags &&
276 !(intel_fb->vblank_flags & VBLANK_FLAG_NO_IRQ)) {
277 drmVBlank vbl;
278 int i;
279
280 vbl.request.type = DRM_VBLANK_ABSOLUTE;
281
282 if ( intel_fb->vblank_flags & VBLANK_FLAG_SECONDARY ) {
283 vbl.request.type |= DRM_VBLANK_SECONDARY;
284 }
285
286 for (i = 0; i < intel_fb->pf_num_pages; i++) {
287 if (!intel_fb->color_rb[i] ||
288 (intel_fb->vbl_waited - intel_fb->color_rb[i]->vbl_pending) <=
289 (1<<23))
290 continue;
291
292 vbl.request.sequence = intel_fb->color_rb[i]->vbl_pending;
293 drmWaitVBlank(intel->driFd, &vbl);
294 }
295
296 intel_fb->vblank_flags = flags;
297 driGetCurrentVBlank(dPriv, intel_fb->vblank_flags, &intel_fb->vbl_seq);
298 intel_fb->vbl_waited = intel_fb->vbl_seq;
299
300 for (i = 0; i < intel_fb->pf_num_pages; i++) {
301 if (intel_fb->color_rb[i])
302 intel_fb->color_rb[i]->vbl_pending = intel_fb->vbl_waited;
303 }
304 }
305 } else {
306 intel_fb->vblank_flags &= ~VBLANK_FLAG_SECONDARY;
307 }
308
309 /* Update Mesa's notion of window size */
310 driUpdateFramebufferSize(ctx, dPriv);
311 intel_fb->Base.Initialized = GL_TRUE; /* XXX remove someday */
312
313 /* Update hardware scissor */
314 ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
315 ctx->Scissor.Width, ctx->Scissor.Height);
316
317 /* Re-calculate viewport related state */
318 ctx->Driver.DepthRange( ctx, ctx->Viewport.Near, ctx->Viewport.Far );
319 }
320
321
322
323 /* A true meta version of this would be very simple and additionally
324 * machine independent. Maybe we'll get there one day.
325 */
326 static void
327 intelClearWithTris(struct intel_context *intel, GLbitfield mask)
328 {
329 GLcontext *ctx = &intel->ctx;
330 struct gl_framebuffer *fb = ctx->DrawBuffer;
331 drm_clip_rect_t clear;
332
333 if (INTEL_DEBUG & DEBUG_BLIT)
334 _mesa_printf("%s 0x%x\n", __FUNCTION__, mask);
335
336 LOCK_HARDWARE(intel);
337
338 /* XXX FBO: was: intel->driDrawable->numClipRects */
339 if (intel->numClipRects) {
340 GLint cx, cy, cw, ch;
341 GLuint buf;
342
343 intel->vtbl.install_meta_state(intel);
344
345 /* Get clear bounds after locking */
346 cx = fb->_Xmin;
347 cy = fb->_Ymin;
348 ch = fb->_Ymax - cx;
349 cw = fb->_Xmax - cy;
350
351 /* note: regardless of 'all', cx, cy, cw, ch are now correct */
352 clear.x1 = cx;
353 clear.y1 = cy;
354 clear.x2 = cx + cw;
355 clear.y2 = cy + ch;
356
357 /* Back and stencil cliprects are the same. Try and do both
358 * buffers at once:
359 */
360 if (mask &
361 (BUFFER_BIT_BACK_LEFT | BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH)) {
362 struct intel_region *backRegion =
363 intel_get_rb_region(fb, BUFFER_BACK_LEFT);
364 struct intel_region *depthRegion =
365 intel_get_rb_region(fb, BUFFER_DEPTH);
366 const GLuint clearColor = (backRegion && backRegion->cpp == 4)
367 ? intel->ClearColor8888 : intel->ClearColor565;
368
369 intel->vtbl.meta_draw_region(intel, backRegion, depthRegion);
370
371 if (mask & BUFFER_BIT_BACK_LEFT)
372 intel->vtbl.meta_color_mask(intel, GL_TRUE);
373 else
374 intel->vtbl.meta_color_mask(intel, GL_FALSE);
375
376 if (mask & BUFFER_BIT_STENCIL)
377 intel->vtbl.meta_stencil_replace(intel,
378 intel->ctx.Stencil.WriteMask[0],
379 intel->ctx.Stencil.Clear);
380 else
381 intel->vtbl.meta_no_stencil_write(intel);
382
383 if (mask & BUFFER_BIT_DEPTH)
384 intel->vtbl.meta_depth_replace(intel);
385 else
386 intel->vtbl.meta_no_depth_write(intel);
387
388 /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
389 * drawing origin may not be correctly emitted.
390 */
391 intel_meta_draw_quad(intel, clear.x1, clear.x2, clear.y1, clear.y2, intel->ctx.Depth.Clear, clearColor, 0, 0, 0, 0); /* texcoords */
392
393 mask &=
394 ~(BUFFER_BIT_BACK_LEFT | BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH);
395 }
396
397 /* clear the remaining (color) renderbuffers */
398 for (buf = 0; buf < BUFFER_COUNT && mask; buf++) {
399 const GLuint bufBit = 1 << buf;
400 if (mask & bufBit) {
401 struct intel_renderbuffer *irbColor =
402 intel_renderbuffer(fb->Attachment[buf].Renderbuffer);
403 GLuint color = (irbColor->region->cpp == 4)
404 ? intel->ClearColor8888 : intel->ClearColor565;
405
406 ASSERT(irbColor);
407
408 intel->vtbl.meta_no_depth_write(intel);
409 intel->vtbl.meta_no_stencil_write(intel);
410 intel->vtbl.meta_color_mask(intel, GL_TRUE);
411 intel->vtbl.meta_draw_region(intel, irbColor->region, NULL);
412
413 /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
414 * drawing origin may not be correctly emitted.
415 */
416 intel_meta_draw_quad(intel, clear.x1, clear.x2, clear.y1, clear.y2, 0, /* depth clear val */
417 color, 0, 0, 0, 0); /* texcoords */
418
419 mask &= ~bufBit;
420 }
421 }
422
423 intel->vtbl.leave_meta_state(intel);
424 intel_batchbuffer_flush(intel->batch);
425 }
426 UNLOCK_HARDWARE(intel);
427 }
428
429
430
431
432 /**
433 * Copy the window contents named by dPriv to the rotated (or reflected)
434 * color buffer.
435 * srcBuf is BUFFER_BIT_FRONT_LEFT or BUFFER_BIT_BACK_LEFT to indicate the source.
436 */
437 void
438 intelRotateWindow(struct intel_context *intel,
439 __DRIdrawablePrivate * dPriv, GLuint srcBuf)
440 {
441
442 intelScreenPrivate *screen = intel->intelScreen;
443 drm_clip_rect_t fullRect;
444 struct intel_framebuffer *intel_fb;
445 struct intel_region *src;
446 const drm_clip_rect_t *clipRects;
447 int numClipRects;
448 int i;
449 GLenum format, type;
450
451 int xOrig, yOrig;
452 int origNumClipRects;
453 drm_clip_rect_t *origRects;
454
455 /*
456 * set up hardware state
457 */
458 intelFlush(&intel->ctx);
459
460 LOCK_HARDWARE(intel);
461
462 if (!intel->numClipRects) {
463 UNLOCK_HARDWARE(intel);
464 return;
465 }
466
467 intel->vtbl.install_meta_state(intel);
468
469 intel->vtbl.meta_no_depth_write(intel);
470 intel->vtbl.meta_no_stencil_write(intel);
471 intel->vtbl.meta_color_mask(intel, GL_FALSE);
472
473
474 /* save current drawing origin and cliprects (restored at end) */
475 xOrig = intel->drawX;
476 yOrig = intel->drawY;
477 origNumClipRects = intel->numClipRects;
478 origRects = intel->pClipRects;
479
480 /*
481 * set drawing origin, cliprects for full-screen access to rotated screen
482 */
483 fullRect.x1 = 0;
484 fullRect.y1 = 0;
485 fullRect.x2 = screen->rotatedWidth;
486 fullRect.y2 = screen->rotatedHeight;
487 intel->drawX = 0;
488 intel->drawY = 0;
489 intel->numClipRects = 1;
490 intel->pClipRects = &fullRect;
491
492 intel->vtbl.meta_draw_region(intel, screen->rotated_region, NULL); /* ? */
493
494 intel_fb = dPriv->driverPrivate;
495
496 if ((srcBuf == BUFFER_BIT_BACK_LEFT && !intel_fb->pf_active)) {
497 src = intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT);
498 clipRects = dPriv->pBackClipRects;
499 numClipRects = dPriv->numBackClipRects;
500 }
501 else {
502 src = intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT);
503 clipRects = dPriv->pClipRects;
504 numClipRects = dPriv->numClipRects;
505 }
506
507 if (src->cpp == 4) {
508 format = GL_BGRA;
509 type = GL_UNSIGNED_BYTE;
510 }
511 else {
512 format = GL_BGR;
513 type = GL_UNSIGNED_SHORT_5_6_5_REV;
514 }
515
516 /* set the whole screen up as a texture to avoid alignment issues */
517 intel->vtbl.meta_tex_rect_source(intel,
518 src->buffer,
519 screen->width,
520 screen->height, src->pitch, format, type);
521
522 intel->vtbl.meta_texture_blend_replace(intel);
523
524 /*
525 * loop over the source window's cliprects
526 */
527 for (i = 0; i < numClipRects; i++) {
528 int srcX0 = clipRects[i].x1;
529 int srcY0 = clipRects[i].y1;
530 int srcX1 = clipRects[i].x2;
531 int srcY1 = clipRects[i].y2;
532 GLfloat verts[4][2], tex[4][2];
533 int j;
534
535 /* build vertices for four corners of clip rect */
536 verts[0][0] = srcX0;
537 verts[0][1] = srcY0;
538 verts[1][0] = srcX1;
539 verts[1][1] = srcY0;
540 verts[2][0] = srcX1;
541 verts[2][1] = srcY1;
542 verts[3][0] = srcX0;
543 verts[3][1] = srcY1;
544
545 /* .. and texcoords */
546 tex[0][0] = srcX0;
547 tex[0][1] = srcY0;
548 tex[1][0] = srcX1;
549 tex[1][1] = srcY0;
550 tex[2][0] = srcX1;
551 tex[2][1] = srcY1;
552 tex[3][0] = srcX0;
553 tex[3][1] = srcY1;
554
555 /* transform coords to rotated screen coords */
556
557 for (j = 0; j < 4; j++) {
558 matrix23TransformCoordf(&screen->rotMatrix,
559 &verts[j][0], &verts[j][1]);
560 }
561
562 /* draw polygon to map source image to dest region */
563 intel_meta_draw_poly(intel, 4, verts, 0, 0, tex);
564
565 } /* cliprect loop */
566
567 intel->vtbl.leave_meta_state(intel);
568 intel_batchbuffer_flush(intel->batch);
569
570 /* restore original drawing origin and cliprects */
571 intel->drawX = xOrig;
572 intel->drawY = yOrig;
573 intel->numClipRects = origNumClipRects;
574 intel->pClipRects = origRects;
575
576 UNLOCK_HARDWARE(intel);
577 }
578
579
580 /**
581 * Called by ctx->Driver.Clear.
582 */
583 static void
584 intelClear(GLcontext *ctx, GLbitfield mask)
585 {
586 struct intel_context *intel = intel_context(ctx);
587 const GLuint colorMask = *((GLuint *) & ctx->Color.ColorMask);
588 GLbitfield tri_mask = 0;
589 GLbitfield blit_mask = 0;
590 GLbitfield swrast_mask = 0;
591 struct gl_framebuffer *fb = ctx->DrawBuffer;
592 GLuint i;
593
594 if (0)
595 fprintf(stderr, "%s\n", __FUNCTION__);
596
597 /* HW color buffers (front, back, aux, generic FBO, etc) */
598 if (colorMask == ~0) {
599 /* clear all R,G,B,A */
600 /* XXX FBO: need to check if colorbuffers are software RBOs! */
601 blit_mask |= (mask & BUFFER_BITS_COLOR);
602 }
603 else {
604 /* glColorMask in effect */
605 tri_mask |= (mask & BUFFER_BITS_COLOR);
606 }
607
608 /* HW stencil */
609 if (mask & BUFFER_BIT_STENCIL) {
610 const struct intel_region *stencilRegion
611 = intel_get_rb_region(fb, BUFFER_STENCIL);
612 if (stencilRegion) {
613 /* have hw stencil */
614 if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff) {
615 /* not clearing all stencil bits, so use triangle clearing */
616 tri_mask |= BUFFER_BIT_STENCIL;
617 }
618 else {
619 /* clearing all stencil bits, use blitting */
620 blit_mask |= BUFFER_BIT_STENCIL;
621 }
622 }
623 }
624
625 /* HW depth */
626 if (mask & BUFFER_BIT_DEPTH) {
627 /* clear depth with whatever method is used for stencil (see above) */
628 if (tri_mask & BUFFER_BIT_STENCIL)
629 tri_mask |= BUFFER_BIT_DEPTH;
630 else
631 blit_mask |= BUFFER_BIT_DEPTH;
632 }
633
634 /* SW fallback clearing */
635 swrast_mask = mask & ~tri_mask & ~blit_mask;
636
637 for (i = 0; i < BUFFER_COUNT; i++) {
638 GLuint bufBit = 1 << i;
639 if ((blit_mask | tri_mask) & bufBit) {
640 if (!fb->Attachment[i].Renderbuffer->ClassID) {
641 blit_mask &= ~bufBit;
642 tri_mask &= ~bufBit;
643 swrast_mask |= bufBit;
644 }
645 }
646 }
647
648
649 intelFlush(ctx); /* XXX intelClearWithBlit also does this */
650
651 if (blit_mask)
652 intelClearWithBlit(ctx, blit_mask);
653
654 if (tri_mask)
655 intelClearWithTris(intel, tri_mask);
656
657 if (swrast_mask)
658 _swrast_Clear(ctx, swrast_mask);
659 }
660
661
662 /* Emit wait for pending flips */
663 void
664 intel_wait_flips(struct intel_context *intel, GLuint batch_flags)
665 {
666 struct intel_framebuffer *intel_fb =
667 (struct intel_framebuffer *) intel->ctx.DrawBuffer;
668 struct intel_renderbuffer *intel_rb =
669 intel_get_renderbuffer(&intel_fb->Base,
670 intel_fb->Base._ColorDrawBufferMask[0] ==
671 BUFFER_BIT_FRONT_LEFT ? BUFFER_FRONT_LEFT :
672 BUFFER_BACK_LEFT);
673
674 if (intel_fb->Base.Name == 0 && intel_rb->pf_pending == intel_fb->pf_seq) {
675 GLint pf_pipes = intel_fb->pf_pipes;
676 BATCH_LOCALS;
677
678 /* Wait for pending flips to take effect */
679 BEGIN_BATCH(2, batch_flags);
680 OUT_BATCH(pf_pipes & 0x1 ? (MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP)
681 : 0);
682 OUT_BATCH(pf_pipes & 0x2 ? (MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_B_FLIP)
683 : 0);
684 ADVANCE_BATCH();
685
686 intel_rb->pf_pending--;
687 }
688 }
689
690
691 /* Flip the front & back buffers
692 */
693 static GLboolean
694 intelPageFlip(const __DRIdrawablePrivate * dPriv)
695 {
696 struct intel_context *intel;
697 int ret;
698 struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
699
700 if (INTEL_DEBUG & DEBUG_IOCTL)
701 fprintf(stderr, "%s\n", __FUNCTION__);
702
703 assert(dPriv);
704 assert(dPriv->driContextPriv);
705 assert(dPriv->driContextPriv->driverPrivate);
706
707 intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate;
708
709 if (intel->intelScreen->drmMinor < 9)
710 return GL_FALSE;
711
712 intelFlush(&intel->ctx);
713
714 ret = 0;
715
716 LOCK_HARDWARE(intel);
717
718 if (dPriv->numClipRects && intel_fb->pf_active) {
719 drm_i915_flip_t flip;
720
721 flip.pipes = intel_fb->pf_pipes;
722
723 ret = drmCommandWrite(intel->driFd, DRM_I915_FLIP, &flip, sizeof(flip));
724 }
725
726 UNLOCK_HARDWARE(intel);
727
728 if (ret || !intel_fb->pf_active)
729 return GL_FALSE;
730
731 if (!dPriv->numClipRects) {
732 usleep(10000); /* throttle invisible client 10ms */
733 }
734
735 intel_fb->pf_current_page = (intel->sarea->pf_current_page >>
736 (intel_fb->pf_pipes & 0x2)) & 0x3;
737
738 if (dPriv->numClipRects != 0) {
739 intel_get_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT)->pf_pending =
740 intel_get_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT)->pf_pending =
741 ++intel_fb->pf_seq;
742 }
743
744 intel_flip_renderbuffers(intel_fb);
745 intel_draw_buffer(&intel->ctx, &intel_fb->Base);
746
747 return GL_TRUE;
748 }
749
750 #if 0
751 void
752 intelSwapBuffers(__DRIdrawablePrivate * dPriv)
753 {
754 if (dPriv->driverPrivate) {
755 const struct gl_framebuffer *fb
756 = (struct gl_framebuffer *) dPriv->driverPrivate;
757 if (fb->Visual.doubleBufferMode) {
758 GET_CURRENT_CONTEXT(ctx);
759 if (ctx && ctx->DrawBuffer == fb) {
760 _mesa_notifySwapBuffers(ctx); /* flush pending rendering */
761 }
762 if (intel->doPageFlip) {
763 intelPageFlip(dPriv);
764 }
765 else {
766 intelCopyBuffer(dPriv);
767 }
768 }
769 }
770 else {
771 _mesa_problem(NULL,
772 "dPriv has no gl_framebuffer pointer in intelSwapBuffers");
773 }
774 }
775 #else
776 /* Trunk version:
777 */
778
779 static GLboolean
780 intelScheduleSwap(const __DRIdrawablePrivate * dPriv, GLboolean *missed_target)
781 {
782 struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
783 unsigned int interval = driGetVBlankInterval(dPriv, intel_fb->vblank_flags);
784 struct intel_context *intel =
785 intelScreenContext(dPriv->driScreenPriv->private);
786 const intelScreenPrivate *intelScreen = intel->intelScreen;
787 unsigned int target;
788 drm_i915_vblank_swap_t swap;
789 GLboolean ret;
790
791 if (!intel_fb->vblank_flags ||
792 (intel_fb->vblank_flags & VBLANK_FLAG_NO_IRQ) ||
793 intelScreen->current_rotation != 0 ||
794 intelScreen->drmMinor < (intel_fb->pf_active ? 9 : 6))
795 return GL_FALSE;
796
797 swap.seqtype = DRM_VBLANK_ABSOLUTE;
798
799 if (intel_fb->vblank_flags & VBLANK_FLAG_SYNC) {
800 swap.seqtype |= DRM_VBLANK_NEXTONMISS;
801 } else if (interval == 0) {
802 return GL_FALSE;
803 }
804
805 swap.drawable = dPriv->hHWDrawable;
806 target = swap.sequence = intel_fb->vbl_seq + interval;
807
808 if ( intel_fb->vblank_flags & VBLANK_FLAG_SECONDARY ) {
809 swap.seqtype |= DRM_VBLANK_SECONDARY;
810 }
811
812 LOCK_HARDWARE(intel);
813
814 intel_batchbuffer_flush(intel->batch);
815
816 if ( intel_fb->pf_active ) {
817 swap.seqtype |= DRM_VBLANK_FLIP;
818
819 intel_fb->pf_current_page = (((intel->sarea->pf_current_page >>
820 (intel_fb->pf_pipes & 0x2)) & 0x3) + 1) %
821 intel_fb->pf_num_pages;
822 }
823
824 if (!drmCommandWriteRead(intel->driFd, DRM_I915_VBLANK_SWAP, &swap,
825 sizeof(swap))) {
826 intel_fb->vbl_seq = swap.sequence;
827 swap.sequence -= target;
828 *missed_target = swap.sequence > 0 && swap.sequence <= (1 << 23);
829
830 intel_get_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT)->vbl_pending =
831 intel_get_renderbuffer(&intel_fb->Base,
832 BUFFER_FRONT_LEFT)->vbl_pending =
833 intel_fb->vbl_seq;
834
835 if (swap.seqtype & DRM_VBLANK_FLIP) {
836 intel_flip_renderbuffers(intel_fb);
837 intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer);
838 }
839
840 ret = GL_TRUE;
841 } else {
842 if (swap.seqtype & DRM_VBLANK_FLIP) {
843 intel_fb->pf_current_page = ((intel->sarea->pf_current_page >>
844 (intel_fb->pf_pipes & 0x2)) & 0x3) %
845 intel_fb->pf_num_pages;
846 }
847
848 ret = GL_FALSE;
849 }
850
851 UNLOCK_HARDWARE(intel);
852
853 return ret;
854 }
855
856 void
857 intelSwapBuffers(__DRIdrawablePrivate * dPriv)
858 {
859 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
860 GET_CURRENT_CONTEXT(ctx);
861 struct intel_context *intel;
862
863 if (ctx == NULL)
864 return;
865
866 intel = intel_context(ctx);
867
868 if (ctx->Visual.doubleBufferMode) {
869 intelScreenPrivate *screen = intel->intelScreen;
870 GLboolean missed_target;
871 struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
872 int64_t ust;
873
874 _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
875
876 if (screen->current_rotation != 0 ||
877 !intelScheduleSwap(dPriv, &missed_target)) {
878 driWaitForVBlank(dPriv, &intel_fb->vbl_seq, intel_fb->vblank_flags,
879 &missed_target);
880
881 if (screen->current_rotation != 0 || !intelPageFlip(dPriv)) {
882 intelCopyBuffer(dPriv, NULL);
883 }
884
885 if (screen->current_rotation != 0) {
886 intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT);
887 }
888 }
889
890 intel_fb->swap_count++;
891 (*dri_interface->getUST) (&ust);
892 if (missed_target) {
893 intel_fb->swap_missed_count++;
894 intel_fb->swap_missed_ust = ust - intel_fb->swap_ust;
895 }
896
897 intel_fb->swap_ust = ust;
898 }
899 }
900 else {
901 /* XXX this shouldn't be an error but we can't handle it for now */
902 fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
903 }
904 }
905 #endif
906
907 void
908 intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
909 {
910 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
911 struct intel_context *intel =
912 (struct intel_context *) dPriv->driContextPriv->driverPrivate;
913 GLcontext *ctx = &intel->ctx;
914
915 if (ctx->Visual.doubleBufferMode) {
916 drm_clip_rect_t rect;
917 #if 1
918 rect.x1 = x + dPriv->x;
919 rect.y1 = (dPriv->h - y - h) + dPriv->y;
920 rect.x2 = rect.x1 + w;
921 rect.y2 = rect.y1 + h;
922 #else
923 rect.x1 = x;
924 rect.y1 = dPriv->h - y;
925 rect.x2 = rect.x1 + w;
926 rect.y2 = rect.y1 + h;
927 #endif
928 _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
929 intelCopyBuffer(dPriv, &rect);
930 }
931 }
932 else {
933 /* XXX this shouldn't be an error but we can't handle it for now */
934 fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
935 }
936 }
937
938
939 /**
940 * Update the hardware state for drawing into a window or framebuffer object.
941 *
942 * Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other
943 * places within the driver.
944 *
945 * Basically, this needs to be called any time the current framebuffer
946 * changes, the renderbuffers change, or we need to draw into different
947 * color buffers.
948 */
949 void
950 intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
951 {
952 struct intel_context *intel = intel_context(ctx);
953 struct intel_region *colorRegion, *depthRegion = NULL;
954 struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL;
955 int front = 0; /* drawing to front color buffer? */
956
957 if (!fb) {
958 /* this can happen during the initial context initialization */
959 return;
960 }
961
962 /* Do this here, not core Mesa, since this function is called from
963 * many places within the driver.
964 */
965 if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
966 /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
967 _mesa_update_framebuffer(ctx);
968 /* this updates the DrawBuffer's Width/Height if it's a FBO */
969 _mesa_update_draw_buffer_bounds(ctx);
970 }
971
972 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
973 /* this may occur when we're called by glBindFrameBuffer() during
974 * the process of someone setting up renderbuffers, etc.
975 */
976 /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
977 return;
978 }
979
980 if (fb->Name)
981 intel_validate_paired_depth_stencil(ctx, fb);
982
983 /*
984 * How many color buffers are we drawing into?
985 */
986 if (fb->_NumColorDrawBuffers[0] != 1) {
987 /* writing to 0 or 2 or 4 color buffers */
988 /*_mesa_debug(ctx, "Software rendering\n");*/
989 FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
990 front = 1; /* might not have back color buffer */
991 }
992 else {
993 /* draw to exactly one color buffer */
994 /*_mesa_debug(ctx, "Hardware rendering\n");*/
995 FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE);
996 if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) {
997 front = 1;
998 }
999 }
1000
1001 /*
1002 * Get the intel_renderbuffer for the colorbuffer we're drawing into.
1003 * And set up cliprects.
1004 */
1005 if (fb->Name == 0) {
1006 intelSetPrivbufClipRects(intel);
1007 /* drawing to window system buffer */
1008 if (front) {
1009 colorRegion = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
1010 }
1011 else {
1012 colorRegion = intel_get_rb_region(fb, BUFFER_BACK_LEFT);
1013 }
1014 }
1015 else {
1016 /* drawing to user-created FBO */
1017 struct intel_renderbuffer *irb;
1018 intelSetRenderbufferClipRects(intel);
1019 irb = intel_renderbuffer(fb->_ColorDrawBuffers[0][0]);
1020 colorRegion = (irb && irb->region) ? irb->region : NULL;
1021 }
1022
1023 /* Update culling direction which changes depending on the
1024 * orientation of the buffer:
1025 */
1026 if (ctx->Driver.FrontFace)
1027 ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
1028 else
1029 ctx->NewState |= _NEW_POLYGON;
1030
1031 if (!colorRegion) {
1032 FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
1033 }
1034 else {
1035 FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE);
1036 }
1037
1038 /***
1039 *** Get depth buffer region and check if we need a software fallback.
1040 *** Note that the depth buffer is usually a DEPTH_STENCIL buffer.
1041 ***/
1042 if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) {
1043 irbDepth = intel_renderbuffer(fb->_DepthBuffer->Wrapped);
1044 if (irbDepth && irbDepth->region) {
1045 FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
1046 depthRegion = irbDepth->region;
1047 }
1048 else {
1049 FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_TRUE);
1050 depthRegion = NULL;
1051 }
1052 }
1053 else {
1054 /* not using depth buffer */
1055 FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
1056 depthRegion = NULL;
1057 }
1058
1059 /***
1060 *** Stencil buffer
1061 *** This can only be hardware accelerated if we're using a
1062 *** combined DEPTH_STENCIL buffer (for now anyway).
1063 ***/
1064 if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) {
1065 irbStencil = intel_renderbuffer(fb->_StencilBuffer->Wrapped);
1066 if (irbStencil && irbStencil->region) {
1067 ASSERT(irbStencil->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
1068 FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
1069 /* need to re-compute stencil hw state */
1070 ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
1071 if (!depthRegion)
1072 depthRegion = irbStencil->region;
1073 }
1074 else {
1075 FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_TRUE);
1076 }
1077 }
1078 else {
1079 /* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */
1080 FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
1081 /* need to re-compute stencil hw state */
1082 ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
1083 }
1084
1085
1086 /**
1087 ** Release old regions, reference new regions
1088 **/
1089 #if 0 /* XXX FBO: this seems to be redundant with i915_state_draw_region() */
1090 if (intel->draw_region != colorRegion) {
1091 intel_region_release(&intel->draw_region);
1092 intel_region_reference(&intel->draw_region, colorRegion);
1093 }
1094 if (intel->intelScreen->depth_region != depthRegion) {
1095 intel_region_release(&intel->intelScreen->depth_region);
1096 intel_region_reference(&intel->intelScreen->depth_region, depthRegion);
1097 }
1098 #endif
1099
1100 intel->vtbl.set_draw_region(intel, colorRegion, depthRegion);
1101
1102 /* update viewport since it depends on window size */
1103 ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y,
1104 ctx->Viewport.Width, ctx->Viewport.Height);
1105
1106 /* Update hardware scissor */
1107 ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
1108 ctx->Scissor.Width, ctx->Scissor.Height);
1109 }
1110
1111
1112 static void
1113 intelDrawBuffer(GLcontext * ctx, GLenum mode)
1114 {
1115 intel_draw_buffer(ctx, ctx->DrawBuffer);
1116 }
1117
1118
1119 static void
1120 intelReadBuffer(GLcontext * ctx, GLenum mode)
1121 {
1122 if (ctx->ReadBuffer == ctx->DrawBuffer) {
1123 /* This will update FBO completeness status.
1124 * A framebuffer will be incomplete if the GL_READ_BUFFER setting
1125 * refers to a missing renderbuffer. Calling glReadBuffer can set
1126 * that straight and can make the drawing buffer complete.
1127 */
1128 intel_draw_buffer(ctx, ctx->DrawBuffer);
1129 }
1130 /* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc)
1131 * reference ctx->ReadBuffer and do appropriate state checks.
1132 */
1133 }
1134
1135
1136 void
1137 intelInitBufferFuncs(struct dd_function_table *functions)
1138 {
1139 functions->Clear = intelClear;
1140 functions->DrawBuffer = intelDrawBuffer;
1141 functions->ReadBuffer = intelReadBuffer;
1142 }