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 **************************************************************************/
37 #include "intel_reg.h"
38 #include "intel_batchbuffer.h"
39 #include "intel_context.h"
40 #include "intel_blit.h"
41 #include "intel_regions.h"
49 * Copy the back buffer to the front buffer.
51 void intelCopyBuffer( const __DRIdrawablePrivate
*dPriv
,
52 const drm_clip_rect_t
*rect
)
54 struct intel_context
*intel
;
55 GLboolean missed_target
;
58 DBG("%s\n", __FUNCTION__
);
61 assert(dPriv
->driContextPriv
);
62 assert(dPriv
->driContextPriv
->driverPrivate
);
64 intel
= (struct intel_context
*) dPriv
->driContextPriv
->driverPrivate
;
65 intelFlush( &intel
->ctx
);
68 bmFinishFence(intel
, intel
->last_swap_fence
);
70 /* The LOCK_HARDWARE is required for the cliprects. Buffer offsets
71 * should work regardless.
73 LOCK_HARDWARE( intel
);
77 UNLOCK_HARDWARE( intel
);
78 driWaitForVBlank( dPriv
, &intel
->vbl_seq
, intel
->vblank_flags
, & missed_target
);
79 LOCK_HARDWARE( intel
);
83 intelScreenPrivate
*intelScreen
= intel
->intelScreen
;
84 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
85 int nbox
= dPriv
->numClipRects
;
86 drm_clip_rect_t
*pbox
= dPriv
->pClipRects
;
87 int cpp
= intelScreen
->cpp
;
88 struct intel_region
*src
, *dst
;
91 int src_pitch
, dst_pitch
;
93 if (intel
->sarea
->pf_current_page
== 0) {
94 dst
= intel
->front_region
;
95 src
= intel
->back_region
;
99 src
= intel
->front_region
;
100 dst
= intel
->back_region
;
103 src_pitch
= src
->pitch
* src
->cpp
;
104 dst_pitch
= dst
->pitch
* dst
->cpp
;
107 BR13
= (0xCC << 16) | (1<<24);
108 CMD
= XY_SRC_COPY_BLT_CMD
;
111 BR13
= (0xCC << 16) | (1<<24) | (1<<25);
112 CMD
= (XY_SRC_COPY_BLT_CMD
| XY_SRC_COPY_BLT_WRITE_ALPHA
|
113 XY_SRC_COPY_BLT_WRITE_RGB
);
126 for (i
= 0 ; i
< nbox
; i
++, pbox
++)
128 drm_clip_rect_t tmp
= *pbox
;
131 if (!intel_intersect_cliprects(&tmp
, &tmp
, rect
))
136 if (tmp
.x1
> tmp
.x2
||
138 tmp
.x2
> intelScreen
->width
||
139 tmp
.y2
> intelScreen
->height
)
142 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS
);
144 OUT_BATCH( dst_pitch
| BR13
);
145 OUT_BATCH( (tmp
.y1
<< 16) | tmp
.x1
);
146 OUT_BATCH( (tmp
.y2
<< 16) | tmp
.x2
);
147 OUT_BATCH( bmBufferOffset(intel
, dst
->buffer
) );
148 OUT_BATCH( (tmp
.y1
<< 16) | tmp
.x1
);
149 OUT_BATCH( src_pitch
);
150 OUT_BATCH( bmBufferOffset(intel
, src
->buffer
) );
155 intel_batchbuffer_flush( intel
->batch
);
156 intel
->second_last_swap_fence
= intel
->last_swap_fence
;
157 intel
->last_swap_fence
= bmSetFence( intel
);
158 UNLOCK_HARDWARE( intel
);
163 (*dri_interface
->getUST
)(&ust
);
165 intel
->swap_missed_count
++;
166 intel
->swap_missed_ust
= ust
- intel
->swap_ust
;
169 intel
->swap_ust
= ust
;
177 void intelEmitFillBlit( struct intel_context
*intel
,
180 struct buffer
*dst_buffer
,
183 GLshort x
, GLshort y
,
184 GLshort w
, GLshort h
,
196 BR13
= (0xF0 << 16) | (1<<24);
197 CMD
= XY_COLOR_BLT_CMD
;
200 BR13
= (0xF0 << 16) | (1<<24) | (1<<25);
201 CMD
= (XY_COLOR_BLT_CMD
| XY_COLOR_BLT_WRITE_ALPHA
|
202 XY_COLOR_BLT_WRITE_RGB
);
213 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS
);
215 OUT_BATCH( dst_pitch
| BR13
);
216 OUT_BATCH( (y
<< 16) | x
);
217 OUT_BATCH( ((y
+h
) << 16) | (x
+w
) );
218 OUT_BATCH( bmBufferOffset(intel
, dst_buffer
) + dst_offset
);
226 void intelEmitCopyBlit( struct intel_context
*intel
,
229 struct buffer
*src_buffer
,
233 struct buffer
*dst_buffer
,
236 GLshort src_x
, GLshort src_y
,
237 GLshort dst_x
, GLshort dst_y
,
238 GLshort w
, GLshort h
)
241 int dst_y2
= dst_y
+ h
;
242 int dst_x2
= dst_x
+ w
;
246 DBG("%s src:buf(%d)/%d %d,%d dst:buf(%d)/%d %d,%d sz:%dx%d\n",
248 src_buffer
, src_pitch
, src_x
, src_y
,
249 dst_buffer
, dst_pitch
, dst_x
, dst_y
,
259 BR13
= (0xCC << 16) | (1<<24);
260 CMD
= XY_SRC_COPY_BLT_CMD
;
263 BR13
= (0xCC << 16) | (1<<24) | (1<<25);
264 CMD
= (XY_SRC_COPY_BLT_CMD
| XY_SRC_COPY_BLT_WRITE_ALPHA
|
265 XY_SRC_COPY_BLT_WRITE_RGB
);
281 if (dst_y2
< dst_y
||
289 /* Initial y values don't seem to work with negative pitches. If
290 * we adjust the offsets manually (below), it seems to work fine.
292 * However, on broadwater at least, only the top version works
293 * correctly with overlapping blits. Luckily we don't need
294 * negative pitches and overlapping blits at the same time, as far
297 * Further, the current i965 driver never requires negative
298 * pitches, so just use the old-style blits for now.
301 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS
);
303 OUT_BATCH( dst_pitch
| BR13
);
304 OUT_BATCH( (dst_y
<< 16) | dst_x
);
305 OUT_BATCH( (dst_y2
<< 16) | dst_x2
);
306 OUT_BATCH( bmBufferOffset(intel
, dst_buffer
) + dst_offset
);
307 OUT_BATCH( (src_y
<< 16) | src_x
);
308 OUT_BATCH( src_pitch
);
309 OUT_BATCH( bmBufferOffset(intel
, src_buffer
) + src_offset
);
313 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS
);
315 OUT_BATCH( (dst_pitch
& 0xffff) | BR13
);
316 OUT_BATCH( (0 << 16) | dst_x
);
317 OUT_BATCH( (h
<< 16) | dst_x2
);
318 OUT_BATCH( bmBufferOffset(intel
, dst_buffer
) + dst_offset
+ dst_y
* dst_pitch
);
319 OUT_BATCH( (0 << 16) | src_x
);
320 OUT_BATCH( (src_pitch
& 0xffff) );
321 OUT_BATCH( bmBufferOffset(intel
, src_buffer
) + src_offset
+ src_y
* src_pitch
);
328 void intelClearWithBlit(GLcontext
*ctx
, GLbitfield flags
, GLboolean all
,
329 GLint cx1
, GLint cy1
, GLint cw
, GLint ch
)
331 struct intel_context
*intel
= intel_context( ctx
);
332 intelScreenPrivate
*intelScreen
= intel
->intelScreen
;
333 GLuint clear_depth
, clear_color
;
335 GLint cpp
= intelScreen
->cpp
;
337 struct intel_region
*front
= intel
->front_region
;
338 struct intel_region
*back
= intel
->back_region
;
339 struct intel_region
*depth
= intel
->depth_region
;
340 GLuint BR13
, FRONT_CMD
, BACK_CMD
, DEPTH_CMD
;
347 clear_color
= intel
->ClearColor
;
350 if (flags
& BUFFER_BIT_DEPTH
) {
351 clear_depth
= (GLuint
)(ctx
->Depth
.Clear
* intel
->ClearDepth
);
354 if (flags
& BUFFER_BIT_STENCIL
) {
355 clear_depth
|= (ctx
->Stencil
.Clear
& 0xff) << 24;
360 BR13
= (0xF0 << 16) | (1<<24);
361 BACK_CMD
= FRONT_CMD
= XY_COLOR_BLT_CMD
;
362 DEPTH_CMD
= XY_COLOR_BLT_CMD
;
365 BR13
= (0xF0 << 16) | (1<<24) | (1<<25);
366 BACK_CMD
= FRONT_CMD
= (XY_COLOR_BLT_CMD
|
367 XY_COLOR_BLT_WRITE_ALPHA
|
368 XY_COLOR_BLT_WRITE_RGB
);
369 DEPTH_CMD
= XY_COLOR_BLT_CMD
;
370 if (flags
& BUFFER_BIT_DEPTH
) DEPTH_CMD
|= XY_COLOR_BLT_WRITE_RGB
;
371 if (flags
& BUFFER_BIT_STENCIL
) DEPTH_CMD
|= XY_COLOR_BLT_WRITE_ALPHA
;
379 intelFlush( &intel
->ctx
);
380 LOCK_HARDWARE( intel
);
382 /* Refresh the cx/y/w/h values as they may have been invalidated
383 * by a new window position or size picked up when we did
384 * LOCK_HARDWARE above. The values passed by mesa are not
388 cx
= ctx
->DrawBuffer
->_Xmin
;
389 cy
= ctx
->DrawBuffer
->_Ymin
;
390 ch
= ctx
->DrawBuffer
->_Ymax
- ctx
->DrawBuffer
->_Ymin
;
391 cw
= ctx
->DrawBuffer
->_Xmax
- ctx
->DrawBuffer
->_Xmin
;
394 /* flip top to bottom */
395 cy
= intel
->driDrawable
->h
-cy1
-ch
;
396 cx
= cx1
+ intel
->drawX
;
399 /* adjust for page flipping */
400 if ( intel
->sarea
->pf_current_page
== 0 ) {
401 front
= intel
->front_region
;
402 back
= intel
->back_region
;
405 back
= intel
->front_region
;
406 front
= intel
->back_region
;
409 front_pitch
= front
->pitch
* front
->cpp
;
410 back_pitch
= back
->pitch
* back
->cpp
;
411 depth_pitch
= depth
->pitch
* depth
->cpp
;
414 FRONT_CMD
|= XY_DST_TILED
;
419 BACK_CMD
|= XY_DST_TILED
;
424 DEPTH_CMD
|= XY_DST_TILED
;
428 for (i
= 0 ; i
< intel
->numClipRects
; i
++)
430 drm_clip_rect_t
*box
= &intel
->pClipRects
[i
];
436 GLint w
= box
->x2
- x
;
437 GLint h
= box
->y2
- y
;
439 if (x
< cx
) w
-= cx
- x
, x
= cx
;
440 if (y
< cy
) h
-= cy
- y
, y
= cy
;
441 if (x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
442 if (y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
443 if (w
<= 0) continue;
444 if (h
<= 0) continue;
457 b
.x2
> intelScreen
->width
||
458 b
.y2
> intelScreen
->height
)
461 if ( flags
& BUFFER_BIT_FRONT_LEFT
) {
462 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS
);
463 OUT_BATCH( FRONT_CMD
);
464 OUT_BATCH( front_pitch
| BR13
);
465 OUT_BATCH( (b
.y1
<< 16) | b
.x1
);
466 OUT_BATCH( (b
.y2
<< 16) | b
.x2
);
467 OUT_BATCH( bmBufferOffset(intel
, front
->buffer
) );
468 OUT_BATCH( clear_color
);
472 if ( flags
& BUFFER_BIT_BACK_LEFT
) {
473 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS
);
474 OUT_BATCH( BACK_CMD
);
475 OUT_BATCH( back_pitch
| BR13
);
476 OUT_BATCH( (b
.y1
<< 16) | b
.x1
);
477 OUT_BATCH( (b
.y2
<< 16) | b
.x2
);
478 OUT_BATCH( bmBufferOffset(intel
, back
->buffer
) );
479 OUT_BATCH( clear_color
);
483 if ( flags
& (BUFFER_BIT_STENCIL
| BUFFER_BIT_DEPTH
) ) {
484 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS
);
485 OUT_BATCH( DEPTH_CMD
);
486 OUT_BATCH( depth_pitch
| BR13
);
487 OUT_BATCH( (b
.y1
<< 16) | b
.x1
);
488 OUT_BATCH( (b
.y2
<< 16) | b
.x2
);
489 OUT_BATCH( bmBufferOffset(intel
, depth
->buffer
) );
490 OUT_BATCH( clear_depth
);
495 intel_batchbuffer_flush( intel
->batch
);
496 UNLOCK_HARDWARE( intel
);