Merge branch 'master' of git+ssh://joukj@git.freedesktop.org/git/mesa/mesa
[mesa.git] / src / mesa / drivers / dri / i965 / intel_blit.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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.
25 *
26 **************************************************************************/
27
28
29 #include <stdio.h>
30 #include <errno.h>
31
32 #include "mtypes.h"
33 #include "context.h"
34 #include "enums.h"
35 #include "vblank.h"
36
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"
43
44 #include "bufmgr.h"
45
46 #define FILE_DEBUG_FLAG DEBUG_BLIT
47
48 /*
49 * Copy the back buffer to the front buffer.
50 */
51 void intelCopyBuffer( __DRIdrawablePrivate *dPriv,
52 const drm_clip_rect_t *rect )
53 {
54 struct intel_context *intel;
55 GLboolean missed_target;
56 int64_t ust;
57
58 DBG("%s\n", __FUNCTION__);
59
60 assert(dPriv);
61 assert(dPriv->driContextPriv);
62 assert(dPriv->driContextPriv->driverPrivate);
63
64 intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate;
65 intelFlush( &intel->ctx );
66
67
68 bmFinishFenceLock(intel, intel->last_swap_fence);
69
70 /* The LOCK_HARDWARE is required for the cliprects. Buffer offsets
71 * should work regardless.
72 */
73 LOCK_HARDWARE( intel );
74
75 if (!rect)
76 {
77 UNLOCK_HARDWARE( intel );
78 driWaitForVBlank( dPriv, &missed_target );
79 LOCK_HARDWARE( intel );
80 }
81
82 {
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;
89 int BR13, CMD;
90 int i;
91 int src_pitch, dst_pitch;
92
93 if (intel->sarea->pf_current_page == 0) {
94 dst = intel->front_region;
95 src = intel->back_region;
96 }
97 else {
98 assert(0);
99 src = intel->front_region;
100 dst = intel->back_region;
101 }
102
103 src_pitch = src->pitch * src->cpp;
104 dst_pitch = dst->pitch * dst->cpp;
105
106 if (cpp == 2) {
107 BR13 = (0xCC << 16) | (1<<24);
108 CMD = XY_SRC_COPY_BLT_CMD;
109 }
110 else {
111 BR13 = (0xCC << 16) | (1<<24) | (1<<25);
112 CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
113 }
114
115 if (src->tiled) {
116 CMD |= XY_SRC_TILED;
117 src_pitch /= 4;
118 }
119
120 if (dst->tiled) {
121 CMD |= XY_DST_TILED;
122 dst_pitch /= 4;
123 }
124
125 for (i = 0 ; i < nbox; i++, pbox++)
126 {
127 drm_clip_rect_t tmp = *pbox;
128
129 if (rect) {
130 if (!intel_intersect_cliprects(&tmp, &tmp, rect))
131 continue;
132 }
133
134
135 if (tmp.x1 > tmp.x2 ||
136 tmp.y1 > tmp.y2 ||
137 tmp.x2 > intelScreen->width ||
138 tmp.y2 > intelScreen->height)
139 continue;
140
141 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
142 OUT_BATCH( CMD );
143 OUT_BATCH( dst_pitch | BR13 );
144 OUT_BATCH( (tmp.y1 << 16) | tmp.x1 );
145 OUT_BATCH( (tmp.y2 << 16) | tmp.x2 );
146 OUT_RELOC( dst->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, 0 );
147 OUT_BATCH( (tmp.y1 << 16) | tmp.x1 );
148 OUT_BATCH( src_pitch );
149 OUT_RELOC( src->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, 0 );
150 ADVANCE_BATCH();
151 }
152 }
153
154 intel_batchbuffer_flush( intel->batch );
155 intel->second_last_swap_fence = intel->last_swap_fence;
156 intel->last_swap_fence = bmSetFenceLock( intel );
157 UNLOCK_HARDWARE( intel );
158
159 if (!rect)
160 {
161 intel->swap_count++;
162 (*dri_interface->getUST)(&ust);
163 if (missed_target) {
164 intel->swap_missed_count++;
165 intel->swap_missed_ust = ust - intel->swap_ust;
166 }
167
168 intel->swap_ust = ust;
169 }
170
171 }
172
173
174
175
176 void intelEmitFillBlit( struct intel_context *intel,
177 GLuint cpp,
178 GLshort dst_pitch,
179 struct buffer *dst_buffer,
180 GLuint dst_offset,
181 GLboolean dst_tiled,
182 GLshort x, GLshort y,
183 GLshort w, GLshort h,
184 GLuint color )
185 {
186 GLuint BR13, CMD;
187 BATCH_LOCALS;
188
189 dst_pitch *= cpp;
190
191 switch(cpp) {
192 case 1:
193 case 2:
194 case 3:
195 BR13 = (0xF0 << 16) | (1<<24);
196 CMD = XY_COLOR_BLT_CMD;
197 break;
198 case 4:
199 BR13 = (0xF0 << 16) | (1<<24) | (1<<25);
200 CMD = XY_COLOR_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
201 break;
202 default:
203 return;
204 }
205
206 if (dst_tiled) {
207 CMD |= XY_DST_TILED;
208 dst_pitch /= 4;
209 }
210
211 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
212 OUT_BATCH( CMD );
213 OUT_BATCH( dst_pitch | BR13 );
214 OUT_BATCH( (y << 16) | x );
215 OUT_BATCH( ((y+h) << 16) | (x+w) );
216 OUT_RELOC( dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, dst_offset );
217 OUT_BATCH( color );
218 ADVANCE_BATCH();
219 }
220
221 static GLuint translate_raster_op(GLenum logicop)
222 {
223 switch(logicop) {
224 case GL_CLEAR: return 0x00;
225 case GL_AND: return 0x88;
226 case GL_AND_REVERSE: return 0x44;
227 case GL_COPY: return 0xCC;
228 case GL_AND_INVERTED: return 0x22;
229 case GL_NOOP: return 0xAA;
230 case GL_XOR: return 0x66;
231 case GL_OR: return 0xEE;
232 case GL_NOR: return 0x11;
233 case GL_EQUIV: return 0x99;
234 case GL_INVERT: return 0x55;
235 case GL_OR_REVERSE: return 0xDD;
236 case GL_COPY_INVERTED: return 0x33;
237 case GL_OR_INVERTED: return 0xBB;
238 case GL_NAND: return 0x77;
239 case GL_SET: return 0xFF;
240 default: return 0;
241 }
242 }
243
244
245 /* Copy BitBlt
246 */
247 void intelEmitCopyBlit( struct intel_context *intel,
248 GLuint cpp,
249 GLshort src_pitch,
250 struct buffer *src_buffer,
251 GLuint src_offset,
252 GLboolean src_tiled,
253 GLshort dst_pitch,
254 struct buffer *dst_buffer,
255 GLuint dst_offset,
256 GLboolean dst_tiled,
257 GLshort src_x, GLshort src_y,
258 GLshort dst_x, GLshort dst_y,
259 GLshort w, GLshort h,
260 GLenum logic_op )
261 {
262 GLuint CMD, BR13;
263 int dst_y2 = dst_y + h;
264 int dst_x2 = dst_x + w;
265 BATCH_LOCALS;
266
267
268 DBG("%s src:buf(%d)/%d %d,%d dst:buf(%d)/%d %d,%d sz:%dx%d op:%d\n",
269 __FUNCTION__,
270 src_buffer, src_pitch, src_x, src_y,
271 dst_buffer, dst_pitch, dst_x, dst_y,
272 w,h,logic_op);
273
274 assert( logic_op - GL_CLEAR >= 0 );
275 assert( logic_op - GL_CLEAR < 0x10 );
276
277 src_pitch *= cpp;
278 dst_pitch *= cpp;
279
280 switch(cpp) {
281 case 1:
282 case 2:
283 case 3:
284 BR13 = (translate_raster_op(logic_op) << 16) | (1<<24);
285 CMD = XY_SRC_COPY_BLT_CMD;
286 break;
287 case 4:
288 BR13 = (translate_raster_op(logic_op) << 16) | (1<<24) |
289 (1<<25);
290 CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
291 break;
292 default:
293 return;
294 }
295
296 if (src_tiled) {
297 CMD |= XY_SRC_TILED;
298 src_pitch /= 4;
299 }
300
301 if (dst_tiled) {
302 CMD |= XY_DST_TILED;
303 dst_pitch /= 4;
304 }
305
306 if (dst_y2 < dst_y ||
307 dst_x2 < dst_x) {
308 return;
309 }
310
311 dst_pitch &= 0xffff;
312 src_pitch &= 0xffff;
313
314 /* Initial y values don't seem to work with negative pitches. If
315 * we adjust the offsets manually (below), it seems to work fine.
316 *
317 * On the other hand, if we always adjust, the hardware doesn't
318 * know which blit directions to use, so overlapping copypixels get
319 * the wrong result.
320 */
321 if (dst_pitch > 0 && src_pitch > 0) {
322 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
323 OUT_BATCH( CMD );
324 OUT_BATCH( dst_pitch | BR13 );
325 OUT_BATCH( (dst_y << 16) | dst_x );
326 OUT_BATCH( (dst_y2 << 16) | dst_x2 );
327 OUT_RELOC( dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
328 dst_offset );
329 OUT_BATCH( (src_y << 16) | src_x );
330 OUT_BATCH( src_pitch );
331 OUT_RELOC( src_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
332 src_offset );
333 ADVANCE_BATCH();
334 }
335 else {
336 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
337 OUT_BATCH( CMD );
338 OUT_BATCH( (dst_pitch & 0xffff) | BR13 );
339 OUT_BATCH( (0 << 16) | dst_x );
340 OUT_BATCH( (h << 16) | dst_x2 );
341 OUT_RELOC( dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
342 dst_offset + dst_y * dst_pitch );
343 OUT_BATCH( (src_pitch & 0xffff) );
344 OUT_RELOC( src_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
345 src_offset + src_y * src_pitch );
346 ADVANCE_BATCH();
347 }
348 }
349
350
351
352 void intelClearWithBlit(GLcontext *ctx, GLbitfield flags)
353 {
354 struct intel_context *intel = intel_context( ctx );
355 intelScreenPrivate *intelScreen = intel->intelScreen;
356 GLuint clear_depth, clear_color;
357 GLint cx, cy, cw, ch;
358 GLint cpp = intelScreen->cpp;
359 GLboolean all;
360 GLint i;
361 struct intel_region *front = intel->front_region;
362 struct intel_region *back = intel->back_region;
363 struct intel_region *depth = intel->depth_region;
364 GLuint BR13, FRONT_CMD, BACK_CMD, DEPTH_CMD;
365 GLuint front_pitch;
366 GLuint back_pitch;
367 GLuint depth_pitch;
368 BATCH_LOCALS;
369
370
371 clear_color = intel->ClearColor;
372 clear_depth = 0;
373
374 if (flags & BUFFER_BIT_DEPTH) {
375 clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth);
376 }
377
378 if (flags & BUFFER_BIT_STENCIL) {
379 clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
380 }
381
382 switch(cpp) {
383 case 2:
384 BR13 = (0xF0 << 16) | (1<<24);
385 BACK_CMD = FRONT_CMD = XY_COLOR_BLT_CMD;
386 DEPTH_CMD = XY_COLOR_BLT_CMD;
387 break;
388 case 4:
389 BR13 = (0xF0 << 16) | (1<<24) | (1<<25);
390 BACK_CMD = FRONT_CMD = XY_COLOR_BLT_CMD |
391 XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
392 DEPTH_CMD = XY_COLOR_BLT_CMD;
393 if (flags & BUFFER_BIT_DEPTH) DEPTH_CMD |= XY_BLT_WRITE_RGB;
394 if (flags & BUFFER_BIT_STENCIL) DEPTH_CMD |= XY_BLT_WRITE_ALPHA;
395 break;
396 default:
397 return;
398 }
399
400
401
402 intelFlush( &intel->ctx );
403 LOCK_HARDWARE( intel );
404 {
405 /* get clear bounds after locking */
406 cx = ctx->DrawBuffer->_Xmin;
407 cy = ctx->DrawBuffer->_Ymin;
408 ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
409 cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
410 all = (cw == ctx->DrawBuffer->Width && ch == ctx->DrawBuffer->Height);
411
412 /* flip top to bottom */
413 cy = intel->driDrawable->h - cy - ch;
414 cx = cx + intel->drawX;
415 cy += intel->drawY;
416
417 /* adjust for page flipping */
418 if ( intel->sarea->pf_current_page == 0 ) {
419 front = intel->front_region;
420 back = intel->back_region;
421 }
422 else {
423 back = intel->front_region;
424 front = intel->back_region;
425 }
426
427 front_pitch = front->pitch * front->cpp;
428 back_pitch = back->pitch * back->cpp;
429 depth_pitch = depth->pitch * depth->cpp;
430
431 if (front->tiled) {
432 FRONT_CMD |= XY_DST_TILED;
433 front_pitch /= 4;
434 }
435
436 if (back->tiled) {
437 BACK_CMD |= XY_DST_TILED;
438 back_pitch /= 4;
439 }
440
441 if (depth->tiled) {
442 DEPTH_CMD |= XY_DST_TILED;
443 depth_pitch /= 4;
444 }
445
446 for (i = 0 ; i < intel->numClipRects ; i++)
447 {
448 drm_clip_rect_t *box = &intel->pClipRects[i];
449 drm_clip_rect_t b;
450
451 if (!all) {
452 GLint x = box->x1;
453 GLint y = box->y1;
454 GLint w = box->x2 - x;
455 GLint h = box->y2 - y;
456
457 if (x < cx) w -= cx - x, x = cx;
458 if (y < cy) h -= cy - y, y = cy;
459 if (x + w > cx + cw) w = cx + cw - x;
460 if (y + h > cy + ch) h = cy + ch - y;
461 if (w <= 0) continue;
462 if (h <= 0) continue;
463
464 b.x1 = x;
465 b.y1 = y;
466 b.x2 = x + w;
467 b.y2 = y + h;
468 } else {
469 b = *box;
470 }
471
472
473 if (b.x1 > b.x2 ||
474 b.y1 > b.y2 ||
475 b.x2 > intelScreen->width ||
476 b.y2 > intelScreen->height)
477 continue;
478
479 if ( flags & BUFFER_BIT_FRONT_LEFT ) {
480 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
481 OUT_BATCH( FRONT_CMD );
482 OUT_BATCH( front_pitch | BR13 );
483 OUT_BATCH( (b.y1 << 16) | b.x1 );
484 OUT_BATCH( (b.y2 << 16) | b.x2 );
485 OUT_RELOC( front->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
486 0 );
487 OUT_BATCH( clear_color );
488 ADVANCE_BATCH();
489 }
490
491 if ( flags & BUFFER_BIT_BACK_LEFT ) {
492 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
493 OUT_BATCH( BACK_CMD );
494 OUT_BATCH( back_pitch | BR13 );
495 OUT_BATCH( (b.y1 << 16) | b.x1 );
496 OUT_BATCH( (b.y2 << 16) | b.x2 );
497 OUT_RELOC( back->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
498 0 );
499 OUT_BATCH( clear_color );
500 ADVANCE_BATCH();
501 }
502
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_RELOC( depth->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
510 0 );
511 OUT_BATCH( clear_depth );
512 ADVANCE_BATCH();
513 }
514 }
515 }
516 intel_batchbuffer_flush( intel->batch );
517 UNLOCK_HARDWARE( intel );
518 }
519
520
521 void
522 intelEmitImmediateColorExpandBlit(struct intel_context *intel,
523 GLuint cpp,
524 GLubyte *src_bits, GLuint src_size,
525 GLuint fg_color,
526 GLshort dst_pitch,
527 struct buffer *dst_buffer,
528 GLuint dst_offset,
529 GLboolean dst_tiled,
530 GLshort x, GLshort y,
531 GLshort w, GLshort h,
532 GLenum logic_op)
533 {
534 struct xy_text_immediate_blit text;
535 int dwords = ALIGN(src_size, 8) / 4;
536 uint32_t opcode, br13;
537
538 assert( logic_op - GL_CLEAR >= 0 );
539 assert( logic_op - GL_CLEAR < 0x10 );
540
541 if (w < 0 || h < 0)
542 return;
543
544 dst_pitch *= cpp;
545
546 if (dst_tiled)
547 dst_pitch /= 4;
548
549 DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d, %d bytes %d dwords\n",
550 __FUNCTION__,
551 dst_buffer, dst_pitch, dst_offset, x, y, w, h, src_size, dwords);
552
553 memset(&text, 0, sizeof(text));
554 text.dw0.client = CLIENT_2D;
555 text.dw0.opcode = OPCODE_XY_TEXT_IMMEDIATE_BLT;
556 text.dw0.pad0 = 0;
557 text.dw0.byte_packed = 1; /* ?maybe? */
558 text.dw0.pad1 = 0;
559 text.dw0.dst_tiled = dst_tiled;
560 text.dw0.pad2 = 0;
561 text.dw0.length = (sizeof(text)/sizeof(int)) - 2 + dwords;
562 text.dw1.dest_y1 = y; /* duplicates info in setup blit */
563 text.dw1.dest_x1 = x;
564 text.dw2.dest_y2 = y + h;
565 text.dw2.dest_x2 = x + w;
566
567 intel_batchbuffer_require_space( intel->batch,
568 (8 * 4) +
569 sizeof(text) +
570 dwords,
571 INTEL_BATCH_NO_CLIPRECTS );
572
573 opcode = XY_SETUP_BLT_CMD;
574 if (cpp == 4)
575 opcode |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
576 if (dst_tiled)
577 opcode |= XY_DST_TILED;
578
579 br13 = dst_pitch | (translate_raster_op(logic_op) << 16) | (1 << 29);
580 if (cpp == 2)
581 br13 |= BR13_565;
582 else
583 br13 |= BR13_8888;
584
585 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
586 OUT_BATCH(opcode);
587 OUT_BATCH(br13);
588 OUT_BATCH((0 << 16) | 0); /* clip x1, y1 */
589 OUT_BATCH((100 << 16) | 100); /* clip x2, y2 */
590 OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, dst_offset);
591 OUT_BATCH(0); /* bg */
592 OUT_BATCH(fg_color); /* fg */
593 OUT_BATCH(0); /* pattern base addr */
594 ADVANCE_BATCH();
595
596 intel_batchbuffer_data( intel->batch,
597 &text,
598 sizeof(text),
599 INTEL_BATCH_NO_CLIPRECTS );
600
601 intel_batchbuffer_data( intel->batch,
602 src_bits,
603 dwords * 4,
604 INTEL_BATCH_NO_CLIPRECTS );
605 }
606