2 * Mesa 3-D graphics library
4 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
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:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
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.
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/depth.h"
31 #include "main/enable.h"
32 #include "main/enums.h"
33 #include "main/fbobject.h"
34 #include "main/image.h"
35 #include "main/macros.h"
36 #include "main/matrix.h"
37 #include "main/readpix.h"
38 #include "main/scissor.h"
39 #include "main/shaderapi.h"
40 #include "main/texobj.h"
41 #include "main/texenv.h"
42 #include "main/teximage.h"
43 #include "main/texparam.h"
44 #include "main/uniforms.h"
45 #include "main/varray.h"
46 #include "main/viewport.h"
47 #include "swrast/swrast.h"
48 #include "drivers/common/meta.h"
50 static struct gl_texture_object
*
51 texture_object_from_renderbuffer(struct gl_context
*, struct gl_renderbuffer
*);
53 static struct gl_sampler_object
*
54 setup_sampler(struct gl_context
*, struct gl_texture_object
*, GLenum target
,
55 GLenum filter
, GLuint srcLevel
);
57 /** Return offset in bytes of the field within a vertex struct */
58 #define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD))
61 setup_glsl_blit_framebuffer(struct gl_context
*ctx
,
62 struct blit_state
*blit
,
63 const struct gl_framebuffer
*drawFb
,
64 struct gl_renderbuffer
*src_rb
,
68 const unsigned texcoord_size
= 2 + (src_rb
->Depth
> 1 ? 1 : 0);
70 /* target = GL_TEXTURE_RECTANGLE is not supported in GLES 3.0 */
71 assert(_mesa_is_desktop_gl(ctx
) || target
== GL_TEXTURE_2D
);
74 _mesa_meta_setup_vertex_objects(ctx
, &blit
->VAO
, &blit
->buf_obj
, true,
77 _mesa_meta_setup_blit_shader(ctx
, target
, do_depth
,
78 do_depth
? &blit
->shaders_with_depth
79 : &blit
->shaders_without_depth
);
83 * Try to do a color or depth glBlitFramebuffer using texturing.
85 * We can do this when the src renderbuffer is actually a texture, or when the
86 * driver exposes BindRenderbufferTexImage().
89 blitframebuffer_texture(struct gl_context
*ctx
,
90 const struct gl_framebuffer
*readFb
,
91 const struct gl_framebuffer
*drawFb
,
92 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
93 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
94 GLenum filter
, GLint flipX
, GLint flipY
,
95 GLboolean glsl_version
, GLboolean do_depth
)
97 int att_index
= do_depth
? BUFFER_DEPTH
: readFb
->_ColorReadBufferIndex
;
98 const struct gl_renderbuffer_attachment
*readAtt
=
99 &readFb
->Attachment
[att_index
];
100 struct blit_state
*blit
= &ctx
->Meta
->Blit
;
101 struct fb_tex_blit_state fb_tex_blit
;
102 const GLint dstX
= MIN2(dstX0
, dstX1
);
103 const GLint dstY
= MIN2(dstY0
, dstY1
);
104 const GLint dstW
= abs(dstX1
- dstX0
);
105 const GLint dstH
= abs(dstY1
- dstY0
);
106 const int srcW
= abs(srcX1
- srcX0
);
107 const int srcH
= abs(srcY1
- srcY0
);
108 struct gl_texture_object
*texObj
;
111 struct gl_renderbuffer
*rb
= readAtt
->Renderbuffer
;
112 struct temp_texture
*meta_temp_texture
;
114 assert(rb
->NumSamples
== 0);
116 _mesa_meta_fb_tex_blit_begin(ctx
, &fb_tex_blit
);
118 if (readAtt
->Texture
&&
119 (readAtt
->Texture
->Target
== GL_TEXTURE_2D
||
120 readAtt
->Texture
->Target
== GL_TEXTURE_RECTANGLE
)) {
121 /* If there's a texture attached of a type we can handle, then just use
124 srcLevel
= readAtt
->TextureLevel
;
125 texObj
= readAtt
->Texture
;
126 } else if (!readAtt
->Texture
&& ctx
->Driver
.BindRenderbufferTexImage
) {
127 texObj
= texture_object_from_renderbuffer(ctx
, rb
);
131 fb_tex_blit
.temp_tex_obj
= texObj
;
134 if (_mesa_is_winsys_fbo(readFb
)) {
136 srcY0
= rb
->Height
- srcY1
;
137 srcY1
= rb
->Height
- temp
;
141 GLenum tex_base_format
;
142 /* Fall back to doing a CopyTexSubImage to get the destination
143 * renderbuffer into a texture.
145 if (ctx
->Meta
->Blit
.no_ctsi_fallback
)
149 meta_temp_texture
= _mesa_meta_get_temp_depth_texture(ctx
);
150 tex_base_format
= GL_DEPTH_COMPONENT
;
152 meta_temp_texture
= _mesa_meta_get_temp_texture(ctx
);
154 _mesa_base_tex_format(ctx
, rb
->InternalFormat
);
158 texObj
= meta_temp_texture
->tex_obj
;
159 if (texObj
== NULL
) {
163 _mesa_meta_setup_copypix_texture(ctx
, meta_temp_texture
,
169 assert(texObj
->Target
== meta_temp_texture
->Target
);
177 target
= texObj
->Target
;
178 fb_tex_blit
.tex_obj
= texObj
;
179 fb_tex_blit
.baseLevelSave
= texObj
->BaseLevel
;
180 fb_tex_blit
.maxLevelSave
= texObj
->MaxLevel
;
181 fb_tex_blit
.stencilSamplingSave
= texObj
->StencilSampling
;
184 setup_glsl_blit_framebuffer(ctx
, blit
, drawFb
, rb
, target
, do_depth
);
187 _mesa_meta_setup_ff_tnl_for_blit(ctx
,
188 &ctx
->Meta
->Blit
.VAO
,
189 &ctx
->Meta
->Blit
.buf_obj
,
194 printf("Blit from texture!\n");
195 printf(" srcAtt %p dstAtt %p\n", readAtt, drawAtt);
196 printf(" srcTex %p dstText %p\n", texObj, drawAtt->Texture);
199 fb_tex_blit
.samp_obj
= setup_sampler(ctx
, texObj
, target
, filter
, srcLevel
);
201 if (ctx
->Extensions
.EXT_texture_sRGB_decode
) {
202 /* The GL 4.4 spec, section 18.3.1 ("Blitting Pixel Rectangles") says:
204 * "When values are taken from the read buffer, if FRAMEBUFFER_SRGB
205 * is enabled and the value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING
206 * for the framebuffer attachment corresponding to the read buffer
207 * is SRGB (see section 9.2.3), the red, green, and blue components
208 * are converted from the non-linear sRGB color space according to
211 * When values are written to the draw buffers, blit operations
212 * bypass most of the fragment pipeline. The only fragment
213 * operations which affect a blit are the pixel ownership test,
214 * the scissor test, and sRGB conversion (see section 17.3.9)."
216 * ES 3.0 contains nearly the exact same text, but omits the part
217 * about GL_FRAMEBUFFER_SRGB as that doesn't exist in ES. Mesa
218 * defaults it to on for ES contexts, so we can safely check it.
221 ctx
->Color
.sRGBEnabled
&& _mesa_is_format_srgb(rb
->Format
);
223 _mesa_set_sampler_srgb_decode(ctx
, fb_tex_blit
.samp_obj
,
224 decode
? GL_DECODE_EXT
225 : GL_SKIP_DECODE_EXT
);
229 _mesa_TexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
230 _mesa_set_enable(ctx
, target
, GL_TRUE
);
233 /* Prepare vertex data (the VBO was previously created and bound) */
235 struct vertex verts
[4];
236 GLfloat s0
, t0
, s1
, t1
;
238 if (target
== GL_TEXTURE_2D
) {
239 const struct gl_texture_image
*texImage
240 = _mesa_select_tex_image(texObj
, target
, srcLevel
);
241 s0
= srcX0
/ (float) texImage
->Width
;
242 s1
= srcX1
/ (float) texImage
->Width
;
243 t0
= srcY0
/ (float) texImage
->Height
;
244 t1
= srcY1
/ (float) texImage
->Height
;
247 assert(target
== GL_TEXTURE_RECTANGLE_ARB
);
254 /* Silence valgrind warnings about reading uninitialized stack. */
255 memset(verts
, 0, sizeof(verts
));
257 /* setup vertex positions */
258 verts
[0].x
= -1.0F
* flipX
;
259 verts
[0].y
= -1.0F
* flipY
;
260 verts
[1].x
= 1.0F
* flipX
;
261 verts
[1].y
= -1.0F
* flipY
;
262 verts
[2].x
= 1.0F
* flipX
;
263 verts
[2].y
= 1.0F
* flipY
;
264 verts
[3].x
= -1.0F
* flipX
;
265 verts
[3].y
= 1.0F
* flipY
;
267 verts
[0].tex
[0] = s0
;
268 verts
[0].tex
[1] = t0
;
269 verts
[0].tex
[2] = readAtt
->Zoffset
;
270 verts
[1].tex
[0] = s1
;
271 verts
[1].tex
[1] = t0
;
272 verts
[1].tex
[2] = readAtt
->Zoffset
;
273 verts
[2].tex
[0] = s1
;
274 verts
[2].tex
[1] = t1
;
275 verts
[2].tex
[2] = readAtt
->Zoffset
;
276 verts
[3].tex
[0] = s0
;
277 verts
[3].tex
[1] = t1
;
278 verts
[3].tex
[2] = readAtt
->Zoffset
;
280 _mesa_buffer_sub_data(ctx
, blit
->buf_obj
, 0, sizeof(verts
), verts
);
284 _mesa_set_viewport(ctx
, 0, dstX
, dstY
, dstW
, dstH
);
285 _mesa_ColorMask(!do_depth
, !do_depth
, !do_depth
, !do_depth
);
286 _mesa_set_enable(ctx
, GL_DEPTH_TEST
, do_depth
);
287 _mesa_DepthMask(do_depth
);
288 _mesa_DepthFunc(GL_ALWAYS
);
290 _mesa_DrawArrays(GL_TRIANGLE_FAN
, 0, 4);
291 _mesa_meta_fb_tex_blit_end(ctx
, target
, &fb_tex_blit
);
297 _mesa_meta_fb_tex_blit_begin(struct gl_context
*ctx
,
298 struct fb_tex_blit_state
*blit
)
300 /* None of the existing callers preinitialize fb_tex_blit_state to zeros,
301 * and both use stack variables. If samp_obj_save is not NULL,
302 * _mesa_reference_sampler_object will try to dereference it. Leaving
303 * random garbage in samp_obj_save can only lead to crashes.
305 * Since the state isn't persistent across calls, we won't catch ref
308 blit
->samp_obj_save
= NULL
;
309 _mesa_reference_sampler_object(ctx
, &blit
->samp_obj_save
,
310 ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].Sampler
);
311 blit
->temp_tex_obj
= NULL
;
315 _mesa_meta_fb_tex_blit_end(struct gl_context
*ctx
, GLenum target
,
316 struct fb_tex_blit_state
*blit
)
318 struct gl_texture_object
*const texObj
=
319 _mesa_get_current_tex_object(ctx
, target
);
321 /* Either there is no temporary texture or the temporary texture is bound. */
322 assert(blit
->temp_tex_obj
== NULL
|| blit
->temp_tex_obj
== texObj
);
324 /* Restore texture object state, the texture binding will be restored by
325 * _mesa_meta_end(). If the texture is the temporary texture that is about
326 * to be destroyed, don't bother restoring its state.
328 if (blit
->temp_tex_obj
== NULL
) {
329 /* If the target restricts values for base level or max level, we assume
330 * that the original values were valid.
332 if (blit
->baseLevelSave
!= texObj
->BaseLevel
)
333 _mesa_texture_parameteriv(ctx
, texObj
, GL_TEXTURE_BASE_LEVEL
,
334 &blit
->baseLevelSave
, false);
336 if (blit
->maxLevelSave
!= texObj
->MaxLevel
)
337 _mesa_texture_parameteriv(ctx
, texObj
, GL_TEXTURE_MAX_LEVEL
,
338 &blit
->maxLevelSave
, false);
340 /* If ARB_stencil_texturing is not supported, the mode won't have changed. */
341 if (texObj
->StencilSampling
!= blit
->stencilSamplingSave
) {
342 /* GLint so the compiler won't complain about type signedness mismatch
343 * in the call to _mesa_texture_parameteriv below.
345 const GLint param
= blit
->stencilSamplingSave
?
346 GL_STENCIL_INDEX
: GL_DEPTH_COMPONENT
;
348 _mesa_texture_parameteriv(ctx
, texObj
, GL_DEPTH_STENCIL_TEXTURE_MODE
,
353 _mesa_bind_sampler(ctx
, ctx
->Texture
.CurrentUnit
, blit
->samp_obj_save
);
354 _mesa_reference_sampler_object(ctx
, &blit
->samp_obj_save
, NULL
);
355 _mesa_reference_sampler_object(ctx
, &blit
->samp_obj
, NULL
);
356 _mesa_delete_nameless_texture(ctx
, blit
->temp_tex_obj
);
359 static struct gl_texture_object
*
360 texture_object_from_renderbuffer(struct gl_context
*ctx
,
361 struct gl_renderbuffer
*rb
)
363 struct gl_texture_image
*texImage
;
364 struct gl_texture_object
*texObj
;
365 const GLenum target
= GL_TEXTURE_2D
;
367 texObj
= ctx
->Driver
.NewTextureObject(ctx
, 0xDEADBEEF, target
);
368 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, 0);
370 if (!ctx
->Driver
.BindRenderbufferTexImage(ctx
, rb
, texImage
)) {
371 _mesa_delete_nameless_texture(ctx
, texObj
);
375 if (ctx
->Driver
.FinishRenderTexture
&& !rb
->NeedsFinishRenderTexture
) {
376 rb
->NeedsFinishRenderTexture
= true;
377 ctx
->Driver
.FinishRenderTexture(ctx
, rb
);
383 static struct gl_sampler_object
*
384 setup_sampler(struct gl_context
*ctx
, struct gl_texture_object
*texObj
,
385 GLenum target
, GLenum filter
, GLuint srcLevel
)
387 struct gl_sampler_object
*samp_obj
=
388 ctx
->Driver
.NewSamplerObject(ctx
, 0xDEADBEEF);
390 if (samp_obj
== NULL
)
393 _mesa_bind_sampler(ctx
, ctx
->Texture
.CurrentUnit
, samp_obj
);
394 _mesa_set_sampler_filters(ctx
, samp_obj
, filter
, filter
);
395 _mesa_set_sampler_wrap(ctx
, samp_obj
, GL_CLAMP_TO_EDGE
, GL_CLAMP_TO_EDGE
,
398 /* Prepare src texture state */
399 _mesa_bind_texture(ctx
, target
, texObj
);
400 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
401 _mesa_texture_parameteriv(ctx
, texObj
, GL_TEXTURE_BASE_LEVEL
,
402 (GLint
*) &srcLevel
, false);
403 _mesa_texture_parameteriv(ctx
, texObj
, GL_TEXTURE_MAX_LEVEL
,
404 (GLint
*) &srcLevel
, false);
411 * Meta implementation of ctx->Driver.BlitFramebuffer() in terms
412 * of texture mapping and polygon rendering.
415 _mesa_meta_BlitFramebuffer(struct gl_context
*ctx
,
416 const struct gl_framebuffer
*readFb
,
417 const struct gl_framebuffer
*drawFb
,
418 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
419 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
420 GLbitfield mask
, GLenum filter
)
422 const GLint dstW
= abs(dstX1
- dstX0
);
423 const GLint dstH
= abs(dstY1
- dstY0
);
424 const GLint dstFlipX
= (dstX1
- dstX0
) / dstW
;
425 const GLint dstFlipY
= (dstY1
- dstY0
) / dstH
;
428 GLint srcX0
, srcY0
, srcX1
, srcY1
;
429 GLint dstX0
, dstY0
, dstX1
, dstY1
;
431 srcX0
, srcY0
, srcX1
, srcY1
,
432 dstX0
, dstY0
, dstX1
, dstY1
435 const GLboolean use_glsl_version
= ctx
->Extensions
.ARB_vertex_shader
&&
436 ctx
->Extensions
.ARB_fragment_shader
;
438 /* Multisample blit is not supported. */
439 if (readFb
->Visual
.samples
> 0)
442 /* Clip a copy of the blit coordinates. If these differ from the input
443 * coordinates, then we'll set the scissor.
445 if (!_mesa_clip_blit(ctx
, readFb
, drawFb
,
446 &clip
.srcX0
, &clip
.srcY0
, &clip
.srcX1
, &clip
.srcY1
,
447 &clip
.dstX0
, &clip
.dstY0
, &clip
.dstX1
, &clip
.dstY1
)) {
448 /* clipped/scissored everything away */
452 /* Only scissor and FRAMEBUFFER_SRGB affect blit. Leave sRGB alone, but
453 * save restore scissor as we'll set a custom scissor if necessary.
455 _mesa_meta_begin(ctx
, MESA_META_ALL
&
456 ~(MESA_META_DRAW_BUFFERS
|
457 MESA_META_FRAMEBUFFER_SRGB
));
459 /* Dithering shouldn't be performed for glBlitFramebuffer */
460 _mesa_set_enable(ctx
, GL_DITHER
, GL_FALSE
);
462 /* If the clipping earlier changed the destination rect at all, then
463 * enable the scissor to clip to it.
465 if (clip
.dstX0
!= dstX0
|| clip
.dstY0
!= dstY0
||
466 clip
.dstX1
!= dstX1
|| clip
.dstY1
!= dstY1
) {
467 _mesa_set_enable(ctx
, GL_SCISSOR_TEST
, GL_TRUE
);
468 _mesa_Scissor(MIN2(clip
.dstX0
, clip
.dstX1
),
469 MIN2(clip
.dstY0
, clip
.dstY1
),
470 abs(clip
.dstX0
- clip
.dstX1
),
471 abs(clip
.dstY0
- clip
.dstY1
));
474 /* Try faster, direct texture approach first */
475 if (mask
& GL_COLOR_BUFFER_BIT
) {
476 if (blitframebuffer_texture(ctx
, readFb
, drawFb
,
477 srcX0
, srcY0
, srcX1
, srcY1
,
478 dstX0
, dstY0
, dstX1
, dstY1
,
479 filter
, dstFlipX
, dstFlipY
,
480 use_glsl_version
, false)) {
481 mask
&= ~GL_COLOR_BUFFER_BIT
;
485 if (mask
& GL_DEPTH_BUFFER_BIT
&& use_glsl_version
) {
486 if (blitframebuffer_texture(ctx
, readFb
, drawFb
,
487 srcX0
, srcY0
, srcX1
, srcY1
,
488 dstX0
, dstY0
, dstX1
, dstY1
,
489 filter
, dstFlipX
, dstFlipY
,
490 use_glsl_version
, true)) {
491 mask
&= ~GL_DEPTH_BUFFER_BIT
;
495 if (mask
& GL_STENCIL_BUFFER_BIT
) {
496 /* XXX can't easily do stencil */
505 _mesa_meta_glsl_blit_cleanup(struct gl_context
*ctx
, struct blit_state
*blit
)
508 _mesa_DeleteVertexArrays(1, &blit
->VAO
);
510 _mesa_reference_buffer_object(ctx
, &blit
->buf_obj
, NULL
);
513 _mesa_meta_blit_shader_table_cleanup(ctx
, &blit
->shaders_with_depth
);
514 _mesa_meta_blit_shader_table_cleanup(ctx
, &blit
->shaders_without_depth
);
516 if (blit
->depthTex
.tex_obj
!= NULL
) {
517 _mesa_delete_nameless_texture(ctx
, blit
->depthTex
.tex_obj
);
518 blit
->depthTex
.tex_obj
= NULL
;
523 _mesa_meta_and_swrast_BlitFramebuffer(struct gl_context
*ctx
,
524 struct gl_framebuffer
*readFb
,
525 struct gl_framebuffer
*drawFb
,
526 GLint srcX0
, GLint srcY0
,
527 GLint srcX1
, GLint srcY1
,
528 GLint dstX0
, GLint dstY0
,
529 GLint dstX1
, GLint dstY1
,
530 GLbitfield mask
, GLenum filter
)
532 mask
= _mesa_meta_BlitFramebuffer(ctx
, readFb
, drawFb
,
533 srcX0
, srcY0
, srcX1
, srcY1
,
534 dstX0
, dstY0
, dstX1
, dstY1
,
539 _swrast_BlitFramebuffer(ctx
, readFb
, drawFb
,
540 srcX0
, srcY0
, srcX1
, srcY1
,
541 dstX0
, dstY0
, dstX1
, dstY1
,