1 /**************************************************************************
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
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"
42 #include "drirenderbuffer.h"
46 #define FILE_DEBUG_FLAG DEBUG_BLIT
49 * XXX move this into a new dri/common/cliprects.c file.
52 intel_intersect_cliprects(drm_clip_rect_t
* dst
,
53 const drm_clip_rect_t
* a
,
54 const drm_clip_rect_t
* b
)
58 GLint bw
= b
->x2
- bx
;
59 GLint bh
= b
->y2
- by
;
62 bw
-= a
->x1
- bx
, bx
= a
->x1
;
64 bh
-= a
->y1
- by
, by
= a
->y1
;
83 * Return pointer to current color drawing region, or NULL.
86 intel_drawbuf_region(struct intel_context
*intel
)
88 struct intel_renderbuffer
*irbColor
=
89 intel_renderbuffer(intel
->ctx
.DrawBuffer
->_ColorDrawBuffers
[0]);
91 return irbColor
->region
;
97 * Return pointer to current color reading region, or NULL.
100 intel_readbuf_region(struct intel_context
*intel
)
102 struct intel_renderbuffer
*irb
103 = intel_renderbuffer(intel
->ctx
.ReadBuffer
->_ColorReadBuffer
);
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
)
116 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
117 struct intel_framebuffer
*intel_fb
= dPriv
->driverPrivate
;
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
;
126 *cliprects
= &intel
->fboRect
;
130 } else if (intel
->front_cliprects
|| dPriv
->numBackClipRects
== 0) {
131 /* use the front clip rects */
132 *cliprects
= dPriv
->pClipRects
;
133 *num_cliprects
= dPriv
->numClipRects
;
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
;
147 * Correct a drawablePrivate's set of vblank flags WRT the current context.
148 * When considering multiple crtcs.
151 intelFixupVblank(struct intel_context
*intel
, __DRIdrawablePrivate
*dPriv
)
154 if (!intel
->intelScreen
->driScrnPriv
->dri2
.enabled
&&
155 intel
->intelScreen
->driScrnPriv
->ddx_version
.minor
>= 7) {
156 volatile drm_i915_sarea_t
*sarea
= intel
->sarea
;
157 drm_clip_rect_t drw_rect
= { .x1
= dPriv
->x
, .x2
= dPriv
->x
+ dPriv
->w
,
158 .y1
= dPriv
->y
, .y2
= dPriv
->y
+ dPriv
->h
};
159 drm_clip_rect_t planeA_rect
= { .x1
= sarea
->planeA_x
, .y1
= sarea
->planeA_y
,
160 .x2
= sarea
->planeA_x
+ sarea
->planeA_w
,
161 .y2
= sarea
->planeA_y
+ sarea
->planeA_h
};
162 drm_clip_rect_t planeB_rect
= { .x1
= sarea
->planeB_x
, .y1
= sarea
->planeB_y
,
163 .x2
= sarea
->planeB_x
+ sarea
->planeB_w
,
164 .y2
= sarea
->planeB_y
+ sarea
->planeB_h
};
165 GLint areaA
= driIntersectArea( drw_rect
, planeA_rect
);
166 GLint areaB
= driIntersectArea( drw_rect
, planeB_rect
);
167 GLuint flags
= dPriv
->vblFlags
;
169 /* Update vblank info
171 if (areaB
> areaA
|| (areaA
== areaB
&& areaB
> 0)) {
172 flags
= dPriv
->vblFlags
| VBLANK_FLAG_SECONDARY
;
174 flags
= dPriv
->vblFlags
& ~VBLANK_FLAG_SECONDARY
;
179 return dPriv
->vblFlags
& ~VBLANK_FLAG_SECONDARY
;
184 * This will be called whenever the currently bound window is moved/resized.
185 * XXX: actually, it seems to NOT be called when the window is only moved (BP).
188 intelWindowMoved(struct intel_context
*intel
)
190 GLcontext
*ctx
= &intel
->ctx
;
191 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
192 struct intel_framebuffer
*intel_fb
= dPriv
->driverPrivate
;
194 if (!intel
->intelScreen
->driScrnPriv
->dri2
.enabled
&&
195 intel
->intelScreen
->driScrnPriv
->ddx_version
.minor
>= 7) {
196 GLuint flags
= intelFixupVblank(intel
, dPriv
);
198 /* Check to see if we changed pipes */
199 if (flags
!= dPriv
->vblFlags
&& dPriv
->vblFlags
&&
200 !(dPriv
->vblFlags
& VBLANK_FLAG_NO_IRQ
)) {
206 * Deal with page flipping
208 vbl
.request
.type
= DRM_VBLANK_ABSOLUTE
;
210 if ( dPriv
->vblFlags
& VBLANK_FLAG_SECONDARY
) {
211 vbl
.request
.type
|= DRM_VBLANK_SECONDARY
;
214 for (i
= 0; i
< 2; i
++) {
215 if (!intel_fb
->color_rb
[i
] ||
216 (intel_fb
->vbl_waited
- intel_fb
->color_rb
[i
]->vbl_pending
) <=
220 vbl
.request
.sequence
= intel_fb
->color_rb
[i
]->vbl_pending
;
221 drmWaitVBlank(intel
->driFd
, &vbl
);
225 * Update msc_base from old pipe
227 driDrawableGetMSC32(dPriv
->driScreenPriv
, dPriv
, &count
);
228 dPriv
->msc_base
= count
;
230 * Then get new vblank_base and vblSeq values
232 dPriv
->vblFlags
= flags
;
233 driGetCurrentVBlank(dPriv
);
234 dPriv
->vblank_base
= dPriv
->vblSeq
;
236 intel_fb
->vbl_waited
= dPriv
->vblSeq
;
238 for (i
= 0; i
< 2; i
++) {
239 if (intel_fb
->color_rb
[i
])
240 intel_fb
->color_rb
[i
]->vbl_pending
= intel_fb
->vbl_waited
;
244 dPriv
->vblFlags
&= ~VBLANK_FLAG_SECONDARY
;
247 /* Update Mesa's notion of window size */
248 driUpdateFramebufferSize(ctx
, dPriv
);
249 intel_fb
->Base
.Initialized
= GL_TRUE
; /* XXX remove someday */
251 /* Update hardware scissor */
252 if (ctx
->Driver
.Scissor
!= NULL
) {
253 ctx
->Driver
.Scissor(ctx
, ctx
->Scissor
.X
, ctx
->Scissor
.Y
,
254 ctx
->Scissor
.Width
, ctx
->Scissor
.Height
);
257 /* Re-calculate viewport related state */
258 if (ctx
->Driver
.DepthRange
!= NULL
)
259 ctx
->Driver
.DepthRange( ctx
, ctx
->Viewport
.Near
, ctx
->Viewport
.Far
);
264 /* A true meta version of this would be very simple and additionally
265 * machine independent. Maybe we'll get there one day.
268 intelClearWithTris(struct intel_context
*intel
, GLbitfield mask
)
270 GLcontext
*ctx
= &intel
->ctx
;
271 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
274 intel
->vtbl
.install_meta_state(intel
);
276 /* Back and stencil cliprects are the same. Try and do both
279 if (mask
& (BUFFER_BIT_BACK_LEFT
| BUFFER_BIT_STENCIL
| BUFFER_BIT_DEPTH
)) {
280 struct intel_region
*backRegion
=
281 intel_get_rb_region(fb
, BUFFER_BACK_LEFT
);
282 struct intel_region
*depthRegion
=
283 intel_get_rb_region(fb
, BUFFER_DEPTH
);
285 intel
->vtbl
.meta_draw_region(intel
, backRegion
, depthRegion
);
287 if (mask
& BUFFER_BIT_BACK_LEFT
)
288 intel
->vtbl
.meta_color_mask(intel
, GL_TRUE
);
290 intel
->vtbl
.meta_color_mask(intel
, GL_FALSE
);
292 if (mask
& BUFFER_BIT_STENCIL
)
293 intel
->vtbl
.meta_stencil_replace(intel
,
294 intel
->ctx
.Stencil
.WriteMask
[0],
295 intel
->ctx
.Stencil
.Clear
);
297 intel
->vtbl
.meta_no_stencil_write(intel
);
299 if (mask
& BUFFER_BIT_DEPTH
)
300 intel
->vtbl
.meta_depth_replace(intel
);
302 intel
->vtbl
.meta_no_depth_write(intel
);
304 intel
->vtbl
.meta_draw_quad(intel
,
309 intel
->ctx
.Depth
.Clear
,
310 intel
->ClearColor8888
,
311 0, 0, 0, 0); /* texcoords */
313 mask
&= ~(BUFFER_BIT_BACK_LEFT
| BUFFER_BIT_STENCIL
| BUFFER_BIT_DEPTH
);
316 /* clear the remaining (color) renderbuffers */
317 for (buf
= 0; buf
< BUFFER_COUNT
&& mask
; buf
++) {
318 const GLuint bufBit
= 1 << buf
;
320 struct intel_renderbuffer
*irbColor
=
321 intel_renderbuffer(fb
->Attachment
[buf
].Renderbuffer
);
325 intel
->vtbl
.meta_no_depth_write(intel
);
326 intel
->vtbl
.meta_no_stencil_write(intel
);
327 intel
->vtbl
.meta_color_mask(intel
, GL_TRUE
);
328 intel
->vtbl
.meta_draw_region(intel
, irbColor
->region
, NULL
);
330 intel
->vtbl
.meta_draw_quad(intel
,
335 0, intel
->ClearColor8888
,
336 0, 0, 0, 0); /* texcoords */
342 intel
->vtbl
.leave_meta_state(intel
);
345 static const char *buffer_names
[] = {
346 [BUFFER_FRONT_LEFT
] = "front",
347 [BUFFER_BACK_LEFT
] = "back",
348 [BUFFER_FRONT_RIGHT
] = "front right",
349 [BUFFER_BACK_RIGHT
] = "back right",
350 [BUFFER_AUX0
] = "aux0",
351 [BUFFER_AUX1
] = "aux1",
352 [BUFFER_AUX2
] = "aux2",
353 [BUFFER_AUX3
] = "aux3",
354 [BUFFER_DEPTH
] = "depth",
355 [BUFFER_STENCIL
] = "stencil",
356 [BUFFER_ACCUM
] = "accum",
357 [BUFFER_COLOR0
] = "color0",
358 [BUFFER_COLOR1
] = "color1",
359 [BUFFER_COLOR2
] = "color2",
360 [BUFFER_COLOR3
] = "color3",
361 [BUFFER_COLOR4
] = "color4",
362 [BUFFER_COLOR5
] = "color5",
363 [BUFFER_COLOR6
] = "color6",
364 [BUFFER_COLOR7
] = "color7",
368 * Called by ctx->Driver.Clear.
371 intelClear(GLcontext
*ctx
, GLbitfield mask
)
373 struct intel_context
*intel
= intel_context(ctx
);
374 const GLuint colorMask
= *((GLuint
*) & ctx
->Color
.ColorMask
);
375 GLbitfield tri_mask
= 0;
376 GLbitfield blit_mask
= 0;
377 GLbitfield swrast_mask
= 0;
378 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
382 fprintf(stderr
, "%s\n", __FUNCTION__
);
384 /* HW color buffers (front, back, aux, generic FBO, etc) */
385 if (colorMask
== ~0) {
386 /* clear all R,G,B,A */
387 /* XXX FBO: need to check if colorbuffers are software RBOs! */
388 blit_mask
|= (mask
& BUFFER_BITS_COLOR
);
391 /* glColorMask in effect */
392 tri_mask
|= (mask
& BUFFER_BITS_COLOR
);
396 if (mask
& BUFFER_BIT_STENCIL
) {
397 const struct intel_region
*stencilRegion
398 = intel_get_rb_region(fb
, BUFFER_STENCIL
);
400 /* have hw stencil */
401 if (IS_965(intel
->intelScreen
->deviceID
) ||
402 (ctx
->Stencil
.WriteMask
[0] & 0xff) != 0xff) {
403 /* We have to use the 3D engine if we're clearing a partial mask
404 * of the stencil buffer, or if we're on a 965 which has a tiled
405 * depth/stencil buffer in a layout we can't blit to.
407 tri_mask
|= BUFFER_BIT_STENCIL
;
410 /* clearing all stencil bits, use blitting */
411 blit_mask
|= BUFFER_BIT_STENCIL
;
417 if (mask
& BUFFER_BIT_DEPTH
) {
418 /* clear depth with whatever method is used for stencil (see above) */
419 if (IS_965(intel
->intelScreen
->deviceID
) ||
420 tri_mask
& BUFFER_BIT_STENCIL
)
421 tri_mask
|= BUFFER_BIT_DEPTH
;
423 blit_mask
|= BUFFER_BIT_DEPTH
;
426 /* SW fallback clearing */
427 swrast_mask
= mask
& ~tri_mask
& ~blit_mask
;
429 for (i
= 0; i
< BUFFER_COUNT
; i
++) {
430 GLuint bufBit
= 1 << i
;
431 if ((blit_mask
| tri_mask
) & bufBit
) {
432 if (!fb
->Attachment
[i
].Renderbuffer
->ClassID
) {
433 blit_mask
&= ~bufBit
;
435 swrast_mask
|= bufBit
;
441 if (INTEL_DEBUG
& DEBUG_BLIT
) {
443 for (i
= 0; i
< BUFFER_COUNT
; i
++) {
444 if (blit_mask
& (1 << i
))
445 DBG(" %s", buffer_names
[i
]);
449 intelClearWithBlit(ctx
, blit_mask
);
453 if (INTEL_DEBUG
& DEBUG_BLIT
) {
455 for (i
= 0; i
< BUFFER_COUNT
; i
++) {
456 if (tri_mask
& (1 << i
))
457 DBG(" %s", buffer_names
[i
]);
461 intelClearWithTris(intel
, tri_mask
);
465 if (INTEL_DEBUG
& DEBUG_BLIT
) {
466 DBG("swrast clear:");
467 for (i
= 0; i
< BUFFER_COUNT
; i
++) {
468 if (swrast_mask
& (1 << i
))
469 DBG(" %s", buffer_names
[i
]);
473 _swrast_Clear(ctx
, swrast_mask
);
478 intelSwapBuffers(__DRIdrawablePrivate
* dPriv
)
480 __DRIscreenPrivate
*psp
= dPriv
->driScreenPriv
;
482 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
483 GET_CURRENT_CONTEXT(ctx
);
484 struct intel_context
*intel
;
489 intel
= intel_context(ctx
);
491 if (ctx
->Visual
.doubleBufferMode
) {
492 GLboolean missed_target
;
493 struct intel_framebuffer
*intel_fb
= dPriv
->driverPrivate
;
496 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
499 * The old swapping ioctl was incredibly racy, just wait for vblank
500 * and do the swap ourselves.
502 driWaitForVBlank(dPriv
, &missed_target
);
505 * Update each buffer's vbl_pending so we don't get too out of
508 intel_get_renderbuffer(&intel_fb
->Base
,
509 BUFFER_BACK_LEFT
)->vbl_pending
= dPriv
->vblSeq
;
510 intel_get_renderbuffer(&intel_fb
->Base
,
511 BUFFER_FRONT_LEFT
)->vbl_pending
= dPriv
->vblSeq
;
513 intelCopyBuffer(dPriv
, NULL
);
515 intel_fb
->swap_count
++;
516 (*psp
->systemTime
->getUST
) (&ust
);
518 intel_fb
->swap_missed_count
++;
519 intel_fb
->swap_missed_ust
= ust
- intel_fb
->swap_ust
;
522 intel_fb
->swap_ust
= ust
;
524 drmCommandNone(intel
->driFd
, DRM_I915_GEM_THROTTLE
);
528 /* XXX this shouldn't be an error but we can't handle it for now */
529 fprintf(stderr
, "%s: drawable has no context!\n", __FUNCTION__
);
534 intelCopySubBuffer(__DRIdrawablePrivate
* dPriv
, int x
, int y
, int w
, int h
)
536 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
537 struct intel_context
*intel
=
538 (struct intel_context
*) dPriv
->driContextPriv
->driverPrivate
;
539 GLcontext
*ctx
= &intel
->ctx
;
541 if (ctx
->Visual
.doubleBufferMode
) {
542 drm_clip_rect_t rect
;
543 rect
.x1
= x
+ dPriv
->x
;
544 rect
.y1
= (dPriv
->h
- y
- h
) + dPriv
->y
;
545 rect
.x2
= rect
.x1
+ w
;
546 rect
.y2
= rect
.y1
+ h
;
547 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
548 intelCopyBuffer(dPriv
, &rect
);
552 /* XXX this shouldn't be an error but we can't handle it for now */
553 fprintf(stderr
, "%s: drawable has no context!\n", __FUNCTION__
);
559 * Update the hardware state for drawing into a window or framebuffer object.
561 * Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other
562 * places within the driver.
564 * Basically, this needs to be called any time the current framebuffer
565 * changes, the renderbuffers change, or we need to draw into different
569 intel_draw_buffer(GLcontext
* ctx
, struct gl_framebuffer
*fb
)
571 struct intel_context
*intel
= intel_context(ctx
);
572 struct intel_region
*colorRegions
[MAX_DRAW_BUFFERS
], *depthRegion
= NULL
;
573 struct intel_renderbuffer
*irbDepth
= NULL
, *irbStencil
= NULL
;
576 /* this can happen during the initial context initialization */
580 /* Do this here, not core Mesa, since this function is called from
581 * many places within the driver.
583 if (ctx
->NewState
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
584 /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
585 _mesa_update_framebuffer(ctx
);
586 /* this updates the DrawBuffer's Width/Height if it's a FBO */
587 _mesa_update_draw_buffer_bounds(ctx
);
590 if (fb
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
591 /* this may occur when we're called by glBindFrameBuffer() during
592 * the process of someone setting up renderbuffers, etc.
594 /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
599 * How many color buffers are we drawing into?
601 if (fb
->_NumColorDrawBuffers
== 0) {
603 colorRegions
[0] = NULL
;
604 intel
->constant_cliprect
= GL_TRUE
;
606 else if (fb
->_NumColorDrawBuffers
> 1) {
608 struct intel_renderbuffer
*irb
;
610 for (i
= 0; i
< fb
->_NumColorDrawBuffers
; i
++) {
611 irb
= intel_renderbuffer(fb
->_ColorDrawBuffers
[i
]);
612 colorRegions
[i
] = irb
? irb
->region
: NULL
;
614 intel
->constant_cliprect
= GL_TRUE
;
617 /* Get the intel_renderbuffer for the single colorbuffer we're drawing
618 * into, and set up cliprects if it's .
621 intel
->constant_cliprect
= intel
->driScreen
->dri2
.enabled
;
622 /* drawing to window system buffer */
623 if (fb
->_ColorDrawBufferIndexes
[0] == BUFFER_FRONT_LEFT
) {
624 if (!intel
->constant_cliprect
&& !intel
->front_cliprects
)
625 intel_batchbuffer_flush(intel
->batch
);
626 intel
->front_cliprects
= GL_TRUE
;
627 colorRegions
[0] = intel_get_rb_region(fb
, BUFFER_FRONT_LEFT
);
630 if (!intel
->constant_cliprect
&& intel
->front_cliprects
)
631 intel_batchbuffer_flush(intel
->batch
);
632 intel
->front_cliprects
= GL_FALSE
;
633 colorRegions
[0]= intel_get_rb_region(fb
, BUFFER_BACK_LEFT
);
637 /* drawing to user-created FBO */
638 struct intel_renderbuffer
*irb
;
639 irb
= intel_renderbuffer(fb
->_ColorDrawBuffers
[0]);
640 colorRegions
[0] = (irb
&& irb
->region
) ? irb
->region
: NULL
;
641 intel
->constant_cliprect
= GL_TRUE
;
645 if (!colorRegions
[0]) {
646 FALLBACK(intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
649 FALLBACK(intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
653 *** Get depth buffer region and check if we need a software fallback.
654 *** Note that the depth buffer is usually a DEPTH_STENCIL buffer.
656 if (fb
->_DepthBuffer
&& fb
->_DepthBuffer
->Wrapped
) {
657 irbDepth
= intel_renderbuffer(fb
->_DepthBuffer
->Wrapped
);
658 if (irbDepth
&& irbDepth
->region
) {
659 FALLBACK(intel
, INTEL_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
660 depthRegion
= irbDepth
->region
;
663 FALLBACK(intel
, INTEL_FALLBACK_DEPTH_BUFFER
, GL_TRUE
);
668 /* not using depth buffer */
669 FALLBACK(intel
, INTEL_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
675 *** This can only be hardware accelerated if we're using a
676 *** combined DEPTH_STENCIL buffer.
678 if (fb
->_StencilBuffer
&& fb
->_StencilBuffer
->Wrapped
) {
679 irbStencil
= intel_renderbuffer(fb
->_StencilBuffer
->Wrapped
);
680 if (irbStencil
&& irbStencil
->region
) {
681 ASSERT(irbStencil
->Base
._ActualFormat
== GL_DEPTH24_STENCIL8_EXT
);
682 FALLBACK(intel
, INTEL_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
685 FALLBACK(intel
, INTEL_FALLBACK_STENCIL_BUFFER
, GL_TRUE
);
689 /* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */
690 FALLBACK(intel
, INTEL_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
694 * Update depth and stencil test state
696 if (ctx
->Driver
.Enable
) {
697 ctx
->Driver
.Enable(ctx
, GL_DEPTH_TEST
,
698 (ctx
->Depth
.Test
&& fb
->Visual
.depthBits
> 0));
699 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
,
700 (ctx
->Stencil
.Enabled
&& fb
->Visual
.stencilBits
> 0));
703 ctx
->NewState
|= (_NEW_DEPTH
| _NEW_STENCIL
);
706 intel
->vtbl
.set_draw_region(intel
, colorRegions
, depthRegion
,
707 fb
->_NumColorDrawBuffers
);
709 /* update viewport since it depends on window size */
710 if (ctx
->Driver
.Viewport
) {
711 ctx
->Driver
.Viewport(ctx
, ctx
->Viewport
.X
, ctx
->Viewport
.Y
,
712 ctx
->Viewport
.Width
, ctx
->Viewport
.Height
);
715 ctx
->NewState
|= _NEW_VIEWPORT
;
718 /* Set state we know depends on drawable parameters:
720 if (ctx
->Driver
.Scissor
)
721 ctx
->Driver
.Scissor(ctx
, ctx
->Scissor
.X
, ctx
->Scissor
.Y
,
722 ctx
->Scissor
.Width
, ctx
->Scissor
.Height
);
723 intel
->NewGLState
|= _NEW_SCISSOR
;
725 if (ctx
->Driver
.DepthRange
)
726 ctx
->Driver
.DepthRange(ctx
,
730 /* Update culling direction which changes depending on the
731 * orientation of the buffer:
733 if (ctx
->Driver
.FrontFace
)
734 ctx
->Driver
.FrontFace(ctx
, ctx
->Polygon
.FrontFace
);
736 ctx
->NewState
|= _NEW_POLYGON
;
741 intelDrawBuffer(GLcontext
* ctx
, GLenum mode
)
743 intel_draw_buffer(ctx
, ctx
->DrawBuffer
);
748 intelReadBuffer(GLcontext
* ctx
, GLenum mode
)
750 if (ctx
->ReadBuffer
== ctx
->DrawBuffer
) {
751 /* This will update FBO completeness status.
752 * A framebuffer will be incomplete if the GL_READ_BUFFER setting
753 * refers to a missing renderbuffer. Calling glReadBuffer can set
754 * that straight and can make the drawing buffer complete.
756 intel_draw_buffer(ctx
, ctx
->DrawBuffer
);
758 /* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc)
759 * reference ctx->ReadBuffer and do appropriate state checks.
765 intelInitBufferFuncs(struct dd_function_table
*functions
)
767 functions
->Clear
= intelClear
;
768 functions
->DrawBuffer
= intelDrawBuffer
;
769 functions
->ReadBuffer
= intelReadBuffer
;