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"
42 #include "intel_structs.h"
50 * Copy the back buffer to the front buffer.
52 void intelCopyBuffer( const __DRIdrawablePrivate
*dPriv
,
53 const drm_clip_rect_t
*rect
)
55 struct intel_context
*intel
;
56 GLboolean missed_target
;
59 DBG("%s\n", __FUNCTION__
);
62 assert(dPriv
->driContextPriv
);
63 assert(dPriv
->driContextPriv
->driverPrivate
);
65 intel
= (struct intel_context
*) dPriv
->driContextPriv
->driverPrivate
;
66 intelFlush( &intel
->ctx
);
69 bmFinishFenceLock(intel
, intel
->last_swap_fence
);
71 /* The LOCK_HARDWARE is required for the cliprects. Buffer offsets
72 * should work regardless.
74 LOCK_HARDWARE( intel
);
78 UNLOCK_HARDWARE( intel
);
79 driWaitForVBlank( dPriv
, &intel
->vbl_seq
, intel
->vblank_flags
, & missed_target
);
80 LOCK_HARDWARE( intel
);
84 intelScreenPrivate
*intelScreen
= intel
->intelScreen
;
85 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
86 int nbox
= dPriv
->numClipRects
;
87 drm_clip_rect_t
*pbox
= dPriv
->pClipRects
;
88 int cpp
= intelScreen
->cpp
;
89 struct intel_region
*src
, *dst
;
92 int src_pitch
, dst_pitch
;
94 if (intel
->sarea
->pf_current_page
== 0) {
95 dst
= intel
->front_region
;
96 src
= intel
->back_region
;
100 src
= intel
->front_region
;
101 dst
= intel
->back_region
;
104 src_pitch
= src
->pitch
* src
->cpp
;
105 dst_pitch
= dst
->pitch
* dst
->cpp
;
108 BR13
= (0xCC << 16) | (1<<24);
109 CMD
= XY_SRC_COPY_BLT_CMD
;
112 BR13
= (0xCC << 16) | (1<<24) | (1<<25);
113 CMD
= (XY_SRC_COPY_BLT_CMD
| XY_SRC_COPY_BLT_WRITE_ALPHA
|
114 XY_SRC_COPY_BLT_WRITE_RGB
);
127 for (i
= 0 ; i
< nbox
; i
++, pbox
++)
129 drm_clip_rect_t tmp
= *pbox
;
132 if (!intel_intersect_cliprects(&tmp
, &tmp
, rect
))
137 if (tmp
.x1
> tmp
.x2
||
139 tmp
.x2
> intelScreen
->width
||
140 tmp
.y2
> intelScreen
->height
)
143 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS
);
145 OUT_BATCH( dst_pitch
| BR13
);
146 OUT_BATCH( (tmp
.y1
<< 16) | tmp
.x1
);
147 OUT_BATCH( (tmp
.y2
<< 16) | tmp
.x2
);
148 OUT_BATCH( bmBufferOffset(intel
, dst
->buffer
) );
149 OUT_BATCH( (tmp
.y1
<< 16) | tmp
.x1
);
150 OUT_BATCH( src_pitch
);
151 OUT_BATCH( bmBufferOffset(intel
, src
->buffer
) );
156 intel_batchbuffer_flush( intel
->batch
);
157 intel
->second_last_swap_fence
= intel
->last_swap_fence
;
158 intel
->last_swap_fence
= bmSetFenceLock( intel
);
159 UNLOCK_HARDWARE( intel
);
164 (*dri_interface
->getUST
)(&ust
);
166 intel
->swap_missed_count
++;
167 intel
->swap_missed_ust
= ust
- intel
->swap_ust
;
170 intel
->swap_ust
= ust
;
178 void intelEmitFillBlit( struct intel_context
*intel
,
181 struct buffer
*dst_buffer
,
184 GLshort x
, GLshort y
,
185 GLshort w
, GLshort h
,
197 BR13
= (0xF0 << 16) | (1<<24);
198 CMD
= XY_COLOR_BLT_CMD
;
201 BR13
= (0xF0 << 16) | (1<<24) | (1<<25);
202 CMD
= (XY_COLOR_BLT_CMD
| XY_COLOR_BLT_WRITE_ALPHA
|
203 XY_COLOR_BLT_WRITE_RGB
);
214 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS
);
216 OUT_BATCH( dst_pitch
| BR13
);
217 OUT_BATCH( (y
<< 16) | x
);
218 OUT_BATCH( ((y
+h
) << 16) | (x
+w
) );
219 OUT_BATCH( bmBufferOffset(intel
, dst_buffer
) + dst_offset
);
224 static GLuint
translate_raster_op(GLenum logicop
)
227 case GL_CLEAR
: return 0x00;
228 case GL_AND
: return 0x88;
229 case GL_AND_REVERSE
: return 0x44;
230 case GL_COPY
: return 0xCC;
231 case GL_AND_INVERTED
: return 0x22;
232 case GL_NOOP
: return 0xAA;
233 case GL_XOR
: return 0x66;
234 case GL_OR
: return 0xEE;
235 case GL_NOR
: return 0x11;
236 case GL_EQUIV
: return 0x99;
237 case GL_INVERT
: return 0x55;
238 case GL_OR_REVERSE
: return 0xDD;
239 case GL_COPY_INVERTED
: return 0x33;
240 case GL_OR_INVERTED
: return 0xBB;
241 case GL_NAND
: return 0x77;
242 case GL_SET
: return 0xFF;
250 void intelEmitCopyBlit( struct intel_context
*intel
,
253 struct buffer
*src_buffer
,
257 struct buffer
*dst_buffer
,
260 GLshort src_x
, GLshort src_y
,
261 GLshort dst_x
, GLshort dst_y
,
262 GLshort w
, GLshort h
,
266 int dst_y2
= dst_y
+ h
;
267 int dst_x2
= dst_x
+ w
;
271 DBG("%s src:buf(%d)/%d %d,%d dst:buf(%d)/%d %d,%d sz:%dx%d op:%d\n",
273 src_buffer
, src_pitch
, src_x
, src_y
,
274 dst_buffer
, dst_pitch
, dst_x
, dst_y
,
277 assert( logic_op
- GL_CLEAR
>= 0 );
278 assert( logic_op
- GL_CLEAR
< 0x10 );
287 BR13
= (translate_raster_op(logic_op
) << 16) | (1<<24);
288 CMD
= XY_SRC_COPY_BLT_CMD
;
291 BR13
= (translate_raster_op(logic_op
) << 16) | (1<<24) |
293 CMD
= (XY_SRC_COPY_BLT_CMD
| XY_SRC_COPY_BLT_WRITE_ALPHA
|
294 XY_SRC_COPY_BLT_WRITE_RGB
);
310 if (dst_y2
< dst_y
||
318 /* Initial y values don't seem to work with negative pitches. If
319 * we adjust the offsets manually (below), it seems to work fine.
321 * On the other hand, if we always adjust, the hardware doesn't
322 * know which blit directions to use, so overlapping copypixels get
325 if (dst_pitch
> 0 && src_pitch
> 0) {
326 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS
);
328 OUT_BATCH( dst_pitch
| BR13
);
329 OUT_BATCH( (dst_y
<< 16) | dst_x
);
330 OUT_BATCH( (dst_y2
<< 16) | dst_x2
);
331 OUT_BATCH( bmBufferOffset(intel
, dst_buffer
) + dst_offset
);
332 OUT_BATCH( (src_y
<< 16) | src_x
);
333 OUT_BATCH( src_pitch
);
334 OUT_BATCH( bmBufferOffset(intel
, src_buffer
) + src_offset
);
338 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS
);
340 OUT_BATCH( (dst_pitch
& 0xffff) | BR13
);
341 OUT_BATCH( (0 << 16) | dst_x
);
342 OUT_BATCH( (h
<< 16) | dst_x2
);
343 OUT_BATCH( bmBufferOffset(intel
, dst_buffer
) + dst_offset
+ dst_y
* dst_pitch
);
344 OUT_BATCH( (0 << 16) | src_x
);
345 OUT_BATCH( (src_pitch
& 0xffff) );
346 OUT_BATCH( bmBufferOffset(intel
, src_buffer
) + src_offset
+ src_y
* src_pitch
);
353 void intelClearWithBlit(GLcontext
*ctx
, GLbitfield flags
)
355 struct intel_context
*intel
= intel_context( ctx
);
356 intelScreenPrivate
*intelScreen
= intel
->intelScreen
;
357 GLuint clear_depth
, clear_color
;
358 GLint cx
, cy
, cw
, ch
;
359 GLint cpp
= intelScreen
->cpp
;
362 struct intel_region
*front
= intel
->front_region
;
363 struct intel_region
*back
= intel
->back_region
;
364 struct intel_region
*depth
= intel
->depth_region
;
365 GLuint BR13
, FRONT_CMD
, BACK_CMD
, DEPTH_CMD
;
372 clear_color
= intel
->ClearColor
;
375 if (flags
& BUFFER_BIT_DEPTH
) {
376 clear_depth
= (GLuint
)(ctx
->Depth
.Clear
* intel
->ClearDepth
);
379 if (flags
& BUFFER_BIT_STENCIL
) {
380 clear_depth
|= (ctx
->Stencil
.Clear
& 0xff) << 24;
385 BR13
= (0xF0 << 16) | (1<<24);
386 BACK_CMD
= FRONT_CMD
= XY_COLOR_BLT_CMD
;
387 DEPTH_CMD
= XY_COLOR_BLT_CMD
;
390 BR13
= (0xF0 << 16) | (1<<24) | (1<<25);
391 BACK_CMD
= FRONT_CMD
= (XY_COLOR_BLT_CMD
|
392 XY_COLOR_BLT_WRITE_ALPHA
|
393 XY_COLOR_BLT_WRITE_RGB
);
394 DEPTH_CMD
= XY_COLOR_BLT_CMD
;
395 if (flags
& BUFFER_BIT_DEPTH
) DEPTH_CMD
|= XY_COLOR_BLT_WRITE_RGB
;
396 if (flags
& BUFFER_BIT_STENCIL
) DEPTH_CMD
|= XY_COLOR_BLT_WRITE_ALPHA
;
404 intelFlush( &intel
->ctx
);
405 LOCK_HARDWARE( intel
);
407 /* get clear bounds after locking */
408 cx
= ctx
->DrawBuffer
->_Xmin
;
409 cy
= ctx
->DrawBuffer
->_Ymin
;
410 ch
= ctx
->DrawBuffer
->_Ymax
- ctx
->DrawBuffer
->_Ymin
;
411 cw
= ctx
->DrawBuffer
->_Xmax
- ctx
->DrawBuffer
->_Xmin
;
412 all
= (cw
== ctx
->DrawBuffer
->Width
&& ch
== ctx
->DrawBuffer
->Height
);
414 /* flip top to bottom */
415 cy
= intel
->driDrawable
->h
- cy
- ch
;
416 cx
= cx
+ intel
->drawX
;
419 /* adjust for page flipping */
420 if ( intel
->sarea
->pf_current_page
== 0 ) {
421 front
= intel
->front_region
;
422 back
= intel
->back_region
;
425 back
= intel
->front_region
;
426 front
= intel
->back_region
;
429 front_pitch
= front
->pitch
* front
->cpp
;
430 back_pitch
= back
->pitch
* back
->cpp
;
431 depth_pitch
= depth
->pitch
* depth
->cpp
;
434 FRONT_CMD
|= XY_DST_TILED
;
439 BACK_CMD
|= XY_DST_TILED
;
444 DEPTH_CMD
|= XY_DST_TILED
;
448 for (i
= 0 ; i
< intel
->numClipRects
; i
++)
450 drm_clip_rect_t
*box
= &intel
->pClipRects
[i
];
456 GLint w
= box
->x2
- x
;
457 GLint h
= box
->y2
- y
;
459 if (x
< cx
) w
-= cx
- x
, x
= cx
;
460 if (y
< cy
) h
-= cy
- y
, y
= cy
;
461 if (x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
462 if (y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
463 if (w
<= 0) continue;
464 if (h
<= 0) continue;
477 b
.x2
> intelScreen
->width
||
478 b
.y2
> intelScreen
->height
)
481 if ( flags
& BUFFER_BIT_FRONT_LEFT
) {
482 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS
);
483 OUT_BATCH( FRONT_CMD
);
484 OUT_BATCH( front_pitch
| BR13
);
485 OUT_BATCH( (b
.y1
<< 16) | b
.x1
);
486 OUT_BATCH( (b
.y2
<< 16) | b
.x2
);
487 OUT_BATCH( bmBufferOffset(intel
, front
->buffer
) );
488 OUT_BATCH( clear_color
);
492 if ( flags
& BUFFER_BIT_BACK_LEFT
) {
493 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS
);
494 OUT_BATCH( BACK_CMD
);
495 OUT_BATCH( back_pitch
| BR13
);
496 OUT_BATCH( (b
.y1
<< 16) | b
.x1
);
497 OUT_BATCH( (b
.y2
<< 16) | b
.x2
);
498 OUT_BATCH( bmBufferOffset(intel
, back
->buffer
) );
499 OUT_BATCH( clear_color
);
503 if ( flags
& (BUFFER_BIT_STENCIL
| BUFFER_BIT_DEPTH
) ) {
504 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS
);
505 OUT_BATCH( DEPTH_CMD
);
506 OUT_BATCH( depth_pitch
| BR13
);
507 OUT_BATCH( (b
.y1
<< 16) | b
.x1
);
508 OUT_BATCH( (b
.y2
<< 16) | b
.x2
);
509 OUT_BATCH( bmBufferOffset(intel
, depth
->buffer
) );
510 OUT_BATCH( clear_depth
);
515 intel_batchbuffer_flush( intel
->batch
);
516 UNLOCK_HARDWARE( intel
);
522 #define BR13_8888 0x3
526 intelEmitImmediateColorExpandBlit(struct intel_context
*intel
,
528 GLubyte
*src_bits
, GLuint src_size
,
531 struct buffer
*dst_buffer
,
534 GLshort x
, GLshort y
,
535 GLshort w
, GLshort h
)
537 struct xy_setup_blit setup
;
538 struct xy_text_immediate_blit text
;
539 int dwords
= ((src_size
+ 7) & ~7) / 4;
550 DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d, %d bytes %d dwords\n",
552 dst_buffer
, dst_pitch
, dst_offset
, x
, y
, w
, h
, src_size
, dwords
);
554 memset(&setup
, 0, sizeof(setup
));
556 setup
.br0
.client
= CLIENT_2D
;
557 setup
.br0
.opcode
= OPCODE_XY_SETUP_BLT
;
558 setup
.br0
.write_alpha
= (cpp
== 4);
559 setup
.br0
.write_rgb
= (cpp
== 4);
560 setup
.br0
.dst_tiled
= dst_tiled
;
561 setup
.br0
.length
= (sizeof(setup
) / sizeof(int)) - 2;
563 setup
.br13
.dest_pitch
= dst_pitch
;
564 setup
.br13
.rop
= 0xcc;
565 setup
.br13
.color_depth
= (cpp
== 4) ? BR13_8888
: BR13_565
;
566 setup
.br13
.clipping_enable
= 0;
567 setup
.br13
.mono_source_transparency
= 1;
569 setup
.dw2
.clip_y1
= 0;
570 setup
.dw2
.clip_x1
= 0;
571 setup
.dw3
.clip_y2
= 100;
572 setup
.dw3
.clip_x2
= 100;
574 setup
.dest_base_addr
= bmBufferOffset(intel
, dst_buffer
) + dst_offset
;
575 setup
.background_color
= 0;
576 setup
.foreground_color
= fg_color
;
577 setup
.pattern_base_addr
= 0;
579 memset(&text
, 0, sizeof(text
));
580 text
.dw0
.client
= CLIENT_2D
;
581 text
.dw0
.opcode
= OPCODE_XY_TEXT_IMMEDIATE_BLT
;
583 text
.dw0
.byte_packed
= 1; /* ?maybe? */
585 text
.dw0
.dst_tiled
= dst_tiled
;
587 text
.dw0
.length
= (sizeof(text
)/sizeof(int)) - 2 + dwords
;
588 text
.dw1
.dest_y1
= y
; /* duplicates info in setup blit */
589 text
.dw1
.dest_x1
= x
;
590 text
.dw2
.dest_y2
= y
+ h
;
591 text
.dw2
.dest_x2
= x
+ w
;
593 intel_batchbuffer_require_space( intel
->batch
,
597 INTEL_BATCH_NO_CLIPRECTS
);
599 intel_batchbuffer_data( intel
->batch
,
602 INTEL_BATCH_NO_CLIPRECTS
);
604 intel_batchbuffer_data( intel
->batch
,
607 INTEL_BATCH_NO_CLIPRECTS
);
609 intel_batchbuffer_data( intel
->batch
,
612 INTEL_BATCH_NO_CLIPRECTS
);