Rename drivers/dri/i915pipe --> drivers/dri/intel_winsys.
[mesa.git] / src / mesa / drivers / dri / intel_winsys / 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_batchbuffer.h"
35 #include "intel_reg.h"
36 #include "context.h"
37 #include "utils.h"
38 #include "drirenderbuffer.h"
39 #include "framebuffer.h"
40 #include "vblank.h"
41
42 #include "pipe/p_context.h"
43
44 /* This block can be removed when libdrm >= 2.3.1 is required */
45
46 #ifndef DRM_VBLANK_FLIP
47
48 #define DRM_VBLANK_FLIP 0x8000000
49
50 typedef struct drm_i915_flip {
51 int pipes;
52 } drm_i915_flip_t;
53
54 #undef DRM_IOCTL_I915_FLIP
55 #define DRM_IOCTL_I915_FLIP DRM_IOW(DRM_COMMAND_BASE + DRM_I915_FLIP, \
56 drm_i915_flip_t)
57
58 #endif
59
60
61 /**
62 * XXX move this into a new dri/common/cliprects.c file.
63 */
64 GLboolean
65 intel_intersect_cliprects(drm_clip_rect_t * dst,
66 const drm_clip_rect_t * a,
67 const drm_clip_rect_t * b)
68 {
69 GLint bx = b->x1;
70 GLint by = b->y1;
71 GLint bw = b->x2 - bx;
72 GLint bh = b->y2 - by;
73
74 if (bx < a->x1)
75 bw -= a->x1 - bx, bx = a->x1;
76 if (by < a->y1)
77 bh -= a->y1 - by, by = a->y1;
78 if (bx + bw > a->x2)
79 bw = a->x2 - bx;
80 if (by + bh > a->y2)
81 bh = a->y2 - by;
82 if (bw <= 0)
83 return GL_FALSE;
84 if (bh <= 0)
85 return GL_FALSE;
86
87 dst->x1 = bx;
88 dst->y1 = by;
89 dst->x2 = bx + bw;
90 dst->y2 = by + bh;
91
92 return GL_TRUE;
93 }
94
95 /**
96 * Return pointer to current color drawing region, or NULL.
97 */
98 struct pipe_region *
99 intel_drawbuf_region(struct intel_context *intel)
100 {
101 struct intel_renderbuffer *irbColor =
102 intel_renderbuffer(intel->ctx.DrawBuffer->_ColorDrawBuffers[0][0]);
103 if (irbColor)
104 return irbColor->region;
105 else
106 return NULL;
107 }
108
109 /**
110 * Return pointer to current color reading region, or NULL.
111 */
112 struct pipe_region *
113 intel_readbuf_region(struct intel_context *intel)
114 {
115 struct intel_renderbuffer *irb
116 = intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer);
117 if (irb)
118 return irb->region;
119 else
120 return NULL;
121 }
122
123
124
125 /**
126 * Update the following fields for rendering:
127 * intel->numClipRects
128 * intel->pClipRects
129 */
130 static void
131 intelSetRenderbufferClipRects(struct intel_context *intel)
132 {
133 /* zero-sized buffers might be legal? */
134 assert(intel->ctx.DrawBuffer->Width > 0);
135 assert(intel->ctx.DrawBuffer->Height > 0);
136 intel->fboRect.x1 = 0;
137 intel->fboRect.y1 = 0;
138 intel->fboRect.x2 = intel->ctx.DrawBuffer->Width;
139 intel->fboRect.y2 = intel->ctx.DrawBuffer->Height;
140 intel->numClipRects = 1;
141 intel->pClipRects = &intel->fboRect;
142 }
143
144
145 /**
146 * This will be called whenever the currently bound window is moved/resized.
147 * XXX: actually, it seems to NOT be called when the window is only moved (BP).
148 */
149 void
150 intelWindowMoved(struct intel_context *intel)
151 {
152 GLcontext *ctx = &intel->ctx;
153 __DRIdrawablePrivate *dPriv = intel->driDrawable;
154 struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
155
156 if (!intel->ctx.DrawBuffer) {
157 /* when would this happen? -BP */
158 assert(0);
159 intel->numClipRects = 0;
160 }
161
162 /* Update Mesa's notion of window size */
163 driUpdateFramebufferSize(ctx, dPriv);
164 intel_fb->Base.Initialized = GL_TRUE; /* XXX remove someday */
165
166 {
167 drmI830Sarea *sarea = intel->sarea;
168 drm_clip_rect_t drw_rect = { .x1 = dPriv->x, .x2 = dPriv->x + dPriv->w,
169 .y1 = dPriv->y, .y2 = dPriv->y + dPriv->h };
170 drm_clip_rect_t pipeA_rect = { .x1 = sarea->pipeA_x, .y1 = sarea->pipeA_y,
171 .x2 = sarea->pipeA_x + sarea->pipeA_w,
172 .y2 = sarea->pipeA_y + sarea->pipeA_h };
173 drm_clip_rect_t pipeB_rect = { .x1 = sarea->pipeB_x, .y1 = sarea->pipeB_y,
174 .x2 = sarea->pipeB_x + sarea->pipeB_w,
175 .y2 = sarea->pipeB_y + sarea->pipeB_h };
176 GLint areaA = driIntersectArea( drw_rect, pipeA_rect );
177 GLint areaB = driIntersectArea( drw_rect, pipeB_rect );
178 GLuint flags = intel_fb->vblank_flags;
179 GLboolean pf_active;
180 GLint pf_pipes;
181
182 /* Update page flipping info
183 */
184 pf_pipes = 0;
185
186 if (areaA > 0)
187 pf_pipes |= 1;
188
189 if (areaB > 0)
190 pf_pipes |= 2;
191
192 intel_fb->pf_current_page = (intel->sarea->pf_current_page >>
193 (intel_fb->pf_pipes & 0x2)) & 0x3;
194
195 intel_fb->pf_num_pages = 2 /*intel->intelScreen->third.handle ? 3 : 2*/;
196
197 pf_active = pf_pipes && (pf_pipes & intel->sarea->pf_active) == pf_pipes;
198
199 if (INTEL_DEBUG & DEBUG_LOCK)
200 if (pf_active != intel_fb->pf_active)
201 _mesa_printf("%s - Page flipping %sactive\n", __progname,
202 pf_active ? "" : "in");
203
204 if (pf_active) {
205 /* Sync pages between pipes if we're flipping on both at the same time */
206 if (pf_pipes == 0x3 && pf_pipes != intel_fb->pf_pipes &&
207 (intel->sarea->pf_current_page & 0x3) !=
208 (((intel->sarea->pf_current_page) >> 2) & 0x3)) {
209 drm_i915_flip_t flip;
210
211 if (intel_fb->pf_current_page ==
212 (intel->sarea->pf_current_page & 0x3)) {
213 /* XXX: This is ugly, but emitting two flips 'in a row' can cause
214 * lockups for unknown reasons.
215 */
216 intel->sarea->pf_current_page =
217 intel->sarea->pf_current_page & 0x3;
218 intel->sarea->pf_current_page |=
219 ((intel_fb->pf_current_page + intel_fb->pf_num_pages - 1) %
220 intel_fb->pf_num_pages) << 2;
221
222 flip.pipes = 0x2;
223 } else {
224 intel->sarea->pf_current_page =
225 intel->sarea->pf_current_page & (0x3 << 2);
226 intel->sarea->pf_current_page |=
227 (intel_fb->pf_current_page + intel_fb->pf_num_pages - 1) %
228 intel_fb->pf_num_pages;
229
230 flip.pipes = 0x1;
231 }
232
233 drmCommandWrite(intel->driFd, DRM_I915_FLIP, &flip, sizeof(flip));
234 }
235
236 intel_fb->pf_pipes = pf_pipes;
237 }
238
239 intel_fb->pf_active = pf_active;
240 intel_flip_renderbuffers(intel_fb);
241 intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer);
242
243 /* Update vblank info
244 */
245 if (areaB > areaA || (areaA == areaB && areaB > 0)) {
246 flags = intel_fb->vblank_flags | VBLANK_FLAG_SECONDARY;
247 } else {
248 flags = intel_fb->vblank_flags & ~VBLANK_FLAG_SECONDARY;
249 }
250
251 if (flags != intel_fb->vblank_flags && intel_fb->vblank_flags &&
252 !(intel_fb->vblank_flags & VBLANK_FLAG_NO_IRQ)) {
253 drmVBlank vbl;
254 int i;
255
256 vbl.request.type = DRM_VBLANK_ABSOLUTE;
257
258 if ( intel_fb->vblank_flags & VBLANK_FLAG_SECONDARY ) {
259 vbl.request.type |= DRM_VBLANK_SECONDARY;
260 }
261
262 for (i = 0; i < intel_fb->pf_num_pages; i++) {
263 if (!intel_fb->color_rb[i] ||
264 (intel_fb->vbl_waited - intel_fb->color_rb[i]->vbl_pending) <=
265 (1<<23))
266 continue;
267
268 vbl.request.sequence = intel_fb->color_rb[i]->vbl_pending;
269 drmWaitVBlank(intel->driFd, &vbl);
270 }
271
272 intel_fb->vblank_flags = flags;
273 driGetCurrentVBlank(dPriv, intel_fb->vblank_flags, &intel_fb->vbl_seq);
274 intel_fb->vbl_waited = intel_fb->vbl_seq;
275
276 for (i = 0; i < intel_fb->pf_num_pages; i++) {
277 if (intel_fb->color_rb[i])
278 intel_fb->color_rb[i]->vbl_pending = intel_fb->vbl_waited;
279 }
280 }
281 }
282
283 /* This will be picked up by looking at the dirty state flags:
284 */
285
286 /* Update hardware scissor */
287 // ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
288 // ctx->Scissor.Width, ctx->Scissor.Height);
289
290 /* Re-calculate viewport related state */
291 // ctx->Driver.DepthRange( ctx, ctx->Viewport.Near, ctx->Viewport.Far );
292 }
293
294
295
296
297
298 /* Emit wait for pending flips */
299 void
300 intel_wait_flips(struct intel_context *intel, GLuint batch_flags)
301 {
302 struct intel_framebuffer *intel_fb =
303 (struct intel_framebuffer *) intel->ctx.DrawBuffer;
304 struct intel_renderbuffer *intel_rb =
305 intel_get_renderbuffer(&intel_fb->Base,
306 intel_fb->Base._ColorDrawBufferMask[0] ==
307 BUFFER_BIT_FRONT_LEFT ? BUFFER_FRONT_LEFT :
308 BUFFER_BACK_LEFT);
309
310 if (intel_fb->Base.Name == 0 && intel_rb->pf_pending == intel_fb->pf_seq) {
311 GLint pf_pipes = intel_fb->pf_pipes;
312 BATCH_LOCALS;
313
314 /* Wait for pending flips to take effect */
315 BEGIN_BATCH(2, batch_flags);
316 OUT_BATCH(pf_pipes & 0x1 ? (MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP)
317 : 0);
318 OUT_BATCH(pf_pipes & 0x2 ? (MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_B_FLIP)
319 : 0);
320 ADVANCE_BATCH();
321
322 intel_rb->pf_pending--;
323 }
324 }
325
326 #if 0
327 /* Flip the front & back buffers
328 */
329 static GLboolean
330 intelPageFlip(const __DRIdrawablePrivate * dPriv)
331 {
332 struct intel_context *intel;
333 int ret;
334 struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
335
336 if (INTEL_DEBUG & DEBUG_IOCTL)
337 fprintf(stderr, "%s\n", __FUNCTION__);
338
339 assert(dPriv);
340 assert(dPriv->driContextPriv);
341 assert(dPriv->driContextPriv->driverPrivate);
342
343 intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate;
344
345 if (intel->intelScreen->drmMinor < 9)
346 return GL_FALSE;
347
348 intelFlush(&intel->ctx);
349
350 ret = 0;
351
352 LOCK_HARDWARE(intel);
353
354 if (dPriv->numClipRects && intel_fb->pf_active) {
355 drm_i915_flip_t flip;
356
357 flip.pipes = intel_fb->pf_pipes;
358
359 ret = drmCommandWrite(intel->driFd, DRM_I915_FLIP, &flip, sizeof(flip));
360 }
361
362 UNLOCK_HARDWARE(intel);
363
364 if (ret || !intel_fb->pf_active)
365 return GL_FALSE;
366
367 if (!dPriv->numClipRects) {
368 usleep(10000); /* throttle invisible client 10ms */
369 }
370
371 intel_fb->pf_current_page = (intel->sarea->pf_current_page >>
372 (intel_fb->pf_pipes & 0x2)) & 0x3;
373
374 if (dPriv->numClipRects != 0) {
375 intel_get_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT)->pf_pending =
376 intel_get_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT)->pf_pending =
377 ++intel_fb->pf_seq;
378 }
379
380 intel_flip_renderbuffers(intel_fb);
381 intel_draw_buffer(&intel->ctx, &intel_fb->Base);
382
383 if (INTEL_DEBUG & DEBUG_IOCTL)
384 fprintf(stderr, "%s: success\n", __FUNCTION__);
385
386 return GL_TRUE;
387 }
388 #endif
389
390
391 static GLboolean
392 intelScheduleSwap(const __DRIdrawablePrivate * dPriv, GLboolean *missed_target)
393 {
394 struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
395 unsigned int interval = driGetVBlankInterval(dPriv, intel_fb->vblank_flags);
396 struct intel_context *intel =
397 intelScreenContext(dPriv->driScreenPriv->private);
398 const intelScreenPrivate *intelScreen = intel->intelScreen;
399 unsigned int target;
400 drm_i915_vblank_swap_t swap;
401 GLboolean ret;
402
403 if (!intel_fb->vblank_flags ||
404 (intel_fb->vblank_flags & VBLANK_FLAG_NO_IRQ) ||
405 intelScreen->drmMinor < (intel_fb->pf_active ? 9 : 6))
406 return GL_FALSE;
407
408 swap.seqtype = DRM_VBLANK_ABSOLUTE;
409
410 if (intel_fb->vblank_flags & VBLANK_FLAG_SYNC) {
411 swap.seqtype |= DRM_VBLANK_NEXTONMISS;
412 } else if (interval == 0) {
413 return GL_FALSE;
414 }
415
416 swap.drawable = dPriv->hHWDrawable;
417 target = swap.sequence = intel_fb->vbl_seq + interval;
418
419 if ( intel_fb->vblank_flags & VBLANK_FLAG_SECONDARY ) {
420 swap.seqtype |= DRM_VBLANK_SECONDARY;
421 }
422
423 LOCK_HARDWARE(intel);
424
425 intel_batchbuffer_flush(intel->batch);
426
427 if ( intel_fb->pf_active ) {
428 swap.seqtype |= DRM_VBLANK_FLIP;
429
430 intel_fb->pf_current_page = (((intel->sarea->pf_current_page >>
431 (intel_fb->pf_pipes & 0x2)) & 0x3) + 1) %
432 intel_fb->pf_num_pages;
433 }
434
435 if (!drmCommandWriteRead(intel->driFd, DRM_I915_VBLANK_SWAP, &swap,
436 sizeof(swap))) {
437 intel_fb->vbl_seq = swap.sequence;
438 swap.sequence -= target;
439 *missed_target = swap.sequence > 0 && swap.sequence <= (1 << 23);
440
441 intel_get_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT)->vbl_pending =
442 intel_get_renderbuffer(&intel_fb->Base,
443 BUFFER_FRONT_LEFT)->vbl_pending =
444 intel_fb->vbl_seq;
445
446 if (swap.seqtype & DRM_VBLANK_FLIP) {
447 intel_flip_renderbuffers(intel_fb);
448 intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer);
449 }
450
451 ret = GL_TRUE;
452 } else {
453 if (swap.seqtype & DRM_VBLANK_FLIP) {
454 intel_fb->pf_current_page = ((intel->sarea->pf_current_page >>
455 (intel_fb->pf_pipes & 0x2)) & 0x3) %
456 intel_fb->pf_num_pages;
457 }
458
459 ret = GL_FALSE;
460 }
461
462 UNLOCK_HARDWARE(intel);
463
464 return ret;
465 }
466
467 void
468 intelSwapBuffers(__DRIdrawablePrivate * dPriv)
469 {
470 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
471 GET_CURRENT_CONTEXT(ctx);
472 struct intel_context *intel;
473
474 if (ctx == NULL)
475 return;
476
477 intel = intel_context(ctx);
478
479 if (ctx->Visual.doubleBufferMode) {
480 GLboolean missed_target;
481 struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
482 int64_t ust;
483
484 _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
485
486 if (!intelScheduleSwap(dPriv, &missed_target)) {
487 driWaitForVBlank(dPriv, &intel_fb->vbl_seq, intel_fb->vblank_flags,
488 &missed_target);
489
490 intelCopyBuffer(dPriv, NULL);
491 }
492
493 intel_fb->swap_count++;
494 (*dri_interface->getUST) (&ust);
495 if (missed_target) {
496 intel_fb->swap_missed_count++;
497 intel_fb->swap_missed_ust = ust - intel_fb->swap_ust;
498 }
499
500 intel_fb->swap_ust = ust;
501 }
502 }
503 else {
504 /* XXX this shouldn't be an error but we can't handle it for now */
505 fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
506 }
507 }
508
509 void
510 intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
511 {
512 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
513 struct intel_context *intel =
514 (struct intel_context *) dPriv->driContextPriv->driverPrivate;
515 GLcontext *ctx = &intel->ctx;
516
517 if (ctx->Visual.doubleBufferMode) {
518 drm_clip_rect_t rect;
519 /* fixup cliprect (driDrawable may have changed?) later */
520 rect.x1 = x;
521 rect.y1 = y;
522 rect.x2 = w;
523 rect.y2 = h;
524 _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
525 intelCopyBuffer(dPriv, &rect);
526 }
527 }
528 else {
529 /* XXX this shouldn't be an error but we can't handle it for now */
530 fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
531 }
532 }
533
534
535 /**
536 * Update the hardware state for drawing into a window or framebuffer object.
537 *
538 * Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other
539 * places within the driver.
540 *
541 * Basically, this needs to be called any time the current framebuffer
542 * changes, the renderbuffers change, or we need to draw into different
543 * color buffers.
544 */
545 void
546 intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
547 {
548 struct intel_context *intel = intel_context(ctx);
549 struct pipe_region *colorRegion, *depthRegion = NULL;
550 struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL;
551
552 if (!fb) {
553 /* this can happen during the initial context initialization */
554 return;
555 }
556
557 /* Do this here, not core Mesa, since this function is called from
558 * many places within the driver.
559 */
560 if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
561 /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
562 _mesa_update_framebuffer(ctx);
563 /* this updates the DrawBuffer's Width/Height if it's a FBO */
564 _mesa_update_draw_buffer_bounds(ctx);
565 }
566
567 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
568 /* this may occur when we're called by glBindFrameBuffer() during
569 * the process of someone setting up renderbuffers, etc.
570 */
571 /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
572 return;
573 }
574
575 if (fb->Name)
576 intel_validate_paired_depth_stencil(ctx, fb);
577
578 /*
579 * How many color buffers are we drawing into?
580 */
581 if (fb->_NumColorDrawBuffers[0] != 1) {
582 /* writing to 0 or 2 or 4 color buffers */
583 /*_mesa_debug(ctx, "Software rendering\n");*/
584 FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
585 }
586 else {
587 /* draw to exactly one color buffer */
588 /*_mesa_debug(ctx, "Hardware rendering\n");*/
589 FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE);
590 }
591
592 /*
593 * Get the intel_renderbuffer for the colorbuffer we're drawing into.
594 * And set up cliprects.
595 */
596 {
597 struct intel_renderbuffer *irb;
598 intelSetRenderbufferClipRects(intel);
599 irb = intel_renderbuffer(fb->_ColorDrawBuffers[0][0]);
600 colorRegion = (irb && irb->region) ? irb->region : NULL;
601 }
602
603 /* Update culling direction which changes depending on the
604 * orientation of the buffer:
605 */
606 if (ctx->Driver.FrontFace)
607 ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
608 else
609 ctx->NewState |= _NEW_POLYGON;
610
611 if (!colorRegion) {
612 FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
613 }
614 else {
615 FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE);
616 }
617
618 /***
619 *** Get depth buffer region and check if we need a software fallback.
620 *** Note that the depth buffer is usually a DEPTH_STENCIL buffer.
621 ***/
622 if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) {
623 irbDepth = intel_renderbuffer(fb->_DepthBuffer->Wrapped);
624 if (irbDepth && irbDepth->region) {
625 FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
626 depthRegion = irbDepth->region;
627 }
628 else {
629 FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_TRUE);
630 depthRegion = NULL;
631 }
632 }
633 else {
634 /* not using depth buffer */
635 FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
636 depthRegion = NULL;
637 }
638
639 /***
640 *** Stencil buffer
641 *** This can only be hardware accelerated if we're using a
642 *** combined DEPTH_STENCIL buffer (for now anyway).
643 ***/
644 if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) {
645 irbStencil = intel_renderbuffer(fb->_StencilBuffer->Wrapped);
646 if (irbStencil && irbStencil->region) {
647 ASSERT(irbStencil->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
648 FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
649 /* need to re-compute stencil hw state */
650 // ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
651 if (!depthRegion)
652 depthRegion = irbStencil->region;
653 }
654 else {
655 FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_TRUE);
656 }
657 }
658 else {
659 /* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */
660 FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
661 /* need to re-compute stencil hw state */
662 // ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
663 }
664
665
666 /**
667 ** Release old regions, reference new regions
668 **/
669
670 // intel->vtbl.set_draw_region(intel, colorRegion, depthRegion);
671
672 /* update viewport since it depends on window size */
673 // ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y,
674 // ctx->Viewport.Width, ctx->Viewport.Height);
675
676 /* Update hardware scissor */
677 // ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
678 // ctx->Scissor.Width, ctx->Scissor.Height);
679 }
680
681
682 static void
683 intelDrawBuffer(GLcontext * ctx, GLenum mode)
684 {
685 intel_draw_buffer(ctx, ctx->DrawBuffer);
686 }
687
688
689 static void
690 intelReadBuffer(GLcontext * ctx, GLenum mode)
691 {
692 if (ctx->ReadBuffer == ctx->DrawBuffer) {
693 /* This will update FBO completeness status.
694 * A framebuffer will be incomplete if the GL_READ_BUFFER setting
695 * refers to a missing renderbuffer. Calling glReadBuffer can set
696 * that straight and can make the drawing buffer complete.
697 */
698 intel_draw_buffer(ctx, ctx->DrawBuffer);
699 }
700 /* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc)
701 * reference ctx->ReadBuffer and do appropriate state checks.
702 */
703 }
704
705
706 void
707 intelInitBufferFuncs(struct dd_function_table *functions)
708 {
709 functions->DrawBuffer = intelDrawBuffer;
710 functions->ReadBuffer = intelReadBuffer;
711 }