8cdd9e98590260155d414dca59cc4141b694fa93
[mesa.git] / src / mesa / drivers / common / meta_blit.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2009 VMware, Inc. 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 "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 #include "main/glheader.h"
26 #include "main/mtypes.h"
27 #include "main/arbprogram.h"
28 #include "main/arrayobj.h"
29 #include "main/blend.h"
30 #include "main/condrender.h"
31 #include "main/depth.h"
32 #include "main/enable.h"
33 #include "main/enums.h"
34 #include "main/fbobject.h"
35 #include "main/image.h"
36 #include "main/macros.h"
37 #include "main/matrix.h"
38 #include "main/multisample.h"
39 #include "main/objectlabel.h"
40 #include "main/readpix.h"
41 #include "main/scissor.h"
42 #include "main/shaderapi.h"
43 #include "main/texobj.h"
44 #include "main/texenv.h"
45 #include "main/teximage.h"
46 #include "main/texparam.h"
47 #include "main/uniforms.h"
48 #include "main/varray.h"
49 #include "main/viewport.h"
50 #include "swrast/swrast.h"
51 #include "drivers/common/meta.h"
52 #include "util/ralloc.h"
53
54 static struct gl_texture_object *
55 texture_object_from_renderbuffer(struct gl_context *, struct gl_renderbuffer *);
56
57 /** Return offset in bytes of the field within a vertex struct */
58 #define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD))
59
60 static void
61 setup_glsl_msaa_blit_shader(struct gl_context *ctx,
62 struct blit_state *blit,
63 const struct gl_framebuffer *drawFb,
64 struct gl_renderbuffer *src_rb,
65 GLenum target)
66 {
67 const char *vs_source;
68 char *fs_source;
69 void *mem_ctx;
70 enum blit_msaa_shader shader_index;
71 bool dst_is_msaa = false;
72 GLenum src_datatype;
73 const char *vec4_prefix;
74 const char *sampler_array_suffix = "";
75 char *name;
76 const char *texcoord_type = "vec2";
77 int samples;
78 int shader_offset = 0;
79
80 if (src_rb) {
81 samples = MAX2(src_rb->NumSamples, 1);
82 src_datatype = _mesa_get_format_datatype(src_rb->Format);
83 } else {
84 /* depth-or-color glCopyTexImage fallback path that passes a NULL rb and
85 * doesn't handle integer.
86 */
87 samples = 1;
88 src_datatype = GL_UNSIGNED_NORMALIZED;
89 }
90
91 /* We expect only power of 2 samples in source multisample buffer. */
92 assert(samples > 0 && util_is_power_of_two_nonzero(samples));
93 while (samples >> (shader_offset + 1)) {
94 shader_offset++;
95 }
96 /* Update the assert if we plan to support more than 16X MSAA. */
97 assert(shader_offset >= 0 && shader_offset <= 4);
98
99 if (drawFb->Visual.samples > 1) {
100 /* If you're calling meta_BlitFramebuffer with the destination
101 * multisampled, this is the only path that will work -- swrast and
102 * CopyTexImage won't work on it either.
103 */
104 assert(ctx->Extensions.ARB_sample_shading);
105
106 dst_is_msaa = true;
107
108 /* We need shader invocation per sample, not per pixel */
109 _mesa_set_enable(ctx, GL_MULTISAMPLE, GL_TRUE);
110 _mesa_set_enable(ctx, GL_SAMPLE_SHADING, GL_TRUE);
111 _mesa_MinSampleShading(1.0);
112 }
113
114 switch (target) {
115 case GL_TEXTURE_2D_MULTISAMPLE:
116 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
117 if (src_rb && (src_rb->_BaseFormat == GL_DEPTH_COMPONENT ||
118 src_rb->_BaseFormat == GL_DEPTH_STENCIL)) {
119 if (dst_is_msaa)
120 shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_COPY;
121 else
122 shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_RESOLVE;
123 } else {
124 if (dst_is_msaa)
125 shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_COPY;
126 else {
127 shader_index = BLIT_1X_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE +
128 shader_offset;
129 }
130 }
131
132 if (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) {
133 shader_index += (BLIT_1X_MSAA_SHADER_2D_MULTISAMPLE_ARRAY_RESOLVE -
134 BLIT_1X_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE);
135 sampler_array_suffix = "Array";
136 texcoord_type = "vec3";
137 }
138 break;
139 default:
140 _mesa_problem(ctx, "Unknown texture target %s\n",
141 _mesa_enum_to_string(target));
142 shader_index = BLIT_2X_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE;
143 }
144
145 /* We rely on the enum being sorted this way. */
146 STATIC_ASSERT(BLIT_1X_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_INT ==
147 BLIT_1X_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE + 5);
148 STATIC_ASSERT(BLIT_1X_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_UINT ==
149 BLIT_1X_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE + 10);
150 if (src_datatype == GL_INT) {
151 shader_index += 5;
152 vec4_prefix = "i";
153 } else if (src_datatype == GL_UNSIGNED_INT) {
154 shader_index += 10;
155 vec4_prefix = "u";
156 } else {
157 vec4_prefix = "";
158 }
159
160 if (blit->msaa_shaders[shader_index]) {
161 _mesa_meta_use_program(ctx, blit->msaa_shaders[shader_index]);
162 return;
163 }
164
165 mem_ctx = ralloc_context(NULL);
166
167 if (shader_index == BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_RESOLVE ||
168 shader_index == BLIT_MSAA_SHADER_2D_MULTISAMPLE_ARRAY_DEPTH_RESOLVE ||
169 shader_index == BLIT_MSAA_SHADER_2D_MULTISAMPLE_ARRAY_DEPTH_COPY ||
170 shader_index == BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_COPY) {
171 char *sample_index;
172 const char *tex_coords = "texCoords";
173
174 if (dst_is_msaa) {
175 sample_index = "gl_SampleID";
176 name = "depth MSAA copy";
177
178 if (ctx->Extensions.ARB_gpu_shader5 && samples >= 16) {
179 /* See comment below for the color copy */
180 tex_coords = "interpolateAtOffset(texCoords, vec2(0.0))";
181 }
182 } else {
183 /* From the GL 4.3 spec:
184 *
185 * "If there is a multisample buffer (the value of SAMPLE_BUFFERS
186 * is one), then values are obtained from the depth samples in
187 * this buffer. It is recommended that the depth value of the
188 * centermost sample be used, though implementations may choose
189 * any function of the depth sample values at each pixel.
190 *
191 * We're slacking and instead of choosing centermost, we've got 0.
192 */
193 sample_index = "0";
194 name = "depth MSAA resolve";
195 }
196
197 vs_source = ralloc_asprintf(mem_ctx,
198 "#version 130\n"
199 "#extension GL_ARB_explicit_attrib_location: enable\n"
200 "layout(location = 0) in vec2 position;\n"
201 "layout(location = 1) in %s textureCoords;\n"
202 "out %s texCoords;\n"
203 "void main()\n"
204 "{\n"
205 " texCoords = textureCoords;\n"
206 " gl_Position = vec4(position, 0.0, 1.0);\n"
207 "}\n",
208 texcoord_type,
209 texcoord_type);
210 fs_source = ralloc_asprintf(mem_ctx,
211 "#version 130\n"
212 "#extension GL_ARB_texture_multisample : enable\n"
213 "#extension GL_ARB_sample_shading : enable\n"
214 "#extension GL_ARB_gpu_shader5 : enable\n"
215 "uniform sampler2DMS%s texSampler;\n"
216 "in %s texCoords;\n"
217 "out vec4 out_color;\n"
218 "\n"
219 "void main()\n"
220 "{\n"
221 " gl_FragDepth = texelFetch(texSampler, i%s(%s), %s).r;\n"
222 "}\n",
223 sampler_array_suffix,
224 texcoord_type,
225 texcoord_type,
226 tex_coords,
227 sample_index);
228 } else {
229 /* You can create 2D_MULTISAMPLE textures with 0 sample count (meaning 1
230 * sample). Yes, this is ridiculous.
231 */
232 char *sample_resolve;
233 const char *merge_function;
234 name = ralloc_asprintf(mem_ctx, "%svec4 MSAA %s",
235 vec4_prefix,
236 dst_is_msaa ? "copy" : "resolve");
237
238 if (dst_is_msaa) {
239 const char *tex_coords;
240
241 if (ctx->Extensions.ARB_gpu_shader5 && samples >= 16) {
242 /* If interpolateAtOffset is available then it will be used to
243 * force the interpolation to the center. This is required at
244 * least on Intel hardware because it is possible to have a sample
245 * position on the 0 x or y axis which means it will lie exactly
246 * on the pixel boundary. If we let the hardware interpolate the
247 * coordinates at one of these positions then it is possible for
248 * it to jump to a neighboring texel when converting to ints due
249 * to rounding errors. This is only done for >= 16x MSAA because
250 * it probably has some overhead. It is more likely that some
251 * hardware will use one of these problematic positions at 16x
252 * MSAA because in that case in D3D they are defined to be at
253 * these positions.
254 */
255 tex_coords = "interpolateAtOffset(texCoords, vec2(0.0))";
256 } else {
257 tex_coords = "texCoords";
258 }
259
260 sample_resolve =
261 ralloc_asprintf(mem_ctx,
262 " out_color = texelFetch(texSampler, "
263 "i%s(%s), gl_SampleID);",
264 texcoord_type, tex_coords);
265
266 merge_function = "";
267 } else {
268 int i;
269 int step;
270
271 if (src_datatype == GL_INT || src_datatype == GL_UNSIGNED_INT) {
272 /* From the OpenGL ES 3.2 spec section 16.2.1:
273 *
274 * "If the source formats are integer types or stencil values,
275 * a single sample's value is selected for each pixel."
276 *
277 * The OpenGL 4.4 spec contains exactly the same language.
278 *
279 * We can accomplish this by making the merge function return just
280 * one of the two samples. The compiler should do the rest.
281 */
282 merge_function = "gvec4 merge(gvec4 a, gvec4 b) { return a; }\n";
283 } else {
284 /* The divide will happen at the end for floats. */
285 merge_function =
286 "vec4 merge(vec4 a, vec4 b) { return (a + b); }\n";
287 }
288
289 /* We're assuming power of two samples for this resolution procedure.
290 *
291 * To avoid losing any floating point precision if the samples all
292 * happen to have the same value, we merge pairs of values at a time
293 * (so the floating point exponent just gets increased), rather than
294 * doing a naive sum and dividing.
295 */
296 assert(util_is_power_of_two_or_zero(samples));
297 /* Fetch each individual sample. */
298 sample_resolve = rzalloc_size(mem_ctx, 1);
299 for (i = 0; i < samples; i++) {
300 ralloc_asprintf_append(&sample_resolve,
301 " gvec4 sample_1_%d = texelFetch(texSampler, i%s(texCoords), %d);\n",
302 i, texcoord_type, i);
303 }
304 /* Now, merge each pair of samples, then merge each pair of those,
305 * etc.
306 */
307 for (step = 2; step <= samples; step *= 2) {
308 for (i = 0; i < samples; i += step) {
309 ralloc_asprintf_append(&sample_resolve,
310 " gvec4 sample_%d_%d = merge(sample_%d_%d, sample_%d_%d);\n",
311 step, i,
312 step / 2, i,
313 step / 2, i + step / 2);
314 }
315 }
316
317 /* Scale the final result. */
318 if (src_datatype == GL_UNSIGNED_INT || src_datatype == GL_INT) {
319 ralloc_asprintf_append(&sample_resolve,
320 " out_color = sample_%d_0;\n",
321 samples);
322 } else {
323 ralloc_asprintf_append(&sample_resolve,
324 " gl_FragColor = sample_%d_0 / %f;\n",
325 samples, (float)samples);
326 }
327 }
328
329 vs_source = ralloc_asprintf(mem_ctx,
330 "#version 130\n"
331 "#extension GL_ARB_explicit_attrib_location: enable\n"
332 "layout(location = 0) in vec2 position;\n"
333 "layout(location = 1) in %s textureCoords;\n"
334 "out %s texCoords;\n"
335 "void main()\n"
336 "{\n"
337 " texCoords = textureCoords;\n"
338 " gl_Position = vec4(position, 0.0, 1.0);\n"
339 "}\n",
340 texcoord_type,
341 texcoord_type);
342 fs_source = ralloc_asprintf(mem_ctx,
343 "#version 130\n"
344 "#extension GL_ARB_texture_multisample : enable\n"
345 "#extension GL_ARB_sample_shading : enable\n"
346 "#extension GL_ARB_gpu_shader5 : enable\n"
347 "#define gvec4 %svec4\n"
348 "uniform %ssampler2DMS%s texSampler;\n"
349 "in %s texCoords;\n"
350 "out gvec4 out_color;\n"
351 "\n"
352 "%s" /* merge_function */
353 "void main()\n"
354 "{\n"
355 "%s\n" /* sample_resolve */
356 "}\n",
357 vec4_prefix,
358 vec4_prefix,
359 sampler_array_suffix,
360 texcoord_type,
361 merge_function,
362 sample_resolve);
363 }
364
365 _mesa_meta_compile_and_link_program(ctx, vs_source, fs_source, name,
366 &blit->msaa_shaders[shader_index]);
367
368 ralloc_free(mem_ctx);
369 }
370
371 static void
372 setup_glsl_blit_framebuffer(struct gl_context *ctx,
373 struct blit_state *blit,
374 const struct gl_framebuffer *drawFb,
375 struct gl_renderbuffer *src_rb,
376 GLenum target, GLenum filter,
377 bool is_scaled_blit,
378 bool do_depth)
379 {
380 unsigned texcoord_size;
381 bool is_target_multisample = target == GL_TEXTURE_2D_MULTISAMPLE ||
382 target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
383
384 /* target = GL_TEXTURE_RECTANGLE is not supported in GLES 3.0 */
385 assert(_mesa_is_desktop_gl(ctx) || target == GL_TEXTURE_2D);
386
387 texcoord_size = 2 + (src_rb->Depth > 1 ? 1 : 0);
388
389 _mesa_meta_setup_vertex_objects(ctx, &blit->VAO, &blit->buf_obj, true,
390 2, texcoord_size, 0);
391
392 if (is_target_multisample) {
393 setup_glsl_msaa_blit_shader(ctx, blit, drawFb, src_rb, target);
394 } else {
395 _mesa_meta_setup_blit_shader(ctx, target, do_depth,
396 do_depth ? &blit->shaders_with_depth
397 : &blit->shaders_without_depth);
398 }
399 }
400
401 /**
402 * Try to do a color or depth glBlitFramebuffer using texturing.
403 *
404 * We can do this when the src renderbuffer is actually a texture, or when the
405 * driver exposes BindRenderbufferTexImage().
406 */
407 static bool
408 blitframebuffer_texture(struct gl_context *ctx,
409 const struct gl_framebuffer *readFb,
410 const struct gl_framebuffer *drawFb,
411 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
412 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
413 GLenum filter, GLint flipX, GLint flipY,
414 GLboolean glsl_version, GLboolean do_depth)
415 {
416 int att_index = do_depth ? BUFFER_DEPTH : readFb->_ColorReadBufferIndex;
417 const struct gl_renderbuffer_attachment *readAtt =
418 &readFb->Attachment[att_index];
419 struct blit_state *blit = &ctx->Meta->Blit;
420 struct fb_tex_blit_state fb_tex_blit;
421 const GLint dstX = MIN2(dstX0, dstX1);
422 const GLint dstY = MIN2(dstY0, dstY1);
423 const GLint dstW = abs(dstX1 - dstX0);
424 const GLint dstH = abs(dstY1 - dstY0);
425 const int srcW = abs(srcX1 - srcX0);
426 const int srcH = abs(srcY1 - srcY0);
427 bool scaled_blit = false;
428 struct gl_texture_object *texObj;
429 GLuint srcLevel;
430 GLenum target;
431 struct gl_renderbuffer *rb = readAtt->Renderbuffer;
432 struct temp_texture *meta_temp_texture;
433
434 if (rb->NumSamples && !ctx->Extensions.ARB_texture_multisample)
435 return false;
436
437 _mesa_meta_fb_tex_blit_begin(ctx, &fb_tex_blit);
438
439 if (readAtt->Texture &&
440 (readAtt->Texture->Target == GL_TEXTURE_2D ||
441 readAtt->Texture->Target == GL_TEXTURE_RECTANGLE ||
442 readAtt->Texture->Target == GL_TEXTURE_2D_MULTISAMPLE ||
443 readAtt->Texture->Target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) {
444 /* If there's a texture attached of a type we can handle, then just use
445 * it directly.
446 */
447 srcLevel = readAtt->TextureLevel;
448 texObj = readAtt->Texture;
449 } else if (!readAtt->Texture && ctx->Driver.BindRenderbufferTexImage) {
450 texObj = texture_object_from_renderbuffer(ctx, rb);
451 if (texObj == NULL)
452 return false;
453
454 fb_tex_blit.temp_tex_obj = texObj;
455
456 srcLevel = 0;
457 if (_mesa_is_winsys_fbo(readFb)) {
458 GLint temp = srcY0;
459 srcY0 = rb->Height - srcY1;
460 srcY1 = rb->Height - temp;
461 flipY = -flipY;
462 }
463 } else {
464 GLenum tex_base_format;
465 /* Fall back to doing a CopyTexSubImage to get the destination
466 * renderbuffer into a texture.
467 */
468 if (ctx->Meta->Blit.no_ctsi_fallback)
469 return false;
470
471 if (rb->NumSamples > 1)
472 return false;
473
474 if (do_depth) {
475 meta_temp_texture = _mesa_meta_get_temp_depth_texture(ctx);
476 tex_base_format = GL_DEPTH_COMPONENT;
477 } else {
478 meta_temp_texture = _mesa_meta_get_temp_texture(ctx);
479 tex_base_format =
480 _mesa_base_tex_format(ctx, rb->InternalFormat);
481 }
482
483 srcLevel = 0;
484 texObj = meta_temp_texture->tex_obj;
485 if (texObj == NULL) {
486 return false;
487 }
488
489 _mesa_meta_setup_copypix_texture(ctx, meta_temp_texture,
490 srcX0, srcY0,
491 srcW, srcH,
492 tex_base_format,
493 filter);
494
495 assert(texObj->Target == meta_temp_texture->Target);
496
497 srcX0 = 0;
498 srcY0 = 0;
499 srcX1 = srcW;
500 srcY1 = srcH;
501 }
502
503 target = texObj->Target;
504 fb_tex_blit.tex_obj = texObj;
505 fb_tex_blit.baseLevelSave = texObj->BaseLevel;
506 fb_tex_blit.maxLevelSave = texObj->MaxLevel;
507 fb_tex_blit.stencilSamplingSave = texObj->StencilSampling;
508
509 scaled_blit = dstW != srcW || dstH != srcH;
510
511 if (glsl_version) {
512 setup_glsl_blit_framebuffer(ctx, blit, drawFb, rb, target, filter, scaled_blit,
513 do_depth);
514 }
515 else {
516 _mesa_meta_setup_ff_tnl_for_blit(ctx,
517 &ctx->Meta->Blit.VAO,
518 &ctx->Meta->Blit.buf_obj,
519 2);
520 }
521
522 /*
523 printf("Blit from texture!\n");
524 printf(" srcAtt %p dstAtt %p\n", readAtt, drawAtt);
525 printf(" srcTex %p dstText %p\n", texObj, drawAtt->Texture);
526 */
527
528 fb_tex_blit.samp_obj = _mesa_meta_setup_sampler(ctx, texObj, target, filter,
529 srcLevel);
530
531 if (ctx->Extensions.EXT_texture_sRGB_decode) {
532 /* The GL 4.4 spec, section 18.3.1 ("Blitting Pixel Rectangles") says:
533 *
534 * "When values are taken from the read buffer, if FRAMEBUFFER_SRGB
535 * is enabled and the value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING
536 * for the framebuffer attachment corresponding to the read buffer
537 * is SRGB (see section 9.2.3), the red, green, and blue components
538 * are converted from the non-linear sRGB color space according to
539 * equation 3.24.
540 *
541 * When values are written to the draw buffers, blit operations
542 * bypass most of the fragment pipeline. The only fragment
543 * operations which affect a blit are the pixel ownership test,
544 * the scissor test, and sRGB conversion (see section 17.3.9)."
545 *
546 * ES 3.0 contains nearly the exact same text, but omits the part
547 * about GL_FRAMEBUFFER_SRGB as that doesn't exist in ES. Mesa
548 * defaults it to on for ES contexts, so we can safely check it.
549 */
550 const bool decode =
551 ctx->Color.sRGBEnabled && _mesa_is_format_srgb(rb->Format);
552
553 _mesa_set_sampler_srgb_decode(ctx, fb_tex_blit.samp_obj,
554 decode ? GL_DECODE_EXT
555 : GL_SKIP_DECODE_EXT);
556 }
557
558 if (!glsl_version) {
559 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
560 _mesa_set_enable(ctx, target, GL_TRUE);
561 }
562
563 /* Prepare vertex data (the VBO was previously created and bound) */
564 {
565 struct vertex verts[4];
566 GLfloat s0, t0, s1, t1;
567
568 if (target == GL_TEXTURE_2D) {
569 const struct gl_texture_image *texImage
570 = _mesa_select_tex_image(texObj, target, srcLevel);
571 s0 = srcX0 / (float) texImage->Width;
572 s1 = srcX1 / (float) texImage->Width;
573 t0 = srcY0 / (float) texImage->Height;
574 t1 = srcY1 / (float) texImage->Height;
575 }
576 else {
577 assert(target == GL_TEXTURE_RECTANGLE_ARB ||
578 target == GL_TEXTURE_2D_MULTISAMPLE ||
579 target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
580 s0 = (float) srcX0;
581 s1 = (float) srcX1;
582 t0 = (float) srcY0;
583 t1 = (float) srcY1;
584 }
585
586 /* Silence valgrind warnings about reading uninitialized stack. */
587 memset(verts, 0, sizeof(verts));
588
589 /* setup vertex positions */
590 verts[0].x = -1.0F * flipX;
591 verts[0].y = -1.0F * flipY;
592 verts[1].x = 1.0F * flipX;
593 verts[1].y = -1.0F * flipY;
594 verts[2].x = 1.0F * flipX;
595 verts[2].y = 1.0F * flipY;
596 verts[3].x = -1.0F * flipX;
597 verts[3].y = 1.0F * flipY;
598
599 verts[0].tex[0] = s0;
600 verts[0].tex[1] = t0;
601 verts[0].tex[2] = readAtt->Zoffset;
602 verts[1].tex[0] = s1;
603 verts[1].tex[1] = t0;
604 verts[1].tex[2] = readAtt->Zoffset;
605 verts[2].tex[0] = s1;
606 verts[2].tex[1] = t1;
607 verts[2].tex[2] = readAtt->Zoffset;
608 verts[3].tex[0] = s0;
609 verts[3].tex[1] = t1;
610 verts[3].tex[2] = readAtt->Zoffset;
611
612 _mesa_buffer_sub_data(ctx, blit->buf_obj, 0, sizeof(verts), verts);
613 }
614
615 /* setup viewport */
616 _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH);
617 _mesa_ColorMask(!do_depth, !do_depth, !do_depth, !do_depth);
618 _mesa_set_enable(ctx, GL_DEPTH_TEST, do_depth);
619 _mesa_DepthMask(do_depth);
620 _mesa_DepthFunc(GL_ALWAYS);
621
622 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
623 _mesa_meta_fb_tex_blit_end(ctx, target, &fb_tex_blit);
624
625 return true;
626 }
627
628 void
629 _mesa_meta_fb_tex_blit_begin(struct gl_context *ctx,
630 struct fb_tex_blit_state *blit)
631 {
632 /* None of the existing callers preinitialize fb_tex_blit_state to zeros,
633 * and both use stack variables. If samp_obj_save is not NULL,
634 * _mesa_reference_sampler_object will try to dereference it. Leaving
635 * random garbage in samp_obj_save can only lead to crashes.
636 *
637 * Since the state isn't persistent across calls, we won't catch ref
638 * counting problems.
639 */
640 blit->samp_obj_save = NULL;
641 _mesa_reference_sampler_object(ctx, &blit->samp_obj_save,
642 ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler);
643 blit->temp_tex_obj = NULL;
644 }
645
646 void
647 _mesa_meta_fb_tex_blit_end(struct gl_context *ctx, GLenum target,
648 struct fb_tex_blit_state *blit)
649 {
650 struct gl_texture_object *const texObj =
651 _mesa_get_current_tex_object(ctx, target);
652
653 /* Either there is no temporary texture or the temporary texture is bound. */
654 assert(blit->temp_tex_obj == NULL || blit->temp_tex_obj == texObj);
655
656 /* Restore texture object state, the texture binding will be restored by
657 * _mesa_meta_end(). If the texture is the temporary texture that is about
658 * to be destroyed, don't bother restoring its state.
659 */
660 if (blit->temp_tex_obj == NULL) {
661 /* If the target restricts values for base level or max level, we assume
662 * that the original values were valid.
663 */
664 if (blit->baseLevelSave != texObj->BaseLevel)
665 _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_BASE_LEVEL,
666 &blit->baseLevelSave, false);
667
668 if (blit->maxLevelSave != texObj->MaxLevel)
669 _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL,
670 &blit->maxLevelSave, false);
671
672 /* If ARB_stencil_texturing is not supported, the mode won't have changed. */
673 if (texObj->StencilSampling != blit->stencilSamplingSave) {
674 /* GLint so the compiler won't complain about type signedness mismatch
675 * in the call to _mesa_texture_parameteriv below.
676 */
677 const GLint param = blit->stencilSamplingSave ?
678 GL_STENCIL_INDEX : GL_DEPTH_COMPONENT;
679
680 _mesa_texture_parameteriv(ctx, texObj, GL_DEPTH_STENCIL_TEXTURE_MODE,
681 &param, false);
682 }
683 }
684
685 _mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, blit->samp_obj_save);
686 _mesa_reference_sampler_object(ctx, &blit->samp_obj_save, NULL);
687 _mesa_reference_sampler_object(ctx, &blit->samp_obj, NULL);
688 _mesa_delete_nameless_texture(ctx, blit->temp_tex_obj);
689 }
690
691 static struct gl_texture_object *
692 texture_object_from_renderbuffer(struct gl_context *ctx,
693 struct gl_renderbuffer *rb)
694 {
695 struct gl_texture_image *texImage;
696 struct gl_texture_object *texObj;
697 const GLenum target = rb->NumSamples > 1
698 ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
699
700 texObj = ctx->Driver.NewTextureObject(ctx, 0xDEADBEEF, target);
701 texImage = _mesa_get_tex_image(ctx, texObj, target, 0);
702
703 if (!ctx->Driver.BindRenderbufferTexImage(ctx, rb, texImage)) {
704 _mesa_delete_nameless_texture(ctx, texObj);
705 return NULL;
706 }
707
708 if (ctx->Driver.FinishRenderTexture && !rb->NeedsFinishRenderTexture) {
709 rb->NeedsFinishRenderTexture = true;
710 ctx->Driver.FinishRenderTexture(ctx, rb);
711 }
712
713 return texObj;
714 }
715
716 struct gl_sampler_object *
717 _mesa_meta_setup_sampler(struct gl_context *ctx,
718 struct gl_texture_object *texObj,
719 GLenum target, GLenum filter, GLuint srcLevel)
720 {
721 struct gl_sampler_object *samp_obj;
722 GLenum tex_filter = (filter == GL_SCALED_RESOLVE_FASTEST_EXT ||
723 filter == GL_SCALED_RESOLVE_NICEST_EXT) ?
724 GL_NEAREST : filter;
725
726 samp_obj = ctx->Driver.NewSamplerObject(ctx, 0xDEADBEEF);
727 if (samp_obj == NULL)
728 return NULL;
729
730 _mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, samp_obj);
731 _mesa_set_sampler_filters(ctx, samp_obj, tex_filter, tex_filter);
732 _mesa_set_sampler_wrap(ctx, samp_obj, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE,
733 samp_obj->WrapR);
734
735 /* Prepare src texture state */
736 _mesa_bind_texture(ctx, target, texObj);
737 if (target != GL_TEXTURE_RECTANGLE_ARB) {
738 _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_BASE_LEVEL,
739 (GLint *) &srcLevel, false);
740 _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL,
741 (GLint *) &srcLevel, false);
742 }
743
744 return samp_obj;
745 }
746
747 /**
748 * Meta implementation of ctx->Driver.BlitFramebuffer() in terms
749 * of texture mapping and polygon rendering.
750 */
751 GLbitfield
752 _mesa_meta_BlitFramebuffer(struct gl_context *ctx,
753 const struct gl_framebuffer *readFb,
754 const struct gl_framebuffer *drawFb,
755 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
756 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
757 GLbitfield mask, GLenum filter)
758 {
759 const GLint dstW = abs(dstX1 - dstX0);
760 const GLint dstH = abs(dstY1 - dstY0);
761 const GLint dstFlipX = (dstX1 - dstX0) / dstW;
762 const GLint dstFlipY = (dstY1 - dstY0) / dstH;
763
764 struct {
765 GLint srcX0, srcY0, srcX1, srcY1;
766 GLint dstX0, dstY0, dstX1, dstY1;
767 } clip = {
768 srcX0, srcY0, srcX1, srcY1,
769 dstX0, dstY0, dstX1, dstY1
770 };
771
772 const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader &&
773 ctx->Extensions.ARB_fragment_shader;
774
775 /* Multisample texture blit support requires texture multisample. */
776 if (readFb->Visual.samples > 0 &&
777 !ctx->Extensions.ARB_texture_multisample) {
778 return mask;
779 }
780
781 /* Clip a copy of the blit coordinates. If these differ from the input
782 * coordinates, then we'll set the scissor.
783 */
784 if (!_mesa_clip_blit(ctx, readFb, drawFb,
785 &clip.srcX0, &clip.srcY0, &clip.srcX1, &clip.srcY1,
786 &clip.dstX0, &clip.dstY0, &clip.dstX1, &clip.dstY1)) {
787 /* clipped/scissored everything away */
788 return 0;
789 }
790
791 /* Only scissor and FRAMEBUFFER_SRGB affect blit. Leave sRGB alone, but
792 * save restore scissor as we'll set a custom scissor if necessary.
793 */
794 _mesa_meta_begin(ctx, MESA_META_ALL &
795 ~(MESA_META_DRAW_BUFFERS |
796 MESA_META_FRAMEBUFFER_SRGB));
797
798 /* Dithering shouldn't be performed for glBlitFramebuffer */
799 _mesa_set_enable(ctx, GL_DITHER, GL_FALSE);
800
801 /* If the clipping earlier changed the destination rect at all, then
802 * enable the scissor to clip to it.
803 */
804 if (clip.dstX0 != dstX0 || clip.dstY0 != dstY0 ||
805 clip.dstX1 != dstX1 || clip.dstY1 != dstY1) {
806 _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_TRUE);
807 _mesa_Scissor(MIN2(clip.dstX0, clip.dstX1),
808 MIN2(clip.dstY0, clip.dstY1),
809 abs(clip.dstX0 - clip.dstX1),
810 abs(clip.dstY0 - clip.dstY1));
811 }
812
813 /* Try faster, direct texture approach first */
814 if (mask & GL_COLOR_BUFFER_BIT) {
815 if (blitframebuffer_texture(ctx, readFb, drawFb,
816 srcX0, srcY0, srcX1, srcY1,
817 dstX0, dstY0, dstX1, dstY1,
818 filter, dstFlipX, dstFlipY,
819 use_glsl_version, false)) {
820 mask &= ~GL_COLOR_BUFFER_BIT;
821 }
822 }
823
824 if (mask & GL_DEPTH_BUFFER_BIT && use_glsl_version) {
825 if (blitframebuffer_texture(ctx, readFb, drawFb,
826 srcX0, srcY0, srcX1, srcY1,
827 dstX0, dstY0, dstX1, dstY1,
828 filter, dstFlipX, dstFlipY,
829 use_glsl_version, true)) {
830 mask &= ~GL_DEPTH_BUFFER_BIT;
831 }
832 }
833
834 if (mask & GL_STENCIL_BUFFER_BIT) {
835 /* XXX can't easily do stencil */
836 }
837
838 _mesa_meta_end(ctx);
839
840 return mask;
841 }
842
843 void
844 _mesa_meta_glsl_blit_cleanup(struct gl_context *ctx, struct blit_state *blit)
845 {
846 if (blit->VAO) {
847 _mesa_DeleteVertexArrays(1, &blit->VAO);
848 blit->VAO = 0;
849 _mesa_reference_buffer_object(ctx, &blit->buf_obj, NULL);
850 }
851
852 _mesa_meta_blit_shader_table_cleanup(ctx, &blit->shaders_with_depth);
853 _mesa_meta_blit_shader_table_cleanup(ctx, &blit->shaders_without_depth);
854
855 if (blit->depthTex.tex_obj != NULL) {
856 _mesa_delete_nameless_texture(ctx, blit->depthTex.tex_obj);
857 blit->depthTex.tex_obj = NULL;
858 }
859 }
860
861 void
862 _mesa_meta_and_swrast_BlitFramebuffer(struct gl_context *ctx,
863 struct gl_framebuffer *readFb,
864 struct gl_framebuffer *drawFb,
865 GLint srcX0, GLint srcY0,
866 GLint srcX1, GLint srcY1,
867 GLint dstX0, GLint dstY0,
868 GLint dstX1, GLint dstY1,
869 GLbitfield mask, GLenum filter)
870 {
871 mask = _mesa_meta_BlitFramebuffer(ctx, readFb, drawFb,
872 srcX0, srcY0, srcX1, srcY1,
873 dstX0, dstY0, dstX1, dstY1,
874 mask, filter);
875 if (mask == 0x0)
876 return;
877
878 _swrast_BlitFramebuffer(ctx, readFb, drawFb,
879 srcX0, srcY0, srcX1, srcY1,
880 dstX0, dstY0, dstX1, dstY1,
881 mask, filter);
882 }