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_depthstencil.h"
33 #include "intel_fbo.h"
34 #include "intel_tris.h"
35 #include "intel_regions.h"
36 #include "intel_batchbuffer.h"
39 #include "drirenderbuffer.h"
40 #include "framebuffer.h"
41 #include "swrast/swrast.h"
46 * XXX move this into a new dri/common/cliprects.c file.
49 intel_intersect_cliprects(drm_clip_rect_t
* dst
,
50 const drm_clip_rect_t
* a
,
51 const drm_clip_rect_t
* b
)
55 GLint bw
= b
->x2
- bx
;
56 GLint bh
= b
->y2
- by
;
59 bw
-= a
->x1
- bx
, bx
= a
->x1
;
61 bh
-= a
->y1
- by
, by
= a
->y1
;
80 * Return pointer to current color drawing region, or NULL.
83 intel_drawbuf_region(struct intel_context
*intel
)
85 struct intel_renderbuffer
*irbColor
=
86 intel_renderbuffer(intel
->ctx
.DrawBuffer
->_ColorDrawBuffers
[0][0]);
88 return irbColor
->region
;
94 * Return pointer to current color reading region, or NULL.
97 intel_readbuf_region(struct intel_context
*intel
)
99 struct intel_renderbuffer
*irb
100 = intel_renderbuffer(intel
->ctx
.ReadBuffer
->_ColorReadBuffer
);
110 * Update the following fields for rendering to a user-created FBO:
111 * intel->numClipRects
117 intelSetRenderbufferClipRects(struct intel_context
*intel
)
119 assert(intel
->ctx
.DrawBuffer
->Width
> 0);
120 assert(intel
->ctx
.DrawBuffer
->Height
> 0);
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 intel
->numClipRects
= 1;
126 intel
->pClipRects
= &intel
->fboRect
;
133 * As above, but for rendering to front buffer of a window.
134 * \sa intelSetRenderbufferClipRects
137 intelSetFrontClipRects(struct intel_context
*intel
)
139 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
144 intel
->numClipRects
= dPriv
->numClipRects
;
145 intel
->pClipRects
= dPriv
->pClipRects
;
146 intel
->drawX
= dPriv
->x
;
147 intel
->drawY
= dPriv
->y
;
152 * As above, but for rendering to back buffer of a window.
155 intelSetBackClipRects(struct intel_context
*intel
)
157 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
162 if (intel
->sarea
->pf_enabled
== 0 && dPriv
->numBackClipRects
== 0) {
163 /* use the front clip rects */
164 intel
->numClipRects
= dPriv
->numClipRects
;
165 intel
->pClipRects
= dPriv
->pClipRects
;
166 intel
->drawX
= dPriv
->x
;
167 intel
->drawY
= dPriv
->y
;
170 /* use the back clip rects */
171 intel
->numClipRects
= dPriv
->numBackClipRects
;
172 intel
->pClipRects
= dPriv
->pBackClipRects
;
173 intel
->drawX
= dPriv
->backX
;
174 intel
->drawY
= dPriv
->backY
;
180 * This will be called whenever the currently bound window is moved/resized.
181 * XXX: actually, it seems to NOT be called when the window is only moved (BP).
184 intelWindowMoved(struct intel_context
*intel
)
186 GLcontext
*ctx
= &intel
->ctx
;
187 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
188 GLframebuffer
*drawFb
= (GLframebuffer
*) dPriv
->driverPrivate
;
190 if (!intel
->ctx
.DrawBuffer
) {
191 /* when would this happen? -BP */
192 intelSetFrontClipRects(intel
);
194 else if (intel
->ctx
.DrawBuffer
->Name
!= 0) {
195 /* drawing to user-created FBO - do nothing */
196 /* Cliprects would be set from intelDrawBuffer() */
199 /* drawing to a window */
200 switch (drawFb
->_ColorDrawBufferMask
[0]) {
201 case BUFFER_BIT_FRONT_LEFT
:
202 intelSetFrontClipRects(intel
);
204 case BUFFER_BIT_BACK_LEFT
:
205 intelSetBackClipRects(intel
);
208 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
209 intelSetFrontClipRects(intel
);
213 /* Update Mesa's notion of window size */
214 driUpdateFramebufferSize(ctx
, dPriv
);
215 drawFb
->Initialized
= GL_TRUE
; /* XXX remove someday */
217 if (intel
->intelScreen
->driScrnPriv
->ddxMinor
>= 7) {
218 drmI830Sarea
*sarea
= intel
->sarea
;
219 drm_clip_rect_t drw_rect
= { .x1
= dPriv
->x
, .x2
= dPriv
->x
+ dPriv
->w
,
220 .y1
= dPriv
->y
, .y2
= dPriv
->y
+ dPriv
->h
};
221 drm_clip_rect_t pipeA_rect
= { .x1
= sarea
->pipeA_x
, .y1
= sarea
->pipeA_y
,
222 .x2
= sarea
->pipeA_x
+ sarea
->pipeA_w
,
223 .y2
= sarea
->pipeA_y
+ sarea
->pipeA_h
};
224 drm_clip_rect_t pipeB_rect
= { .x1
= sarea
->pipeB_x
, .y1
= sarea
->pipeB_y
,
225 .x2
= sarea
->pipeB_x
+ sarea
->pipeB_w
,
226 .y2
= sarea
->pipeB_y
+ sarea
->pipeB_h
};
227 GLint areaA
= driIntersectArea( drw_rect
, pipeA_rect
);
228 GLint areaB
= driIntersectArea( drw_rect
, pipeB_rect
);
229 GLuint flags
= intel
->vblank_flags
;
231 if (areaB
> areaA
|| (areaA
== areaB
&& areaB
> 0)) {
232 flags
= intel
->vblank_flags
| VBLANK_FLAG_SECONDARY
;
234 flags
= intel
->vblank_flags
& ~VBLANK_FLAG_SECONDARY
;
237 if (flags
!= intel
->vblank_flags
) {
238 intel
->vblank_flags
= flags
;
239 driGetCurrentVBlank(dPriv
, intel
->vblank_flags
, &intel
->vbl_seq
);
242 intel
->vblank_flags
&= ~VBLANK_FLAG_SECONDARY
;
245 /* Update hardware scissor */
246 ctx
->Driver
.Scissor(ctx
, ctx
->Scissor
.X
, ctx
->Scissor
.Y
,
247 ctx
->Scissor
.Width
, ctx
->Scissor
.Height
);
249 /* Re-calculate viewport related state */
250 ctx
->Driver
.DepthRange( ctx
, ctx
->Viewport
.Near
, ctx
->Viewport
.Far
);
255 /* A true meta version of this would be very simple and additionally
256 * machine independent. Maybe we'll get there one day.
259 intelClearWithTris(struct intel_context
*intel
, GLbitfield mask
)
261 GLcontext
*ctx
= &intel
->ctx
;
262 drm_clip_rect_t clear
;
264 if (INTEL_DEBUG
& DEBUG_BLIT
)
265 _mesa_printf("%s 0x%x\n", __FUNCTION__
, mask
);
267 LOCK_HARDWARE(intel
);
269 /* XXX FBO: was: intel->driDrawable->numClipRects */
270 if (intel
->numClipRects
) {
271 GLint cx
, cy
, cw
, ch
;
274 intel
->vtbl
.install_meta_state(intel
);
276 /* Get clear bounds after locking */
277 cx
= ctx
->DrawBuffer
->_Xmin
;
278 cy
= ctx
->DrawBuffer
->_Ymin
;
279 ch
= ctx
->DrawBuffer
->_Ymax
- ctx
->DrawBuffer
->_Ymin
;
280 cw
= ctx
->DrawBuffer
->_Xmax
- ctx
->DrawBuffer
->_Xmin
;
282 /* note: regardless of 'all', cx, cy, cw, ch are now correct */
288 /* Back and stencil cliprects are the same. Try and do both
292 (BUFFER_BIT_BACK_LEFT
| BUFFER_BIT_STENCIL
| BUFFER_BIT_DEPTH
)) {
293 struct intel_region
*backRegion
=
294 intel_get_rb_region(ctx
->DrawBuffer
, BUFFER_BACK_LEFT
);
295 struct intel_region
*depthRegion
=
296 intel_get_rb_region(ctx
->DrawBuffer
, BUFFER_DEPTH
);
297 const GLuint clearColor
= (backRegion
&& backRegion
->cpp
== 4)
298 ? intel
->ClearColor8888
: intel
->ClearColor565
;
300 intel
->vtbl
.meta_draw_region(intel
, backRegion
, depthRegion
);
302 if (mask
& BUFFER_BIT_BACK_LEFT
)
303 intel
->vtbl
.meta_color_mask(intel
, GL_TRUE
);
305 intel
->vtbl
.meta_color_mask(intel
, GL_FALSE
);
307 if (mask
& BUFFER_BIT_STENCIL
)
308 intel
->vtbl
.meta_stencil_replace(intel
,
309 intel
->ctx
.Stencil
.WriteMask
[0],
310 intel
->ctx
.Stencil
.Clear
);
312 intel
->vtbl
.meta_no_stencil_write(intel
);
314 if (mask
& BUFFER_BIT_DEPTH
)
315 intel
->vtbl
.meta_depth_replace(intel
);
317 intel
->vtbl
.meta_no_depth_write(intel
);
319 /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
320 * drawing origin may not be correctly emitted.
322 intel_meta_draw_quad(intel
, clear
.x1
, clear
.x2
, clear
.y1
, clear
.y2
, intel
->ctx
.Depth
.Clear
, clearColor
, 0, 0, 0, 0); /* texcoords */
325 ~(BUFFER_BIT_BACK_LEFT
| BUFFER_BIT_STENCIL
| BUFFER_BIT_DEPTH
);
328 /* clear the remaining (color) renderbuffers */
329 for (buf
= 0; buf
< BUFFER_COUNT
&& mask
; buf
++) {
330 const GLuint bufBit
= 1 << buf
;
332 struct intel_renderbuffer
*irbColor
=
333 intel_renderbuffer(ctx
->DrawBuffer
->
334 Attachment
[buf
].Renderbuffer
);
335 GLuint color
= (irbColor
->region
->cpp
== 4)
336 ? intel
->ClearColor8888
: intel
->ClearColor565
;
340 intel
->vtbl
.meta_no_depth_write(intel
);
341 intel
->vtbl
.meta_no_stencil_write(intel
);
342 intel
->vtbl
.meta_color_mask(intel
, GL_TRUE
);
343 intel
->vtbl
.meta_draw_region(intel
, irbColor
->region
, NULL
);
345 /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
346 * drawing origin may not be correctly emitted.
348 intel_meta_draw_quad(intel
, clear
.x1
, clear
.x2
, clear
.y1
, clear
.y2
, 0, /* depth clear val */
349 color
, 0, 0, 0, 0); /* texcoords */
355 intel
->vtbl
.leave_meta_state(intel
);
356 intel_batchbuffer_flush(intel
->batch
);
358 UNLOCK_HARDWARE(intel
);
365 * Copy the window contents named by dPriv to the rotated (or reflected)
367 * srcBuf is BUFFER_BIT_FRONT_LEFT or BUFFER_BIT_BACK_LEFT to indicate the source.
370 intelRotateWindow(struct intel_context
*intel
,
371 __DRIdrawablePrivate
* dPriv
, GLuint srcBuf
)
373 intelScreenPrivate
*screen
= intel
->intelScreen
;
374 drm_clip_rect_t fullRect
;
375 struct intel_region
*src
;
376 const drm_clip_rect_t
*clipRects
;
382 int origNumClipRects
;
383 drm_clip_rect_t
*origRects
;
386 * set up hardware state
388 intelFlush(&intel
->ctx
);
390 LOCK_HARDWARE(intel
);
392 if (!intel
->numClipRects
) {
393 UNLOCK_HARDWARE(intel
);
397 intel
->vtbl
.install_meta_state(intel
);
399 intel
->vtbl
.meta_no_depth_write(intel
);
400 intel
->vtbl
.meta_no_stencil_write(intel
);
401 intel
->vtbl
.meta_color_mask(intel
, GL_FALSE
);
404 /* save current drawing origin and cliprects (restored at end) */
405 xOrig
= intel
->drawX
;
406 yOrig
= intel
->drawY
;
407 origNumClipRects
= intel
->numClipRects
;
408 origRects
= intel
->pClipRects
;
411 * set drawing origin, cliprects for full-screen access to rotated screen
415 fullRect
.x2
= screen
->rotatedWidth
;
416 fullRect
.y2
= screen
->rotatedHeight
;
419 intel
->numClipRects
= 1;
420 intel
->pClipRects
= &fullRect
;
422 intel
->vtbl
.meta_draw_region(intel
, screen
->rotated_region
, NULL
); /* ? */
424 if (srcBuf
== BUFFER_BIT_FRONT_LEFT
) {
425 src
= intel
->intelScreen
->front_region
;
426 clipRects
= dPriv
->pClipRects
;
427 numClipRects
= dPriv
->numClipRects
;
430 src
= intel
->intelScreen
->back_region
;
431 clipRects
= dPriv
->pBackClipRects
;
432 numClipRects
= dPriv
->numBackClipRects
;
437 type
= GL_UNSIGNED_BYTE
;
441 type
= GL_UNSIGNED_SHORT_5_6_5_REV
;
444 /* set the whole screen up as a texture to avoid alignment issues */
445 intel
->vtbl
.meta_tex_rect_source(intel
,
448 screen
->height
, src
->pitch
, format
, type
);
450 intel
->vtbl
.meta_texture_blend_replace(intel
);
453 * loop over the source window's cliprects
455 for (i
= 0; i
< numClipRects
; i
++) {
456 int srcX0
= clipRects
[i
].x1
;
457 int srcY0
= clipRects
[i
].y1
;
458 int srcX1
= clipRects
[i
].x2
;
459 int srcY1
= clipRects
[i
].y2
;
460 GLfloat verts
[4][2], tex
[4][2];
463 /* build vertices for four corners of clip rect */
473 /* .. and texcoords */
483 /* transform coords to rotated screen coords */
485 for (j
= 0; j
< 4; j
++) {
486 matrix23TransformCoordf(&screen
->rotMatrix
,
487 &verts
[j
][0], &verts
[j
][1]);
490 /* draw polygon to map source image to dest region */
491 intel_meta_draw_poly(intel
, 4, verts
, 0, 0, tex
);
493 } /* cliprect loop */
495 intel
->vtbl
.leave_meta_state(intel
);
496 intel_batchbuffer_flush(intel
->batch
);
498 /* restore original drawing origin and cliprects */
499 intel
->drawX
= xOrig
;
500 intel
->drawY
= yOrig
;
501 intel
->numClipRects
= origNumClipRects
;
502 intel
->pClipRects
= origRects
;
504 UNLOCK_HARDWARE(intel
);
509 * Called by ctx->Driver.Clear.
512 intelClear(GLcontext
*ctx
, GLbitfield mask
)
514 struct intel_context
*intel
= intel_context(ctx
);
515 const GLuint colorMask
= *((GLuint
*) & ctx
->Color
.ColorMask
);
516 GLbitfield tri_mask
= 0;
517 GLbitfield blit_mask
= 0;
518 GLbitfield swrast_mask
= 0;
522 fprintf(stderr
, "%s\n", __FUNCTION__
);
524 /* HW color buffers (front, back, aux, generic FBO, etc) */
525 if (colorMask
== ~0) {
526 /* clear all R,G,B,A */
527 /* XXX FBO: need to check if colorbuffers are software RBOs! */
528 blit_mask
|= (mask
& BUFFER_BITS_COLOR
);
531 /* glColorMask in effect */
532 tri_mask
|= (mask
& BUFFER_BITS_COLOR
);
536 if (mask
& BUFFER_BIT_STENCIL
) {
537 const struct intel_region
*stencilRegion
538 = intel_get_rb_region(ctx
->DrawBuffer
, BUFFER_STENCIL
);
540 /* have hw stencil */
541 if ((ctx
->Stencil
.WriteMask
[0] & 0xff) != 0xff) {
542 /* not clearing all stencil bits, so use triangle clearing */
543 tri_mask
|= BUFFER_BIT_STENCIL
;
546 /* clearing all stencil bits, use blitting */
547 blit_mask
|= BUFFER_BIT_STENCIL
;
553 if (mask
& BUFFER_BIT_DEPTH
) {
554 /* clear depth with whatever method is used for stencil (see above) */
555 if (tri_mask
& BUFFER_BIT_STENCIL
)
556 tri_mask
|= BUFFER_BIT_DEPTH
;
558 blit_mask
|= BUFFER_BIT_DEPTH
;
561 /* SW fallback clearing */
562 swrast_mask
= mask
& ~tri_mask
& ~blit_mask
;
564 for (i
= 0; i
< BUFFER_COUNT
; i
++) {
565 GLuint bufBit
= 1 << i
;
566 if ((blit_mask
| tri_mask
) & bufBit
) {
567 if (!ctx
->DrawBuffer
->Attachment
[i
].Renderbuffer
->ClassID
) {
568 blit_mask
&= ~bufBit
;
570 swrast_mask
|= bufBit
;
576 intelFlush(ctx
); /* XXX intelClearWithBlit also does this */
579 intelClearWithBlit(ctx
, blit_mask
);
582 intelClearWithTris(intel
, tri_mask
);
585 _swrast_Clear(ctx
, swrast_mask
);
590 /* Flip the front & back buffers
593 intelPageFlip(const __DRIdrawablePrivate
* dPriv
)
596 struct intel_context
*intel
;
599 if (INTEL_DEBUG
& DEBUG_IOCTL
)
600 fprintf(stderr
, "%s\n", __FUNCTION__
);
603 assert(dPriv
->driContextPriv
);
604 assert(dPriv
->driContextPriv
->driverPrivate
);
606 intel
= (struct intel_context
*) dPriv
->driContextPriv
->driverPrivate
;
608 intelFlush(&intel
->ctx
);
609 LOCK_HARDWARE(intel
);
611 if (dPriv
->pClipRects
) {
612 *(drm_clip_rect_t
*) intel
->sarea
->boxes
= dPriv
->pClipRects
[0];
613 intel
->sarea
->nbox
= 1;
616 ret
= drmCommandNone(intel
->driFd
, DRM_I830_FLIP
);
618 fprintf(stderr
, "%s: %d\n", __FUNCTION__
, ret
);
619 UNLOCK_HARDWARE(intel
);
623 tmp
= intel
->sarea
->last_enqueue
;
624 intelRefillBatchLocked(intel
);
625 UNLOCK_HARDWARE(intel
);
628 intelSetDrawBuffer(&intel
->ctx
, intel
->ctx
.Color
.DriverDrawBuffer
);
634 intelSwapBuffers(__DRIdrawablePrivate
* dPriv
)
636 if (dPriv
->driverPrivate
) {
637 const struct gl_framebuffer
*fb
638 = (struct gl_framebuffer
*) dPriv
->driverPrivate
;
639 if (fb
->Visual
.doubleBufferMode
) {
640 GET_CURRENT_CONTEXT(ctx
);
641 if (ctx
&& ctx
->DrawBuffer
== fb
) {
642 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering */
644 if (0 /*intel->doPageFlip */ ) { /* doPageFlip is never set !!! */
645 intelPageFlip(dPriv
);
648 intelCopyBuffer(dPriv
);
654 "dPriv has no gl_framebuffer pointer in intelSwapBuffers");
661 intelSwapBuffers(__DRIdrawablePrivate
* dPriv
)
663 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
664 GET_CURRENT_CONTEXT(ctx
);
665 struct intel_context
*intel
;
670 intel
= intel_context(ctx
);
672 if (ctx
->Visual
.doubleBufferMode
) {
673 intelScreenPrivate
*screen
= intel
->intelScreen
;
674 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
675 if (0 /*intel->doPageFlip */ ) { /* doPageFlip is never set !!! */
676 intelPageFlip(dPriv
);
679 intelCopyBuffer(dPriv
, NULL
);
681 if (screen
->current_rotation
!= 0) {
682 intelRotateWindow(intel
, dPriv
, BUFFER_BIT_FRONT_LEFT
);
687 /* XXX this shouldn't be an error but we can't handle it for now */
688 fprintf(stderr
, "%s: drawable has no context!\n", __FUNCTION__
);
694 intelCopySubBuffer(__DRIdrawablePrivate
* dPriv
, int x
, int y
, int w
, int h
)
696 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
697 struct intel_context
*intel
=
698 (struct intel_context
*) dPriv
->driContextPriv
->driverPrivate
;
699 GLcontext
*ctx
= &intel
->ctx
;
701 if (ctx
->Visual
.doubleBufferMode
) {
702 drm_clip_rect_t rect
;
703 rect
.x1
= x
+ dPriv
->x
;
704 rect
.y1
= (dPriv
->h
- y
- h
) + dPriv
->y
;
705 rect
.x2
= rect
.x1
+ w
;
706 rect
.y2
= rect
.y1
+ h
;
707 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
708 intelCopyBuffer(dPriv
, &rect
);
712 /* XXX this shouldn't be an error but we can't handle it for now */
713 fprintf(stderr
, "%s: drawable has no context!\n", __FUNCTION__
);
719 * Update the hardware state for drawing into a window or framebuffer object.
721 * Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other
722 * places within the driver.
724 * Basically, this needs to be called any time the current framebuffer
725 * changes, the renderbuffers change, or we need to draw into different
729 intel_draw_buffer(GLcontext
* ctx
, struct gl_framebuffer
*fb
)
731 struct intel_context
*intel
= intel_context(ctx
);
732 struct intel_region
*colorRegion
, *depthRegion
= NULL
;
733 struct intel_renderbuffer
*irbDepth
= NULL
, *irbStencil
= NULL
;
734 int front
= 0; /* drawing to front color buffer? */
737 /* this can happen during the initial context initialization */
741 /* Do this here, note core Mesa, since this function is called from
742 * many places within the driver.
744 if (ctx
->NewState
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
745 /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
746 _mesa_update_framebuffer(ctx
);
747 /* this updates the DrawBuffer's Width/Height if it's a FBO */
748 _mesa_update_draw_buffer_bounds(ctx
);
751 if (fb
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
752 /* this may occur when we're called by glBindFrameBuffer() during
753 * the process of someone setting up renderbuffers, etc.
755 /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
760 intel_validate_paired_depth_stencil(ctx
, fb
);
763 * How many color buffers are we drawing into?
765 if (fb
->_NumColorDrawBuffers
[0] != 1
767 /* XXX FBO temporary - always use software rendering */
771 /* writing to 0 or 2 or 4 color buffers */
772 /*_mesa_debug(ctx, "Software rendering\n");*/
773 FALLBACK(intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
774 front
= 1; /* might not have back color buffer */
777 /* draw to exactly one color buffer */
778 /*_mesa_debug(ctx, "Hardware rendering\n");*/
779 FALLBACK(intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
780 if (fb
->_ColorDrawBufferMask
[0] == BUFFER_BIT_FRONT_LEFT
) {
786 * Get the intel_renderbuffer for the colorbuffer we're drawing into.
787 * And set up cliprects.
790 /* drawing to window system buffer */
791 if (intel
->sarea
->pf_current_page
== 1) {
792 /* page flipped back/front */
796 intelSetFrontClipRects(intel
);
797 colorRegion
= intel_get_rb_region(fb
, BUFFER_FRONT_LEFT
);
800 intelSetBackClipRects(intel
);
801 colorRegion
= intel_get_rb_region(fb
, BUFFER_BACK_LEFT
);
805 /* drawing to user-created FBO */
806 struct intel_renderbuffer
*irb
;
807 intelSetRenderbufferClipRects(intel
);
808 irb
= intel_renderbuffer(fb
->_ColorDrawBuffers
[0][0]);
809 colorRegion
= (irb
&& irb
->region
) ? irb
->region
: NULL
;
812 /* Update culling direction which changes depending on the
813 * orientation of the buffer:
815 if (ctx
->Driver
.FrontFace
)
816 ctx
->Driver
.FrontFace(ctx
, ctx
->Polygon
.FrontFace
);
818 ctx
->NewState
|= _NEW_POLYGON
;
821 FALLBACK(intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
824 FALLBACK(intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
828 *** Get depth buffer region and check if we need a software fallback.
829 *** Note that the depth buffer is usually a DEPTH_STENCIL buffer.
831 if (fb
->_DepthBuffer
&& fb
->_DepthBuffer
->Wrapped
) {
832 irbDepth
= intel_renderbuffer(fb
->_DepthBuffer
->Wrapped
);
833 if (irbDepth
&& irbDepth
->region
) {
834 FALLBACK(intel
, INTEL_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
835 depthRegion
= irbDepth
->region
;
838 FALLBACK(intel
, INTEL_FALLBACK_DEPTH_BUFFER
, GL_TRUE
);
843 /* not using depth buffer */
844 FALLBACK(intel
, INTEL_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
850 *** This can only be hardware accelerated if we're using a
851 *** combined DEPTH_STENCIL buffer (for now anyway).
853 if (fb
->_StencilBuffer
&& fb
->_StencilBuffer
->Wrapped
) {
854 irbStencil
= intel_renderbuffer(fb
->_StencilBuffer
->Wrapped
);
855 if (irbStencil
&& irbStencil
->region
) {
856 ASSERT(irbStencil
->Base
._ActualFormat
== GL_DEPTH24_STENCIL8_EXT
);
857 FALLBACK(intel
, INTEL_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
858 /* need to re-compute stencil hw state */
859 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
, ctx
->Stencil
.Enabled
);
861 depthRegion
= irbStencil
->region
;
864 FALLBACK(intel
, INTEL_FALLBACK_STENCIL_BUFFER
, GL_TRUE
);
868 /* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */
869 FALLBACK(intel
, INTEL_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
870 /* need to re-compute stencil hw state */
871 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
, ctx
->Stencil
.Enabled
);
876 ** Release old regions, reference new regions
878 #if 0 /* XXX FBO: this seems to be redundant with i915_state_draw_region() */
879 if (intel
->draw_region
!= colorRegion
) {
880 intel_region_release(&intel
->draw_region
);
881 intel_region_reference(&intel
->draw_region
, colorRegion
);
883 if (intel
->intelScreen
->depth_region
!= depthRegion
) {
884 intel_region_release(&intel
->intelScreen
->depth_region
);
885 intel_region_reference(&intel
->intelScreen
->depth_region
, depthRegion
);
889 intel
->vtbl
.set_draw_region(intel
, colorRegion
, depthRegion
);
891 /* update viewport since it depends on window size */
892 ctx
->Driver
.Viewport(ctx
, ctx
->Viewport
.X
, ctx
->Viewport
.Y
,
893 ctx
->Viewport
.Width
, ctx
->Viewport
.Height
);
895 /* Update hardware scissor */
896 ctx
->Driver
.Scissor(ctx
, ctx
->Scissor
.X
, ctx
->Scissor
.Y
,
897 ctx
->Scissor
.Width
, ctx
->Scissor
.Height
);
902 intelDrawBuffer(GLcontext
* ctx
, GLenum mode
)
904 intel_draw_buffer(ctx
, ctx
->DrawBuffer
);
909 intelReadBuffer(GLcontext
* ctx
, GLenum mode
)
911 if (ctx
->ReadBuffer
== ctx
->DrawBuffer
) {
912 /* This will update FBO completeness status.
913 * A framebuffer will be incomplete if the GL_READ_BUFFER setting
914 * refers to a missing renderbuffer. Calling glReadBuffer can set
915 * that straight and can make the drawing buffer complete.
917 intel_draw_buffer(ctx
, ctx
->DrawBuffer
);
919 /* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc)
920 * reference ctx->ReadBuffer and do appropriate state checks.
926 intelInitBufferFuncs(struct dd_function_table
*functions
)
928 functions
->Clear
= intelClear
;
929 functions
->DrawBuffer
= intelDrawBuffer
;
930 functions
->ReadBuffer
= intelReadBuffer
;