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"
44 #include "dri_bufmgr.h"
46 #define FILE_DEBUG_FLAG DEBUG_BLIT
49 * Copy the back color buffer to the front color buffer.
50 * Used for SwapBuffers().
53 intelCopyBuffer(__DRIdrawablePrivate
*dPriv
,
54 const drm_clip_rect_t
*rect
)
56 struct intel_context
*intel
;
57 GLboolean missed_target
;
60 DBG("%s\n", __FUNCTION__
);
63 assert(dPriv
->driContextPriv
);
64 assert(dPriv
->driContextPriv
->driverPrivate
);
66 intel
= (struct intel_context
*) dPriv
->driContextPriv
->driverPrivate
;
67 intelFlush( &intel
->ctx
);
69 if (intel
->last_swap_fence
) {
70 dri_fence_wait(intel
->last_swap_fence
);
71 dri_fence_unreference(intel
->last_swap_fence
);
72 intel
->last_swap_fence
= NULL
;
74 intel
->last_swap_fence
= intel
->first_swap_fence
;
75 intel
->first_swap_fence
= NULL
;
77 /* The LOCK_HARDWARE is required for the cliprects. Buffer offsets
78 * should work regardless.
84 UNLOCK_HARDWARE( intel
);
85 driWaitForVBlank( dPriv
, &missed_target
);
86 LOCK_HARDWARE( intel
);
90 intelScreenPrivate
*intelScreen
= intel
->intelScreen
;
91 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
92 struct intel_region
*src
, *dst
;
93 int nbox
= dPriv
->numClipRects
;
94 drm_clip_rect_t
*pbox
= dPriv
->pClipRects
;
95 int cpp
= intelScreen
->cpp
;
96 int src_pitch
, dst_pitch
;
100 if (intel
->sarea
->pf_current_page
== 0) {
101 dst
= intel
->front_region
;
102 src
= intel
->back_region
;
106 src
= intel
->front_region
;
107 dst
= intel
->back_region
;
110 src_pitch
= src
->pitch
* src
->cpp
;
111 dst_pitch
= dst
->pitch
* dst
->cpp
;
114 BR13
= (0xCC << 16) | (1 << 24);
115 CMD
= XY_SRC_COPY_BLT_CMD
;
118 BR13
= (0xCC << 16) | (1 << 24) | (1 << 25);
119 CMD
= XY_SRC_COPY_BLT_CMD
| XY_BLT_WRITE_ALPHA
| XY_BLT_WRITE_RGB
;
131 for (i
= 0; i
< nbox
; i
++, pbox
++) {
132 drm_clip_rect_t box
= *pbox
;
135 if (!intel_intersect_cliprects(&box
, &box
, rect
))
139 if (box
.x1
> box
.x2
||
141 box
.x2
> intelScreen
->width
||
142 box
.y2
> intelScreen
->height
)
145 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS
);
147 OUT_BATCH(BR13
| dst_pitch
);
148 OUT_BATCH((box
.y1
<< 16) | box
.x1
);
149 OUT_BATCH((box
.y2
<< 16) | box
.x2
);
150 OUT_RELOC(dst
->buffer
, DRM_BO_FLAG_MEM_TT
| DRM_BO_FLAG_WRITE
, 0);
151 OUT_BATCH((box
.y1
<< 16) | box
.x1
);
152 OUT_BATCH(src_pitch
);
153 OUT_RELOC(src
->buffer
, DRM_BO_FLAG_MEM_TT
| DRM_BO_FLAG_READ
, 0);
157 if (intel
->first_swap_fence
)
158 dri_fence_unreference(intel
->first_swap_fence
);
159 intel_batchbuffer_flush(intel
->batch
);
160 intel
->first_swap_fence
= intel
->batch
->last_fence
;
161 if (intel
->first_swap_fence
)
162 dri_fence_reference(intel
->first_swap_fence
);
164 UNLOCK_HARDWARE(intel
);
169 (*dri_interface
->getUST
)(&ust
);
171 intel
->swap_missed_count
++;
172 intel
->swap_missed_ust
= ust
- intel
->swap_ust
;
175 intel
->swap_ust
= ust
;
184 intelEmitFillBlit(struct intel_context
*intel
,
190 GLshort x
, GLshort y
,
191 GLshort w
, GLshort h
,
203 BR13
= (0xF0 << 16) | (1 << 24);
204 CMD
= XY_COLOR_BLT_CMD
;
207 BR13
= (0xF0 << 16) | (1 << 24) | (1 << 25);
208 CMD
= XY_COLOR_BLT_CMD
| XY_BLT_WRITE_ALPHA
| XY_BLT_WRITE_RGB
;
219 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS
);
221 OUT_BATCH(BR13
| dst_pitch
);
222 OUT_BATCH((y
<< 16) | x
);
223 OUT_BATCH(((y
+ h
) << 16) | (x
+ w
));
224 OUT_RELOC(dst_buffer
, DRM_BO_FLAG_MEM_TT
| DRM_BO_FLAG_WRITE
, dst_offset
);
229 static GLuint
translate_raster_op(GLenum logicop
)
232 case GL_CLEAR
: return 0x00;
233 case GL_AND
: return 0x88;
234 case GL_AND_REVERSE
: return 0x44;
235 case GL_COPY
: return 0xCC;
236 case GL_AND_INVERTED
: return 0x22;
237 case GL_NOOP
: return 0xAA;
238 case GL_XOR
: return 0x66;
239 case GL_OR
: return 0xEE;
240 case GL_NOR
: return 0x11;
241 case GL_EQUIV
: return 0x99;
242 case GL_INVERT
: return 0x55;
243 case GL_OR_REVERSE
: return 0xDD;
244 case GL_COPY_INVERTED
: return 0x33;
245 case GL_OR_INVERTED
: return 0xBB;
246 case GL_NAND
: return 0x77;
247 case GL_SET
: return 0xFF;
256 intelEmitCopyBlit(struct intel_context
*intel
,
266 GLshort src_x
, GLshort src_y
,
267 GLshort dst_x
, GLshort dst_y
,
268 GLshort w
, GLshort h
,
272 int dst_y2
= dst_y
+ h
;
273 int dst_x2
= dst_x
+ w
;
277 DBG("%s src:buf(%d)/%d+%d %d,%d dst:buf(%d)/%d+%d %d,%d sz:%dx%d op:%d\n",
279 src_buffer
, src_pitch
, src_offset
, src_x
, src_y
,
280 dst_buffer
, dst_pitch
, dst_offset
, dst_x
, dst_y
,
283 assert( logic_op
- GL_CLEAR
>= 0 );
284 assert( logic_op
- GL_CLEAR
< 0x10 );
289 BR13
= translate_raster_op(logic_op
) << 16;
296 CMD
= XY_SRC_COPY_BLT_CMD
;
299 BR13
|= (1 << 24) | (1 << 25);
300 CMD
= XY_SRC_COPY_BLT_CMD
| XY_BLT_WRITE_ALPHA
| XY_BLT_WRITE_RGB
;
315 if (dst_y2
< dst_y
|| dst_x2
< dst_x
) {
322 /* Initial y values don't seem to work with negative pitches. If
323 * we adjust the offsets manually (below), it seems to work fine.
325 * On the other hand, if we always adjust, the hardware doesn't
326 * know which blit directions to use, so overlapping copypixels get
329 if (dst_pitch
> 0 && src_pitch
> 0) {
330 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS
);
332 OUT_BATCH(BR13
| dst_pitch
);
333 OUT_BATCH((dst_y
<< 16) | dst_x
);
334 OUT_BATCH((dst_y2
<< 16) | dst_x2
);
335 OUT_RELOC(dst_buffer
, DRM_BO_FLAG_MEM_TT
| DRM_BO_FLAG_WRITE
,
337 OUT_BATCH((src_y
<< 16) | src_x
);
338 OUT_BATCH(src_pitch
);
339 OUT_RELOC(src_buffer
, DRM_BO_FLAG_MEM_TT
| DRM_BO_FLAG_READ
,
344 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS
);
346 OUT_BATCH(BR13
| dst_pitch
);
347 OUT_BATCH((0 << 16) | dst_x
);
348 OUT_BATCH((h
<< 16) | dst_x2
);
349 OUT_RELOC(dst_buffer
, DRM_BO_FLAG_MEM_TT
| DRM_BO_FLAG_WRITE
,
350 dst_offset
+ dst_y
* dst_pitch
);
351 OUT_BATCH((0 << 16) | src_x
);
352 OUT_BATCH(src_pitch
);
353 OUT_RELOC(src_buffer
, DRM_BO_FLAG_MEM_TT
| DRM_BO_FLAG_READ
,
354 src_offset
+ src_y
* src_pitch
);
362 intelClearWithBlit(GLcontext
*ctx
, GLbitfield mask
)
364 struct intel_context
*intel
= intel_context(ctx
);
365 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
366 intelScreenPrivate
*intelScreen
= intel
->intelScreen
;
367 GLuint clear_depth
, clear_color
;
368 GLint cpp
= intelScreen
->cpp
;
371 struct intel_region
*front
= intel
->front_region
;
372 struct intel_region
*back
= intel
->back_region
;
373 struct intel_region
*depth
= intel
->depth_region
;
374 GLuint BR13
, FRONT_CMD
, BACK_CMD
, DEPTH_CMD
;
380 clear_color
= intel
->ClearColor
;
383 if (mask
& BUFFER_BIT_DEPTH
) {
384 clear_depth
= (GLuint
) (fb
->_DepthMax
* ctx
->Depth
.Clear
);
387 if (mask
& BUFFER_BIT_STENCIL
) {
388 clear_depth
|= (ctx
->Stencil
.Clear
& 0xff) << 24;
393 BR13
= (0xF0 << 16) | (1 << 24);
394 BACK_CMD
= FRONT_CMD
= XY_COLOR_BLT_CMD
;
395 DEPTH_CMD
= XY_COLOR_BLT_CMD
;
398 BR13
= (0xF0 << 16) | (1 << 24) | (1 << 25);
399 BACK_CMD
= FRONT_CMD
= XY_COLOR_BLT_CMD
|
400 XY_BLT_WRITE_ALPHA
| XY_BLT_WRITE_RGB
;
401 DEPTH_CMD
= XY_COLOR_BLT_CMD
;
402 if (mask
& BUFFER_BIT_DEPTH
) DEPTH_CMD
|= XY_BLT_WRITE_RGB
;
403 if (mask
& BUFFER_BIT_STENCIL
) DEPTH_CMD
|= XY_BLT_WRITE_ALPHA
;
410 intelFlush(&intel
->ctx
);
411 LOCK_HARDWARE( intel
);
412 if (intel
->numClipRects
) {
413 GLint cx
, cy
, cw
, ch
;
415 /* Get clear bounds after locking */
420 all
= (cw
== fb
->Width
&& ch
== fb
->Height
);
422 /* flip top to bottom */
423 cy
= intel
->driDrawable
->h
- cy
- ch
;
424 cx
= cx
+ intel
->drawX
;
427 /* adjust for page flipping */
428 if ( intel
->sarea
->pf_current_page
== 0 ) {
429 front
= intel
->front_region
;
430 back
= intel
->back_region
;
433 back
= intel
->front_region
;
434 front
= intel
->back_region
;
437 front_pitch
= front
->pitch
* front
->cpp
;
438 back_pitch
= back
->pitch
* back
->cpp
;
439 depth_pitch
= depth
->pitch
* depth
->cpp
;
442 FRONT_CMD
|= XY_DST_TILED
;
447 BACK_CMD
|= XY_DST_TILED
;
452 DEPTH_CMD
|= XY_DST_TILED
;
456 for (i
= 0 ; i
< intel
->numClipRects
; i
++)
458 drm_clip_rect_t
*box
= &intel
->pClipRects
[i
];
464 GLint w
= box
->x2
- x
;
465 GLint h
= box
->y2
- y
;
467 if (x
< cx
) w
-= cx
- x
, x
= cx
;
468 if (y
< cy
) h
-= cy
- y
, y
= cy
;
469 if (x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
470 if (y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
471 if (w
<= 0) continue;
472 if (h
<= 0) continue;
485 b
.x2
> intelScreen
->width
||
486 b
.y2
> intelScreen
->height
)
489 if ( mask
& BUFFER_BIT_FRONT_LEFT
) {
490 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS
);
491 OUT_BATCH(FRONT_CMD
);
492 OUT_BATCH(BR13
| front_pitch
);
493 OUT_BATCH((b
.y1
<< 16) | b
.x1
);
494 OUT_BATCH((b
.y2
<< 16) | b
.x2
);
495 OUT_RELOC(front
->buffer
, DRM_BO_FLAG_MEM_TT
| DRM_BO_FLAG_WRITE
,
497 OUT_BATCH(clear_color
);
501 if ( mask
& BUFFER_BIT_BACK_LEFT
) {
502 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS
);
504 OUT_BATCH(BR13
| back_pitch
);
505 OUT_BATCH((b
.y1
<< 16) | b
.x1
);
506 OUT_BATCH((b
.y2
<< 16) | b
.x2
);
507 OUT_RELOC(back
->buffer
, DRM_BO_FLAG_MEM_TT
| DRM_BO_FLAG_WRITE
,
509 OUT_BATCH(clear_color
);
513 if ( mask
& (BUFFER_BIT_STENCIL
| BUFFER_BIT_DEPTH
) ) {
514 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS
);
515 OUT_BATCH(DEPTH_CMD
);
516 OUT_BATCH(BR13
| depth_pitch
);
517 OUT_BATCH((b
.y1
<< 16) | b
.x1
);
518 OUT_BATCH((b
.y2
<< 16) | b
.x2
);
519 OUT_RELOC(depth
->buffer
, DRM_BO_FLAG_MEM_TT
| DRM_BO_FLAG_WRITE
,
521 OUT_BATCH(clear_depth
);
525 intel_batchbuffer_flush(intel
->batch
);
528 UNLOCK_HARDWARE(intel
);
533 intelEmitImmediateColorExpandBlit(struct intel_context
*intel
,
535 GLubyte
*src_bits
, GLuint src_size
,
541 GLshort x
, GLshort y
,
542 GLshort w
, GLshort h
,
545 struct xy_text_immediate_blit text
;
546 int dwords
= ALIGN(src_size
, 8) / 4;
547 uint32_t opcode
, br13
;
549 assert( logic_op
- GL_CLEAR
>= 0 );
550 assert( logic_op
- GL_CLEAR
< 0x10 );
560 DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d, %d bytes %d dwords\n",
562 dst_buffer
, dst_pitch
, dst_offset
, x
, y
, w
, h
, src_size
, dwords
);
564 memset(&text
, 0, sizeof(text
));
565 text
.dw0
.client
= CLIENT_2D
;
566 text
.dw0
.opcode
= OPCODE_XY_TEXT_IMMEDIATE_BLT
;
568 text
.dw0
.byte_packed
= 1; /* ?maybe? */
570 text
.dw0
.dst_tiled
= dst_tiled
;
572 text
.dw0
.length
= (sizeof(text
)/sizeof(int)) - 2 + dwords
;
573 text
.dw1
.dest_y1
= y
; /* duplicates info in setup blit */
574 text
.dw1
.dest_x1
= x
;
575 text
.dw2
.dest_y2
= y
+ h
;
576 text
.dw2
.dest_x2
= x
+ w
;
578 intel_batchbuffer_require_space( intel
->batch
,
582 INTEL_BATCH_NO_CLIPRECTS
);
584 opcode
= XY_SETUP_BLT_CMD
;
586 opcode
|= XY_BLT_WRITE_ALPHA
| XY_BLT_WRITE_RGB
;
588 opcode
|= XY_DST_TILED
;
590 br13
= dst_pitch
| (translate_raster_op(logic_op
) << 16) | (1 << 29);
596 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS
);
599 OUT_BATCH((0 << 16) | 0); /* clip x1, y1 */
600 OUT_BATCH((100 << 16) | 100); /* clip x2, y2 */
601 OUT_RELOC(dst_buffer
, DRM_BO_FLAG_MEM_TT
| DRM_BO_FLAG_WRITE
, dst_offset
);
602 OUT_BATCH(0); /* bg */
603 OUT_BATCH(fg_color
); /* fg */
604 OUT_BATCH(0); /* pattern base addr */
607 intel_batchbuffer_data( intel
->batch
,
610 INTEL_BATCH_NO_CLIPRECTS
);
612 intel_batchbuffer_data( intel
->batch
,
615 INTEL_BATCH_NO_CLIPRECTS
);