Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 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 "main/mtypes.h" |
||
30 | #include "main/context.h" |
||
31 | #include "main/enums.h" |
||
32 | #include "main/colormac.h" |
||
33 | #include "main/fbobject.h" |
||
34 | |||
35 | #include "intel_blit.h" |
||
36 | #include "intel_buffers.h" |
||
37 | #include "intel_context.h" |
||
38 | #include "intel_fbo.h" |
||
39 | #include "intel_reg.h" |
||
40 | #include "intel_regions.h" |
||
41 | #include "intel_batchbuffer.h" |
||
42 | #include "intel_mipmap_tree.h" |
||
43 | |||
44 | #define FILE_DEBUG_FLAG DEBUG_BLIT |
||
45 | |||
46 | static void |
||
47 | intel_miptree_set_alpha_to_one(struct intel_context *intel, |
||
48 | struct intel_mipmap_tree *mt, |
||
49 | int x, int y, int width, int height); |
||
50 | |||
51 | static GLuint translate_raster_op(GLenum logicop) |
||
52 | { |
||
53 | switch(logicop) { |
||
54 | case GL_CLEAR: return 0x00; |
||
55 | case GL_AND: return 0x88; |
||
56 | case GL_AND_REVERSE: return 0x44; |
||
57 | case GL_COPY: return 0xCC; |
||
58 | case GL_AND_INVERTED: return 0x22; |
||
59 | case GL_NOOP: return 0xAA; |
||
60 | case GL_XOR: return 0x66; |
||
61 | case GL_OR: return 0xEE; |
||
62 | case GL_NOR: return 0x11; |
||
63 | case GL_EQUIV: return 0x99; |
||
64 | case GL_INVERT: return 0x55; |
||
65 | case GL_OR_REVERSE: return 0xDD; |
||
66 | case GL_COPY_INVERTED: return 0x33; |
||
67 | case GL_OR_INVERTED: return 0xBB; |
||
68 | case GL_NAND: return 0x77; |
||
69 | case GL_SET: return 0xFF; |
||
70 | default: return 0; |
||
71 | } |
||
72 | } |
||
73 | |||
74 | static uint32_t |
||
75 | br13_for_cpp(int cpp) |
||
76 | { |
||
77 | switch (cpp) { |
||
78 | case 4: |
||
79 | return BR13_8888; |
||
80 | break; |
||
81 | case 2: |
||
82 | return BR13_565; |
||
83 | break; |
||
84 | case 1: |
||
85 | return BR13_8; |
||
86 | break; |
||
87 | default: |
||
88 | assert(0); |
||
89 | return 0; |
||
90 | } |
||
91 | } |
||
92 | |||
93 | /** |
||
94 | * Implements a rectangular block transfer (blit) of pixels between two |
||
95 | * miptrees. |
||
96 | * |
||
97 | * Our blitter can operate on 1, 2, or 4-byte-per-pixel data, with generous, |
||
98 | * but limited, pitches and sizes allowed. |
||
99 | * |
||
100 | * The src/dst coordinates are relative to the given level/slice of the |
||
101 | * miptree. |
||
102 | * |
||
103 | * If @src_flip or @dst_flip is set, then the rectangle within that miptree |
||
104 | * will be inverted (including scanline order) when copying. This is common |
||
105 | * in GL when copying between window system and user-created |
||
106 | * renderbuffers/textures. |
||
107 | */ |
||
108 | bool |
||
109 | intel_miptree_blit(struct intel_context *intel, |
||
110 | struct intel_mipmap_tree *src_mt, |
||
111 | int src_level, int src_slice, |
||
112 | uint32_t src_x, uint32_t src_y, bool src_flip, |
||
113 | struct intel_mipmap_tree *dst_mt, |
||
114 | int dst_level, int dst_slice, |
||
115 | uint32_t dst_x, uint32_t dst_y, bool dst_flip, |
||
116 | uint32_t width, uint32_t height, |
||
117 | GLenum logicop) |
||
118 | { |
||
119 | /* No sRGB decode or encode is done by the hardware blitter, which is |
||
120 | * consistent with what we want in the callers (glCopyTexSubImage(), |
||
121 | * glBlitFramebuffer(), texture validation, etc.). |
||
122 | */ |
||
123 | gl_format src_format = _mesa_get_srgb_format_linear(src_mt->format); |
||
124 | gl_format dst_format = _mesa_get_srgb_format_linear(dst_mt->format); |
||
125 | |||
126 | /* The blitter doesn't support doing any format conversions. We do also |
||
127 | * support blitting ARGB8888 to XRGB8888 (trivial, the values dropped into |
||
128 | * the X channel don't matter), and XRGB8888 to ARGB8888 by setting the A |
||
129 | * channel to 1.0 at the end. |
||
130 | */ |
||
131 | if (src_format != dst_format && |
||
132 | ((src_format != MESA_FORMAT_ARGB8888 && |
||
133 | src_format != MESA_FORMAT_XRGB8888) || |
||
134 | (dst_format != MESA_FORMAT_ARGB8888 && |
||
135 | dst_format != MESA_FORMAT_XRGB8888))) { |
||
136 | perf_debug("%s: Can't use hardware blitter from %s to %s, " |
||
137 | "falling back.\n", __FUNCTION__, |
||
138 | _mesa_get_format_name(src_format), |
||
139 | _mesa_get_format_name(dst_format)); |
||
140 | return false; |
||
141 | } |
||
142 | |||
143 | /* According to the Ivy Bridge PRM, Vol1 Part4, section 1.2.1.2 (Graphics |
||
144 | * Data Size Limitations): |
||
145 | * |
||
146 | * The BLT engine is capable of transferring very large quantities of |
||
147 | * graphics data. Any graphics data read from and written to the |
||
148 | * destination is permitted to represent a number of pixels that |
||
149 | * occupies up to 65,536 scan lines and up to 32,768 bytes per scan line |
||
150 | * at the destination. The maximum number of pixels that may be |
||
151 | * represented per scan line’s worth of graphics data depends on the |
||
152 | * color depth. |
||
153 | * |
||
154 | * Furthermore, intelEmitCopyBlit (which is called below) uses a signed |
||
155 | * 16-bit integer to represent buffer pitch, so it can only handle buffer |
||
156 | * pitches < 32k. |
||
157 | * |
||
158 | * As a result of these two limitations, we can only use the blitter to do |
||
159 | * this copy when the region's pitch is less than 32k. |
||
160 | */ |
||
161 | if (src_mt->region->pitch > 32768 || |
||
162 | dst_mt->region->pitch > 32768) { |
||
163 | perf_debug("Falling back due to >32k pitch\n"); |
||
164 | return false; |
||
165 | } |
||
166 | |||
167 | if (src_flip) |
||
168 | src_y = src_mt->level[src_level].height - src_y - height; |
||
169 | |||
170 | if (dst_flip) |
||
171 | dst_y = dst_mt->level[dst_level].height - dst_y - height; |
||
172 | |||
173 | int src_pitch = src_mt->region->pitch; |
||
174 | if (src_flip != dst_flip) |
||
175 | src_pitch = -src_pitch; |
||
176 | |||
177 | uint32_t src_image_x, src_image_y; |
||
178 | intel_miptree_get_image_offset(src_mt, src_level, src_slice, |
||
179 | &src_image_x, &src_image_y); |
||
180 | src_x += src_image_x; |
||
181 | src_y += src_image_y; |
||
182 | |||
183 | uint32_t dst_image_x, dst_image_y; |
||
184 | intel_miptree_get_image_offset(dst_mt, dst_level, dst_slice, |
||
185 | &dst_image_x, &dst_image_y); |
||
186 | dst_x += dst_image_x; |
||
187 | dst_y += dst_image_y; |
||
188 | |||
189 | if (!intelEmitCopyBlit(intel, |
||
190 | src_mt->cpp, |
||
191 | src_pitch, |
||
192 | src_mt->region->bo, src_mt->offset, |
||
193 | src_mt->region->tiling, |
||
194 | dst_mt->region->pitch, |
||
195 | dst_mt->region->bo, dst_mt->offset, |
||
196 | dst_mt->region->tiling, |
||
197 | src_x, src_y, |
||
198 | dst_x, dst_y, |
||
199 | width, height, |
||
200 | logicop)) { |
||
201 | return false; |
||
202 | } |
||
203 | |||
204 | if (src_mt->format == MESA_FORMAT_XRGB8888 && |
||
205 | dst_mt->format == MESA_FORMAT_ARGB8888) { |
||
206 | intel_miptree_set_alpha_to_one(intel, dst_mt, |
||
207 | dst_x, dst_y, |
||
208 | width, height); |
||
209 | } |
||
210 | |||
211 | return true; |
||
212 | } |
||
213 | |||
214 | /* Copy BitBlt |
||
215 | */ |
||
216 | bool |
||
217 | intelEmitCopyBlit(struct intel_context *intel, |
||
218 | GLuint cpp, |
||
219 | GLshort src_pitch, |
||
220 | drm_intel_bo *src_buffer, |
||
221 | GLuint src_offset, |
||
222 | uint32_t src_tiling, |
||
223 | GLshort dst_pitch, |
||
224 | drm_intel_bo *dst_buffer, |
||
225 | GLuint dst_offset, |
||
226 | uint32_t dst_tiling, |
||
227 | GLshort src_x, GLshort src_y, |
||
228 | GLshort dst_x, GLshort dst_y, |
||
229 | GLshort w, GLshort h, |
||
230 | GLenum logic_op) |
||
231 | { |
||
232 | GLuint CMD, BR13, pass = 0; |
||
233 | int dst_y2 = dst_y + h; |
||
234 | int dst_x2 = dst_x + w; |
||
235 | drm_intel_bo *aper_array[3]; |
||
236 | bool dst_y_tiled = dst_tiling == I915_TILING_Y; |
||
237 | bool src_y_tiled = src_tiling == I915_TILING_Y; |
||
238 | BATCH_LOCALS; |
||
239 | |||
240 | if (dst_tiling != I915_TILING_NONE) { |
||
241 | if (dst_offset & 4095) |
||
242 | return false; |
||
243 | } |
||
244 | if (src_tiling != I915_TILING_NONE) { |
||
245 | if (src_offset & 4095) |
||
246 | return false; |
||
247 | } |
||
248 | if (dst_y_tiled || src_y_tiled) |
||
249 | return false; |
||
250 | |||
251 | /* do space check before going any further */ |
||
252 | do { |
||
253 | aper_array[0] = intel->batch.bo; |
||
254 | aper_array[1] = dst_buffer; |
||
255 | aper_array[2] = src_buffer; |
||
256 | |||
257 | if (dri_bufmgr_check_aperture_space(aper_array, 3) != 0) { |
||
258 | intel_batchbuffer_flush(intel); |
||
259 | pass++; |
||
260 | } else |
||
261 | break; |
||
262 | } while (pass < 2); |
||
263 | |||
264 | if (pass >= 2) |
||
265 | return false; |
||
266 | |||
267 | intel_batchbuffer_require_space(intel, 8 * 4); |
||
268 | DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", |
||
269 | __FUNCTION__, |
||
270 | src_buffer, src_pitch, src_offset, src_x, src_y, |
||
271 | dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, w, h); |
||
272 | |||
273 | /* Blit pitch must be dword-aligned. Otherwise, the hardware appears to drop |
||
274 | * the low bits. |
||
275 | */ |
||
276 | if (src_pitch % 4 != 0 || dst_pitch % 4 != 0) |
||
277 | return false; |
||
278 | |||
279 | /* For big formats (such as floating point), do the copy using 16 or 32bpp |
||
280 | * and multiply the coordinates. |
||
281 | */ |
||
282 | if (cpp > 4) { |
||
283 | if (cpp % 4 == 2) { |
||
284 | dst_x *= cpp / 2; |
||
285 | dst_x2 *= cpp / 2; |
||
286 | src_x *= cpp / 2; |
||
287 | cpp = 2; |
||
288 | } else { |
||
289 | assert(cpp % 4 == 0); |
||
290 | dst_x *= cpp / 4; |
||
291 | dst_x2 *= cpp / 4; |
||
292 | src_x *= cpp / 4; |
||
293 | cpp = 4; |
||
294 | } |
||
295 | } |
||
296 | |||
297 | BR13 = br13_for_cpp(cpp) | translate_raster_op(logic_op) << 16; |
||
298 | |||
299 | switch (cpp) { |
||
300 | case 1: |
||
301 | case 2: |
||
302 | CMD = XY_SRC_COPY_BLT_CMD; |
||
303 | break; |
||
304 | case 4: |
||
305 | CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; |
||
306 | break; |
||
307 | default: |
||
308 | return false; |
||
309 | } |
||
310 | |||
311 | if (dst_y2 <= dst_y || dst_x2 <= dst_x) { |
||
312 | return true; |
||
313 | } |
||
314 | |||
315 | assert(dst_x < dst_x2); |
||
316 | assert(dst_y < dst_y2); |
||
317 | |||
318 | BEGIN_BATCH(8); |
||
319 | |||
320 | OUT_BATCH(CMD | (8 - 2)); |
||
321 | OUT_BATCH(BR13 | (uint16_t)dst_pitch); |
||
322 | OUT_BATCH((dst_y << 16) | dst_x); |
||
323 | OUT_BATCH((dst_y2 << 16) | dst_x2); |
||
324 | OUT_RELOC_FENCED(dst_buffer, |
||
325 | I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
||
326 | dst_offset); |
||
327 | OUT_BATCH((src_y << 16) | src_x); |
||
328 | OUT_BATCH((uint16_t)src_pitch); |
||
329 | OUT_RELOC_FENCED(src_buffer, |
||
330 | I915_GEM_DOMAIN_RENDER, 0, |
||
331 | src_offset); |
||
332 | |||
333 | ADVANCE_BATCH(); |
||
334 | |||
335 | intel_batchbuffer_emit_mi_flush(intel); |
||
336 | |||
337 | return true; |
||
338 | } |
||
339 | |||
340 | |||
341 | /** |
||
342 | * Use blitting to clear the renderbuffers named by 'flags'. |
||
343 | * Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferIndexes field |
||
344 | * since that might include software renderbuffers or renderbuffers |
||
345 | * which we're clearing with triangles. |
||
346 | * \param mask bitmask of BUFFER_BIT_* values indicating buffers to clear |
||
347 | */ |
||
348 | GLbitfield |
||
349 | intelClearWithBlit(struct gl_context *ctx, GLbitfield mask) |
||
350 | { |
||
351 | struct intel_context *intel = intel_context(ctx); |
||
352 | struct gl_framebuffer *fb = ctx->DrawBuffer; |
||
353 | GLuint clear_depth_value, clear_depth_mask; |
||
354 | GLint cx, cy, cw, ch; |
||
355 | GLbitfield fail_mask = 0; |
||
356 | BATCH_LOCALS; |
||
357 | |||
358 | /* Note: we don't use this function on Gen7+ hardware, so we can safely |
||
359 | * ignore fast color clear issues. |
||
360 | */ |
||
361 | assert(intel->gen < 7); |
||
362 | |||
363 | /* |
||
364 | * Compute values for clearing the buffers. |
||
365 | */ |
||
366 | clear_depth_value = 0; |
||
367 | clear_depth_mask = 0; |
||
368 | if (mask & BUFFER_BIT_DEPTH) { |
||
369 | clear_depth_value = (GLuint) (fb->_DepthMax * ctx->Depth.Clear); |
||
370 | clear_depth_mask = XY_BLT_WRITE_RGB; |
||
371 | } |
||
372 | if (mask & BUFFER_BIT_STENCIL) { |
||
373 | clear_depth_value |= (ctx->Stencil.Clear & 0xff) << 24; |
||
374 | clear_depth_mask |= XY_BLT_WRITE_ALPHA; |
||
375 | } |
||
376 | |||
377 | cx = fb->_Xmin; |
||
378 | if (_mesa_is_winsys_fbo(fb)) |
||
379 | cy = ctx->DrawBuffer->Height - fb->_Ymax; |
||
380 | else |
||
381 | cy = fb->_Ymin; |
||
382 | cw = fb->_Xmax - fb->_Xmin; |
||
383 | ch = fb->_Ymax - fb->_Ymin; |
||
384 | |||
385 | if (cw == 0 || ch == 0) |
||
386 | return 0; |
||
387 | |||
388 | /* Loop over all renderbuffers */ |
||
389 | mask &= (1 << BUFFER_COUNT) - 1; |
||
390 | while (mask) { |
||
391 | GLuint buf = ffs(mask) - 1; |
||
392 | bool is_depth_stencil = buf == BUFFER_DEPTH || buf == BUFFER_STENCIL; |
||
393 | struct intel_renderbuffer *irb; |
||
394 | int x1, y1, x2, y2; |
||
395 | uint32_t clear_val; |
||
396 | uint32_t BR13, CMD; |
||
397 | struct intel_region *region; |
||
398 | int pitch, cpp; |
||
399 | drm_intel_bo *aper_array[2]; |
||
400 | |||
401 | mask &= ~(1 << buf); |
||
402 | |||
403 | irb = intel_get_renderbuffer(fb, buf); |
||
404 | if (irb && irb->mt) { |
||
405 | region = irb->mt->region; |
||
406 | assert(region); |
||
407 | assert(region->bo); |
||
408 | } else { |
||
409 | fail_mask |= 1 << buf; |
||
410 | continue; |
||
411 | } |
||
412 | |||
413 | /* OK, clear this renderbuffer */ |
||
414 | x1 = cx + irb->draw_x; |
||
415 | y1 = cy + irb->draw_y; |
||
416 | x2 = cx + cw + irb->draw_x; |
||
417 | y2 = cy + ch + irb->draw_y; |
||
418 | |||
419 | pitch = region->pitch; |
||
420 | cpp = region->cpp; |
||
421 | |||
422 | DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n", |
||
423 | __FUNCTION__, |
||
424 | region->bo, pitch, |
||
425 | x1, y1, x2 - x1, y2 - y1); |
||
426 | |||
427 | BR13 = 0xf0 << 16; |
||
428 | CMD = XY_COLOR_BLT_CMD; |
||
429 | |||
430 | /* Setup the blit command */ |
||
431 | if (cpp == 4) { |
||
432 | if (is_depth_stencil) { |
||
433 | CMD |= clear_depth_mask; |
||
434 | } else { |
||
435 | /* clearing RGBA */ |
||
436 | CMD |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; |
||
437 | } |
||
438 | } |
||
439 | |||
440 | assert(region->tiling != I915_TILING_Y); |
||
441 | |||
442 | BR13 |= pitch; |
||
443 | |||
444 | if (is_depth_stencil) { |
||
445 | clear_val = clear_depth_value; |
||
446 | } else { |
||
447 | uint8_t clear[4]; |
||
448 | GLfloat *color = ctx->Color.ClearColor.f; |
||
449 | |||
450 | _mesa_unclamped_float_rgba_to_ubyte(clear, color); |
||
451 | |||
452 | switch (intel_rb_format(irb)) { |
||
453 | case MESA_FORMAT_ARGB8888: |
||
454 | case MESA_FORMAT_XRGB8888: |
||
455 | clear_val = PACK_COLOR_8888(clear[3], clear[0], |
||
456 | clear[1], clear[2]); |
||
457 | break; |
||
458 | case MESA_FORMAT_RGB565: |
||
459 | clear_val = PACK_COLOR_565(clear[0], clear[1], clear[2]); |
||
460 | break; |
||
461 | case MESA_FORMAT_ARGB4444: |
||
462 | clear_val = PACK_COLOR_4444(clear[3], clear[0], |
||
463 | clear[1], clear[2]); |
||
464 | break; |
||
465 | case MESA_FORMAT_ARGB1555: |
||
466 | clear_val = PACK_COLOR_1555(clear[3], clear[0], |
||
467 | clear[1], clear[2]); |
||
468 | break; |
||
469 | case MESA_FORMAT_A8: |
||
470 | clear_val = PACK_COLOR_8888(clear[3], clear[3], |
||
471 | clear[3], clear[3]); |
||
472 | break; |
||
473 | default: |
||
474 | fail_mask |= 1 << buf; |
||
475 | continue; |
||
476 | } |
||
477 | } |
||
478 | |||
479 | BR13 |= br13_for_cpp(cpp); |
||
480 | |||
481 | assert(x1 < x2); |
||
482 | assert(y1 < y2); |
||
483 | |||
484 | /* do space check before going any further */ |
||
485 | aper_array[0] = intel->batch.bo; |
||
486 | aper_array[1] = region->bo; |
||
487 | |||
488 | if (drm_intel_bufmgr_check_aperture_space(aper_array, |
||
489 | ARRAY_SIZE(aper_array)) != 0) { |
||
490 | intel_batchbuffer_flush(intel); |
||
491 | } |
||
492 | |||
493 | BEGIN_BATCH(6); |
||
494 | OUT_BATCH(CMD | (6 - 2)); |
||
495 | OUT_BATCH(BR13); |
||
496 | OUT_BATCH((y1 << 16) | x1); |
||
497 | OUT_BATCH((y2 << 16) | x2); |
||
498 | OUT_RELOC_FENCED(region->bo, |
||
499 | I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
||
500 | 0); |
||
501 | OUT_BATCH(clear_val); |
||
502 | ADVANCE_BATCH(); |
||
503 | |||
504 | if (intel->always_flush_cache) |
||
505 | intel_batchbuffer_emit_mi_flush(intel); |
||
506 | |||
507 | if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) |
||
508 | mask &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL); |
||
509 | } |
||
510 | |||
511 | return fail_mask; |
||
512 | } |
||
513 | |||
514 | bool |
||
515 | intelEmitImmediateColorExpandBlit(struct intel_context *intel, |
||
516 | GLuint cpp, |
||
517 | GLubyte *src_bits, GLuint src_size, |
||
518 | GLuint fg_color, |
||
519 | GLshort dst_pitch, |
||
520 | drm_intel_bo *dst_buffer, |
||
521 | GLuint dst_offset, |
||
522 | uint32_t dst_tiling, |
||
523 | GLshort x, GLshort y, |
||
524 | GLshort w, GLshort h, |
||
525 | GLenum logic_op) |
||
526 | { |
||
527 | int dwords = ALIGN(src_size, 8) / 4; |
||
528 | uint32_t opcode, br13, blit_cmd; |
||
529 | |||
530 | if (dst_tiling != I915_TILING_NONE) { |
||
531 | if (dst_offset & 4095) |
||
532 | return false; |
||
533 | if (dst_tiling == I915_TILING_Y) |
||
534 | return false; |
||
535 | } |
||
536 | |||
537 | assert( logic_op - GL_CLEAR >= 0 ); |
||
538 | assert( logic_op - GL_CLEAR < 0x10 ); |
||
539 | assert(dst_pitch > 0); |
||
540 | |||
541 | if (w < 0 || h < 0) |
||
542 | return true; |
||
543 | |||
544 | DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d, %d bytes %d dwords\n", |
||
545 | __FUNCTION__, |
||
546 | dst_buffer, dst_pitch, dst_offset, x, y, w, h, src_size, dwords); |
||
547 | |||
548 | intel_batchbuffer_require_space(intel, |
||
549 | (8 * 4) + |
||
550 | (3 * 4) + |
||
551 | dwords * 4); |
||
552 | |||
553 | opcode = XY_SETUP_BLT_CMD; |
||
554 | if (cpp == 4) |
||
555 | opcode |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; |
||
556 | |||
557 | br13 = dst_pitch | (translate_raster_op(logic_op) << 16) | (1 << 29); |
||
558 | br13 |= br13_for_cpp(cpp); |
||
559 | |||
560 | blit_cmd = XY_TEXT_IMMEDIATE_BLIT_CMD | XY_TEXT_BYTE_PACKED; /* packing? */ |
||
561 | if (dst_tiling != I915_TILING_NONE) |
||
562 | blit_cmd |= XY_DST_TILED; |
||
563 | |||
564 | BEGIN_BATCH(8 + 3); |
||
565 | OUT_BATCH(opcode | (8 - 2)); |
||
566 | OUT_BATCH(br13); |
||
567 | OUT_BATCH((0 << 16) | 0); /* clip x1, y1 */ |
||
568 | OUT_BATCH((100 << 16) | 100); /* clip x2, y2 */ |
||
569 | OUT_RELOC_FENCED(dst_buffer, |
||
570 | I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
||
571 | dst_offset); |
||
572 | OUT_BATCH(0); /* bg */ |
||
573 | OUT_BATCH(fg_color); /* fg */ |
||
574 | OUT_BATCH(0); /* pattern base addr */ |
||
575 | |||
576 | OUT_BATCH(blit_cmd | ((3 - 2) + dwords)); |
||
577 | OUT_BATCH((y << 16) | x); |
||
578 | OUT_BATCH(((y + h) << 16) | (x + w)); |
||
579 | ADVANCE_BATCH(); |
||
580 | |||
581 | intel_batchbuffer_data(intel, src_bits, dwords * 4); |
||
582 | |||
583 | intel_batchbuffer_emit_mi_flush(intel); |
||
584 | |||
585 | return true; |
||
586 | } |
||
587 | |||
588 | /* We don't have a memmove-type blit like some other hardware, so we'll do a |
||
589 | * rectangular blit covering a large space, then emit 1-scanline blit at the |
||
590 | * end to cover the last if we need. |
||
591 | */ |
||
592 | void |
||
593 | intel_emit_linear_blit(struct intel_context *intel, |
||
594 | drm_intel_bo *dst_bo, |
||
595 | unsigned int dst_offset, |
||
596 | drm_intel_bo *src_bo, |
||
597 | unsigned int src_offset, |
||
598 | unsigned int size) |
||
599 | { |
||
600 | struct gl_context *ctx = &intel->ctx; |
||
601 | GLuint pitch, height; |
||
602 | bool ok; |
||
603 | |||
604 | /* The pitch given to the GPU must be DWORD aligned, and |
||
605 | * we want width to match pitch. Max width is (1 << 15 - 1), |
||
606 | * rounding that down to the nearest DWORD is 1 << 15 - 4 |
||
607 | */ |
||
608 | pitch = ROUND_DOWN_TO(MIN2(size, (1 << 15) - 1), 4); |
||
609 | height = (pitch == 0) ? 1 : size / pitch; |
||
610 | ok = intelEmitCopyBlit(intel, 1, |
||
611 | pitch, src_bo, src_offset, I915_TILING_NONE, |
||
612 | pitch, dst_bo, dst_offset, I915_TILING_NONE, |
||
613 | 0, 0, /* src x/y */ |
||
614 | 0, 0, /* dst x/y */ |
||
615 | pitch, height, /* w, h */ |
||
616 | GL_COPY); |
||
617 | if (!ok) |
||
618 | _mesa_problem(ctx, "Failed to linear blit %dx%d\n", pitch, height); |
||
619 | |||
620 | src_offset += pitch * height; |
||
621 | dst_offset += pitch * height; |
||
622 | size -= pitch * height; |
||
623 | assert (size < (1 << 15)); |
||
624 | pitch = ALIGN(size, 4); |
||
625 | if (size != 0) { |
||
626 | ok = intelEmitCopyBlit(intel, 1, |
||
627 | pitch, src_bo, src_offset, I915_TILING_NONE, |
||
628 | pitch, dst_bo, dst_offset, I915_TILING_NONE, |
||
629 | 0, 0, /* src x/y */ |
||
630 | 0, 0, /* dst x/y */ |
||
631 | size, 1, /* w, h */ |
||
632 | GL_COPY); |
||
633 | if (!ok) |
||
634 | _mesa_problem(ctx, "Failed to linear blit %dx%d\n", size, 1); |
||
635 | } |
||
636 | } |
||
637 | |||
638 | /** |
||
639 | * Used to initialize the alpha value of an ARGB8888 miptree after copying |
||
640 | * into it from an XRGB8888 source. |
||
641 | * |
||
642 | * This is very common with glCopyTexImage2D(). Note that the coordinates are |
||
643 | * relative to the start of the miptree, not relative to a slice within the |
||
644 | * miptree. |
||
645 | */ |
||
646 | static void |
||
647 | intel_miptree_set_alpha_to_one(struct intel_context *intel, |
||
648 | struct intel_mipmap_tree *mt, |
||
649 | int x, int y, int width, int height) |
||
650 | { |
||
651 | struct intel_region *region = mt->region; |
||
652 | uint32_t BR13, CMD; |
||
653 | int pitch, cpp; |
||
654 | drm_intel_bo *aper_array[2]; |
||
655 | BATCH_LOCALS; |
||
656 | |||
657 | pitch = region->pitch; |
||
658 | cpp = region->cpp; |
||
659 | |||
660 | DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n", |
||
661 | __FUNCTION__, region->bo, pitch, x, y, width, height); |
||
662 | |||
663 | BR13 = br13_for_cpp(cpp) | 0xf0 << 16; |
||
664 | CMD = XY_COLOR_BLT_CMD; |
||
665 | CMD |= XY_BLT_WRITE_ALPHA; |
||
666 | |||
667 | BR13 |= pitch; |
||
668 | |||
669 | /* do space check before going any further */ |
||
670 | aper_array[0] = intel->batch.bo; |
||
671 | aper_array[1] = region->bo; |
||
672 | |||
673 | if (drm_intel_bufmgr_check_aperture_space(aper_array, |
||
674 | ARRAY_SIZE(aper_array)) != 0) { |
||
675 | intel_batchbuffer_flush(intel); |
||
676 | } |
||
677 | |||
678 | BEGIN_BATCH(6); |
||
679 | OUT_BATCH(CMD | (6 - 2)); |
||
680 | OUT_BATCH(BR13); |
||
681 | OUT_BATCH((y << 16) | x); |
||
682 | OUT_BATCH(((y + height) << 16) | (x + width)); |
||
683 | OUT_RELOC_FENCED(region->bo, |
||
684 | I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
||
685 | 0); |
||
686 | OUT_BATCH(0xffffffff); /* white, but only alpha gets written */ |
||
687 | ADVANCE_BATCH(); |
||
688 | |||
689 | intel_batchbuffer_emit_mi_flush(intel); |
||
690 | }><>><>><>><>>><>><>><>><>><>><>><>><>><>>>>><>><>>>><>><>><>><>><>><>>><>><>><>>>=>=>><>>> |