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 intelBufferSize(GLframebuffer
* buffer
, GLuint
* width
, GLuint
* height
)
111 GET_CURRENT_CONTEXT(ctx
);
112 struct intel_context
*intel
= intel_context(ctx
);
113 /* Need to lock to make sure the driDrawable is uptodate. This
114 * information is used to resize Mesa's software buffers, so it has
117 /* XXX This isn't 100% correct, the given buffer might not be
118 * bound to the current context!
120 LOCK_HARDWARE(intel
);
121 if (intel
->driDrawable
) {
122 *width
= intel
->driDrawable
->w
;
123 *height
= intel
->driDrawable
->h
;
129 UNLOCK_HARDWARE(intel
);
135 * Update the following fields for rendering to a user-created FBO:
136 * intel->numClipRects
142 intelSetRenderbufferClipRects(struct intel_context
*intel
)
144 assert(intel
->ctx
.DrawBuffer
->Width
> 0);
145 assert(intel
->ctx
.DrawBuffer
->Height
> 0);
146 intel
->fboRect
.x1
= 0;
147 intel
->fboRect
.y1
= 0;
148 intel
->fboRect
.x2
= intel
->ctx
.DrawBuffer
->Width
;
149 intel
->fboRect
.y2
= intel
->ctx
.DrawBuffer
->Height
;
150 intel
->numClipRects
= 1;
151 intel
->pClipRects
= &intel
->fboRect
;
158 * As above, but for rendering to front buffer of a window.
159 * \sa intelSetRenderbufferClipRects
162 intelSetFrontClipRects(struct intel_context
*intel
)
164 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
169 intel
->numClipRects
= dPriv
->numClipRects
;
170 intel
->pClipRects
= dPriv
->pClipRects
;
171 intel
->drawX
= dPriv
->x
;
172 intel
->drawY
= dPriv
->y
;
177 * As above, but for rendering to back buffer of a window.
180 intelSetBackClipRects(struct intel_context
*intel
)
182 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
187 if (intel
->sarea
->pf_enabled
== 0 && dPriv
->numBackClipRects
== 0) {
188 /* use the front clip rects */
189 intel
->numClipRects
= dPriv
->numClipRects
;
190 intel
->pClipRects
= dPriv
->pClipRects
;
191 intel
->drawX
= dPriv
->x
;
192 intel
->drawY
= dPriv
->y
;
195 /* use the back clip rects */
196 intel
->numClipRects
= dPriv
->numBackClipRects
;
197 intel
->pClipRects
= dPriv
->pBackClipRects
;
198 intel
->drawX
= dPriv
->backX
;
199 intel
->drawY
= dPriv
->backY
;
205 * This will be called whenever the currently bound window is moved/resized.
206 * XXX: actually, it seems to NOT be called when the window is only moved (BP).
209 intelWindowMoved(struct intel_context
*intel
)
211 GLcontext
*ctx
= &intel
->ctx
;
213 if (!intel
->ctx
.DrawBuffer
) {
214 /* when would this happen? -BP */
215 intelSetFrontClipRects(intel
);
217 else if (intel
->ctx
.DrawBuffer
->Name
!= 0) {
218 /* drawing to user-created FBO - do nothing */
219 /* Cliprects would be set from intelDrawBuffer() */
222 /* drawing to a window */
223 switch (intel
->ctx
.DrawBuffer
->_ColorDrawBufferMask
[0]) {
224 case BUFFER_BIT_FRONT_LEFT
:
225 intelSetFrontClipRects(intel
);
227 case BUFFER_BIT_BACK_LEFT
:
228 intelSetBackClipRects(intel
);
231 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
232 intelSetFrontClipRects(intel
);
236 /* this update Mesa's notion of window size */
237 if (ctx
->WinSysDrawBuffer
) {
238 _mesa_resize_framebuffer(ctx
, ctx
->WinSysDrawBuffer
,
239 intel
->driDrawable
->w
, intel
->driDrawable
->h
);
242 if (intel
->intelScreen
->driScrnPriv
->ddxMinor
>= 7 && intel
->driDrawable
) {
243 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
244 drmI830Sarea
*sarea
= intel
->sarea
;
245 drm_clip_rect_t drw_rect
= { .x1
= dPriv
->x
, .x2
= dPriv
->x
+ dPriv
->w
,
246 .y1
= dPriv
->y
, .y2
= dPriv
->y
+ dPriv
->h
};
247 drm_clip_rect_t pipeA_rect
= { .x1
= sarea
->pipeA_x
, .y1
= sarea
->pipeA_y
,
248 .x2
= sarea
->pipeA_x
+ sarea
->pipeA_w
,
249 .y2
= sarea
->pipeA_y
+ sarea
->pipeA_h
};
250 drm_clip_rect_t pipeB_rect
= { .x1
= sarea
->pipeB_x
, .y1
= sarea
->pipeB_y
,
251 .x2
= sarea
->pipeB_x
+ sarea
->pipeB_w
,
252 .y2
= sarea
->pipeB_y
+ sarea
->pipeB_h
};
253 GLint areaA
= driIntersectArea( drw_rect
, pipeA_rect
);
254 GLint areaB
= driIntersectArea( drw_rect
, pipeB_rect
);
255 GLuint flags
= intel
->vblank_flags
;
257 if (areaB
> areaA
|| (areaA
== areaB
&& areaB
> 0)) {
258 flags
= intel
->vblank_flags
| VBLANK_FLAG_SECONDARY
;
260 flags
= intel
->vblank_flags
& ~VBLANK_FLAG_SECONDARY
;
263 if (flags
!= intel
->vblank_flags
) {
264 intel
->vblank_flags
= flags
;
265 driGetCurrentVBlank(dPriv
, intel
->vblank_flags
, &intel
->vbl_seq
);
268 intel
->vblank_flags
&= ~VBLANK_FLAG_SECONDARY
;
271 /* Update hardware scissor */
272 ctx
->Driver
.Scissor(ctx
, ctx
->Scissor
.X
, ctx
->Scissor
.Y
,
273 ctx
->Scissor
.Width
, ctx
->Scissor
.Height
);
278 /* A true meta version of this would be very simple and additionally
279 * machine independent. Maybe we'll get there one day.
282 intelClearWithTris(struct intel_context
*intel
,
284 GLboolean allFoo
, GLint cxFoo
, GLint cyFoo
, GLint cwFoo
, GLint chFoo
)
286 GLcontext
*ctx
= &intel
->ctx
;
287 drm_clip_rect_t clear
;
289 if (INTEL_DEBUG
& DEBUG_BLIT
)
290 _mesa_printf("%s 0x%x\n", __FUNCTION__
, mask
);
292 LOCK_HARDWARE(intel
);
294 /* XXX FBO: was: intel->driDrawable->numClipRects */
295 if (intel
->numClipRects
) {
296 GLint cx
, cy
, cw
, ch
;
299 intel
->vtbl
.install_meta_state(intel
);
301 /* Get clear bounds after locking */
302 cx
= ctx
->DrawBuffer
->_Xmin
;
303 cy
= ctx
->DrawBuffer
->_Ymin
;
304 ch
= ctx
->DrawBuffer
->_Ymax
- ctx
->DrawBuffer
->_Ymin
;
305 cw
= ctx
->DrawBuffer
->_Xmax
- ctx
->DrawBuffer
->_Xmin
;
307 /* note: regardless of 'all', cx, cy, cw, ch are now correct */
313 /* Back and stencil cliprects are the same. Try and do both
317 (BUFFER_BIT_BACK_LEFT
| BUFFER_BIT_STENCIL
| BUFFER_BIT_DEPTH
)) {
318 struct intel_region
*backRegion
=
319 intel_get_rb_region(ctx
->DrawBuffer
, BUFFER_BACK_LEFT
);
320 struct intel_region
*depthRegion
=
321 intel_get_rb_region(ctx
->DrawBuffer
, BUFFER_DEPTH
);
322 const GLuint clearColor
= (backRegion
&& backRegion
->cpp
== 4)
323 ? intel
->ClearColor8888
: intel
->ClearColor565
;
325 intel
->vtbl
.meta_draw_region(intel
, backRegion
, depthRegion
);
327 if (mask
& BUFFER_BIT_BACK_LEFT
)
328 intel
->vtbl
.meta_color_mask(intel
, GL_TRUE
);
330 intel
->vtbl
.meta_color_mask(intel
, GL_FALSE
);
332 if (mask
& BUFFER_BIT_STENCIL
)
333 intel
->vtbl
.meta_stencil_replace(intel
,
334 intel
->ctx
.Stencil
.WriteMask
[0],
335 intel
->ctx
.Stencil
.Clear
);
337 intel
->vtbl
.meta_no_stencil_write(intel
);
339 if (mask
& BUFFER_BIT_DEPTH
)
340 intel
->vtbl
.meta_depth_replace(intel
);
342 intel
->vtbl
.meta_no_depth_write(intel
);
344 /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
345 * drawing origin may not be correctly emitted.
347 intel_meta_draw_quad(intel
, clear
.x1
, clear
.x2
, clear
.y1
, clear
.y2
, intel
->ctx
.Depth
.Clear
, clearColor
, 0, 0, 0, 0); /* texcoords */
350 ~(BUFFER_BIT_BACK_LEFT
| BUFFER_BIT_STENCIL
| BUFFER_BIT_DEPTH
);
353 /* clear the remaining (color) renderbuffers */
354 for (buf
= 0; buf
< BUFFER_COUNT
&& mask
; buf
++) {
355 const GLuint bufBit
= 1 << buf
;
357 struct intel_renderbuffer
*irbColor
=
358 intel_renderbuffer(ctx
->DrawBuffer
->
359 Attachment
[buf
].Renderbuffer
);
360 GLuint color
= (irbColor
->region
->cpp
== 4)
361 ? intel
->ClearColor8888
: intel
->ClearColor565
;
365 intel
->vtbl
.meta_no_depth_write(intel
);
366 intel
->vtbl
.meta_no_stencil_write(intel
);
367 intel
->vtbl
.meta_color_mask(intel
, GL_TRUE
);
368 intel
->vtbl
.meta_draw_region(intel
, irbColor
->region
, NULL
);
370 /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
371 * drawing origin may not be correctly emitted.
373 intel_meta_draw_quad(intel
, clear
.x1
, clear
.x2
, clear
.y1
, clear
.y2
, 0, /* depth clear val */
374 color
, 0, 0, 0, 0); /* texcoords */
380 intel
->vtbl
.leave_meta_state(intel
);
381 intel_batchbuffer_flush(intel
->batch
);
383 UNLOCK_HARDWARE(intel
);
390 * Copy the window contents named by dPriv to the rotated (or reflected)
392 * srcBuf is BUFFER_BIT_FRONT_LEFT or BUFFER_BIT_BACK_LEFT to indicate the source.
395 intelRotateWindow(struct intel_context
*intel
,
396 __DRIdrawablePrivate
* dPriv
, GLuint srcBuf
)
398 intelScreenPrivate
*screen
= intel
->intelScreen
;
399 drm_clip_rect_t fullRect
;
400 struct intel_region
*src
;
401 const drm_clip_rect_t
*clipRects
;
407 int origNumClipRects
;
408 drm_clip_rect_t
*origRects
;
411 * set up hardware state
413 intelFlush(&intel
->ctx
);
415 LOCK_HARDWARE(intel
);
417 if (!intel
->numClipRects
) {
418 UNLOCK_HARDWARE(intel
);
422 intel
->vtbl
.install_meta_state(intel
);
424 intel
->vtbl
.meta_no_depth_write(intel
);
425 intel
->vtbl
.meta_no_stencil_write(intel
);
426 intel
->vtbl
.meta_color_mask(intel
, GL_FALSE
);
429 /* save current drawing origin and cliprects (restored at end) */
430 xOrig
= intel
->drawX
;
431 yOrig
= intel
->drawY
;
432 origNumClipRects
= intel
->numClipRects
;
433 origRects
= intel
->pClipRects
;
436 * set drawing origin, cliprects for full-screen access to rotated screen
440 fullRect
.x2
= screen
->rotatedWidth
;
441 fullRect
.y2
= screen
->rotatedHeight
;
444 intel
->numClipRects
= 1;
445 intel
->pClipRects
= &fullRect
;
447 intel
->vtbl
.meta_draw_region(intel
, screen
->rotated_region
, NULL
); /* ? */
449 if (srcBuf
== BUFFER_BIT_FRONT_LEFT
) {
450 src
= intel
->intelScreen
->front_region
;
451 clipRects
= dPriv
->pClipRects
;
452 numClipRects
= dPriv
->numClipRects
;
455 src
= intel
->intelScreen
->back_region
;
456 clipRects
= dPriv
->pBackClipRects
;
457 numClipRects
= dPriv
->numBackClipRects
;
462 type
= GL_UNSIGNED_BYTE
;
466 type
= GL_UNSIGNED_SHORT_5_6_5_REV
;
469 /* set the whole screen up as a texture to avoid alignment issues */
470 intel
->vtbl
.meta_tex_rect_source(intel
,
473 screen
->height
, src
->pitch
, format
, type
);
475 intel
->vtbl
.meta_texture_blend_replace(intel
);
478 * loop over the source window's cliprects
480 for (i
= 0; i
< numClipRects
; i
++) {
481 int srcX0
= clipRects
[i
].x1
;
482 int srcY0
= clipRects
[i
].y1
;
483 int srcX1
= clipRects
[i
].x2
;
484 int srcY1
= clipRects
[i
].y2
;
485 GLfloat verts
[4][2], tex
[4][2];
488 /* build vertices for four corners of clip rect */
498 /* .. and texcoords */
508 /* transform coords to rotated screen coords */
510 for (j
= 0; j
< 4; j
++) {
511 matrix23TransformCoordf(&screen
->rotMatrix
,
512 &verts
[j
][0], &verts
[j
][1]);
515 /* draw polygon to map source image to dest region */
516 intel_meta_draw_poly(intel
, 4, verts
, 0, 0, tex
);
518 } /* cliprect loop */
520 intel
->vtbl
.leave_meta_state(intel
);
521 intel_batchbuffer_flush(intel
->batch
);
523 /* restore original drawing origin and cliprects */
524 intel
->drawX
= xOrig
;
525 intel
->drawY
= yOrig
;
526 intel
->numClipRects
= origNumClipRects
;
527 intel
->pClipRects
= origRects
;
529 UNLOCK_HARDWARE(intel
);
534 * Called by ctx->Driver.Clear.
537 intelClear(GLcontext
* ctx
,
539 GLboolean allFoo
, GLint cxFoo
, GLint cyFoo
, GLint cwFoo
, GLint chFoo
)
541 struct intel_context
*intel
= intel_context(ctx
);
542 const GLuint colorMask
= *((GLuint
*) & ctx
->Color
.ColorMask
);
543 GLbitfield tri_mask
= 0;
544 GLbitfield blit_mask
= 0;
545 GLbitfield swrast_mask
= 0;
549 fprintf(stderr
, "%s\n", __FUNCTION__
);
551 /* HW color buffers (front, back, aux, generic FBO, etc) */
552 if (colorMask
== ~0) {
553 /* clear all R,G,B,A */
554 /* XXX FBO: need to check if colorbuffers are software RBOs! */
555 blit_mask
|= (mask
& BUFFER_BITS_COLOR
);
558 /* glColorMask in effect */
559 tri_mask
|= (mask
& BUFFER_BITS_COLOR
);
563 if (mask
& BUFFER_BIT_STENCIL
) {
564 const struct intel_region
*stencilRegion
565 = intel_get_rb_region(ctx
->DrawBuffer
, BUFFER_STENCIL
);
567 /* have hw stencil */
568 if ((ctx
->Stencil
.WriteMask
[0] & 0xff) != 0xff) {
569 /* not clearing all stencil bits, so use triangle clearing */
570 tri_mask
|= BUFFER_BIT_STENCIL
;
573 /* clearing all stencil bits, use blitting */
574 blit_mask
|= BUFFER_BIT_STENCIL
;
580 if (mask
& BUFFER_BIT_DEPTH
) {
581 /* clear depth with whatever method is used for stencil (see above) */
582 if (tri_mask
& BUFFER_BIT_STENCIL
)
583 tri_mask
|= BUFFER_BIT_DEPTH
;
585 blit_mask
|= BUFFER_BIT_DEPTH
;
588 /* SW fallback clearing */
589 swrast_mask
= mask
& ~tri_mask
& ~blit_mask
;
591 for (i
= 0; i
< BUFFER_COUNT
; i
++) {
592 GLuint bufBit
= 1 << i
;
593 if ((blit_mask
| tri_mask
) & bufBit
) {
594 if (!ctx
->DrawBuffer
->Attachment
[i
].Renderbuffer
->ClassID
) {
595 blit_mask
&= ~bufBit
;
597 swrast_mask
|= bufBit
;
603 intelFlush(ctx
); /* XXX intelClearWithBlit also does this */
606 intelClearWithBlit(ctx
, blit_mask
, 0, 0, 0, 0, 0);
609 intelClearWithTris(intel
, tri_mask
, 0, 0, 0, 0, 0);
612 _swrast_Clear(ctx
, swrast_mask
, 0, 0, 0, 0, 0);
617 /* Flip the front & back buffers
620 intelPageFlip(const __DRIdrawablePrivate
* dPriv
)
623 struct intel_context
*intel
;
626 if (INTEL_DEBUG
& DEBUG_IOCTL
)
627 fprintf(stderr
, "%s\n", __FUNCTION__
);
630 assert(dPriv
->driContextPriv
);
631 assert(dPriv
->driContextPriv
->driverPrivate
);
633 intel
= (struct intel_context
*) dPriv
->driContextPriv
->driverPrivate
;
635 intelFlush(&intel
->ctx
);
636 LOCK_HARDWARE(intel
);
638 if (dPriv
->pClipRects
) {
639 *(drm_clip_rect_t
*) intel
->sarea
->boxes
= dPriv
->pClipRects
[0];
640 intel
->sarea
->nbox
= 1;
643 ret
= drmCommandNone(intel
->driFd
, DRM_I830_FLIP
);
645 fprintf(stderr
, "%s: %d\n", __FUNCTION__
, ret
);
646 UNLOCK_HARDWARE(intel
);
650 tmp
= intel
->sarea
->last_enqueue
;
651 intelRefillBatchLocked(intel
);
652 UNLOCK_HARDWARE(intel
);
655 intelSetDrawBuffer(&intel
->ctx
, intel
->ctx
.Color
.DriverDrawBuffer
);
661 intelSwapBuffers(__DRIdrawablePrivate
* dPriv
)
663 if (dPriv
->driverPrivate
) {
664 const struct gl_framebuffer
*fb
665 = (struct gl_framebuffer
*) dPriv
->driverPrivate
;
666 if (fb
->Visual
.doubleBufferMode
) {
667 GET_CURRENT_CONTEXT(ctx
);
668 if (ctx
&& ctx
->DrawBuffer
== fb
) {
669 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering */
671 if (0 /*intel->doPageFlip */ ) { /* doPageFlip is never set !!! */
672 intelPageFlip(dPriv
);
675 intelCopyBuffer(dPriv
);
681 "dPriv has no gl_framebuffer pointer in intelSwapBuffers");
688 intelSwapBuffers(__DRIdrawablePrivate
* dPriv
)
690 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
691 GET_CURRENT_CONTEXT(ctx
);
692 struct intel_context
*intel
;
697 intel
= intel_context(ctx
);
699 if (ctx
->Visual
.doubleBufferMode
) {
700 intelScreenPrivate
*screen
= intel
->intelScreen
;
701 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
702 if (0 /*intel->doPageFlip */ ) { /* doPageFlip is never set !!! */
703 intelPageFlip(dPriv
);
706 intelCopyBuffer(dPriv
, NULL
);
708 if (screen
->current_rotation
!= 0) {
709 intelRotateWindow(intel
, dPriv
, BUFFER_BIT_FRONT_LEFT
);
714 /* XXX this shouldn't be an error but we can't handle it for now */
715 fprintf(stderr
, "%s: drawable has no context!\n", __FUNCTION__
);
721 intelCopySubBuffer(__DRIdrawablePrivate
* dPriv
, int x
, int y
, int w
, int h
)
723 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
724 struct intel_context
*intel
=
725 (struct intel_context
*) dPriv
->driContextPriv
->driverPrivate
;
726 GLcontext
*ctx
= &intel
->ctx
;
728 if (ctx
->Visual
.doubleBufferMode
) {
729 drm_clip_rect_t rect
;
730 rect
.x1
= x
+ dPriv
->x
;
731 rect
.y1
= (dPriv
->h
- y
- h
) + dPriv
->y
;
732 rect
.x2
= rect
.x1
+ w
;
733 rect
.y2
= rect
.y1
+ h
;
734 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
735 intelCopyBuffer(dPriv
, &rect
);
739 /* XXX this shouldn't be an error but we can't handle it for now */
740 fprintf(stderr
, "%s: drawable has no context!\n", __FUNCTION__
);
746 * Update the hardware state for drawing into a window or framebuffer object.
748 * Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other
749 * places within the driver.
751 * Basically, this needs to be called any time the current framebuffer
752 * changes, the renderbuffers change, or we need to draw into different
756 intel_draw_buffer(GLcontext
* ctx
, struct gl_framebuffer
*fb
)
758 struct intel_context
*intel
= intel_context(ctx
);
759 struct intel_region
*colorRegion
, *depthRegion
= NULL
;
760 struct intel_renderbuffer
*irbDepth
= NULL
, *irbStencil
= NULL
;
761 int front
= 0; /* drawing to front color buffer? */
764 /* this can happen during the initial context initialization */
768 /* Do this here, note core Mesa, since this function is called from
769 * many places within the driver.
771 if (ctx
->NewState
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
772 /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
773 _mesa_update_framebuffer(ctx
);
774 /* this updates the DrawBuffer's Width/Height if it's a FBO */
775 _mesa_update_draw_buffer_bounds(ctx
);
778 if (fb
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
779 /* this may occur when we're called by glBindFrameBuffer() during
780 * the process of someone setting up renderbuffers, etc.
782 /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
787 intel_validate_paired_depth_stencil(ctx
, fb
);
790 * How many color buffers are we drawing into?
792 if (fb
->_NumColorDrawBuffers
[0] != 1
794 /* XXX FBO temporary - always use software rendering */
798 /* writing to 0 or 2 or 4 color buffers */
799 /*_mesa_debug(ctx, "Software rendering\n");*/
800 FALLBACK(intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
801 front
= 1; /* might not have back color buffer */
804 /* draw to exactly one color buffer */
805 /*_mesa_debug(ctx, "Hardware rendering\n");*/
806 FALLBACK(intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
807 if (fb
->_ColorDrawBufferMask
[0] == BUFFER_BIT_FRONT_LEFT
) {
813 * Get the intel_renderbuffer for the colorbuffer we're drawing into.
814 * And set up cliprects.
817 /* drawing to window system buffer */
818 if (intel
->sarea
->pf_current_page
== 1) {
819 /* page flipped back/front */
823 intelSetFrontClipRects(intel
);
824 colorRegion
= intel_get_rb_region(fb
, BUFFER_FRONT_LEFT
);
827 intelSetBackClipRects(intel
);
828 colorRegion
= intel_get_rb_region(fb
, BUFFER_BACK_LEFT
);
832 /* drawing to user-created FBO */
833 struct intel_renderbuffer
*irb
;
834 intelSetRenderbufferClipRects(intel
);
835 irb
= intel_renderbuffer(fb
->_ColorDrawBuffers
[0][0]);
836 colorRegion
= (irb
&& irb
->region
) ? irb
->region
: NULL
;
839 /* Update culling direction which changes depending on the
840 * orientation of the buffer:
842 if (ctx
->Driver
.FrontFace
)
843 ctx
->Driver
.FrontFace(ctx
, ctx
->Polygon
.FrontFace
);
845 ctx
->NewState
|= _NEW_POLYGON
;
848 FALLBACK(intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
851 FALLBACK(intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
855 *** Get depth buffer region and check if we need a software fallback.
856 *** Note that the depth buffer is usually a DEPTH_STENCIL buffer.
858 if (fb
->_DepthBuffer
&& fb
->_DepthBuffer
->Wrapped
) {
859 irbDepth
= intel_renderbuffer(fb
->_DepthBuffer
->Wrapped
);
860 if (irbDepth
->region
) {
861 FALLBACK(intel
, INTEL_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
862 depthRegion
= irbDepth
->region
;
865 FALLBACK(intel
, INTEL_FALLBACK_DEPTH_BUFFER
, GL_TRUE
);
870 /* not using depth buffer */
871 FALLBACK(intel
, INTEL_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
877 *** This can only be hardware accelerated if we're using a
878 *** combined DEPTH_STENCIL buffer (for now anyway).
880 if (fb
->_StencilBuffer
&& fb
->_StencilBuffer
->Wrapped
) {
881 irbStencil
= intel_renderbuffer(fb
->_StencilBuffer
->Wrapped
);
882 if (irbStencil
&& irbStencil
->region
) {
883 ASSERT(irbStencil
->Base
._ActualFormat
== GL_DEPTH24_STENCIL8_EXT
);
884 FALLBACK(intel
, INTEL_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
885 /* need to re-compute stencil hw state */
886 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
, ctx
->Stencil
.Enabled
);
888 depthRegion
= irbStencil
->region
;
891 FALLBACK(intel
, INTEL_FALLBACK_STENCIL_BUFFER
, GL_TRUE
);
895 /* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */
896 FALLBACK(intel
, INTEL_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
897 /* need to re-compute stencil hw state */
898 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
, ctx
->Stencil
.Enabled
);
903 ** Release old regions, reference new regions
905 #if 0 /* XXX FBO: this seems to be redundant with i915_state_draw_region() */
906 if (intel
->draw_region
!= colorRegion
) {
907 intel_region_release(&intel
->draw_region
);
908 intel_region_reference(&intel
->draw_region
, colorRegion
);
910 if (intel
->intelScreen
->depth_region
!= depthRegion
) {
911 intel_region_release(&intel
->intelScreen
->depth_region
);
912 intel_region_reference(&intel
->intelScreen
->depth_region
, depthRegion
);
916 intel
->vtbl
.set_draw_region(intel
, colorRegion
, depthRegion
);
918 /* update viewport since it depends on window size */
919 ctx
->Driver
.Viewport(ctx
, ctx
->Viewport
.X
, ctx
->Viewport
.Y
,
920 ctx
->Viewport
.Width
, ctx
->Viewport
.Height
);
922 /* Update hardware scissor */
923 ctx
->Driver
.Scissor(ctx
, ctx
->Scissor
.X
, ctx
->Scissor
.Y
,
924 ctx
->Scissor
.Width
, ctx
->Scissor
.Height
);
929 intelDrawBuffer(GLcontext
* ctx
, GLenum mode
)
931 intel_draw_buffer(ctx
, ctx
->DrawBuffer
);
936 intelReadBuffer(GLcontext
* ctx
, GLenum mode
)
938 if (ctx
->ReadBuffer
== ctx
->DrawBuffer
) {
939 /* This will update FBO completeness status.
940 * A framebuffer will be incomplete if the GL_READ_BUFFER setting
941 * refers to a missing renderbuffer. Calling glReadBuffer can set
942 * that straight and can make the drawing buffer complete.
944 intel_draw_buffer(ctx
, ctx
->DrawBuffer
);
946 /* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc)
947 * reference ctx->ReadBuffer and do appropriate state checks.
953 intelInitBufferFuncs(struct dd_function_table
*functions
)
955 functions
->Clear
= intelClear
;
956 functions
->GetBufferSize
= intelBufferSize
;
957 functions
->ResizeBuffers
= _mesa_resize_framebuffer
;
958 functions
->DrawBuffer
= intelDrawBuffer
;
959 functions
->ReadBuffer
= intelReadBuffer
;