Add a comment about the interactions of negative pitches, overlapping
[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
43 #include "bufmgr.h"
44
45
46
47
48 /*
49 * Copy the back buffer to the front buffer.
50 */
51 void intelCopyBuffer( const __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 bmFinishFence(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, &intel->vbl_seq, intel->vblank_flags, & 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_SRC_COPY_BLT_WRITE_ALPHA |
113 XY_SRC_COPY_BLT_WRITE_RGB);
114 }
115
116 if (src->tiled) {
117 CMD |= XY_SRC_TILED;
118 src_pitch /= 4;
119 }
120
121 if (dst->tiled) {
122 CMD |= XY_DST_TILED;
123 dst_pitch /= 4;
124 }
125
126 for (i = 0 ; i < nbox; i++, pbox++)
127 {
128 drm_clip_rect_t tmp = *pbox;
129
130 if (rect) {
131 if (!intel_intersect_cliprects(&tmp, &tmp, rect))
132 continue;
133 }
134
135
136 if (tmp.x1 > tmp.x2 ||
137 tmp.y1 > tmp.y2 ||
138 tmp.x2 > intelScreen->width ||
139 tmp.y2 > intelScreen->height)
140 continue;
141
142 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
143 OUT_BATCH( CMD );
144 OUT_BATCH( dst_pitch | BR13 );
145 OUT_BATCH( (tmp.y1 << 16) | tmp.x1 );
146 OUT_BATCH( (tmp.y2 << 16) | tmp.x2 );
147 OUT_BATCH( bmBufferOffset(intel, dst->buffer) );
148 OUT_BATCH( (tmp.y1 << 16) | tmp.x1 );
149 OUT_BATCH( src_pitch );
150 OUT_BATCH( bmBufferOffset(intel, src->buffer) );
151 ADVANCE_BATCH();
152 }
153 }
154
155 intel_batchbuffer_flush( intel->batch );
156 intel->second_last_swap_fence = intel->last_swap_fence;
157 intel->last_swap_fence = bmSetFence( intel );
158 UNLOCK_HARDWARE( intel );
159
160 if (!rect)
161 {
162 intel->swap_count++;
163 (*dri_interface->getUST)(&ust);
164 if (missed_target) {
165 intel->swap_missed_count++;
166 intel->swap_missed_ust = ust - intel->swap_ust;
167 }
168
169 intel->swap_ust = ust;
170 }
171
172 }
173
174
175
176
177 void intelEmitFillBlit( struct intel_context *intel,
178 GLuint cpp,
179 GLshort dst_pitch,
180 struct buffer *dst_buffer,
181 GLuint dst_offset,
182 GLboolean dst_tiled,
183 GLshort x, GLshort y,
184 GLshort w, GLshort h,
185 GLuint color )
186 {
187 GLuint BR13, CMD;
188 BATCH_LOCALS;
189
190 dst_pitch *= cpp;
191
192 switch(cpp) {
193 case 1:
194 case 2:
195 case 3:
196 BR13 = (0xF0 << 16) | (1<<24);
197 CMD = XY_COLOR_BLT_CMD;
198 break;
199 case 4:
200 BR13 = (0xF0 << 16) | (1<<24) | (1<<25);
201 CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
202 XY_COLOR_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_BATCH( bmBufferOffset(intel, dst_buffer) + dst_offset );
219 OUT_BATCH( color );
220 ADVANCE_BATCH();
221 }
222
223
224 /* Copy BitBlt
225 */
226 void intelEmitCopyBlit( struct intel_context *intel,
227 GLuint cpp,
228 GLshort src_pitch,
229 struct buffer *src_buffer,
230 GLuint src_offset,
231 GLboolean src_tiled,
232 GLshort dst_pitch,
233 struct buffer *dst_buffer,
234 GLuint dst_offset,
235 GLboolean dst_tiled,
236 GLshort src_x, GLshort src_y,
237 GLshort dst_x, GLshort dst_y,
238 GLshort w, GLshort h )
239 {
240 GLuint CMD, BR13;
241 int dst_y2 = dst_y + h;
242 int dst_x2 = dst_x + w;
243 BATCH_LOCALS;
244
245
246 DBG("%s src:buf(%d)/%d %d,%d dst:buf(%d)/%d %d,%d sz:%dx%d\n",
247 __FUNCTION__,
248 src_buffer, src_pitch, src_x, src_y,
249 dst_buffer, dst_pitch, dst_x, dst_y,
250 w,h);
251
252 src_pitch *= cpp;
253 dst_pitch *= cpp;
254
255 switch(cpp) {
256 case 1:
257 case 2:
258 case 3:
259 BR13 = (0xCC << 16) | (1<<24);
260 CMD = XY_SRC_COPY_BLT_CMD;
261 break;
262 case 4:
263 BR13 = (0xCC << 16) | (1<<24) | (1<<25);
264 CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
265 XY_SRC_COPY_BLT_WRITE_RGB);
266 break;
267 default:
268 return;
269 }
270
271 if (src_tiled) {
272 CMD |= XY_SRC_TILED;
273 src_pitch /= 4;
274 }
275
276 if (dst_tiled) {
277 CMD |= XY_DST_TILED;
278 dst_pitch /= 4;
279 }
280
281 if (dst_y2 < dst_y ||
282 dst_x2 < dst_x) {
283 return;
284 }
285
286 dst_pitch &= 0xffff;
287 src_pitch &= 0xffff;
288
289 /* Initial y values don't seem to work with negative pitches. If
290 * we adjust the offsets manually (below), it seems to work fine.
291 *
292 * However, on broadwater at least, only the top version works
293 * correctly with overlapping blits. Luckily we don't need
294 * negative pitches and overlapping blits at the same time, as far
295 * as I know anyhow.
296 *
297 * Further, the current i965 driver never requires negative
298 * pitches, so just use the old-style blits for now.
299 */
300 if (1) {
301 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
302 OUT_BATCH( CMD );
303 OUT_BATCH( dst_pitch | BR13 );
304 OUT_BATCH( (dst_y << 16) | dst_x );
305 OUT_BATCH( (dst_y2 << 16) | dst_x2 );
306 OUT_BATCH( bmBufferOffset(intel, dst_buffer) + dst_offset );
307 OUT_BATCH( (src_y << 16) | src_x );
308 OUT_BATCH( src_pitch );
309 OUT_BATCH( bmBufferOffset(intel, src_buffer) + src_offset );
310 ADVANCE_BATCH();
311 }
312 else {
313 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
314 OUT_BATCH( CMD );
315 OUT_BATCH( (dst_pitch & 0xffff) | BR13 );
316 OUT_BATCH( (0 << 16) | dst_x );
317 OUT_BATCH( (h << 16) | dst_x2 );
318 OUT_BATCH( bmBufferOffset(intel, dst_buffer) + dst_offset + dst_y * dst_pitch );
319 OUT_BATCH( (0 << 16) | src_x );
320 OUT_BATCH( (src_pitch & 0xffff) );
321 OUT_BATCH( bmBufferOffset(intel, src_buffer) + src_offset + src_y * src_pitch );
322 ADVANCE_BATCH();
323 }
324 }
325
326
327
328 void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
329 GLint cx1, GLint cy1, GLint cw, GLint ch)
330 {
331 struct intel_context *intel = intel_context( ctx );
332 intelScreenPrivate *intelScreen = intel->intelScreen;
333 GLuint clear_depth, clear_color;
334 GLint cx, cy;
335 GLint cpp = intelScreen->cpp;
336 GLint i;
337 struct intel_region *front = intel->front_region;
338 struct intel_region *back = intel->back_region;
339 struct intel_region *depth = intel->depth_region;
340 GLuint BR13, FRONT_CMD, BACK_CMD, DEPTH_CMD;
341 GLuint front_pitch;
342 GLuint back_pitch;
343 GLuint depth_pitch;
344 BATCH_LOCALS;
345
346
347 clear_color = intel->ClearColor;
348 clear_depth = 0;
349
350 if (flags & BUFFER_BIT_DEPTH) {
351 clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth);
352 }
353
354 if (flags & BUFFER_BIT_STENCIL) {
355 clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
356 }
357
358 switch(cpp) {
359 case 2:
360 BR13 = (0xF0 << 16) | (1<<24);
361 BACK_CMD = FRONT_CMD = XY_COLOR_BLT_CMD;
362 DEPTH_CMD = XY_COLOR_BLT_CMD;
363 break;
364 case 4:
365 BR13 = (0xF0 << 16) | (1<<24) | (1<<25);
366 BACK_CMD = FRONT_CMD = (XY_COLOR_BLT_CMD |
367 XY_COLOR_BLT_WRITE_ALPHA |
368 XY_COLOR_BLT_WRITE_RGB);
369 DEPTH_CMD = XY_COLOR_BLT_CMD;
370 if (flags & BUFFER_BIT_DEPTH) DEPTH_CMD |= XY_COLOR_BLT_WRITE_RGB;
371 if (flags & BUFFER_BIT_STENCIL) DEPTH_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
372 break;
373 default:
374 return;
375 }
376
377
378
379 intelFlush( &intel->ctx );
380 LOCK_HARDWARE( intel );
381 {
382 /* Refresh the cx/y/w/h values as they may have been invalidated
383 * by a new window position or size picked up when we did
384 * LOCK_HARDWARE above. The values passed by mesa are not
385 * reliable.
386 */
387 {
388 cx = ctx->DrawBuffer->_Xmin;
389 cy = ctx->DrawBuffer->_Ymin;
390 ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
391 cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
392 }
393
394 /* flip top to bottom */
395 cy = intel->driDrawable->h-cy1-ch;
396 cx = cx1 + intel->drawX;
397 cy += intel->drawY;
398
399 /* adjust for page flipping */
400 if ( intel->sarea->pf_current_page == 0 ) {
401 front = intel->front_region;
402 back = intel->back_region;
403 }
404 else {
405 back = intel->front_region;
406 front = intel->back_region;
407 }
408
409 front_pitch = front->pitch * front->cpp;
410 back_pitch = back->pitch * back->cpp;
411 depth_pitch = depth->pitch * depth->cpp;
412
413 if (front->tiled) {
414 FRONT_CMD |= XY_DST_TILED;
415 front_pitch /= 4;
416 }
417
418 if (back->tiled) {
419 BACK_CMD |= XY_DST_TILED;
420 back_pitch /= 4;
421 }
422
423 if (depth->tiled) {
424 DEPTH_CMD |= XY_DST_TILED;
425 depth_pitch /= 4;
426 }
427
428 for (i = 0 ; i < intel->numClipRects ; i++)
429 {
430 drm_clip_rect_t *box = &intel->pClipRects[i];
431 drm_clip_rect_t b;
432
433 if (!all) {
434 GLint x = box->x1;
435 GLint y = box->y1;
436 GLint w = box->x2 - x;
437 GLint h = box->y2 - y;
438
439 if (x < cx) w -= cx - x, x = cx;
440 if (y < cy) h -= cy - y, y = cy;
441 if (x + w > cx + cw) w = cx + cw - x;
442 if (y + h > cy + ch) h = cy + ch - y;
443 if (w <= 0) continue;
444 if (h <= 0) continue;
445
446 b.x1 = x;
447 b.y1 = y;
448 b.x2 = x + w;
449 b.y2 = y + h;
450 } else {
451 b = *box;
452 }
453
454
455 if (b.x1 > b.x2 ||
456 b.y1 > b.y2 ||
457 b.x2 > intelScreen->width ||
458 b.y2 > intelScreen->height)
459 continue;
460
461 if ( flags & BUFFER_BIT_FRONT_LEFT ) {
462 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
463 OUT_BATCH( FRONT_CMD );
464 OUT_BATCH( front_pitch | BR13 );
465 OUT_BATCH( (b.y1 << 16) | b.x1 );
466 OUT_BATCH( (b.y2 << 16) | b.x2 );
467 OUT_BATCH( bmBufferOffset(intel, front->buffer) );
468 OUT_BATCH( clear_color );
469 ADVANCE_BATCH();
470 }
471
472 if ( flags & BUFFER_BIT_BACK_LEFT ) {
473 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
474 OUT_BATCH( BACK_CMD );
475 OUT_BATCH( back_pitch | BR13 );
476 OUT_BATCH( (b.y1 << 16) | b.x1 );
477 OUT_BATCH( (b.y2 << 16) | b.x2 );
478 OUT_BATCH( bmBufferOffset(intel, back->buffer) );
479 OUT_BATCH( clear_color );
480 ADVANCE_BATCH();
481 }
482
483 if ( flags & (BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH) ) {
484 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
485 OUT_BATCH( DEPTH_CMD );
486 OUT_BATCH( depth_pitch | BR13 );
487 OUT_BATCH( (b.y1 << 16) | b.x1 );
488 OUT_BATCH( (b.y2 << 16) | b.x2 );
489 OUT_BATCH( bmBufferOffset(intel, depth->buffer) );
490 OUT_BATCH( clear_depth );
491 ADVANCE_BATCH();
492 }
493 }
494 }
495 intel_batchbuffer_flush( intel->batch );
496 UNLOCK_HARDWARE( intel );
497 }
498
499