3da1420cddc2dccaec390b0c1f3f251f62a979ef
[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 "context.h"
38 #include "utils.h"
39 #include "framebuffer.h"
40 #include "swrast/swrast.h"
41 #include "vblank.h"
42
43
44 /**
45 * XXX move this into a new dri/common/cliprects.c file.
46 */
47 GLboolean
48 intel_intersect_cliprects(drm_clip_rect_t * dst,
49 const drm_clip_rect_t * a,
50 const drm_clip_rect_t * b)
51 {
52 GLint bx = b->x1;
53 GLint by = b->y1;
54 GLint bw = b->x2 - bx;
55 GLint bh = b->y2 - by;
56
57 if (bx < a->x1)
58 bw -= a->x1 - bx, bx = a->x1;
59 if (by < a->y1)
60 bh -= a->y1 - by, by = a->y1;
61 if (bx + bw > a->x2)
62 bw = a->x2 - bx;
63 if (by + bh > a->y2)
64 bh = a->y2 - by;
65 if (bw <= 0)
66 return GL_FALSE;
67 if (bh <= 0)
68 return GL_FALSE;
69
70 dst->x1 = bx;
71 dst->y1 = by;
72 dst->x2 = bx + bw;
73 dst->y2 = by + bh;
74
75 return GL_TRUE;
76 }
77
78 /**
79 * Return pointer to current color drawing region, or NULL.
80 */
81 struct intel_region *
82 intel_drawbuf_region(struct intel_context *intel)
83 {
84 struct intel_renderbuffer *irbColor =
85 intel_renderbuffer(intel->ctx.DrawBuffer->_ColorDrawBuffers[0][0]);
86 if (irbColor)
87 return irbColor->region;
88 else
89 return NULL;
90 }
91
92 /**
93 * Return pointer to current color reading region, or NULL.
94 */
95 struct intel_region *
96 intel_readbuf_region(struct intel_context *intel)
97 {
98 struct intel_renderbuffer *irb
99 = intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer);
100 if (irb)
101 return irb->region;
102 else
103 return NULL;
104 }
105
106
107
108 static void
109 intelBufferSize(GLframebuffer * buffer, GLuint * width, GLuint * height)
110 {
111 GET_CURRENT_CONTEXT(ctx);
112 struct intel_context *intel = intel_context(ctx);
113 /* Need to lock to make sure the driDrawable is uptodate. This
114 * information is used to resize Mesa's software buffers, so it has
115 * to be correct.
116 */
117 /* XXX This isn't 100% correct, the given buffer might not be
118 * bound to the current context!
119 */
120 LOCK_HARDWARE(intel);
121 if (intel->driDrawable) {
122 *width = intel->driDrawable->w;
123 *height = intel->driDrawable->h;
124 }
125 else {
126 *width = 0;
127 *height = 0;
128 }
129 UNLOCK_HARDWARE(intel);
130 }
131
132
133
134 /**
135 * Update the following fields for rendering to a user-created FBO:
136 * intel->numClipRects
137 * intel->pClipRects
138 * intel->drawX
139 * intel->drawY
140 */
141 static void
142 intelSetRenderbufferClipRects(struct intel_context *intel)
143 {
144 assert(intel->ctx.DrawBuffer->Width > 0);
145 assert(intel->ctx.DrawBuffer->Height > 0);
146 intel->fboRect.x1 = 0;
147 intel->fboRect.y1 = 0;
148 intel->fboRect.x2 = intel->ctx.DrawBuffer->Width;
149 intel->fboRect.y2 = intel->ctx.DrawBuffer->Height;
150 intel->numClipRects = 1;
151 intel->pClipRects = &intel->fboRect;
152 intel->drawX = 0;
153 intel->drawY = 0;
154 }
155
156
157 /**
158 * As above, but for rendering to front buffer of a window.
159 * \sa intelSetRenderbufferClipRects
160 */
161 static void
162 intelSetFrontClipRects(struct intel_context *intel)
163 {
164 __DRIdrawablePrivate *dPriv = intel->driDrawable;
165
166 if (!dPriv)
167 return;
168
169 intel->numClipRects = dPriv->numClipRects;
170 intel->pClipRects = dPriv->pClipRects;
171 intel->drawX = dPriv->x;
172 intel->drawY = dPriv->y;
173 }
174
175
176 /**
177 * As above, but for rendering to back buffer of a window.
178 */
179 static void
180 intelSetBackClipRects(struct intel_context *intel)
181 {
182 __DRIdrawablePrivate *dPriv = intel->driDrawable;
183
184 if (!dPriv)
185 return;
186
187 if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) {
188 /* use the front clip rects */
189 intel->numClipRects = dPriv->numClipRects;
190 intel->pClipRects = dPriv->pClipRects;
191 intel->drawX = dPriv->x;
192 intel->drawY = dPriv->y;
193 }
194 else {
195 /* use the back clip rects */
196 intel->numClipRects = dPriv->numBackClipRects;
197 intel->pClipRects = dPriv->pBackClipRects;
198 intel->drawX = dPriv->backX;
199 intel->drawY = dPriv->backY;
200 }
201 }
202
203
204 /**
205 * This will be called whenever the currently bound window is moved/resized.
206 * XXX: actually, it seems to NOT be called when the window is only moved (BP).
207 */
208 void
209 intelWindowMoved(struct intel_context *intel)
210 {
211 GLcontext *ctx = &intel->ctx;
212
213 if (!intel->ctx.DrawBuffer) {
214 /* when would this happen? -BP */
215 intelSetFrontClipRects(intel);
216 }
217 else if (intel->ctx.DrawBuffer->Name != 0) {
218 /* drawing to user-created FBO - do nothing */
219 /* Cliprects would be set from intelDrawBuffer() */
220 }
221 else {
222 /* drawing to a window */
223 switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) {
224 case BUFFER_BIT_FRONT_LEFT:
225 intelSetFrontClipRects(intel);
226 break;
227 case BUFFER_BIT_BACK_LEFT:
228 intelSetBackClipRects(intel);
229 break;
230 default:
231 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
232 intelSetFrontClipRects(intel);
233 }
234 }
235
236 /* this update Mesa's notion of window size */
237 if (ctx->WinSysDrawBuffer) {
238 _mesa_resize_framebuffer(ctx, ctx->WinSysDrawBuffer,
239 intel->driDrawable->w, intel->driDrawable->h);
240 }
241
242 if (intel->intelScreen->driScrnPriv->ddxMinor >= 7 && intel->driDrawable) {
243 __DRIdrawablePrivate *dPriv = intel->driDrawable;
244 drmI830Sarea *sarea = intel->sarea;
245 drm_clip_rect_t drw_rect = { .x1 = dPriv->x, .x2 = dPriv->x + dPriv->w,
246 .y1 = dPriv->y, .y2 = dPriv->y + dPriv->h };
247 drm_clip_rect_t pipeA_rect = { .x1 = sarea->pipeA_x, .y1 = sarea->pipeA_y,
248 .x2 = sarea->pipeA_x + sarea->pipeA_w,
249 .y2 = sarea->pipeA_y + sarea->pipeA_h };
250 drm_clip_rect_t pipeB_rect = { .x1 = sarea->pipeB_x, .y1 = sarea->pipeB_y,
251 .x2 = sarea->pipeB_x + sarea->pipeB_w,
252 .y2 = sarea->pipeB_y + sarea->pipeB_h };
253 GLint areaA = driIntersectArea( drw_rect, pipeA_rect );
254 GLint areaB = driIntersectArea( drw_rect, pipeB_rect );
255 GLuint flags = intel->vblank_flags;
256
257 if (areaB > areaA || (areaA == areaB && areaB > 0)) {
258 flags = intel->vblank_flags | VBLANK_FLAG_SECONDARY;
259 } else {
260 flags = intel->vblank_flags & ~VBLANK_FLAG_SECONDARY;
261 }
262
263 if (flags != intel->vblank_flags) {
264 intel->vblank_flags = flags;
265 driGetCurrentVBlank(dPriv, intel->vblank_flags, &intel->vbl_seq);
266 }
267 } else {
268 intel->vblank_flags &= ~VBLANK_FLAG_SECONDARY;
269 }
270
271 /* Update hardware scissor */
272 ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
273 ctx->Scissor.Width, ctx->Scissor.Height);
274 }
275
276
277
278 /* A true meta version of this would be very simple and additionally
279 * machine independent. Maybe we'll get there one day.
280 */
281 static void
282 intelClearWithTris(struct intel_context *intel,
283 GLbitfield mask,
284 GLboolean allFoo, GLint cxFoo, GLint cyFoo, GLint cwFoo, GLint chFoo)
285 {
286 GLcontext *ctx = &intel->ctx;
287 drm_clip_rect_t clear;
288
289 if (INTEL_DEBUG & DEBUG_BLIT)
290 _mesa_printf("%s 0x%x\n", __FUNCTION__, mask);
291
292 LOCK_HARDWARE(intel);
293
294 /* XXX FBO: was: intel->driDrawable->numClipRects */
295 if (intel->numClipRects) {
296 GLint cx, cy, cw, ch;
297 GLuint buf;
298
299 intel->vtbl.install_meta_state(intel);
300
301 /* Get clear bounds after locking */
302 cx = ctx->DrawBuffer->_Xmin;
303 cy = ctx->DrawBuffer->_Ymin;
304 ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
305 cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
306
307 /* note: regardless of 'all', cx, cy, cw, ch are now correct */
308 clear.x1 = cx;
309 clear.y1 = cy;
310 clear.x2 = cx + cw;
311 clear.y2 = cy + ch;
312
313 /* Back and stencil cliprects are the same. Try and do both
314 * buffers at once:
315 */
316 if (mask &
317 (BUFFER_BIT_BACK_LEFT | BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH)) {
318 struct intel_region *backRegion =
319 intel_get_rb_region(ctx->DrawBuffer, BUFFER_BACK_LEFT);
320 struct intel_region *depthRegion =
321 intel_get_rb_region(ctx->DrawBuffer, BUFFER_DEPTH);
322 const GLuint clearColor = (backRegion && backRegion->cpp == 4)
323 ? intel->ClearColor8888 : intel->ClearColor565;
324
325 intel->vtbl.meta_draw_region(intel, backRegion, depthRegion);
326
327 if (mask & BUFFER_BIT_BACK_LEFT)
328 intel->vtbl.meta_color_mask(intel, GL_TRUE);
329 else
330 intel->vtbl.meta_color_mask(intel, GL_FALSE);
331
332 if (mask & BUFFER_BIT_STENCIL)
333 intel->vtbl.meta_stencil_replace(intel,
334 intel->ctx.Stencil.WriteMask[0],
335 intel->ctx.Stencil.Clear);
336 else
337 intel->vtbl.meta_no_stencil_write(intel);
338
339 if (mask & BUFFER_BIT_DEPTH)
340 intel->vtbl.meta_depth_replace(intel);
341 else
342 intel->vtbl.meta_no_depth_write(intel);
343
344 /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
345 * drawing origin may not be correctly emitted.
346 */
347 intel_meta_draw_quad(intel, clear.x1, clear.x2, clear.y1, clear.y2, intel->ctx.Depth.Clear, clearColor, 0, 0, 0, 0); /* texcoords */
348
349 mask &=
350 ~(BUFFER_BIT_BACK_LEFT | BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH);
351 }
352
353 /* clear the remaining (color) renderbuffers */
354 for (buf = 0; buf < BUFFER_COUNT && mask; buf++) {
355 const GLuint bufBit = 1 << buf;
356 if (mask & bufBit) {
357 struct intel_renderbuffer *irbColor =
358 intel_renderbuffer(ctx->DrawBuffer->
359 Attachment[buf].Renderbuffer);
360 GLuint color = (irbColor->region->cpp == 4)
361 ? intel->ClearColor8888 : intel->ClearColor565;
362
363 ASSERT(irbColor);
364
365 intel->vtbl.meta_no_depth_write(intel);
366 intel->vtbl.meta_no_stencil_write(intel);
367 intel->vtbl.meta_color_mask(intel, GL_TRUE);
368 intel->vtbl.meta_draw_region(intel, irbColor->region, NULL);
369
370 /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
371 * drawing origin may not be correctly emitted.
372 */
373 intel_meta_draw_quad(intel, clear.x1, clear.x2, clear.y1, clear.y2, 0, /* depth clear val */
374 color, 0, 0, 0, 0); /* texcoords */
375
376 mask &= ~bufBit;
377 }
378 }
379
380 intel->vtbl.leave_meta_state(intel);
381 intel_batchbuffer_flush(intel->batch);
382 }
383 UNLOCK_HARDWARE(intel);
384 }
385
386
387
388
389 /**
390 * Copy the window contents named by dPriv to the rotated (or reflected)
391 * color buffer.
392 * srcBuf is BUFFER_BIT_FRONT_LEFT or BUFFER_BIT_BACK_LEFT to indicate the source.
393 */
394 void
395 intelRotateWindow(struct intel_context *intel,
396 __DRIdrawablePrivate * dPriv, GLuint srcBuf)
397 {
398 intelScreenPrivate *screen = intel->intelScreen;
399 drm_clip_rect_t fullRect;
400 struct intel_region *src;
401 const drm_clip_rect_t *clipRects;
402 int numClipRects;
403 int i;
404 GLenum format, type;
405
406 int xOrig, yOrig;
407 int origNumClipRects;
408 drm_clip_rect_t *origRects;
409
410 /*
411 * set up hardware state
412 */
413 intelFlush(&intel->ctx);
414
415 LOCK_HARDWARE(intel);
416
417 if (!intel->numClipRects) {
418 UNLOCK_HARDWARE(intel);
419 return;
420 }
421
422 intel->vtbl.install_meta_state(intel);
423
424 intel->vtbl.meta_no_depth_write(intel);
425 intel->vtbl.meta_no_stencil_write(intel);
426 intel->vtbl.meta_color_mask(intel, GL_FALSE);
427
428
429 /* save current drawing origin and cliprects (restored at end) */
430 xOrig = intel->drawX;
431 yOrig = intel->drawY;
432 origNumClipRects = intel->numClipRects;
433 origRects = intel->pClipRects;
434
435 /*
436 * set drawing origin, cliprects for full-screen access to rotated screen
437 */
438 fullRect.x1 = 0;
439 fullRect.y1 = 0;
440 fullRect.x2 = screen->rotatedWidth;
441 fullRect.y2 = screen->rotatedHeight;
442 intel->drawX = 0;
443 intel->drawY = 0;
444 intel->numClipRects = 1;
445 intel->pClipRects = &fullRect;
446
447 intel->vtbl.meta_draw_region(intel, screen->rotated_region, NULL); /* ? */
448
449 if (srcBuf == BUFFER_BIT_FRONT_LEFT) {
450 src = intel->intelScreen->front_region;
451 clipRects = dPriv->pClipRects;
452 numClipRects = dPriv->numClipRects;
453 }
454 else {
455 src = intel->intelScreen->back_region;
456 clipRects = dPriv->pBackClipRects;
457 numClipRects = dPriv->numBackClipRects;
458 }
459
460 if (src->cpp == 4) {
461 format = GL_BGRA;
462 type = GL_UNSIGNED_BYTE;
463 }
464 else {
465 format = GL_BGR;
466 type = GL_UNSIGNED_SHORT_5_6_5_REV;
467 }
468
469 /* set the whole screen up as a texture to avoid alignment issues */
470 intel->vtbl.meta_tex_rect_source(intel,
471 src->buffer,
472 screen->width,
473 screen->height, src->pitch, format, type);
474
475 intel->vtbl.meta_texture_blend_replace(intel);
476
477 /*
478 * loop over the source window's cliprects
479 */
480 for (i = 0; i < numClipRects; i++) {
481 int srcX0 = clipRects[i].x1;
482 int srcY0 = clipRects[i].y1;
483 int srcX1 = clipRects[i].x2;
484 int srcY1 = clipRects[i].y2;
485 GLfloat verts[4][2], tex[4][2];
486 int j;
487
488 /* build vertices for four corners of clip rect */
489 verts[0][0] = srcX0;
490 verts[0][1] = srcY0;
491 verts[1][0] = srcX1;
492 verts[1][1] = srcY0;
493 verts[2][0] = srcX1;
494 verts[2][1] = srcY1;
495 verts[3][0] = srcX0;
496 verts[3][1] = srcY1;
497
498 /* .. and texcoords */
499 tex[0][0] = srcX0;
500 tex[0][1] = srcY0;
501 tex[1][0] = srcX1;
502 tex[1][1] = srcY0;
503 tex[2][0] = srcX1;
504 tex[2][1] = srcY1;
505 tex[3][0] = srcX0;
506 tex[3][1] = srcY1;
507
508 /* transform coords to rotated screen coords */
509
510 for (j = 0; j < 4; j++) {
511 matrix23TransformCoordf(&screen->rotMatrix,
512 &verts[j][0], &verts[j][1]);
513 }
514
515 /* draw polygon to map source image to dest region */
516 intel_meta_draw_poly(intel, 4, verts, 0, 0, tex);
517
518 } /* cliprect loop */
519
520 intel->vtbl.leave_meta_state(intel);
521 intel_batchbuffer_flush(intel->batch);
522
523 /* restore original drawing origin and cliprects */
524 intel->drawX = xOrig;
525 intel->drawY = yOrig;
526 intel->numClipRects = origNumClipRects;
527 intel->pClipRects = origRects;
528
529 UNLOCK_HARDWARE(intel);
530 }
531
532
533 /**
534 * Called by ctx->Driver.Clear.
535 */
536 static void
537 intelClear(GLcontext * ctx,
538 GLbitfield mask,
539 GLboolean allFoo, GLint cxFoo, GLint cyFoo, GLint cwFoo, GLint chFoo)
540 {
541 struct intel_context *intel = intel_context(ctx);
542 const GLuint colorMask = *((GLuint *) & ctx->Color.ColorMask);
543 GLbitfield tri_mask = 0;
544 GLbitfield blit_mask = 0;
545 GLbitfield swrast_mask = 0;
546 GLuint i;
547
548 if (0)
549 fprintf(stderr, "%s\n", __FUNCTION__);
550
551 /* HW color buffers (front, back, aux, generic FBO, etc) */
552 if (colorMask == ~0) {
553 /* clear all R,G,B,A */
554 /* XXX FBO: need to check if colorbuffers are software RBOs! */
555 blit_mask |= (mask & BUFFER_BITS_COLOR);
556 }
557 else {
558 /* glColorMask in effect */
559 tri_mask |= (mask & BUFFER_BITS_COLOR);
560 }
561
562 /* HW stencil */
563 if (mask & BUFFER_BIT_STENCIL) {
564 const struct intel_region *stencilRegion
565 = intel_get_rb_region(ctx->DrawBuffer, BUFFER_STENCIL);
566 if (stencilRegion) {
567 /* have hw stencil */
568 if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff) {
569 /* not clearing all stencil bits, so use triangle clearing */
570 tri_mask |= BUFFER_BIT_STENCIL;
571 }
572 else {
573 /* clearing all stencil bits, use blitting */
574 blit_mask |= BUFFER_BIT_STENCIL;
575 }
576 }
577 }
578
579 /* HW depth */
580 if (mask & BUFFER_BIT_DEPTH) {
581 /* clear depth with whatever method is used for stencil (see above) */
582 if (tri_mask & BUFFER_BIT_STENCIL)
583 tri_mask |= BUFFER_BIT_DEPTH;
584 else
585 blit_mask |= BUFFER_BIT_DEPTH;
586 }
587
588 /* SW fallback clearing */
589 swrast_mask = mask & ~tri_mask & ~blit_mask;
590
591 for (i = 0; i < BUFFER_COUNT; i++) {
592 GLuint bufBit = 1 << i;
593 if ((blit_mask | tri_mask) & bufBit) {
594 if (!ctx->DrawBuffer->Attachment[i].Renderbuffer->ClassID) {
595 blit_mask &= ~bufBit;
596 tri_mask &= ~bufBit;
597 swrast_mask |= bufBit;
598 }
599 }
600 }
601
602
603 intelFlush(ctx); /* XXX intelClearWithBlit also does this */
604
605 if (blit_mask)
606 intelClearWithBlit(ctx, blit_mask, 0, 0, 0, 0, 0);
607
608 if (tri_mask)
609 intelClearWithTris(intel, tri_mask, 0, 0, 0, 0, 0);
610
611 if (swrast_mask)
612 _swrast_Clear(ctx, swrast_mask, 0, 0, 0, 0, 0);
613 }
614
615
616
617 /* Flip the front & back buffers
618 */
619 static void
620 intelPageFlip(const __DRIdrawablePrivate * dPriv)
621 {
622 #if 0
623 struct intel_context *intel;
624 int tmp, ret;
625
626 if (INTEL_DEBUG & DEBUG_IOCTL)
627 fprintf(stderr, "%s\n", __FUNCTION__);
628
629 assert(dPriv);
630 assert(dPriv->driContextPriv);
631 assert(dPriv->driContextPriv->driverPrivate);
632
633 intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate;
634
635 intelFlush(&intel->ctx);
636 LOCK_HARDWARE(intel);
637
638 if (dPriv->pClipRects) {
639 *(drm_clip_rect_t *) intel->sarea->boxes = dPriv->pClipRects[0];
640 intel->sarea->nbox = 1;
641 }
642
643 ret = drmCommandNone(intel->driFd, DRM_I830_FLIP);
644 if (ret) {
645 fprintf(stderr, "%s: %d\n", __FUNCTION__, ret);
646 UNLOCK_HARDWARE(intel);
647 exit(1);
648 }
649
650 tmp = intel->sarea->last_enqueue;
651 intelRefillBatchLocked(intel);
652 UNLOCK_HARDWARE(intel);
653
654
655 intelSetDrawBuffer(&intel->ctx, intel->ctx.Color.DriverDrawBuffer);
656 #endif
657 }
658
659 #if 0
660 void
661 intelSwapBuffers(__DRIdrawablePrivate * dPriv)
662 {
663 if (dPriv->driverPrivate) {
664 const struct gl_framebuffer *fb
665 = (struct gl_framebuffer *) dPriv->driverPrivate;
666 if (fb->Visual.doubleBufferMode) {
667 GET_CURRENT_CONTEXT(ctx);
668 if (ctx && ctx->DrawBuffer == fb) {
669 _mesa_notifySwapBuffers(ctx); /* flush pending rendering */
670 }
671 if (0 /*intel->doPageFlip */ ) { /* doPageFlip is never set !!! */
672 intelPageFlip(dPriv);
673 }
674 else {
675 intelCopyBuffer(dPriv);
676 }
677 }
678 }
679 else {
680 _mesa_problem(NULL,
681 "dPriv has no gl_framebuffer pointer in intelSwapBuffers");
682 }
683 }
684 #else
685 /* Trunk version:
686 */
687 void
688 intelSwapBuffers(__DRIdrawablePrivate * dPriv)
689 {
690 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
691 GET_CURRENT_CONTEXT(ctx);
692 struct intel_context *intel;
693
694 if (ctx == NULL)
695 return;
696
697 intel = intel_context(ctx);
698
699 if (ctx->Visual.doubleBufferMode) {
700 intelScreenPrivate *screen = intel->intelScreen;
701 _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
702 if (0 /*intel->doPageFlip */ ) { /* doPageFlip is never set !!! */
703 intelPageFlip(dPriv);
704 }
705 else {
706 intelCopyBuffer(dPriv, NULL);
707 }
708 if (screen->current_rotation != 0) {
709 intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT);
710 }
711 }
712 }
713 else {
714 /* XXX this shouldn't be an error but we can't handle it for now */
715 fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
716 }
717 }
718 #endif
719
720 void
721 intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
722 {
723 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
724 struct intel_context *intel =
725 (struct intel_context *) dPriv->driContextPriv->driverPrivate;
726 GLcontext *ctx = &intel->ctx;
727
728 if (ctx->Visual.doubleBufferMode) {
729 drm_clip_rect_t rect;
730 rect.x1 = x + dPriv->x;
731 rect.y1 = (dPriv->h - y - h) + dPriv->y;
732 rect.x2 = rect.x1 + w;
733 rect.y2 = rect.y1 + h;
734 _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
735 intelCopyBuffer(dPriv, &rect);
736 }
737 }
738 else {
739 /* XXX this shouldn't be an error but we can't handle it for now */
740 fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
741 }
742 }
743
744
745 /**
746 * Update the hardware state for drawing into a window or framebuffer object.
747 *
748 * Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other
749 * places within the driver.
750 *
751 * Basically, this needs to be called any time the current framebuffer
752 * changes, the renderbuffers change, or we need to draw into different
753 * color buffers.
754 */
755 void
756 intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
757 {
758 struct intel_context *intel = intel_context(ctx);
759 struct intel_region *colorRegion, *depthRegion = NULL;
760 struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL;
761 int front = 0; /* drawing to front color buffer? */
762
763 if (!fb) {
764 /* this can happen during the initial context initialization */
765 return;
766 }
767
768 /* Do this here, note core Mesa, since this function is called from
769 * many places within the driver.
770 */
771 if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
772 /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
773 _mesa_update_framebuffer(ctx);
774 /* this updates the DrawBuffer's Width/Height if it's a FBO */
775 _mesa_update_draw_buffer_bounds(ctx);
776 }
777
778 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
779 /* this may occur when we're called by glBindFrameBuffer() during
780 * the process of someone setting up renderbuffers, etc.
781 */
782 /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
783 return;
784 }
785
786 if (fb->Name)
787 intel_validate_paired_depth_stencil(ctx, fb);
788
789 /*
790 * How many color buffers are we drawing into?
791 */
792 if (fb->_NumColorDrawBuffers[0] != 1
793 #if 0
794 /* XXX FBO temporary - always use software rendering */
795 || 1
796 #endif
797 ) {
798 /* writing to 0 or 2 or 4 color buffers */
799 /*_mesa_debug(ctx, "Software rendering\n");*/
800 FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
801 front = 1; /* might not have back color buffer */
802 }
803 else {
804 /* draw to exactly one color buffer */
805 /*_mesa_debug(ctx, "Hardware rendering\n");*/
806 FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE);
807 if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) {
808 front = 1;
809 }
810 }
811
812 /*
813 * Get the intel_renderbuffer for the colorbuffer we're drawing into.
814 * And set up cliprects.
815 */
816 if (fb->Name == 0) {
817 /* drawing to window system buffer */
818 if (intel->sarea->pf_current_page == 1) {
819 /* page flipped back/front */
820 front ^= 1;
821 }
822 if (front) {
823 intelSetFrontClipRects(intel);
824 colorRegion = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
825 }
826 else {
827 intelSetBackClipRects(intel);
828 colorRegion = intel_get_rb_region(fb, BUFFER_BACK_LEFT);
829 }
830 }
831 else {
832 /* drawing to user-created FBO */
833 struct intel_renderbuffer *irb;
834 intelSetRenderbufferClipRects(intel);
835 irb = intel_renderbuffer(fb->_ColorDrawBuffers[0][0]);
836 colorRegion = (irb && irb->region) ? irb->region : NULL;
837 }
838
839 /* Update culling direction which changes depending on the
840 * orientation of the buffer:
841 */
842 if (ctx->Driver.FrontFace)
843 ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
844 else
845 ctx->NewState |= _NEW_POLYGON;
846
847 if (!colorRegion) {
848 FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
849 }
850 else {
851 FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE);
852 }
853
854 /***
855 *** Get depth buffer region and check if we need a software fallback.
856 *** Note that the depth buffer is usually a DEPTH_STENCIL buffer.
857 ***/
858 if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) {
859 irbDepth = intel_renderbuffer(fb->_DepthBuffer->Wrapped);
860 if (irbDepth->region) {
861 FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
862 depthRegion = irbDepth->region;
863 }
864 else {
865 FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_TRUE);
866 depthRegion = NULL;
867 }
868 }
869 else {
870 /* not using depth buffer */
871 FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
872 depthRegion = NULL;
873 }
874
875 /***
876 *** Stencil buffer
877 *** This can only be hardware accelerated if we're using a
878 *** combined DEPTH_STENCIL buffer (for now anyway).
879 ***/
880 if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) {
881 irbStencil = intel_renderbuffer(fb->_StencilBuffer->Wrapped);
882 if (irbStencil && irbStencil->region) {
883 ASSERT(irbStencil->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
884 FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
885 /* need to re-compute stencil hw state */
886 ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
887 if (!depthRegion)
888 depthRegion = irbStencil->region;
889 }
890 else {
891 FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_TRUE);
892 }
893 }
894 else {
895 /* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */
896 FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
897 /* need to re-compute stencil hw state */
898 ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
899 }
900
901
902 /**
903 ** Release old regions, reference new regions
904 **/
905 #if 0 /* XXX FBO: this seems to be redundant with i915_state_draw_region() */
906 if (intel->draw_region != colorRegion) {
907 intel_region_release(&intel->draw_region);
908 intel_region_reference(&intel->draw_region, colorRegion);
909 }
910 if (intel->intelScreen->depth_region != depthRegion) {
911 intel_region_release(&intel->intelScreen->depth_region);
912 intel_region_reference(&intel->intelScreen->depth_region, depthRegion);
913 }
914 #endif
915
916 intel->vtbl.set_draw_region(intel, colorRegion, depthRegion);
917
918 /* update viewport since it depends on window size */
919 ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y,
920 ctx->Viewport.Width, ctx->Viewport.Height);
921
922 /* Update hardware scissor */
923 ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
924 ctx->Scissor.Width, ctx->Scissor.Height);
925 }
926
927
928 static void
929 intelDrawBuffer(GLcontext * ctx, GLenum mode)
930 {
931 intel_draw_buffer(ctx, ctx->DrawBuffer);
932 }
933
934
935 static void
936 intelReadBuffer(GLcontext * ctx, GLenum mode)
937 {
938 if (ctx->ReadBuffer == ctx->DrawBuffer) {
939 /* This will update FBO completeness status.
940 * A framebuffer will be incomplete if the GL_READ_BUFFER setting
941 * refers to a missing renderbuffer. Calling glReadBuffer can set
942 * that straight and can make the drawing buffer complete.
943 */
944 intel_draw_buffer(ctx, ctx->DrawBuffer);
945 }
946 /* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc)
947 * reference ctx->ReadBuffer and do appropriate state checks.
948 */
949 }
950
951
952 void
953 intelInitBufferFuncs(struct dd_function_table *functions)
954 {
955 functions->Clear = intelClear;
956 functions->GetBufferSize = intelBufferSize;
957 functions->ResizeBuffers = _mesa_resize_framebuffer;
958 functions->DrawBuffer = intelDrawBuffer;
959 functions->ReadBuffer = intelReadBuffer;
960 }