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 "framebuffer.h"
40 #include "swrast/swrast.h"
45 * XXX move this into a new dri/common/cliprects.c file.
48 intel_intersect_cliprects(drm_clip_rect_t
* dst
,
49 const drm_clip_rect_t
* a
,
50 const drm_clip_rect_t
* b
)
54 GLint bw
= b
->x2
- bx
;
55 GLint bh
= b
->y2
- by
;
58 bw
-= a
->x1
- bx
, bx
= a
->x1
;
60 bh
-= a
->y1
- by
, by
= a
->y1
;
79 * Return pointer to current color drawing region, or NULL.
82 intel_drawbuf_region(struct intel_context
*intel
)
84 struct intel_renderbuffer
*irbColor
=
85 intel_renderbuffer(intel
->ctx
.DrawBuffer
->_ColorDrawBuffers
[0][0]);
87 return irbColor
->region
;
93 * Return pointer to current color reading region, or NULL.
96 intel_readbuf_region(struct intel_context
*intel
)
98 struct intel_renderbuffer
*irb
99 = intel_renderbuffer(intel
->ctx
.ReadBuffer
->_ColorReadBuffer
);
109 * Update the following fields for rendering to a user-created FBO:
110 * intel->numClipRects
116 intelSetRenderbufferClipRects(struct intel_context
*intel
)
118 assert(intel
->ctx
.DrawBuffer
->Width
> 0);
119 assert(intel
->ctx
.DrawBuffer
->Height
> 0);
120 intel
->fboRect
.x1
= 0;
121 intel
->fboRect
.y1
= 0;
122 intel
->fboRect
.x2
= intel
->ctx
.DrawBuffer
->Width
;
123 intel
->fboRect
.y2
= intel
->ctx
.DrawBuffer
->Height
;
124 intel
->numClipRects
= 1;
125 intel
->pClipRects
= &intel
->fboRect
;
132 * As above, but for rendering to front buffer of a window.
133 * \sa intelSetRenderbufferClipRects
136 intelSetFrontClipRects(struct intel_context
*intel
)
138 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
143 intel
->numClipRects
= dPriv
->numClipRects
;
144 intel
->pClipRects
= dPriv
->pClipRects
;
145 intel
->drawX
= dPriv
->x
;
146 intel
->drawY
= dPriv
->y
;
151 * As above, but for rendering to back buffer of a window.
154 intelSetBackClipRects(struct intel_context
*intel
)
156 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
161 if (intel
->sarea
->pf_enabled
== 0 && dPriv
->numBackClipRects
== 0) {
162 /* use the front clip rects */
163 intel
->numClipRects
= dPriv
->numClipRects
;
164 intel
->pClipRects
= dPriv
->pClipRects
;
165 intel
->drawX
= dPriv
->x
;
166 intel
->drawY
= dPriv
->y
;
169 /* use the back clip rects */
170 intel
->numClipRects
= dPriv
->numBackClipRects
;
171 intel
->pClipRects
= dPriv
->pBackClipRects
;
172 intel
->drawX
= dPriv
->backX
;
173 intel
->drawY
= dPriv
->backY
;
179 * This will be called whenever the currently bound window is moved/resized.
180 * XXX: actually, it seems to NOT be called when the window is only moved (BP).
183 intelWindowMoved(struct intel_context
*intel
)
185 GLcontext
*ctx
= &intel
->ctx
;
187 if (!intel
->ctx
.DrawBuffer
) {
188 /* when would this happen? -BP */
189 intelSetFrontClipRects(intel
);
191 else if (intel
->ctx
.DrawBuffer
->Name
!= 0) {
192 /* drawing to user-created FBO - do nothing */
193 /* Cliprects would be set from intelDrawBuffer() */
196 /* drawing to a window */
197 switch (intel
->ctx
.DrawBuffer
->_ColorDrawBufferMask
[0]) {
198 case BUFFER_BIT_FRONT_LEFT
:
199 intelSetFrontClipRects(intel
);
201 case BUFFER_BIT_BACK_LEFT
:
202 intelSetBackClipRects(intel
);
205 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
206 intelSetFrontClipRects(intel
);
210 /* this update Mesa's notion of window size */
211 if (ctx
->WinSysDrawBuffer
) {
212 _mesa_resize_framebuffer(ctx
, ctx
->WinSysDrawBuffer
,
213 intel
->driDrawable
->w
, intel
->driDrawable
->h
);
216 if (intel
->intelScreen
->driScrnPriv
->ddxMinor
>= 7 && intel
->driDrawable
) {
217 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
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
);
252 /* A true meta version of this would be very simple and additionally
253 * machine independent. Maybe we'll get there one day.
256 intelClearWithTris(struct intel_context
*intel
, GLbitfield mask
)
258 GLcontext
*ctx
= &intel
->ctx
;
259 drm_clip_rect_t clear
;
261 if (INTEL_DEBUG
& DEBUG_BLIT
)
262 _mesa_printf("%s 0x%x\n", __FUNCTION__
, mask
);
264 LOCK_HARDWARE(intel
);
266 /* XXX FBO: was: intel->driDrawable->numClipRects */
267 if (intel
->numClipRects
) {
268 GLint cx
, cy
, cw
, ch
;
271 intel
->vtbl
.install_meta_state(intel
);
273 /* Get clear bounds after locking */
274 cx
= ctx
->DrawBuffer
->_Xmin
;
275 cy
= ctx
->DrawBuffer
->_Ymin
;
276 ch
= ctx
->DrawBuffer
->_Ymax
- ctx
->DrawBuffer
->_Ymin
;
277 cw
= ctx
->DrawBuffer
->_Xmax
- ctx
->DrawBuffer
->_Xmin
;
279 /* note: regardless of 'all', cx, cy, cw, ch are now correct */
285 /* Back and stencil cliprects are the same. Try and do both
289 (BUFFER_BIT_BACK_LEFT
| BUFFER_BIT_STENCIL
| BUFFER_BIT_DEPTH
)) {
290 struct intel_region
*backRegion
=
291 intel_get_rb_region(ctx
->DrawBuffer
, BUFFER_BACK_LEFT
);
292 struct intel_region
*depthRegion
=
293 intel_get_rb_region(ctx
->DrawBuffer
, BUFFER_DEPTH
);
294 const GLuint clearColor
= (backRegion
&& backRegion
->cpp
== 4)
295 ? intel
->ClearColor8888
: intel
->ClearColor565
;
297 intel
->vtbl
.meta_draw_region(intel
, backRegion
, depthRegion
);
299 if (mask
& BUFFER_BIT_BACK_LEFT
)
300 intel
->vtbl
.meta_color_mask(intel
, GL_TRUE
);
302 intel
->vtbl
.meta_color_mask(intel
, GL_FALSE
);
304 if (mask
& BUFFER_BIT_STENCIL
)
305 intel
->vtbl
.meta_stencil_replace(intel
,
306 intel
->ctx
.Stencil
.WriteMask
[0],
307 intel
->ctx
.Stencil
.Clear
);
309 intel
->vtbl
.meta_no_stencil_write(intel
);
311 if (mask
& BUFFER_BIT_DEPTH
)
312 intel
->vtbl
.meta_depth_replace(intel
);
314 intel
->vtbl
.meta_no_depth_write(intel
);
316 /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
317 * drawing origin may not be correctly emitted.
319 intel_meta_draw_quad(intel
, clear
.x1
, clear
.x2
, clear
.y1
, clear
.y2
, intel
->ctx
.Depth
.Clear
, clearColor
, 0, 0, 0, 0); /* texcoords */
322 ~(BUFFER_BIT_BACK_LEFT
| BUFFER_BIT_STENCIL
| BUFFER_BIT_DEPTH
);
325 /* clear the remaining (color) renderbuffers */
326 for (buf
= 0; buf
< BUFFER_COUNT
&& mask
; buf
++) {
327 const GLuint bufBit
= 1 << buf
;
329 struct intel_renderbuffer
*irbColor
=
330 intel_renderbuffer(ctx
->DrawBuffer
->
331 Attachment
[buf
].Renderbuffer
);
332 GLuint color
= (irbColor
->region
->cpp
== 4)
333 ? intel
->ClearColor8888
: intel
->ClearColor565
;
337 intel
->vtbl
.meta_no_depth_write(intel
);
338 intel
->vtbl
.meta_no_stencil_write(intel
);
339 intel
->vtbl
.meta_color_mask(intel
, GL_TRUE
);
340 intel
->vtbl
.meta_draw_region(intel
, irbColor
->region
, NULL
);
342 /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
343 * drawing origin may not be correctly emitted.
345 intel_meta_draw_quad(intel
, clear
.x1
, clear
.x2
, clear
.y1
, clear
.y2
, 0, /* depth clear val */
346 color
, 0, 0, 0, 0); /* texcoords */
352 intel
->vtbl
.leave_meta_state(intel
);
353 intel_batchbuffer_flush(intel
->batch
);
355 UNLOCK_HARDWARE(intel
);
362 * Copy the window contents named by dPriv to the rotated (or reflected)
364 * srcBuf is BUFFER_BIT_FRONT_LEFT or BUFFER_BIT_BACK_LEFT to indicate the source.
367 intelRotateWindow(struct intel_context
*intel
,
368 __DRIdrawablePrivate
* dPriv
, GLuint srcBuf
)
370 intelScreenPrivate
*screen
= intel
->intelScreen
;
371 drm_clip_rect_t fullRect
;
372 struct intel_region
*src
;
373 const drm_clip_rect_t
*clipRects
;
379 int origNumClipRects
;
380 drm_clip_rect_t
*origRects
;
383 * set up hardware state
385 intelFlush(&intel
->ctx
);
387 LOCK_HARDWARE(intel
);
389 if (!intel
->numClipRects
) {
390 UNLOCK_HARDWARE(intel
);
394 intel
->vtbl
.install_meta_state(intel
);
396 intel
->vtbl
.meta_no_depth_write(intel
);
397 intel
->vtbl
.meta_no_stencil_write(intel
);
398 intel
->vtbl
.meta_color_mask(intel
, GL_FALSE
);
401 /* save current drawing origin and cliprects (restored at end) */
402 xOrig
= intel
->drawX
;
403 yOrig
= intel
->drawY
;
404 origNumClipRects
= intel
->numClipRects
;
405 origRects
= intel
->pClipRects
;
408 * set drawing origin, cliprects for full-screen access to rotated screen
412 fullRect
.x2
= screen
->rotatedWidth
;
413 fullRect
.y2
= screen
->rotatedHeight
;
416 intel
->numClipRects
= 1;
417 intel
->pClipRects
= &fullRect
;
419 intel
->vtbl
.meta_draw_region(intel
, screen
->rotated_region
, NULL
); /* ? */
421 if (srcBuf
== BUFFER_BIT_FRONT_LEFT
) {
422 src
= intel
->intelScreen
->front_region
;
423 clipRects
= dPriv
->pClipRects
;
424 numClipRects
= dPriv
->numClipRects
;
427 src
= intel
->intelScreen
->back_region
;
428 clipRects
= dPriv
->pBackClipRects
;
429 numClipRects
= dPriv
->numBackClipRects
;
434 type
= GL_UNSIGNED_BYTE
;
438 type
= GL_UNSIGNED_SHORT_5_6_5_REV
;
441 /* set the whole screen up as a texture to avoid alignment issues */
442 intel
->vtbl
.meta_tex_rect_source(intel
,
445 screen
->height
, src
->pitch
, format
, type
);
447 intel
->vtbl
.meta_texture_blend_replace(intel
);
450 * loop over the source window's cliprects
452 for (i
= 0; i
< numClipRects
; i
++) {
453 int srcX0
= clipRects
[i
].x1
;
454 int srcY0
= clipRects
[i
].y1
;
455 int srcX1
= clipRects
[i
].x2
;
456 int srcY1
= clipRects
[i
].y2
;
457 GLfloat verts
[4][2], tex
[4][2];
460 /* build vertices for four corners of clip rect */
470 /* .. and texcoords */
480 /* transform coords to rotated screen coords */
482 for (j
= 0; j
< 4; j
++) {
483 matrix23TransformCoordf(&screen
->rotMatrix
,
484 &verts
[j
][0], &verts
[j
][1]);
487 /* draw polygon to map source image to dest region */
488 intel_meta_draw_poly(intel
, 4, verts
, 0, 0, tex
);
490 } /* cliprect loop */
492 intel
->vtbl
.leave_meta_state(intel
);
493 intel_batchbuffer_flush(intel
->batch
);
495 /* restore original drawing origin and cliprects */
496 intel
->drawX
= xOrig
;
497 intel
->drawY
= yOrig
;
498 intel
->numClipRects
= origNumClipRects
;
499 intel
->pClipRects
= origRects
;
501 UNLOCK_HARDWARE(intel
);
506 * Called by ctx->Driver.Clear.
509 intelClear(GLcontext
*ctx
, GLbitfield mask
)
511 struct intel_context
*intel
= intel_context(ctx
);
512 const GLuint colorMask
= *((GLuint
*) & ctx
->Color
.ColorMask
);
513 GLbitfield tri_mask
= 0;
514 GLbitfield blit_mask
= 0;
515 GLbitfield swrast_mask
= 0;
519 fprintf(stderr
, "%s\n", __FUNCTION__
);
521 /* HW color buffers (front, back, aux, generic FBO, etc) */
522 if (colorMask
== ~0) {
523 /* clear all R,G,B,A */
524 /* XXX FBO: need to check if colorbuffers are software RBOs! */
525 blit_mask
|= (mask
& BUFFER_BITS_COLOR
);
528 /* glColorMask in effect */
529 tri_mask
|= (mask
& BUFFER_BITS_COLOR
);
533 if (mask
& BUFFER_BIT_STENCIL
) {
534 const struct intel_region
*stencilRegion
535 = intel_get_rb_region(ctx
->DrawBuffer
, BUFFER_STENCIL
);
537 /* have hw stencil */
538 if ((ctx
->Stencil
.WriteMask
[0] & 0xff) != 0xff) {
539 /* not clearing all stencil bits, so use triangle clearing */
540 tri_mask
|= BUFFER_BIT_STENCIL
;
543 /* clearing all stencil bits, use blitting */
544 blit_mask
|= BUFFER_BIT_STENCIL
;
550 if (mask
& BUFFER_BIT_DEPTH
) {
551 /* clear depth with whatever method is used for stencil (see above) */
552 if (tri_mask
& BUFFER_BIT_STENCIL
)
553 tri_mask
|= BUFFER_BIT_DEPTH
;
555 blit_mask
|= BUFFER_BIT_DEPTH
;
558 /* SW fallback clearing */
559 swrast_mask
= mask
& ~tri_mask
& ~blit_mask
;
561 for (i
= 0; i
< BUFFER_COUNT
; i
++) {
562 GLuint bufBit
= 1 << i
;
563 if ((blit_mask
| tri_mask
) & bufBit
) {
564 if (!ctx
->DrawBuffer
->Attachment
[i
].Renderbuffer
->ClassID
) {
565 blit_mask
&= ~bufBit
;
567 swrast_mask
|= bufBit
;
573 intelFlush(ctx
); /* XXX intelClearWithBlit also does this */
576 intelClearWithBlit(ctx
, blit_mask
);
579 intelClearWithTris(intel
, tri_mask
);
582 _swrast_Clear(ctx
, swrast_mask
);
587 /* Flip the front & back buffers
590 intelPageFlip(const __DRIdrawablePrivate
* dPriv
)
593 struct intel_context
*intel
;
596 if (INTEL_DEBUG
& DEBUG_IOCTL
)
597 fprintf(stderr
, "%s\n", __FUNCTION__
);
600 assert(dPriv
->driContextPriv
);
601 assert(dPriv
->driContextPriv
->driverPrivate
);
603 intel
= (struct intel_context
*) dPriv
->driContextPriv
->driverPrivate
;
605 intelFlush(&intel
->ctx
);
606 LOCK_HARDWARE(intel
);
608 if (dPriv
->pClipRects
) {
609 *(drm_clip_rect_t
*) intel
->sarea
->boxes
= dPriv
->pClipRects
[0];
610 intel
->sarea
->nbox
= 1;
613 ret
= drmCommandNone(intel
->driFd
, DRM_I830_FLIP
);
615 fprintf(stderr
, "%s: %d\n", __FUNCTION__
, ret
);
616 UNLOCK_HARDWARE(intel
);
620 tmp
= intel
->sarea
->last_enqueue
;
621 intelRefillBatchLocked(intel
);
622 UNLOCK_HARDWARE(intel
);
625 intelSetDrawBuffer(&intel
->ctx
, intel
->ctx
.Color
.DriverDrawBuffer
);
631 intelSwapBuffers(__DRIdrawablePrivate
* dPriv
)
633 if (dPriv
->driverPrivate
) {
634 const struct gl_framebuffer
*fb
635 = (struct gl_framebuffer
*) dPriv
->driverPrivate
;
636 if (fb
->Visual
.doubleBufferMode
) {
637 GET_CURRENT_CONTEXT(ctx
);
638 if (ctx
&& ctx
->DrawBuffer
== fb
) {
639 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering */
641 if (0 /*intel->doPageFlip */ ) { /* doPageFlip is never set !!! */
642 intelPageFlip(dPriv
);
645 intelCopyBuffer(dPriv
);
651 "dPriv has no gl_framebuffer pointer in intelSwapBuffers");
658 intelSwapBuffers(__DRIdrawablePrivate
* dPriv
)
660 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
661 GET_CURRENT_CONTEXT(ctx
);
662 struct intel_context
*intel
;
667 intel
= intel_context(ctx
);
669 if (ctx
->Visual
.doubleBufferMode
) {
670 intelScreenPrivate
*screen
= intel
->intelScreen
;
671 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
672 if (0 /*intel->doPageFlip */ ) { /* doPageFlip is never set !!! */
673 intelPageFlip(dPriv
);
676 intelCopyBuffer(dPriv
, NULL
);
678 if (screen
->current_rotation
!= 0) {
679 intelRotateWindow(intel
, dPriv
, BUFFER_BIT_FRONT_LEFT
);
684 /* XXX this shouldn't be an error but we can't handle it for now */
685 fprintf(stderr
, "%s: drawable has no context!\n", __FUNCTION__
);
691 intelCopySubBuffer(__DRIdrawablePrivate
* dPriv
, int x
, int y
, int w
, int h
)
693 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
694 struct intel_context
*intel
=
695 (struct intel_context
*) dPriv
->driContextPriv
->driverPrivate
;
696 GLcontext
*ctx
= &intel
->ctx
;
698 if (ctx
->Visual
.doubleBufferMode
) {
699 drm_clip_rect_t rect
;
700 rect
.x1
= x
+ dPriv
->x
;
701 rect
.y1
= (dPriv
->h
- y
- h
) + dPriv
->y
;
702 rect
.x2
= rect
.x1
+ w
;
703 rect
.y2
= rect
.y1
+ h
;
704 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
705 intelCopyBuffer(dPriv
, &rect
);
709 /* XXX this shouldn't be an error but we can't handle it for now */
710 fprintf(stderr
, "%s: drawable has no context!\n", __FUNCTION__
);
716 * Update the hardware state for drawing into a window or framebuffer object.
718 * Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other
719 * places within the driver.
721 * Basically, this needs to be called any time the current framebuffer
722 * changes, the renderbuffers change, or we need to draw into different
726 intel_draw_buffer(GLcontext
* ctx
, struct gl_framebuffer
*fb
)
728 struct intel_context
*intel
= intel_context(ctx
);
729 struct intel_region
*colorRegion
, *depthRegion
= NULL
;
730 struct intel_renderbuffer
*irbDepth
= NULL
, *irbStencil
= NULL
;
731 int front
= 0; /* drawing to front color buffer? */
734 /* this can happen during the initial context initialization */
738 /* Do this here, note core Mesa, since this function is called from
739 * many places within the driver.
741 if (ctx
->NewState
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
742 /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
743 _mesa_update_framebuffer(ctx
);
744 /* this updates the DrawBuffer's Width/Height if it's a FBO */
745 _mesa_update_draw_buffer_bounds(ctx
);
748 if (fb
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
749 /* this may occur when we're called by glBindFrameBuffer() during
750 * the process of someone setting up renderbuffers, etc.
752 /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
757 intel_validate_paired_depth_stencil(ctx
, fb
);
760 * How many color buffers are we drawing into?
762 if (fb
->_NumColorDrawBuffers
[0] != 1
764 /* XXX FBO temporary - always use software rendering */
768 /* writing to 0 or 2 or 4 color buffers */
769 /*_mesa_debug(ctx, "Software rendering\n");*/
770 FALLBACK(intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
771 front
= 1; /* might not have back color buffer */
774 /* draw to exactly one color buffer */
775 /*_mesa_debug(ctx, "Hardware rendering\n");*/
776 FALLBACK(intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
777 if (fb
->_ColorDrawBufferMask
[0] == BUFFER_BIT_FRONT_LEFT
) {
783 * Get the intel_renderbuffer for the colorbuffer we're drawing into.
784 * And set up cliprects.
787 /* drawing to window system buffer */
788 if (intel
->sarea
->pf_current_page
== 1) {
789 /* page flipped back/front */
793 intelSetFrontClipRects(intel
);
794 colorRegion
= intel_get_rb_region(fb
, BUFFER_FRONT_LEFT
);
797 intelSetBackClipRects(intel
);
798 colorRegion
= intel_get_rb_region(fb
, BUFFER_BACK_LEFT
);
802 /* drawing to user-created FBO */
803 struct intel_renderbuffer
*irb
;
804 intelSetRenderbufferClipRects(intel
);
805 irb
= intel_renderbuffer(fb
->_ColorDrawBuffers
[0][0]);
806 colorRegion
= (irb
&& irb
->region
) ? irb
->region
: NULL
;
809 /* Update culling direction which changes depending on the
810 * orientation of the buffer:
812 if (ctx
->Driver
.FrontFace
)
813 ctx
->Driver
.FrontFace(ctx
, ctx
->Polygon
.FrontFace
);
815 ctx
->NewState
|= _NEW_POLYGON
;
818 FALLBACK(intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
821 FALLBACK(intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
825 *** Get depth buffer region and check if we need a software fallback.
826 *** Note that the depth buffer is usually a DEPTH_STENCIL buffer.
828 if (fb
->_DepthBuffer
&& fb
->_DepthBuffer
->Wrapped
) {
829 irbDepth
= intel_renderbuffer(fb
->_DepthBuffer
->Wrapped
);
830 if (irbDepth
&& irbDepth
->region
) {
831 FALLBACK(intel
, INTEL_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
832 depthRegion
= irbDepth
->region
;
835 FALLBACK(intel
, INTEL_FALLBACK_DEPTH_BUFFER
, GL_TRUE
);
840 /* not using depth buffer */
841 FALLBACK(intel
, INTEL_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
847 *** This can only be hardware accelerated if we're using a
848 *** combined DEPTH_STENCIL buffer (for now anyway).
850 if (fb
->_StencilBuffer
&& fb
->_StencilBuffer
->Wrapped
) {
851 irbStencil
= intel_renderbuffer(fb
->_StencilBuffer
->Wrapped
);
852 if (irbStencil
&& irbStencil
->region
) {
853 ASSERT(irbStencil
->Base
._ActualFormat
== GL_DEPTH24_STENCIL8_EXT
);
854 FALLBACK(intel
, INTEL_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
855 /* need to re-compute stencil hw state */
856 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
, ctx
->Stencil
.Enabled
);
858 depthRegion
= irbStencil
->region
;
861 FALLBACK(intel
, INTEL_FALLBACK_STENCIL_BUFFER
, GL_TRUE
);
865 /* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */
866 FALLBACK(intel
, INTEL_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
867 /* need to re-compute stencil hw state */
868 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
, ctx
->Stencil
.Enabled
);
873 ** Release old regions, reference new regions
875 #if 0 /* XXX FBO: this seems to be redundant with i915_state_draw_region() */
876 if (intel
->draw_region
!= colorRegion
) {
877 intel_region_release(&intel
->draw_region
);
878 intel_region_reference(&intel
->draw_region
, colorRegion
);
880 if (intel
->intelScreen
->depth_region
!= depthRegion
) {
881 intel_region_release(&intel
->intelScreen
->depth_region
);
882 intel_region_reference(&intel
->intelScreen
->depth_region
, depthRegion
);
886 intel
->vtbl
.set_draw_region(intel
, colorRegion
, depthRegion
);
888 /* update viewport since it depends on window size */
889 ctx
->Driver
.Viewport(ctx
, ctx
->Viewport
.X
, ctx
->Viewport
.Y
,
890 ctx
->Viewport
.Width
, ctx
->Viewport
.Height
);
892 /* Update hardware scissor */
893 ctx
->Driver
.Scissor(ctx
, ctx
->Scissor
.X
, ctx
->Scissor
.Y
,
894 ctx
->Scissor
.Width
, ctx
->Scissor
.Height
);
899 intelDrawBuffer(GLcontext
* ctx
, GLenum mode
)
901 intel_draw_buffer(ctx
, ctx
->DrawBuffer
);
906 intelReadBuffer(GLcontext
* ctx
, GLenum mode
)
908 if (ctx
->ReadBuffer
== ctx
->DrawBuffer
) {
909 /* This will update FBO completeness status.
910 * A framebuffer will be incomplete if the GL_READ_BUFFER setting
911 * refers to a missing renderbuffer. Calling glReadBuffer can set
912 * that straight and can make the drawing buffer complete.
914 intel_draw_buffer(ctx
, ctx
->DrawBuffer
);
916 /* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc)
917 * reference ctx->ReadBuffer and do appropriate state checks.
923 intelInitBufferFuncs(struct dd_function_table
*functions
)
925 functions
->Clear
= intelClear
;
926 functions
->DrawBuffer
= intelDrawBuffer
;
927 functions
->ReadBuffer
= intelReadBuffer
;