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_regions.h"
32 #include "intel_batchbuffer.h"
34 #include "framebuffer.h"
36 #include "swrast/swrast.h"
38 GLboolean
intel_intersect_cliprects( drm_clip_rect_t
*dst
,
39 const drm_clip_rect_t
*a
,
40 const drm_clip_rect_t
*b
)
42 dst
->x1
= MAX2(a
->x1
, b
->x1
);
43 dst
->x2
= MIN2(a
->x2
, b
->x2
);
44 dst
->y1
= MAX2(a
->y1
, b
->y1
);
45 dst
->y2
= MIN2(a
->y2
, b
->y2
);
47 return (dst
->x1
<= dst
->x2
&&
51 struct intel_region
*intel_drawbuf_region( struct intel_context
*intel
)
53 switch (intel
->ctx
.DrawBuffer
->_ColorDrawBufferMask
[0]) {
54 case BUFFER_BIT_FRONT_LEFT
:
55 return intel
->front_region
;
56 case BUFFER_BIT_BACK_LEFT
:
57 return intel
->back_region
;
59 /* Not necessary to fallback - could handle either NONE or
60 * FRONT_AND_BACK cases below.
66 struct intel_region
*intel_readbuf_region( struct intel_context
*intel
)
68 GLcontext
*ctx
= &intel
->ctx
;
70 /* This will have to change to support EXT_fbo's, but is correct
73 switch (ctx
->ReadBuffer
->_ColorReadBufferIndex
) {
74 case BUFFER_FRONT_LEFT
:
75 return intel
->front_region
;
76 case BUFFER_BACK_LEFT
:
77 return intel
->back_region
;
86 static void intelBufferSize(GLframebuffer
*buffer
,
90 GET_CURRENT_CONTEXT(ctx
);
91 struct intel_context
*intel
= intel_context(ctx
);
92 /* Need to lock to make sure the driDrawable is uptodate. This
93 * information is used to resize Mesa's software buffers, so it has
97 if (intel
->driDrawable
) {
98 *width
= intel
->driDrawable
->w
;
99 *height
= intel
->driDrawable
->h
;
105 UNLOCK_HARDWARE(intel
);
109 static void intelSetFrontClipRects( struct intel_context
*intel
)
111 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
115 intel
->numClipRects
= dPriv
->numClipRects
;
116 intel
->pClipRects
= dPriv
->pClipRects
;
117 intel
->drawX
= dPriv
->x
;
118 intel
->drawY
= dPriv
->y
;
122 static void intelSetBackClipRects( struct intel_context
*intel
)
124 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
128 if (intel
->sarea
->pf_enabled
== 0 && dPriv
->numBackClipRects
== 0) {
129 intel
->numClipRects
= dPriv
->numClipRects
;
130 intel
->pClipRects
= dPriv
->pClipRects
;
131 intel
->drawX
= dPriv
->x
;
132 intel
->drawY
= dPriv
->y
;
134 intel
->numClipRects
= dPriv
->numBackClipRects
;
135 intel
->pClipRects
= dPriv
->pBackClipRects
;
136 intel
->drawX
= dPriv
->backX
;
137 intel
->drawY
= dPriv
->backY
;
139 if (dPriv
->numBackClipRects
== 1 &&
140 dPriv
->x
== dPriv
->backX
&&
141 dPriv
->y
== dPriv
->backY
) {
143 /* Repeat the calculation of the back cliprect dimensions here
144 * as early versions of dri.a in the Xserver are incorrect. Try
145 * very hard not to restrict future versions of dri.a which
146 * might eg. allocate truly private back buffers.
153 x2
= dPriv
->x
+ dPriv
->w
;
154 y2
= dPriv
->y
+ dPriv
->h
;
158 if (x2
> intel
->intelScreen
->width
) x2
= intel
->intelScreen
->width
;
159 if (y2
> intel
->intelScreen
->height
) y2
= intel
->intelScreen
->height
;
161 if (x1
== dPriv
->pBackClipRects
[0].x1
&&
162 y1
== dPriv
->pBackClipRects
[0].y1
) {
164 dPriv
->pBackClipRects
[0].x2
= x2
;
165 dPriv
->pBackClipRects
[0].y2
= y2
;
172 void intelWindowMoved( struct intel_context
*intel
)
174 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
176 if (!intel
->ctx
.DrawBuffer
) {
177 intelSetFrontClipRects( intel
);
180 switch (intel
->ctx
.DrawBuffer
->_ColorDrawBufferMask
[0]) {
181 case BUFFER_BIT_FRONT_LEFT
:
182 intelSetFrontClipRects( intel
);
184 case BUFFER_BIT_BACK_LEFT
:
185 intelSetBackClipRects( intel
);
188 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
189 intelSetFrontClipRects( intel
);
193 _mesa_resize_framebuffer(&intel
->ctx
,
194 (GLframebuffer
*)dPriv
->driverPrivate
,
197 /* Set state we know depends on drawable parameters:
200 GLcontext
*ctx
= &intel
->ctx
;
202 if (ctx
->Driver
.Scissor
)
203 ctx
->Driver
.Scissor( ctx
, ctx
->Scissor
.X
, ctx
->Scissor
.Y
,
204 ctx
->Scissor
.Width
, ctx
->Scissor
.Height
);
206 if (ctx
->Driver
.DepthRange
)
207 ctx
->Driver
.DepthRange( ctx
,
211 intel
->NewGLState
|= _NEW_SCISSOR
;
217 /* A true meta version of this would be very simple and additionally
218 * machine independent. Maybe we'll get there one day.
220 static void intelClearWithTris(struct intel_context
*intel
,
226 drm_clip_rect_t clear
;
228 if (INTEL_DEBUG
& DEBUG_DRI
)
229 _mesa_printf("%s %x\n", __FUNCTION__
, mask
);
233 intel
->vtbl
.install_meta_state(intel
);
235 /* Refresh the cx/y/w/h values as they may have been invalidated
236 * by a new window position or size picked up when we did
237 * LOCK_HARDWARE above. The values passed by mesa are not
241 GLcontext
*ctx
= &intel
->ctx
;
242 cx
= ctx
->DrawBuffer
->_Xmin
;
243 cy
= ctx
->DrawBuffer
->_Ymin
;
244 ch
= ctx
->DrawBuffer
->_Ymax
- ctx
->DrawBuffer
->_Ymin
;
245 cw
= ctx
->DrawBuffer
->_Xmax
- ctx
->DrawBuffer
->_Xmin
;
253 /* Back and stencil cliprects are the same. Try and do both
256 if (mask
& (BUFFER_BIT_BACK_LEFT
|BUFFER_BIT_STENCIL
|BUFFER_BIT_DEPTH
)) {
257 intel
->vtbl
.meta_draw_region(intel
,
259 intel
->depth_region
);
261 if (mask
& BUFFER_BIT_BACK_LEFT
)
262 intel
->vtbl
.meta_color_mask(intel
, GL_TRUE
);
264 intel
->vtbl
.meta_color_mask(intel
, GL_FALSE
);
266 if (mask
& BUFFER_BIT_STENCIL
)
267 intel
->vtbl
.meta_stencil_replace( intel
,
268 intel
->ctx
.Stencil
.WriteMask
[0],
269 intel
->ctx
.Stencil
.Clear
);
271 intel
->vtbl
.meta_no_stencil_write(intel
);
273 if (mask
& BUFFER_BIT_DEPTH
)
274 intel
->vtbl
.meta_depth_replace( intel
);
276 intel
->vtbl
.meta_no_depth_write(intel
);
278 /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
279 * drawing origin may not be correctly emitted.
281 intel
->vtbl
.meta_draw_quad(intel
,
284 intel
->ctx
.Depth
.Clear
,
285 intel
->clear_chan
[0],
286 intel
->clear_chan
[1],
287 intel
->clear_chan
[2],
288 intel
->clear_chan
[3],
292 /* Front may have different cliprects:
294 if (mask
& BUFFER_BIT_FRONT_LEFT
) {
295 intel
->vtbl
.meta_no_depth_write(intel
);
296 intel
->vtbl
.meta_no_stencil_write(intel
);
297 intel
->vtbl
.meta_color_mask(intel
, GL_TRUE
);
298 intel
->vtbl
.meta_draw_region(intel
,
300 intel
->depth_region
);
302 /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
303 * drawing origin may not be correctly emitted.
305 intel
->vtbl
.meta_draw_quad(intel
,
309 intel
->clear_chan
[0],
310 intel
->clear_chan
[1],
311 intel
->clear_chan
[2],
312 intel
->clear_chan
[3],
316 intel
->vtbl
.leave_meta_state( intel
);
324 static void intelClear(GLcontext
*ctx
,
330 struct intel_context
*intel
= intel_context( ctx
);
331 const GLuint colorMask
= *((GLuint
*) &ctx
->Color
.ColorMask
);
332 GLbitfield tri_mask
= 0;
333 GLbitfield blit_mask
= 0;
334 GLbitfield swrast_mask
= 0;
336 if (INTEL_DEBUG
& DEBUG_DRI
)
337 fprintf(stderr
, "%s %x all %d dims %d,%d %dx%d\n", __FUNCTION__
,
338 mask
, all
, cx
, cy
, cw
, ch
);
341 if (mask
& BUFFER_BIT_FRONT_LEFT
) {
342 if (colorMask
== ~0) {
343 blit_mask
|= BUFFER_BIT_FRONT_LEFT
;
346 tri_mask
|= BUFFER_BIT_FRONT_LEFT
;
350 if (mask
& BUFFER_BIT_BACK_LEFT
) {
351 if (colorMask
== ~0) {
352 blit_mask
|= BUFFER_BIT_BACK_LEFT
;
355 tri_mask
|= BUFFER_BIT_BACK_LEFT
;
360 if (mask
& BUFFER_BIT_STENCIL
) {
361 if (!intel
->hw_stencil
) {
362 swrast_mask
|= BUFFER_BIT_STENCIL
;
364 else if ((ctx
->Stencil
.WriteMask
[0] & 0xff) != 0xff ||
365 intel
->depth_region
->tiled
) {
366 tri_mask
|= BUFFER_BIT_STENCIL
;
369 blit_mask
|= BUFFER_BIT_STENCIL
;
373 /* Do depth with stencil if possible to avoid 2nd pass over the
376 if (mask
& BUFFER_BIT_DEPTH
) {
377 if ((tri_mask
& BUFFER_BIT_STENCIL
) ||
378 intel
->depth_region
->tiled
)
379 tri_mask
|= BUFFER_BIT_DEPTH
;
381 blit_mask
|= BUFFER_BIT_DEPTH
;
384 swrast_mask
|= (mask
& BUFFER_BIT_ACCUM
);
389 intelClearWithBlit( ctx
, blit_mask
, all
, cx
, cy
, cw
, ch
);
392 intelClearWithTris( intel
, tri_mask
, all
, cx
, cy
, cw
, ch
);
395 _swrast_Clear( ctx
, swrast_mask
, all
, cx
, cy
, cw
, ch
);
404 /* Flip the front & back buffers
406 static void intelPageFlip( const __DRIdrawablePrivate
*dPriv
)
409 struct intel_context
*intel
;
412 if (INTEL_DEBUG
& DEBUG_IOCTL
)
413 fprintf(stderr
, "%s\n", __FUNCTION__
);
416 assert(dPriv
->driContextPriv
);
417 assert(dPriv
->driContextPriv
->driverPrivate
);
419 intel
= (struct intel_context
*) dPriv
->driContextPriv
->driverPrivate
;
421 intelFlush( &intel
->ctx
);
422 LOCK_HARDWARE( intel
);
424 if (dPriv
->pClipRects
) {
425 *(drm_clip_rect_t
*)intel
->sarea
->boxes
= dPriv
->pClipRects
[0];
426 intel
->sarea
->nbox
= 1;
429 ret
= drmCommandNone(intel
->driFd
, DRM_I830_FLIP
);
431 fprintf(stderr
, "%s: %d\n", __FUNCTION__
, ret
);
432 UNLOCK_HARDWARE( intel
);
436 tmp
= intel
->sarea
->last_enqueue
;
437 intelRefillBatchLocked( intel
);
438 UNLOCK_HARDWARE( intel
);
441 intelSetDrawBuffer( &intel
->ctx
, intel
->ctx
.Color
.DriverDrawBuffer
);
446 void intelSwapBuffers( __DRIdrawablePrivate
*dPriv
)
448 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
449 struct intel_context
*intel
;
451 intel
= (struct intel_context
*) dPriv
->driContextPriv
->driverPrivate
;
453 if (ctx
->Visual
.doubleBufferMode
) {
454 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
455 if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */
456 intelPageFlip( dPriv
);
458 intelCopyBuffer( dPriv
, NULL
);
460 if (intel
->aub_file
) {
462 intel
->vtbl
.aub_dump_bmp( intel
, 1 );
468 /* XXX this shouldn't be an error but we can't handle it for now */
469 fprintf(stderr
, "%s: drawable has no context!\n", __FUNCTION__
);
473 void intelCopySubBuffer( __DRIdrawablePrivate
*dPriv
,
474 int x
, int y
, int w
, int h
)
476 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
477 struct intel_context
*intel
= dPriv
->driContextPriv
->driverPrivate
;
478 GLcontext
*ctx
= &intel
->ctx
;
480 if (ctx
->Visual
.doubleBufferMode
) {
481 drm_clip_rect_t rect
;
482 rect
.x1
= x
+ dPriv
->x
;
483 rect
.y1
= (dPriv
->h
- y
- h
) + dPriv
->y
;
484 rect
.x2
= rect
.x1
+ w
;
485 rect
.y2
= rect
.y1
+ h
;
486 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
487 intelCopyBuffer( dPriv
, &rect
);
490 /* XXX this shouldn't be an error but we can't handle it for now */
491 fprintf(stderr
, "%s: drawable has no context!\n", __FUNCTION__
);
496 static void intelDrawBuffer(GLcontext
*ctx
, GLenum mode
)
498 struct intel_context
*intel
= intel_context(ctx
);
501 if (!ctx
->DrawBuffer
)
504 switch ( ctx
->DrawBuffer
->_ColorDrawBufferMask
[0] ) {
505 case BUFFER_BIT_FRONT_LEFT
:
507 FALLBACK( intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
509 case BUFFER_BIT_BACK_LEFT
:
511 FALLBACK( intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
514 FALLBACK( intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
518 if ( intel
->sarea
->pf_current_page
== 1 )
521 intelSetFrontClipRects( intel
);
525 if (intel
->draw_region
!= intel
->front_region
) {
526 intel_region_release(intel
, &intel
->draw_region
);
527 intel_region_reference(&intel
->draw_region
, intel
->front_region
);
530 if (intel
->draw_region
!= intel
->back_region
) {
531 intel_region_release(intel
, &intel
->draw_region
);
532 intel_region_reference(&intel
->draw_region
, intel
->back_region
);
536 intel
->vtbl
.set_draw_region( intel
,
538 intel
->depth_region
);
541 static void intelReadBuffer( GLcontext
*ctx
, GLenum mode
)
543 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
548 void intelInitBufferFuncs( struct dd_function_table
*functions
)
550 functions
->Clear
= intelClear
;
551 functions
->GetBufferSize
= intelBufferSize
;
552 functions
->DrawBuffer
= intelDrawBuffer
;
553 functions
->ReadBuffer
= intelReadBuffer
;