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