Remove x/y/width/height parameters from Clear functions.
[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 bmFinishFence(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, &intel->vbl_seq, intel->vblank_flags, & missed_target );
80 LOCK_HARDWARE( intel );
81 }
82
83 {
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;
90 int BR13, CMD;
91 int i;
92 int src_pitch, dst_pitch;
93
94 if (intel->sarea->pf_current_page == 0) {
95 dst = intel->front_region;
96 src = intel->back_region;
97 }
98 else {
99 assert(0);
100 src = intel->front_region;
101 dst = intel->back_region;
102 }
103
104 src_pitch = src->pitch * src->cpp;
105 dst_pitch = dst->pitch * dst->cpp;
106
107 if (cpp == 2) {
108 BR13 = (0xCC << 16) | (1<<24);
109 CMD = XY_SRC_COPY_BLT_CMD;
110 }
111 else {
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);
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_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) );
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 = bmSetFence( 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_COLOR_BLT_WRITE_ALPHA |
203 XY_COLOR_BLT_WRITE_RGB);
204 break;
205 default:
206 return;
207 }
208
209 if (dst_tiled) {
210 CMD |= XY_DST_TILED;
211 dst_pitch /= 4;
212 }
213
214 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
215 OUT_BATCH( CMD );
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 );
220 OUT_BATCH( color );
221 ADVANCE_BATCH();
222 }
223
224
225 /* Copy BitBlt
226 */
227 void intelEmitCopyBlit( struct intel_context *intel,
228 GLuint cpp,
229 GLshort src_pitch,
230 struct buffer *src_buffer,
231 GLuint src_offset,
232 GLboolean src_tiled,
233 GLshort dst_pitch,
234 struct buffer *dst_buffer,
235 GLuint dst_offset,
236 GLboolean dst_tiled,
237 GLshort src_x, GLshort src_y,
238 GLshort dst_x, GLshort dst_y,
239 GLshort w, GLshort h )
240 {
241 GLuint CMD, BR13;
242 int dst_y2 = dst_y + h;
243 int dst_x2 = dst_x + w;
244 BATCH_LOCALS;
245
246
247 DBG("%s src:buf(%d)/%d %d,%d dst:buf(%d)/%d %d,%d sz:%dx%d\n",
248 __FUNCTION__,
249 src_buffer, src_pitch, src_x, src_y,
250 dst_buffer, dst_pitch, dst_x, dst_y,
251 w,h);
252
253 src_pitch *= cpp;
254 dst_pitch *= cpp;
255
256 switch(cpp) {
257 case 1:
258 case 2:
259 case 3:
260 BR13 = (0xCC << 16) | (1<<24);
261 CMD = XY_SRC_COPY_BLT_CMD;
262 break;
263 case 4:
264 BR13 = (0xCC << 16) | (1<<24) | (1<<25);
265 CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
266 XY_SRC_COPY_BLT_WRITE_RGB);
267 break;
268 default:
269 return;
270 }
271
272 if (src_tiled) {
273 CMD |= XY_SRC_TILED;
274 src_pitch /= 4;
275 }
276
277 if (dst_tiled) {
278 CMD |= XY_DST_TILED;
279 dst_pitch /= 4;
280 }
281
282 if (dst_y2 < dst_y ||
283 dst_x2 < dst_x) {
284 return;
285 }
286
287 dst_pitch &= 0xffff;
288 src_pitch &= 0xffff;
289
290 /* Initial y values don't seem to work with negative pitches. If
291 * we adjust the offsets manually (below), it seems to work fine.
292 *
293 * On the other hand, if we always adjust, the hardware doesn't
294 * know which blit directions to use, so overlapping copypixels get
295 * the wrong result.
296 */
297 if (dst_pitch > 0 && src_pitch > 0) {
298 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
299 OUT_BATCH( CMD );
300 OUT_BATCH( dst_pitch | BR13 );
301 OUT_BATCH( (dst_y << 16) | dst_x );
302 OUT_BATCH( (dst_y2 << 16) | dst_x2 );
303 OUT_BATCH( bmBufferOffset(intel, dst_buffer) + dst_offset );
304 OUT_BATCH( (src_y << 16) | src_x );
305 OUT_BATCH( src_pitch );
306 OUT_BATCH( bmBufferOffset(intel, src_buffer) + src_offset );
307 ADVANCE_BATCH();
308 }
309 else {
310 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
311 OUT_BATCH( CMD );
312 OUT_BATCH( (dst_pitch & 0xffff) | BR13 );
313 OUT_BATCH( (0 << 16) | dst_x );
314 OUT_BATCH( (h << 16) | dst_x2 );
315 OUT_BATCH( bmBufferOffset(intel, dst_buffer) + dst_offset + dst_y * dst_pitch );
316 OUT_BATCH( (0 << 16) | src_x );
317 OUT_BATCH( (src_pitch & 0xffff) );
318 OUT_BATCH( bmBufferOffset(intel, src_buffer) + src_offset + src_y * src_pitch );
319 ADVANCE_BATCH();
320 }
321 }
322
323
324
325 void intelClearWithBlit(GLcontext *ctx, GLbitfield flags)
326 {
327 struct intel_context *intel = intel_context( ctx );
328 intelScreenPrivate *intelScreen = intel->intelScreen;
329 GLuint clear_depth, clear_color;
330 GLint cx, cy, cw, ch;
331 GLint cpp = intelScreen->cpp;
332 GLboolean all;
333 GLint i;
334 struct intel_region *front = intel->front_region;
335 struct intel_region *back = intel->back_region;
336 struct intel_region *depth = intel->depth_region;
337 GLuint BR13, FRONT_CMD, BACK_CMD, DEPTH_CMD;
338 GLuint front_pitch;
339 GLuint back_pitch;
340 GLuint depth_pitch;
341 BATCH_LOCALS;
342
343
344 clear_color = intel->ClearColor;
345 clear_depth = 0;
346
347 if (flags & BUFFER_BIT_DEPTH) {
348 clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth);
349 }
350
351 if (flags & BUFFER_BIT_STENCIL) {
352 clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
353 }
354
355 switch(cpp) {
356 case 2:
357 BR13 = (0xF0 << 16) | (1<<24);
358 BACK_CMD = FRONT_CMD = XY_COLOR_BLT_CMD;
359 DEPTH_CMD = XY_COLOR_BLT_CMD;
360 break;
361 case 4:
362 BR13 = (0xF0 << 16) | (1<<24) | (1<<25);
363 BACK_CMD = FRONT_CMD = (XY_COLOR_BLT_CMD |
364 XY_COLOR_BLT_WRITE_ALPHA |
365 XY_COLOR_BLT_WRITE_RGB);
366 DEPTH_CMD = XY_COLOR_BLT_CMD;
367 if (flags & BUFFER_BIT_DEPTH) DEPTH_CMD |= XY_COLOR_BLT_WRITE_RGB;
368 if (flags & BUFFER_BIT_STENCIL) DEPTH_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
369 break;
370 default:
371 return;
372 }
373
374
375
376 intelFlush( &intel->ctx );
377 LOCK_HARDWARE( intel );
378 {
379 /* get clear bounds after locking */
380 cx = ctx->DrawBuffer->_Xmin;
381 cy = ctx->DrawBuffer->_Ymin;
382 ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
383 cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
384 all = (cw == ctx->DrawBuffer->Width && ch == ctx->DrawBuffer->Height);
385
386 /* flip top to bottom */
387 cy = intel->driDrawable->h - cy - ch;
388 cx = cx + intel->drawX;
389 cy += intel->drawY;
390
391 /* adjust for page flipping */
392 if ( intel->sarea->pf_current_page == 0 ) {
393 front = intel->front_region;
394 back = intel->back_region;
395 }
396 else {
397 back = intel->front_region;
398 front = intel->back_region;
399 }
400
401 front_pitch = front->pitch * front->cpp;
402 back_pitch = back->pitch * back->cpp;
403 depth_pitch = depth->pitch * depth->cpp;
404
405 if (front->tiled) {
406 FRONT_CMD |= XY_DST_TILED;
407 front_pitch /= 4;
408 }
409
410 if (back->tiled) {
411 BACK_CMD |= XY_DST_TILED;
412 back_pitch /= 4;
413 }
414
415 if (depth->tiled) {
416 DEPTH_CMD |= XY_DST_TILED;
417 depth_pitch /= 4;
418 }
419
420 for (i = 0 ; i < intel->numClipRects ; i++)
421 {
422 drm_clip_rect_t *box = &intel->pClipRects[i];
423 drm_clip_rect_t b;
424
425 if (!all) {
426 GLint x = box->x1;
427 GLint y = box->y1;
428 GLint w = box->x2 - x;
429 GLint h = box->y2 - y;
430
431 if (x < cx) w -= cx - x, x = cx;
432 if (y < cy) h -= cy - y, y = cy;
433 if (x + w > cx + cw) w = cx + cw - x;
434 if (y + h > cy + ch) h = cy + ch - y;
435 if (w <= 0) continue;
436 if (h <= 0) continue;
437
438 b.x1 = x;
439 b.y1 = y;
440 b.x2 = x + w;
441 b.y2 = y + h;
442 } else {
443 b = *box;
444 }
445
446
447 if (b.x1 > b.x2 ||
448 b.y1 > b.y2 ||
449 b.x2 > intelScreen->width ||
450 b.y2 > intelScreen->height)
451 continue;
452
453 if ( flags & BUFFER_BIT_FRONT_LEFT ) {
454 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
455 OUT_BATCH( FRONT_CMD );
456 OUT_BATCH( front_pitch | BR13 );
457 OUT_BATCH( (b.y1 << 16) | b.x1 );
458 OUT_BATCH( (b.y2 << 16) | b.x2 );
459 OUT_BATCH( bmBufferOffset(intel, front->buffer) );
460 OUT_BATCH( clear_color );
461 ADVANCE_BATCH();
462 }
463
464 if ( flags & BUFFER_BIT_BACK_LEFT ) {
465 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
466 OUT_BATCH( BACK_CMD );
467 OUT_BATCH( back_pitch | BR13 );
468 OUT_BATCH( (b.y1 << 16) | b.x1 );
469 OUT_BATCH( (b.y2 << 16) | b.x2 );
470 OUT_BATCH( bmBufferOffset(intel, back->buffer) );
471 OUT_BATCH( clear_color );
472 ADVANCE_BATCH();
473 }
474
475 if ( flags & (BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH) ) {
476 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
477 OUT_BATCH( DEPTH_CMD );
478 OUT_BATCH( depth_pitch | BR13 );
479 OUT_BATCH( (b.y1 << 16) | b.x1 );
480 OUT_BATCH( (b.y2 << 16) | b.x2 );
481 OUT_BATCH( bmBufferOffset(intel, depth->buffer) );
482 OUT_BATCH( clear_depth );
483 ADVANCE_BATCH();
484 }
485 }
486 }
487 intel_batchbuffer_flush( intel->batch );
488 UNLOCK_HARDWARE( intel );
489 }
490
491
492
493 #define BR13_565 0x1
494 #define BR13_8888 0x3
495
496
497 void
498 intelEmitImmediateColorExpandBlit(struct intel_context *intel,
499 GLuint cpp,
500 GLubyte *src_bits, GLuint src_size,
501 GLuint fg_color,
502 GLshort dst_pitch,
503 struct buffer *dst_buffer,
504 GLuint dst_offset,
505 GLboolean dst_tiled,
506 GLshort x, GLshort y,
507 GLshort w, GLshort h)
508 {
509 struct xy_setup_blit setup;
510 struct xy_text_immediate_blit text;
511 int dwords = ((src_size + 7) & ~7) / 4;
512
513
514 if (w < 0 || h < 0)
515 return;
516
517 dst_pitch *= cpp;
518
519 if (dst_tiled)
520 dst_pitch /= 4;
521
522 DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d, %d bytes %d dwords\n",
523 __FUNCTION__,
524 dst_buffer, dst_pitch, dst_offset, x, y, w, h, src_size, dwords);
525
526 memset(&setup, 0, sizeof(setup));
527
528 setup.br0.client = CLIENT_2D;
529 setup.br0.opcode = OPCODE_XY_SETUP_BLT;
530 setup.br0.write_alpha = (cpp == 4);
531 setup.br0.write_rgb = (cpp == 4);
532 setup.br0.dst_tiled = dst_tiled;
533 setup.br0.length = (sizeof(setup) / sizeof(int)) - 2;
534
535 setup.br13.dest_pitch = dst_pitch;
536 setup.br13.rop = 0xcc;
537 setup.br13.color_depth = (cpp == 4) ? BR13_8888 : BR13_565;
538 setup.br13.clipping_enable = 0;
539 setup.br13.mono_source_transparency = 1;
540
541 setup.dw2.clip_y1 = 0;
542 setup.dw2.clip_x1 = 0;
543 setup.dw3.clip_y2 = 100;
544 setup.dw3.clip_x2 = 100;
545
546 setup.dest_base_addr = bmBufferOffset(intel, dst_buffer) + dst_offset;
547 setup.background_color = 0;
548 setup.foreground_color = fg_color;
549 setup.pattern_base_addr = 0;
550
551 memset(&text, 0, sizeof(text));
552 text.dw0.client = CLIENT_2D;
553 text.dw0.opcode = OPCODE_XY_TEXT_IMMEDIATE_BLT;
554 text.dw0.pad0 = 0;
555 text.dw0.byte_packed = 1; /* ?maybe? */
556 text.dw0.pad1 = 0;
557 text.dw0.dst_tiled = dst_tiled;
558 text.dw0.pad2 = 0;
559 text.dw0.length = (sizeof(text)/sizeof(int)) - 2 + dwords;
560 text.dw1.dest_y1 = y; /* duplicates info in setup blit */
561 text.dw1.dest_x1 = x;
562 text.dw2.dest_y2 = y + h;
563 text.dw2.dest_x2 = x + w;
564
565 intel_batchbuffer_require_space( intel->batch,
566 sizeof(setup) +
567 sizeof(text) +
568 dwords,
569 INTEL_BATCH_NO_CLIPRECTS );
570
571 intel_batchbuffer_data( intel->batch,
572 &setup,
573 sizeof(setup),
574 INTEL_BATCH_NO_CLIPRECTS );
575
576 intel_batchbuffer_data( intel->batch,
577 &text,
578 sizeof(text),
579 INTEL_BATCH_NO_CLIPRECTS );
580
581 intel_batchbuffer_data( intel->batch,
582 src_bits,
583 dwords * 4,
584 INTEL_BATCH_NO_CLIPRECTS );
585 }
586