c57618b388b5f0ccc172714c55d352bb25461a2a
[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 if (1) {
293 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
294 OUT_BATCH( CMD );
295 OUT_BATCH( dst_pitch | BR13 );
296 OUT_BATCH( (dst_y << 16) | dst_x );
297 OUT_BATCH( (dst_y2 << 16) | dst_x2 );
298 OUT_BATCH( bmBufferOffset(intel, dst_buffer) + dst_offset );
299 OUT_BATCH( (src_y << 16) | src_x );
300 OUT_BATCH( src_pitch );
301 OUT_BATCH( bmBufferOffset(intel, src_buffer) + src_offset );
302 ADVANCE_BATCH();
303 }
304 else {
305 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
306 OUT_BATCH( CMD );
307 OUT_BATCH( (dst_pitch & 0xffff) | BR13 );
308 OUT_BATCH( (0 << 16) | dst_x );
309 OUT_BATCH( (h << 16) | dst_x2 );
310 OUT_BATCH( bmBufferOffset(intel, dst_buffer) + dst_offset + dst_y * dst_pitch );
311 OUT_BATCH( (0 << 16) | src_x );
312 OUT_BATCH( (src_pitch & 0xffff) );
313 OUT_BATCH( bmBufferOffset(intel, src_buffer) + src_offset + src_y * src_pitch );
314 ADVANCE_BATCH();
315 }
316 }
317
318
319
320 void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
321 GLint cx1, GLint cy1, GLint cw, GLint ch)
322 {
323 struct intel_context *intel = intel_context( ctx );
324 intelScreenPrivate *intelScreen = intel->intelScreen;
325 GLuint clear_depth, clear_color;
326 GLint cx, cy;
327 GLint cpp = intelScreen->cpp;
328 GLint i;
329 struct intel_region *front = intel->front_region;
330 struct intel_region *back = intel->back_region;
331 struct intel_region *depth = intel->depth_region;
332 GLuint BR13, FRONT_CMD, BACK_CMD, DEPTH_CMD;
333 GLuint front_pitch;
334 GLuint back_pitch;
335 GLuint depth_pitch;
336 BATCH_LOCALS;
337
338
339 clear_color = intel->ClearColor;
340 clear_depth = 0;
341
342 if (flags & BUFFER_BIT_DEPTH) {
343 clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth);
344 }
345
346 if (flags & BUFFER_BIT_STENCIL) {
347 clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
348 }
349
350 switch(cpp) {
351 case 2:
352 BR13 = (0xF0 << 16) | (1<<24);
353 BACK_CMD = FRONT_CMD = XY_COLOR_BLT_CMD;
354 DEPTH_CMD = XY_COLOR_BLT_CMD;
355 break;
356 case 4:
357 BR13 = (0xF0 << 16) | (1<<24) | (1<<25);
358 BACK_CMD = FRONT_CMD = (XY_COLOR_BLT_CMD |
359 XY_COLOR_BLT_WRITE_ALPHA |
360 XY_COLOR_BLT_WRITE_RGB);
361 DEPTH_CMD = XY_COLOR_BLT_CMD;
362 if (flags & BUFFER_BIT_DEPTH) DEPTH_CMD |= XY_COLOR_BLT_WRITE_RGB;
363 if (flags & BUFFER_BIT_STENCIL) DEPTH_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
364 break;
365 default:
366 return;
367 }
368
369
370
371 intelFlush( &intel->ctx );
372 LOCK_HARDWARE( intel );
373 {
374 /* Refresh the cx/y/w/h values as they may have been invalidated
375 * by a new window position or size picked up when we did
376 * LOCK_HARDWARE above. The values passed by mesa are not
377 * reliable.
378 */
379 {
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 }
385
386 /* flip top to bottom */
387 cy = intel->driDrawable->h-cy1-ch;
388 cx = cx1 + 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