intel: remove/disable the "paired depth/stencil" code
[mesa.git] / src / mesa / drivers / dri / intel / 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_chipset.h"
33 #include "intel_depthstencil.h"
34 #include "intel_fbo.h"
35 #include "intel_regions.h"
36 #include "intel_batchbuffer.h"
37 #include "intel_reg.h"
38 #include "main/context.h"
39 #include "main/framebuffer.h"
40 #include "swrast/swrast.h"
41 #include "utils.h"
42 #include "drirenderbuffer.h"
43 #include "vblank.h"
44 #include "i915_drm.h"
45
46 #define FILE_DEBUG_FLAG DEBUG_BLIT
47
48 /**
49 * XXX move this into a new dri/common/cliprects.c file.
50 */
51 GLboolean
52 intel_intersect_cliprects(drm_clip_rect_t * dst,
53 const drm_clip_rect_t * a,
54 const drm_clip_rect_t * b)
55 {
56 GLint bx = b->x1;
57 GLint by = b->y1;
58 GLint bw = b->x2 - bx;
59 GLint bh = b->y2 - by;
60
61 if (bx < a->x1)
62 bw -= a->x1 - bx, bx = a->x1;
63 if (by < a->y1)
64 bh -= a->y1 - by, by = a->y1;
65 if (bx + bw > a->x2)
66 bw = a->x2 - bx;
67 if (by + bh > a->y2)
68 bh = a->y2 - by;
69 if (bw <= 0)
70 return GL_FALSE;
71 if (bh <= 0)
72 return GL_FALSE;
73
74 dst->x1 = bx;
75 dst->y1 = by;
76 dst->x2 = bx + bw;
77 dst->y2 = by + bh;
78
79 return GL_TRUE;
80 }
81
82 /**
83 * Return pointer to current color drawing region, or NULL.
84 */
85 struct intel_region *
86 intel_drawbuf_region(struct intel_context *intel)
87 {
88 struct intel_renderbuffer *irbColor =
89 intel_renderbuffer(intel->ctx.DrawBuffer->_ColorDrawBuffers[0]);
90 if (irbColor)
91 return irbColor->region;
92 else
93 return NULL;
94 }
95
96 /**
97 * Return pointer to current color reading region, or NULL.
98 */
99 struct intel_region *
100 intel_readbuf_region(struct intel_context *intel)
101 {
102 struct intel_renderbuffer *irb
103 = intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer);
104 if (irb)
105 return irb->region;
106 else
107 return NULL;
108 }
109
110 void
111 intel_get_cliprects(struct intel_context *intel,
112 struct drm_clip_rect **cliprects,
113 unsigned int *num_cliprects,
114 int *x_off, int *y_off)
115 {
116 __DRIdrawablePrivate *dPriv = intel->driDrawable;
117 struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
118
119 if (intel->constant_cliprect) {
120 /* FBO or DRI2 rendering, which can just use the fb's size. */
121 intel->fboRect.x1 = 0;
122 intel->fboRect.y1 = 0;
123 intel->fboRect.x2 = intel->ctx.DrawBuffer->Width;
124 intel->fboRect.y2 = intel->ctx.DrawBuffer->Height;
125
126 *cliprects = &intel->fboRect;
127 *num_cliprects = 1;
128 *x_off = 0;
129 *y_off = 0;
130 } else if (intel->front_cliprects || dPriv->numBackClipRects == 0) {
131 /* use the front clip rects */
132 *cliprects = dPriv->pClipRects;
133 *num_cliprects = dPriv->numClipRects;
134 *x_off = dPriv->x;
135 *y_off = dPriv->y;
136 }
137 else {
138 /* use the back clip rects */
139 *num_cliprects = dPriv->numBackClipRects;
140 *cliprects = dPriv->pBackClipRects;
141 *x_off = dPriv->backX;
142 *y_off = dPriv->backY;
143 }
144 }
145
146 /**
147 * This will be called whenever the currently bound window is moved/resized.
148 * XXX: actually, it seems to NOT be called when the window is only moved (BP).
149 */
150 void
151 intelWindowMoved(struct intel_context *intel)
152 {
153 GLcontext *ctx = &intel->ctx;
154 __DRIdrawablePrivate *dPriv = intel->driDrawable;
155 struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
156
157 if (!intel->intelScreen->driScrnPriv->dri2.enabled &&
158 intel->intelScreen->driScrnPriv->ddx_version.minor >= 7) {
159 volatile drm_i915_sarea_t *sarea = intel->sarea;
160 drm_clip_rect_t drw_rect = { .x1 = dPriv->x, .x2 = dPriv->x + dPriv->w,
161 .y1 = dPriv->y, .y2 = dPriv->y + dPriv->h };
162 drm_clip_rect_t planeA_rect = { .x1 = sarea->planeA_x, .y1 = sarea->planeA_y,
163 .x2 = sarea->planeA_x + sarea->planeA_w,
164 .y2 = sarea->planeA_y + sarea->planeA_h };
165 drm_clip_rect_t planeB_rect = { .x1 = sarea->planeB_x, .y1 = sarea->planeB_y,
166 .x2 = sarea->planeB_x + sarea->planeB_w,
167 .y2 = sarea->planeB_y + sarea->planeB_h };
168 GLint areaA = driIntersectArea( drw_rect, planeA_rect );
169 GLint areaB = driIntersectArea( drw_rect, planeB_rect );
170 GLuint flags = dPriv->vblFlags;
171
172 /* Update vblank info
173 */
174 if (areaB > areaA || (areaA == areaB && areaB > 0)) {
175 flags = dPriv->vblFlags | VBLANK_FLAG_SECONDARY;
176 } else {
177 flags = dPriv->vblFlags & ~VBLANK_FLAG_SECONDARY;
178 }
179
180 /* Check to see if we changed pipes */
181 if (flags != dPriv->vblFlags && dPriv->vblFlags &&
182 !(dPriv->vblFlags & VBLANK_FLAG_NO_IRQ)) {
183 int64_t count;
184 drmVBlank vbl;
185 int i;
186
187 /*
188 * Deal with page flipping
189 */
190 vbl.request.type = DRM_VBLANK_ABSOLUTE;
191
192 if ( dPriv->vblFlags & VBLANK_FLAG_SECONDARY ) {
193 vbl.request.type |= DRM_VBLANK_SECONDARY;
194 }
195
196 for (i = 0; i < 2; i++) {
197 if (!intel_fb->color_rb[i] ||
198 (intel_fb->vbl_waited - intel_fb->color_rb[i]->vbl_pending) <=
199 (1<<23))
200 continue;
201
202 vbl.request.sequence = intel_fb->color_rb[i]->vbl_pending;
203 drmWaitVBlank(intel->driFd, &vbl);
204 }
205
206 /*
207 * Update msc_base from old pipe
208 */
209 driDrawableGetMSC32(dPriv->driScreenPriv, dPriv, &count);
210 dPriv->msc_base = count;
211 /*
212 * Then get new vblank_base and vblSeq values
213 */
214 dPriv->vblFlags = flags;
215 driGetCurrentVBlank(dPriv);
216 dPriv->vblank_base = dPriv->vblSeq;
217
218 intel_fb->vbl_waited = dPriv->vblSeq;
219
220 for (i = 0; i < 2; i++) {
221 if (intel_fb->color_rb[i])
222 intel_fb->color_rb[i]->vbl_pending = intel_fb->vbl_waited;
223 }
224 }
225 } else {
226 dPriv->vblFlags &= ~VBLANK_FLAG_SECONDARY;
227 }
228
229 /* Update Mesa's notion of window size */
230 driUpdateFramebufferSize(ctx, dPriv);
231 intel_fb->Base.Initialized = GL_TRUE; /* XXX remove someday */
232
233 /* Update hardware scissor */
234 if (ctx->Driver.Scissor != NULL) {
235 ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
236 ctx->Scissor.Width, ctx->Scissor.Height);
237 }
238
239 /* Re-calculate viewport related state */
240 if (ctx->Driver.DepthRange != NULL)
241 ctx->Driver.DepthRange( ctx, ctx->Viewport.Near, ctx->Viewport.Far );
242 }
243
244
245
246 /* A true meta version of this would be very simple and additionally
247 * machine independent. Maybe we'll get there one day.
248 */
249 static void
250 intelClearWithTris(struct intel_context *intel, GLbitfield mask)
251 {
252 GLcontext *ctx = &intel->ctx;
253 struct gl_framebuffer *fb = ctx->DrawBuffer;
254 GLuint buf;
255
256 intel->vtbl.install_meta_state(intel);
257
258 /* Back and stencil cliprects are the same. Try and do both
259 * buffers at once:
260 */
261 if (mask & (BUFFER_BIT_BACK_LEFT | BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH)) {
262 struct intel_region *backRegion =
263 intel_get_rb_region(fb, BUFFER_BACK_LEFT);
264 struct intel_region *depthRegion =
265 intel_get_rb_region(fb, BUFFER_DEPTH);
266
267 intel->vtbl.meta_draw_region(intel, backRegion, depthRegion);
268
269 if (mask & BUFFER_BIT_BACK_LEFT)
270 intel->vtbl.meta_color_mask(intel, GL_TRUE);
271 else
272 intel->vtbl.meta_color_mask(intel, GL_FALSE);
273
274 if (mask & BUFFER_BIT_STENCIL)
275 intel->vtbl.meta_stencil_replace(intel,
276 intel->ctx.Stencil.WriteMask[0],
277 intel->ctx.Stencil.Clear);
278 else
279 intel->vtbl.meta_no_stencil_write(intel);
280
281 if (mask & BUFFER_BIT_DEPTH)
282 intel->vtbl.meta_depth_replace(intel);
283 else
284 intel->vtbl.meta_no_depth_write(intel);
285
286 intel->vtbl.meta_draw_quad(intel,
287 fb->_Xmin,
288 fb->_Xmax,
289 fb->_Ymin,
290 fb->_Ymax,
291 intel->ctx.Depth.Clear,
292 intel->ClearColor8888,
293 0, 0, 0, 0); /* texcoords */
294
295 mask &= ~(BUFFER_BIT_BACK_LEFT | BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH);
296 }
297
298 /* clear the remaining (color) renderbuffers */
299 for (buf = 0; buf < BUFFER_COUNT && mask; buf++) {
300 const GLuint bufBit = 1 << buf;
301 if (mask & bufBit) {
302 struct intel_renderbuffer *irbColor =
303 intel_renderbuffer(fb->Attachment[buf].Renderbuffer);
304
305 ASSERT(irbColor);
306
307 intel->vtbl.meta_no_depth_write(intel);
308 intel->vtbl.meta_no_stencil_write(intel);
309 intel->vtbl.meta_color_mask(intel, GL_TRUE);
310 intel->vtbl.meta_draw_region(intel, irbColor->region, NULL);
311
312 intel->vtbl.meta_draw_quad(intel,
313 fb->_Xmin,
314 fb->_Xmax,
315 fb->_Ymin,
316 fb->_Ymax,
317 0, intel->ClearColor8888,
318 0, 0, 0, 0); /* texcoords */
319
320 mask &= ~bufBit;
321 }
322 }
323
324 intel->vtbl.leave_meta_state(intel);
325 }
326
327 static const char *buffer_names[] = {
328 [BUFFER_FRONT_LEFT] = "front",
329 [BUFFER_BACK_LEFT] = "back",
330 [BUFFER_FRONT_RIGHT] = "front right",
331 [BUFFER_BACK_RIGHT] = "back right",
332 [BUFFER_AUX0] = "aux0",
333 [BUFFER_AUX1] = "aux1",
334 [BUFFER_AUX2] = "aux2",
335 [BUFFER_AUX3] = "aux3",
336 [BUFFER_DEPTH] = "depth",
337 [BUFFER_STENCIL] = "stencil",
338 [BUFFER_ACCUM] = "accum",
339 [BUFFER_COLOR0] = "color0",
340 [BUFFER_COLOR1] = "color1",
341 [BUFFER_COLOR2] = "color2",
342 [BUFFER_COLOR3] = "color3",
343 [BUFFER_COLOR4] = "color4",
344 [BUFFER_COLOR5] = "color5",
345 [BUFFER_COLOR6] = "color6",
346 [BUFFER_COLOR7] = "color7",
347 };
348
349 /**
350 * Called by ctx->Driver.Clear.
351 */
352 static void
353 intelClear(GLcontext *ctx, GLbitfield mask)
354 {
355 struct intel_context *intel = intel_context(ctx);
356 const GLuint colorMask = *((GLuint *) & ctx->Color.ColorMask);
357 GLbitfield tri_mask = 0;
358 GLbitfield blit_mask = 0;
359 GLbitfield swrast_mask = 0;
360 struct gl_framebuffer *fb = ctx->DrawBuffer;
361 GLuint i;
362
363 if (0)
364 fprintf(stderr, "%s\n", __FUNCTION__);
365
366 /* HW color buffers (front, back, aux, generic FBO, etc) */
367 if (colorMask == ~0) {
368 /* clear all R,G,B,A */
369 /* XXX FBO: need to check if colorbuffers are software RBOs! */
370 blit_mask |= (mask & BUFFER_BITS_COLOR);
371 }
372 else {
373 /* glColorMask in effect */
374 tri_mask |= (mask & BUFFER_BITS_COLOR);
375 }
376
377 /* HW stencil */
378 if (mask & BUFFER_BIT_STENCIL) {
379 const struct intel_region *stencilRegion
380 = intel_get_rb_region(fb, BUFFER_STENCIL);
381 if (stencilRegion) {
382 /* have hw stencil */
383 if (IS_965(intel->intelScreen->deviceID) ||
384 (ctx->Stencil.WriteMask[0] & 0xff) != 0xff) {
385 /* We have to use the 3D engine if we're clearing a partial mask
386 * of the stencil buffer, or if we're on a 965 which has a tiled
387 * depth/stencil buffer in a layout we can't blit to.
388 */
389 tri_mask |= BUFFER_BIT_STENCIL;
390 }
391 else {
392 /* clearing all stencil bits, use blitting */
393 blit_mask |= BUFFER_BIT_STENCIL;
394 }
395 }
396 }
397
398 /* HW depth */
399 if (mask & BUFFER_BIT_DEPTH) {
400 /* clear depth with whatever method is used for stencil (see above) */
401 if (IS_965(intel->intelScreen->deviceID) ||
402 tri_mask & BUFFER_BIT_STENCIL)
403 tri_mask |= BUFFER_BIT_DEPTH;
404 else
405 blit_mask |= BUFFER_BIT_DEPTH;
406 }
407
408 /* SW fallback clearing */
409 swrast_mask = mask & ~tri_mask & ~blit_mask;
410
411 for (i = 0; i < BUFFER_COUNT; i++) {
412 GLuint bufBit = 1 << i;
413 if ((blit_mask | tri_mask) & bufBit) {
414 if (!fb->Attachment[i].Renderbuffer->ClassID) {
415 blit_mask &= ~bufBit;
416 tri_mask &= ~bufBit;
417 swrast_mask |= bufBit;
418 }
419 }
420 }
421
422 if (blit_mask) {
423 if (INTEL_DEBUG & DEBUG_BLIT) {
424 DBG("blit clear:");
425 for (i = 0; i < BUFFER_COUNT; i++) {
426 if (blit_mask & (1 << i))
427 DBG(" %s", buffer_names[i]);
428 }
429 DBG("\n");
430 }
431 intelClearWithBlit(ctx, blit_mask);
432 }
433
434 if (tri_mask) {
435 if (INTEL_DEBUG & DEBUG_BLIT) {
436 DBG("tri clear:");
437 for (i = 0; i < BUFFER_COUNT; i++) {
438 if (tri_mask & (1 << i))
439 DBG(" %s", buffer_names[i]);
440 }
441 DBG("\n");
442 }
443 intelClearWithTris(intel, tri_mask);
444 }
445
446 if (swrast_mask) {
447 if (INTEL_DEBUG & DEBUG_BLIT) {
448 DBG("swrast clear:");
449 for (i = 0; i < BUFFER_COUNT; i++) {
450 if (swrast_mask & (1 << i))
451 DBG(" %s", buffer_names[i]);
452 }
453 DBG("\n");
454 }
455 _swrast_Clear(ctx, swrast_mask);
456 }
457 }
458
459 void
460 intelSwapBuffers(__DRIdrawablePrivate * dPriv)
461 {
462 __DRIscreenPrivate *psp = dPriv->driScreenPriv;
463
464 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
465 GET_CURRENT_CONTEXT(ctx);
466 struct intel_context *intel;
467
468 if (ctx == NULL)
469 return;
470
471 intel = intel_context(ctx);
472
473 if (ctx->Visual.doubleBufferMode) {
474 GLboolean missed_target;
475 struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
476 int64_t ust;
477
478 _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
479
480 /*
481 * The old swapping ioctl was incredibly racy, just wait for vblank
482 * and do the swap ourselves.
483 */
484 driWaitForVBlank(dPriv, &missed_target);
485
486 /*
487 * Update each buffer's vbl_pending so we don't get too out of
488 * sync
489 */
490 intel_get_renderbuffer(&intel_fb->Base,
491 BUFFER_BACK_LEFT)->vbl_pending = dPriv->vblSeq;
492 intel_get_renderbuffer(&intel_fb->Base,
493 BUFFER_FRONT_LEFT)->vbl_pending = dPriv->vblSeq;
494
495 intelCopyBuffer(dPriv, NULL);
496
497 intel_fb->swap_count++;
498 (*psp->systemTime->getUST) (&ust);
499 if (missed_target) {
500 intel_fb->swap_missed_count++;
501 intel_fb->swap_missed_ust = ust - intel_fb->swap_ust;
502 }
503
504 intel_fb->swap_ust = ust;
505 }
506 drmCommandNone(intel->driFd, DRM_I915_GEM_THROTTLE);
507
508 }
509 else {
510 /* XXX this shouldn't be an error but we can't handle it for now */
511 fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
512 }
513 }
514
515 void
516 intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
517 {
518 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
519 struct intel_context *intel =
520 (struct intel_context *) dPriv->driContextPriv->driverPrivate;
521 GLcontext *ctx = &intel->ctx;
522
523 if (ctx->Visual.doubleBufferMode) {
524 drm_clip_rect_t rect;
525 rect.x1 = x + dPriv->x;
526 rect.y1 = (dPriv->h - y - h) + dPriv->y;
527 rect.x2 = rect.x1 + w;
528 rect.y2 = rect.y1 + h;
529 _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
530 intelCopyBuffer(dPriv, &rect);
531 }
532 }
533 else {
534 /* XXX this shouldn't be an error but we can't handle it for now */
535 fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
536 }
537 }
538
539
540 /**
541 * Update the hardware state for drawing into a window or framebuffer object.
542 *
543 * Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other
544 * places within the driver.
545 *
546 * Basically, this needs to be called any time the current framebuffer
547 * changes, the renderbuffers change, or we need to draw into different
548 * color buffers.
549 */
550 void
551 intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
552 {
553 struct intel_context *intel = intel_context(ctx);
554 struct intel_region *colorRegions[MAX_DRAW_BUFFERS], *depthRegion = NULL;
555 struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL;
556
557 if (!fb) {
558 /* this can happen during the initial context initialization */
559 return;
560 }
561
562 /* Do this here, not core Mesa, since this function is called from
563 * many places within the driver.
564 */
565 if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
566 /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
567 _mesa_update_framebuffer(ctx);
568 /* this updates the DrawBuffer's Width/Height if it's a FBO */
569 _mesa_update_draw_buffer_bounds(ctx);
570 }
571
572 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
573 /* this may occur when we're called by glBindFrameBuffer() during
574 * the process of someone setting up renderbuffers, etc.
575 */
576 /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
577 return;
578 }
579
580 /*
581 * How many color buffers are we drawing into?
582 */
583 if (fb->_NumColorDrawBuffers == 0) {
584 /* writing to 0 */
585 colorRegions[0] = NULL;
586 intel->constant_cliprect = GL_TRUE;
587 }
588 else if (fb->_NumColorDrawBuffers > 1) {
589 int i;
590 struct intel_renderbuffer *irb;
591
592 for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
593 irb = intel_renderbuffer(fb->_ColorDrawBuffers[i]);
594 colorRegions[i] = irb ? irb->region : NULL;
595 }
596 intel->constant_cliprect = GL_TRUE;
597 }
598 else {
599 /* Get the intel_renderbuffer for the single colorbuffer we're drawing
600 * into, and set up cliprects if it's .
601 */
602 if (fb->Name == 0) {
603 intel->constant_cliprect = intel->driScreen->dri2.enabled;
604 /* drawing to window system buffer */
605 if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
606 if (!intel->constant_cliprect && !intel->front_cliprects)
607 intel_batchbuffer_flush(intel->batch);
608 intel->front_cliprects = GL_TRUE;
609 colorRegions[0] = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
610 }
611 else {
612 if (!intel->constant_cliprect && intel->front_cliprects)
613 intel_batchbuffer_flush(intel->batch);
614 intel->front_cliprects = GL_FALSE;
615 colorRegions[0]= intel_get_rb_region(fb, BUFFER_BACK_LEFT);
616 }
617 }
618 else {
619 /* drawing to user-created FBO */
620 struct intel_renderbuffer *irb;
621 irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]);
622 colorRegions[0] = (irb && irb->region) ? irb->region : NULL;
623 intel->constant_cliprect = GL_TRUE;
624 }
625 }
626
627 if (!colorRegions[0]) {
628 FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
629 }
630 else {
631 FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE);
632 }
633
634 /***
635 *** Get depth buffer region and check if we need a software fallback.
636 *** Note that the depth buffer is usually a DEPTH_STENCIL buffer.
637 ***/
638 if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) {
639 irbDepth = intel_renderbuffer(fb->_DepthBuffer->Wrapped);
640 if (irbDepth && irbDepth->region) {
641 FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
642 depthRegion = irbDepth->region;
643 }
644 else {
645 FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_TRUE);
646 depthRegion = NULL;
647 }
648 }
649 else {
650 /* not using depth buffer */
651 FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
652 depthRegion = NULL;
653 }
654
655 /***
656 *** Stencil buffer
657 *** This can only be hardware accelerated if we're using a
658 *** combined DEPTH_STENCIL buffer.
659 ***/
660 if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) {
661 irbStencil = intel_renderbuffer(fb->_StencilBuffer->Wrapped);
662 if (irbStencil && irbStencil->region) {
663 ASSERT(irbStencil->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
664 FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
665 }
666 else {
667 FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_TRUE);
668 }
669 }
670 else {
671 /* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */
672 FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
673 }
674
675 /*
676 * Update depth and stencil test state
677 */
678 if (ctx->Driver.Enable) {
679 ctx->Driver.Enable(ctx, GL_DEPTH_TEST,
680 (ctx->Depth.Test && fb->Visual.depthBits > 0));
681 ctx->Driver.Enable(ctx, GL_STENCIL_TEST,
682 (ctx->Stencil.Enabled && fb->Visual.stencilBits > 0));
683 }
684 else {
685 ctx->NewState |= (_NEW_DEPTH | _NEW_STENCIL);
686 }
687
688 intel->vtbl.set_draw_region(intel, colorRegions, depthRegion,
689 fb->_NumColorDrawBuffers);
690
691 /* update viewport since it depends on window size */
692 if (ctx->Driver.Viewport) {
693 ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y,
694 ctx->Viewport.Width, ctx->Viewport.Height);
695 }
696 else {
697 ctx->NewState |= _NEW_VIEWPORT;
698 }
699
700 /* Set state we know depends on drawable parameters:
701 */
702 if (ctx->Driver.Scissor)
703 ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
704 ctx->Scissor.Width, ctx->Scissor.Height);
705 intel->NewGLState |= _NEW_SCISSOR;
706
707 if (ctx->Driver.DepthRange)
708 ctx->Driver.DepthRange(ctx,
709 ctx->Viewport.Near,
710 ctx->Viewport.Far);
711
712 /* Update culling direction which changes depending on the
713 * orientation of the buffer:
714 */
715 if (ctx->Driver.FrontFace)
716 ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
717 else
718 ctx->NewState |= _NEW_POLYGON;
719 }
720
721
722 static void
723 intelDrawBuffer(GLcontext * ctx, GLenum mode)
724 {
725 intel_draw_buffer(ctx, ctx->DrawBuffer);
726 }
727
728
729 static void
730 intelReadBuffer(GLcontext * ctx, GLenum mode)
731 {
732 if (ctx->ReadBuffer == ctx->DrawBuffer) {
733 /* This will update FBO completeness status.
734 * A framebuffer will be incomplete if the GL_READ_BUFFER setting
735 * refers to a missing renderbuffer. Calling glReadBuffer can set
736 * that straight and can make the drawing buffer complete.
737 */
738 intel_draw_buffer(ctx, ctx->DrawBuffer);
739 }
740 /* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc)
741 * reference ctx->ReadBuffer and do appropriate state checks.
742 */
743 }
744
745
746 void
747 intelInitBufferFuncs(struct dd_function_table *functions)
748 {
749 functions->Clear = intelClear;
750 functions->DrawBuffer = intelDrawBuffer;
751 functions->ReadBuffer = intelReadBuffer;
752 }