Move i915tex driver into place as just i915.
[mesa.git] / src / mesa / drivers / dri / i915 / 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
36 #include "intel_batchbuffer.h"
37 #include "intel_blit.h"
38 #include "intel_buffers.h"
39 #include "intel_context.h"
40 #include "intel_fbo.h"
41 #include "intel_reg.h"
42 #include "intel_regions.h"
43 #include "vblank.h"
44
45 #define FILE_DEBUG_FLAG DEBUG_BLIT
46
47 /**
48 * Copy the back color buffer to the front color buffer.
49 * Used for SwapBuffers().
50 */
51 void
52 intelCopyBuffer(const __DRIdrawablePrivate * dPriv,
53 const drm_clip_rect_t * rect)
54 {
55
56 struct intel_context *intel;
57 const intelScreenPrivate *intelScreen;
58
59 DBG("%s\n", __FUNCTION__);
60
61 assert(dPriv);
62
63 intel = intelScreenContext(dPriv->driScreenPriv->private);
64 if (!intel)
65 return;
66
67 intelScreen = intel->intelScreen;
68
69 if (intel->last_swap_fence) {
70 dri_fence_wait(intel->last_swap_fence);
71 dri_fence_unreference(intel->last_swap_fence);
72 intel->last_swap_fence = NULL;
73 }
74 intel->last_swap_fence = intel->first_swap_fence;
75 intel->first_swap_fence = NULL;
76
77 /* The LOCK_HARDWARE is required for the cliprects. Buffer offsets
78 * should work regardless.
79 */
80 LOCK_HARDWARE(intel);
81
82 if (dPriv && dPriv->numClipRects) {
83 struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
84 const struct intel_region *frontRegion
85 = intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT);
86 const struct intel_region *backRegion
87 = intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT);
88 const int nbox = dPriv->numClipRects;
89 const drm_clip_rect_t *pbox = dPriv->pClipRects;
90 const int pitch = frontRegion->pitch;
91 const int cpp = frontRegion->cpp;
92 int BR13, CMD;
93 int i;
94
95 ASSERT(intel_fb);
96 ASSERT(intel_fb->Base.Name == 0); /* Not a user-created FBO */
97 ASSERT(frontRegion);
98 ASSERT(backRegion);
99 ASSERT(frontRegion->pitch == backRegion->pitch);
100 ASSERT(frontRegion->cpp == backRegion->cpp);
101
102 if (cpp == 2) {
103 BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
104 CMD = XY_SRC_COPY_BLT_CMD;
105 }
106 else {
107 BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25);
108 CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
109 XY_SRC_COPY_BLT_WRITE_RGB);
110 }
111
112 for (i = 0; i < nbox; i++, pbox++) {
113 drm_clip_rect_t box;
114
115 if (pbox->x1 > pbox->x2 ||
116 pbox->y1 > pbox->y2 ||
117 pbox->x2 > intelScreen->width || pbox->y2 > intelScreen->height)
118 continue;
119
120 box = *pbox;
121
122 if (rect) {
123 if (rect->x1 > box.x1)
124 box.x1 = rect->x1;
125 if (rect->y1 > box.y1)
126 box.y1 = rect->y1;
127 if (rect->x2 < box.x2)
128 box.x2 = rect->x2;
129 if (rect->y2 < box.y2)
130 box.y2 = rect->y2;
131
132 if (box.x1 > box.x2 || box.y1 > box.y2)
133 continue;
134 }
135
136 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
137 OUT_BATCH(CMD);
138 OUT_BATCH(BR13);
139 OUT_BATCH((pbox->y1 << 16) | pbox->x1);
140 OUT_BATCH((pbox->y2 << 16) | pbox->x2);
141
142 OUT_RELOC(frontRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
143 0);
144 OUT_BATCH((pbox->y1 << 16) | pbox->x1);
145 OUT_BATCH(BR13 & 0xffff);
146 OUT_RELOC(backRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
147 0);
148
149 ADVANCE_BATCH();
150 }
151
152 if (intel->first_swap_fence)
153 dri_fence_unreference(intel->first_swap_fence);
154 intel_batchbuffer_flush(intel->batch);
155 intel->first_swap_fence = intel->batch->last_fence;
156 dri_fence_reference(intel->first_swap_fence);
157 }
158
159 UNLOCK_HARDWARE(intel);
160 }
161
162
163
164
165 void
166 intelEmitFillBlit(struct intel_context *intel,
167 GLuint cpp,
168 GLshort dst_pitch,
169 dri_bo *dst_buffer,
170 GLuint dst_offset,
171 GLshort x, GLshort y, GLshort w, GLshort h, GLuint color)
172 {
173 GLuint BR13, CMD;
174 BATCH_LOCALS;
175
176 dst_pitch *= cpp;
177
178 switch (cpp) {
179 case 1:
180 case 2:
181 case 3:
182 BR13 = dst_pitch | (0xF0 << 16) | (1 << 24);
183 CMD = XY_COLOR_BLT_CMD;
184 break;
185 case 4:
186 BR13 = dst_pitch | (0xF0 << 16) | (1 << 24) | (1 << 25);
187 CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
188 XY_COLOR_BLT_WRITE_RGB);
189 break;
190 default:
191 return;
192 }
193
194 DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
195 __FUNCTION__, dst_buffer, dst_pitch, dst_offset, x, y, w, h);
196
197
198 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
199 OUT_BATCH(CMD);
200 OUT_BATCH(BR13);
201 OUT_BATCH((y << 16) | x);
202 OUT_BATCH(((y + h) << 16) | (x + w));
203 OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, dst_offset);
204 OUT_BATCH(color);
205 ADVANCE_BATCH();
206 }
207
208
209 static GLuint translate_raster_op(GLenum logicop)
210 {
211 switch(logicop) {
212 case GL_CLEAR: return 0x00;
213 case GL_AND: return 0x88;
214 case GL_AND_REVERSE: return 0x44;
215 case GL_COPY: return 0xCC;
216 case GL_AND_INVERTED: return 0x22;
217 case GL_NOOP: return 0xAA;
218 case GL_XOR: return 0x66;
219 case GL_OR: return 0xEE;
220 case GL_NOR: return 0x11;
221 case GL_EQUIV: return 0x99;
222 case GL_INVERT: return 0x55;
223 case GL_OR_REVERSE: return 0xDD;
224 case GL_COPY_INVERTED: return 0x33;
225 case GL_OR_INVERTED: return 0xBB;
226 case GL_NAND: return 0x77;
227 case GL_SET: return 0xFF;
228 default: return 0;
229 }
230 }
231
232
233 /* Copy BitBlt
234 */
235 void
236 intelEmitCopyBlit(struct intel_context *intel,
237 GLuint cpp,
238 GLshort src_pitch,
239 dri_bo *src_buffer,
240 GLuint src_offset,
241 GLshort dst_pitch,
242 dri_bo *dst_buffer,
243 GLuint dst_offset,
244 GLshort src_x, GLshort src_y,
245 GLshort dst_x, GLshort dst_y,
246 GLshort w, GLshort h,
247 GLenum logic_op)
248 {
249 GLuint CMD, BR13;
250 int dst_y2 = dst_y + h;
251 int dst_x2 = dst_x + w;
252 BATCH_LOCALS;
253
254
255 DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
256 __FUNCTION__,
257 src_buffer, src_pitch, src_offset, src_x, src_y,
258 dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, w, h);
259
260 src_pitch *= cpp;
261 dst_pitch *= cpp;
262
263 switch (cpp) {
264 case 1:
265 case 2:
266 case 3:
267 BR13 = (((GLint) dst_pitch) & 0xffff) |
268 (translate_raster_op(logic_op) << 16) | (1 << 24);
269 CMD = XY_SRC_COPY_BLT_CMD;
270 break;
271 case 4:
272 BR13 =
273 (((GLint) dst_pitch) & 0xffff) |
274 (translate_raster_op(logic_op) << 16) | (1 << 24) | (1 << 25);
275 CMD =
276 (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
277 XY_SRC_COPY_BLT_WRITE_RGB);
278 break;
279 default:
280 return;
281 }
282
283 if (dst_y2 < dst_y || dst_x2 < dst_x) {
284 return;
285 }
286
287 /* Initial y values don't seem to work with negative pitches. If
288 * we adjust the offsets manually (below), it seems to work fine.
289 *
290 * On the other hand, if we always adjust, the hardware doesn't
291 * know which blit directions to use, so overlapping copypixels get
292 * the wrong result.
293 */
294 if (dst_pitch > 0 && src_pitch > 0) {
295 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
296 OUT_BATCH(CMD);
297 OUT_BATCH(BR13);
298 OUT_BATCH((dst_y << 16) | dst_x);
299 OUT_BATCH((dst_y2 << 16) | dst_x2);
300 OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, dst_offset);
301 OUT_BATCH((src_y << 16) | src_x);
302 OUT_BATCH(((GLint) src_pitch & 0xffff));
303 OUT_RELOC(src_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, src_offset);
304 ADVANCE_BATCH();
305 }
306 else {
307 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
308 OUT_BATCH(CMD);
309 OUT_BATCH(BR13);
310 OUT_BATCH((0 << 16) | dst_x);
311 OUT_BATCH((h << 16) | dst_x2);
312 OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
313 dst_offset + dst_y * dst_pitch);
314 OUT_BATCH((0 << 16) | src_x);
315 OUT_BATCH(((GLint) src_pitch & 0xffff));
316 OUT_RELOC(src_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
317 src_offset + src_y * src_pitch);
318 ADVANCE_BATCH();
319 }
320 }
321
322
323 /**
324 * Use blitting to clear the renderbuffers named by 'flags'.
325 * Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferMask field
326 * since that might include software renderbuffers or renderbuffers
327 * which we're clearing with triangles.
328 * \param mask bitmask of BUFFER_BIT_* values indicating buffers to clear
329 */
330 void
331 intelClearWithBlit(GLcontext * ctx, GLbitfield mask)
332 {
333 struct intel_context *intel = intel_context(ctx);
334 struct gl_framebuffer *fb = ctx->DrawBuffer;
335 GLuint clear_depth;
336 GLbitfield skipBuffers = 0;
337 BATCH_LOCALS;
338
339 DBG("%s %x\n", __FUNCTION__, mask);
340
341 /*
342 * Compute values for clearing the buffers.
343 */
344 clear_depth = 0;
345 if (mask & BUFFER_BIT_DEPTH) {
346 clear_depth = (GLuint) (fb->_DepthMax * ctx->Depth.Clear);
347 }
348 if (mask & BUFFER_BIT_STENCIL) {
349 clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
350 }
351
352 /* If clearing both depth and stencil, skip BUFFER_BIT_STENCIL in
353 * the loop below.
354 */
355 if ((mask & BUFFER_BIT_DEPTH) && (mask & BUFFER_BIT_STENCIL)) {
356 skipBuffers = BUFFER_BIT_STENCIL;
357 }
358
359 /* XXX Move this flush/lock into the following conditional? */
360 intelFlush(&intel->ctx);
361 LOCK_HARDWARE(intel);
362
363 if (intel->numClipRects) {
364 GLint cx, cy, cw, ch;
365 drm_clip_rect_t clear;
366 int i;
367
368 /* Get clear bounds after locking */
369 cx = fb->_Xmin;
370 cy = fb->_Ymin;
371 cw = fb->_Xmax - cx;
372 ch = fb->_Ymax - cy;
373
374 if (fb->Name == 0) {
375 /* clearing a window */
376
377 /* flip top to bottom */
378 clear.x1 = cx + intel->drawX;
379 clear.y1 = intel->driDrawable->y + intel->driDrawable->h - cy - ch;
380 clear.x2 = clear.x1 + cw;
381 clear.y2 = clear.y1 + ch;
382 }
383 else {
384 /* clearing FBO */
385 assert(intel->numClipRects == 1);
386 assert(intel->pClipRects == &intel->fboRect);
387 clear.x1 = cx;
388 clear.y1 = cy;
389 clear.x2 = clear.x1 + cw;
390 clear.y2 = clear.y1 + ch;
391 /* no change to mask */
392 }
393
394 for (i = 0; i < intel->numClipRects; i++) {
395 const drm_clip_rect_t *box = &intel->pClipRects[i];
396 drm_clip_rect_t b;
397 GLuint buf;
398 GLuint clearMask = mask; /* use copy, since we modify it below */
399 GLboolean all = (cw == fb->Width && ch == fb->Height);
400
401 if (!all) {
402 intel_intersect_cliprects(&b, &clear, box);
403 }
404 else {
405 b = *box;
406 }
407
408 if (0)
409 _mesa_printf("clear %d,%d..%d,%d, mask %x\n",
410 b.x1, b.y1, b.x2, b.y2, mask);
411
412 /* Loop over all renderbuffers */
413 for (buf = 0; buf < BUFFER_COUNT && clearMask; buf++) {
414 const GLbitfield bufBit = 1 << buf;
415 if ((clearMask & bufBit) && !(bufBit & skipBuffers)) {
416 /* OK, clear this renderbuffer */
417 struct intel_region *irb_region =
418 intel_get_rb_region(fb, buf);
419 dri_bo *write_buffer =
420 intel_region_buffer(intel->intelScreen, irb_region,
421 all ? INTEL_WRITE_FULL :
422 INTEL_WRITE_PART);
423
424 GLuint clearVal;
425 GLint pitch, cpp;
426 GLuint BR13, CMD;
427
428 ASSERT(irb_region);
429
430 pitch = irb_region->pitch;
431 cpp = irb_region->cpp;
432
433 DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
434 __FUNCTION__,
435 irb_region->buffer, (pitch * cpp),
436 irb_region->draw_offset,
437 b.x1, b.y1, b.x2 - b.x1, b.y2 - b.y1);
438
439
440 /* Setup the blit command */
441 if (cpp == 4) {
442 BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24) | (1 << 25);
443 if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) {
444 CMD = XY_COLOR_BLT_CMD;
445 if (clearMask & BUFFER_BIT_DEPTH)
446 CMD |= XY_COLOR_BLT_WRITE_RGB;
447 if (clearMask & BUFFER_BIT_STENCIL)
448 CMD |= XY_COLOR_BLT_WRITE_ALPHA;
449 }
450 else {
451 /* clearing RGBA */
452 CMD = (XY_COLOR_BLT_CMD |
453 XY_COLOR_BLT_WRITE_ALPHA |
454 XY_COLOR_BLT_WRITE_RGB);
455 }
456 }
457 else {
458 ASSERT(cpp == 2 || cpp == 0);
459 BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24);
460 CMD = XY_COLOR_BLT_CMD;
461 }
462
463 if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) {
464 clearVal = clear_depth;
465 }
466 else {
467 clearVal = (cpp == 4)
468 ? intel->ClearColor8888 : intel->ClearColor565;
469 }
470 /*
471 _mesa_debug(ctx, "hardware blit clear buf %d rb id %d\n",
472 buf, irb->Base.Name);
473 */
474 intel_wait_flips(intel, INTEL_BATCH_NO_CLIPRECTS);
475
476 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
477 OUT_BATCH(CMD);
478 OUT_BATCH(BR13);
479 OUT_BATCH((b.y1 << 16) | b.x1);
480 OUT_BATCH((b.y2 << 16) | b.x2);
481 OUT_RELOC(write_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
482 irb_region->draw_offset);
483 OUT_BATCH(clearVal);
484 ADVANCE_BATCH();
485 clearMask &= ~bufBit; /* turn off bit, for faster loop exit */
486 }
487 }
488 }
489 intel_batchbuffer_flush(intel->batch);
490 }
491
492 UNLOCK_HARDWARE(intel);
493 }