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
;
214 /* This works because the lock is always grabbed before emitting
215 * commands and commands are always flushed prior to releasing
218 intel
->NewGLState
|= _NEW_WINDOW_POS
;
223 /* A true meta version of this would be very simple and additionally
224 * machine independent. Maybe we'll get there one day.
226 static void intelClearWithTris(struct intel_context
*intel
,
229 GLcontext
*ctx
= &intel
->ctx
;
230 drm_clip_rect_t clear
;
231 GLint cx
, cy
, cw
, ch
;
233 if (INTEL_DEBUG
& DEBUG_DRI
)
234 _mesa_printf("%s %x\n", __FUNCTION__
, mask
);
238 intel
->vtbl
.install_meta_state(intel
, META_FULL
);
240 /* Get clear bounds after locking */
241 cx
= ctx
->DrawBuffer
->_Xmin
;
242 cy
= ctx
->DrawBuffer
->_Ymin
;
243 cw
= ctx
->DrawBuffer
->_Xmax
- ctx
->DrawBuffer
->_Xmin
;
244 ch
= ctx
->DrawBuffer
->_Ymax
- ctx
->DrawBuffer
->_Ymin
;
251 /* Back and stencil cliprects are the same. Try and do both
254 if (mask
& (BUFFER_BIT_BACK_LEFT
|BUFFER_BIT_STENCIL
|BUFFER_BIT_DEPTH
)) {
255 intel
->vtbl
.meta_draw_region(intel
,
257 intel
->depth_region
);
259 if (mask
& BUFFER_BIT_BACK_LEFT
)
260 intel
->vtbl
.meta_color_mask(intel
, GL_TRUE
);
262 intel
->vtbl
.meta_color_mask(intel
, GL_FALSE
);
264 if (mask
& BUFFER_BIT_STENCIL
)
265 intel
->vtbl
.meta_stencil_replace( intel
,
266 intel
->ctx
.Stencil
.WriteMask
[0],
267 intel
->ctx
.Stencil
.Clear
);
269 intel
->vtbl
.meta_no_stencil_write(intel
);
271 if (mask
& BUFFER_BIT_DEPTH
)
272 intel
->vtbl
.meta_depth_replace( intel
);
274 intel
->vtbl
.meta_no_depth_write(intel
);
276 /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
277 * drawing origin may not be correctly emitted.
279 intel
->vtbl
.meta_draw_quad(intel
,
282 intel
->ctx
.Depth
.Clear
,
283 intel
->clear_chan
[0],
284 intel
->clear_chan
[1],
285 intel
->clear_chan
[2],
286 intel
->clear_chan
[3],
290 /* Front may have different cliprects:
292 if (mask
& BUFFER_BIT_FRONT_LEFT
) {
293 intel
->vtbl
.meta_no_depth_write(intel
);
294 intel
->vtbl
.meta_no_stencil_write(intel
);
295 intel
->vtbl
.meta_color_mask(intel
, GL_TRUE
);
296 intel
->vtbl
.meta_draw_region(intel
,
298 intel
->depth_region
);
300 /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
301 * drawing origin may not be correctly emitted.
303 intel
->vtbl
.meta_draw_quad(intel
,
307 intel
->clear_chan
[0],
308 intel
->clear_chan
[1],
309 intel
->clear_chan
[2],
310 intel
->clear_chan
[3],
314 intel
->vtbl
.leave_meta_state( intel
);
322 static void intelClear(GLcontext
*ctx
, GLbitfield mask
)
324 struct intel_context
*intel
= intel_context( ctx
);
325 const GLuint colorMask
= *((GLuint
*) &ctx
->Color
.ColorMask
);
326 GLbitfield tri_mask
= 0;
327 GLbitfield blit_mask
= 0;
328 GLbitfield swrast_mask
= 0;
330 if (INTEL_DEBUG
& DEBUG_DRI
)
331 fprintf(stderr
, "%s %x\n", __FUNCTION__
, mask
);
334 if (mask
& BUFFER_BIT_FRONT_LEFT
) {
335 if (colorMask
== ~0) {
336 blit_mask
|= BUFFER_BIT_FRONT_LEFT
;
339 tri_mask
|= BUFFER_BIT_FRONT_LEFT
;
343 if (mask
& BUFFER_BIT_BACK_LEFT
) {
344 if (colorMask
== ~0) {
345 blit_mask
|= BUFFER_BIT_BACK_LEFT
;
348 tri_mask
|= BUFFER_BIT_BACK_LEFT
;
353 if (mask
& BUFFER_BIT_STENCIL
) {
354 if (!intel
->hw_stencil
) {
355 swrast_mask
|= BUFFER_BIT_STENCIL
;
357 else if ((ctx
->Stencil
.WriteMask
[0] & 0xff) != 0xff ||
358 intel
->depth_region
->tiled
) {
359 tri_mask
|= BUFFER_BIT_STENCIL
;
362 blit_mask
|= BUFFER_BIT_STENCIL
;
366 /* Do depth with stencil if possible to avoid 2nd pass over the
369 if (mask
& BUFFER_BIT_DEPTH
) {
370 if ((tri_mask
& BUFFER_BIT_STENCIL
) ||
371 intel
->depth_region
->tiled
)
372 tri_mask
|= BUFFER_BIT_DEPTH
;
374 blit_mask
|= BUFFER_BIT_DEPTH
;
377 swrast_mask
|= (mask
& BUFFER_BIT_ACCUM
);
382 intelClearWithBlit( ctx
, blit_mask
);
385 intelClearWithTris( intel
, tri_mask
);
388 _swrast_Clear( ctx
, swrast_mask
);
397 /* Flip the front & back buffers
399 static void intelPageFlip( const __DRIdrawablePrivate
*dPriv
)
402 struct intel_context
*intel
;
405 if (INTEL_DEBUG
& DEBUG_IOCTL
)
406 fprintf(stderr
, "%s\n", __FUNCTION__
);
409 assert(dPriv
->driContextPriv
);
410 assert(dPriv
->driContextPriv
->driverPrivate
);
412 intel
= (struct intel_context
*) dPriv
->driContextPriv
->driverPrivate
;
414 intelFlush( &intel
->ctx
);
415 LOCK_HARDWARE( intel
);
417 if (dPriv
->pClipRects
) {
418 *(drm_clip_rect_t
*)intel
->sarea
->boxes
= dPriv
->pClipRects
[0];
419 intel
->sarea
->nbox
= 1;
422 ret
= drmCommandNone(intel
->driFd
, DRM_I830_FLIP
);
424 fprintf(stderr
, "%s: %d\n", __FUNCTION__
, ret
);
425 UNLOCK_HARDWARE( intel
);
429 tmp
= intel
->sarea
->last_enqueue
;
430 intelRefillBatchLocked( intel
);
431 UNLOCK_HARDWARE( intel
);
434 intelSetDrawBuffer( &intel
->ctx
, intel
->ctx
.Color
.DriverDrawBuffer
);
439 void intelSwapBuffers( __DRIdrawablePrivate
*dPriv
)
441 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
442 struct intel_context
*intel
;
444 intel
= (struct intel_context
*) dPriv
->driContextPriv
->driverPrivate
;
446 if (ctx
->Visual
.doubleBufferMode
) {
447 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
448 if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */
449 intelPageFlip( dPriv
);
451 intelCopyBuffer( dPriv
, NULL
);
453 if (intel
->aub_file
) {
455 intel
->vtbl
.aub_dump_bmp( intel
, 1 );
461 /* XXX this shouldn't be an error but we can't handle it for now */
462 fprintf(stderr
, "%s: drawable has no context!\n", __FUNCTION__
);
466 void intelCopySubBuffer( __DRIdrawablePrivate
*dPriv
,
467 int x
, int y
, int w
, int h
)
469 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
470 struct intel_context
*intel
= dPriv
->driContextPriv
->driverPrivate
;
471 GLcontext
*ctx
= &intel
->ctx
;
473 if (ctx
->Visual
.doubleBufferMode
) {
474 drm_clip_rect_t rect
;
475 rect
.x1
= x
+ dPriv
->x
;
476 rect
.y1
= (dPriv
->h
- y
- h
) + dPriv
->y
;
477 rect
.x2
= rect
.x1
+ w
;
478 rect
.y2
= rect
.y1
+ h
;
479 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
480 intelCopyBuffer( dPriv
, &rect
);
483 /* XXX this shouldn't be an error but we can't handle it for now */
484 fprintf(stderr
, "%s: drawable has no context!\n", __FUNCTION__
);
489 static void intelDrawBuffer(GLcontext
*ctx
, GLenum mode
)
491 struct intel_context
*intel
= intel_context(ctx
);
494 if (!ctx
->DrawBuffer
)
497 switch ( ctx
->DrawBuffer
->_ColorDrawBufferMask
[0] ) {
498 case BUFFER_BIT_FRONT_LEFT
:
500 FALLBACK( intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
502 case BUFFER_BIT_BACK_LEFT
:
504 FALLBACK( intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
507 FALLBACK( intel
, INTEL_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
511 if ( intel
->sarea
->pf_current_page
== 1 )
514 intelSetFrontClipRects( intel
);
518 if (intel
->draw_region
!= intel
->front_region
) {
519 intel_region_release(intel
, &intel
->draw_region
);
520 intel_region_reference(&intel
->draw_region
, intel
->front_region
);
523 if (intel
->draw_region
!= intel
->back_region
) {
524 intel_region_release(intel
, &intel
->draw_region
);
525 intel_region_reference(&intel
->draw_region
, intel
->back_region
);
529 intel
->vtbl
.set_draw_region( intel
,
531 intel
->depth_region
);
534 static void intelReadBuffer( GLcontext
*ctx
, GLenum mode
)
536 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
541 void intelInitBufferFuncs( struct dd_function_table
*functions
)
543 functions
->Clear
= intelClear
;
544 functions
->GetBufferSize
= intelBufferSize
;
545 functions
->DrawBuffer
= intelDrawBuffer
;
546 functions
->ReadBuffer
= intelReadBuffer
;