• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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"
49 
50 static struct gl_texture_object *
51 texture_object_from_renderbuffer(struct gl_context *, struct gl_renderbuffer *);
52 
53 static struct gl_sampler_object *
54 setup_sampler(struct gl_context *, struct gl_texture_object *, GLenum target,
55               GLenum filter, GLuint srcLevel);
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
setup_glsl_blit_framebuffer(struct gl_context * ctx,struct blit_state * blit,const struct gl_framebuffer * drawFb,struct gl_renderbuffer * src_rb,GLenum target,bool do_depth)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,
65                             GLenum target,
66                             bool do_depth)
67 {
68    const unsigned texcoord_size = 2 + (src_rb->Depth > 1 ? 1 : 0);
69 
70    /* target = GL_TEXTURE_RECTANGLE is not supported in GLES 3.0 */
71    assert(_mesa_is_desktop_gl(ctx) || target == GL_TEXTURE_2D);
72 
73 
74    _mesa_meta_setup_vertex_objects(ctx, &blit->VAO, &blit->buf_obj, true,
75                                    2, texcoord_size, 0);
76 
77    _mesa_meta_setup_blit_shader(ctx, target, do_depth,
78                                 do_depth ? &blit->shaders_with_depth
79                                          : &blit->shaders_without_depth);
80 }
81 
82 /**
83  * Try to do a color or depth glBlitFramebuffer using texturing.
84  *
85  * We can do this when the src renderbuffer is actually a texture, or when the
86  * driver exposes BindRenderbufferTexImage().
87  */
88 static bool
blitframebuffer_texture(struct gl_context * ctx,const struct gl_framebuffer * readFb,const struct gl_framebuffer * drawFb,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLenum filter,GLint flipX,GLint flipY,GLboolean glsl_version,GLboolean do_depth)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)
96 {
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;
109    GLuint srcLevel;
110    GLenum target;
111    struct gl_renderbuffer *rb = readAtt->Renderbuffer;
112    struct temp_texture *meta_temp_texture;
113 
114    assert(rb->NumSamples == 0);
115 
116    _mesa_meta_fb_tex_blit_begin(ctx, &fb_tex_blit);
117 
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
122        * it directly.
123        */
124       srcLevel = readAtt->TextureLevel;
125       texObj = readAtt->Texture;
126    } else if (!readAtt->Texture && ctx->Driver.BindRenderbufferTexImage) {
127       texObj = texture_object_from_renderbuffer(ctx, rb);
128       if (texObj == NULL)
129          return false;
130 
131       fb_tex_blit.temp_tex_obj = texObj;
132 
133       srcLevel = 0;
134       if (_mesa_is_winsys_fbo(readFb)) {
135          GLint temp = srcY0;
136          srcY0 = rb->Height - srcY1;
137          srcY1 = rb->Height - temp;
138          flipY = -flipY;
139       }
140    } else {
141       GLenum tex_base_format;
142       /* Fall back to doing a CopyTexSubImage to get the destination
143        * renderbuffer into a texture.
144        */
145       if (ctx->Meta->Blit.no_ctsi_fallback)
146          return false;
147 
148       if (do_depth) {
149          meta_temp_texture = _mesa_meta_get_temp_depth_texture(ctx);
150          tex_base_format = GL_DEPTH_COMPONENT;
151       } else {
152          meta_temp_texture = _mesa_meta_get_temp_texture(ctx);
153          tex_base_format =
154             _mesa_base_tex_format(ctx, rb->InternalFormat);
155       }
156 
157       srcLevel = 0;
158       texObj = meta_temp_texture->tex_obj;
159       if (texObj == NULL) {
160          return false;
161       }
162 
163       _mesa_meta_setup_copypix_texture(ctx, meta_temp_texture,
164                                        srcX0, srcY0,
165                                        srcW, srcH,
166                                        tex_base_format,
167                                        filter);
168 
169       assert(texObj->Target == meta_temp_texture->Target);
170 
171       srcX0 = 0;
172       srcY0 = 0;
173       srcX1 = srcW;
174       srcY1 = srcH;
175    }
176 
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;
182 
183    if (glsl_version) {
184       setup_glsl_blit_framebuffer(ctx, blit, drawFb, rb, target, do_depth);
185    }
186    else {
187       _mesa_meta_setup_ff_tnl_for_blit(ctx,
188                                        &ctx->Meta->Blit.VAO,
189                                        &ctx->Meta->Blit.buf_obj,
190                                        2);
191    }
192 
193    /*
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);
197    */
198 
199    fb_tex_blit.samp_obj = setup_sampler(ctx, texObj, target, filter, srcLevel);
200 
201    if (ctx->Extensions.EXT_texture_sRGB_decode) {
202       /* The GL 4.4 spec, section 18.3.1 ("Blitting Pixel Rectangles") says:
203        *
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
209        *     equation 3.24.
210        *
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)."
215        *
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.
219        */
220       const bool decode =
221          ctx->Color.sRGBEnabled && _mesa_is_format_srgb(rb->Format);
222 
223       _mesa_set_sampler_srgb_decode(ctx, fb_tex_blit.samp_obj,
224                                     decode ? GL_DECODE_EXT
225                                            : GL_SKIP_DECODE_EXT);
226    }
227 
228    if (!glsl_version) {
229       _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
230       _mesa_set_enable(ctx, target, GL_TRUE);
231    }
232 
233    /* Prepare vertex data (the VBO was previously created and bound) */
234    {
235       struct vertex verts[4];
236       GLfloat s0, t0, s1, t1;
237 
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;
245       }
246       else {
247          assert(target == GL_TEXTURE_RECTANGLE_ARB);
248          s0 = (float) srcX0;
249          s1 = (float) srcX1;
250          t0 = (float) srcY0;
251          t1 = (float) srcY1;
252       }
253 
254       /* Silence valgrind warnings about reading uninitialized stack. */
255       memset(verts, 0, sizeof(verts));
256 
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;
266 
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;
279 
280       _mesa_buffer_sub_data(ctx, blit->buf_obj, 0, sizeof(verts), verts);
281    }
282 
283    /* setup viewport */
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);
289 
290    _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
291    _mesa_meta_fb_tex_blit_end(ctx, target, &fb_tex_blit);
292 
293    return true;
294 }
295 
296 void
_mesa_meta_fb_tex_blit_begin(struct gl_context * ctx,struct fb_tex_blit_state * blit)297 _mesa_meta_fb_tex_blit_begin(struct gl_context *ctx,
298                              struct fb_tex_blit_state *blit)
299 {
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.
304     *
305     * Since the state isn't persistent across calls, we won't catch ref
306     * counting problems.
307     */
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;
312 }
313 
314 void
_mesa_meta_fb_tex_blit_end(struct gl_context * ctx,GLenum target,struct fb_tex_blit_state * blit)315 _mesa_meta_fb_tex_blit_end(struct gl_context *ctx, GLenum target,
316                            struct fb_tex_blit_state *blit)
317 {
318    struct gl_texture_object *const texObj =
319       _mesa_get_current_tex_object(ctx, target);
320 
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);
323 
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.
327     */
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.
331        */
332       if (blit->baseLevelSave != texObj->BaseLevel)
333          _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_BASE_LEVEL,
334                                    &blit->baseLevelSave, false);
335 
336       if (blit->maxLevelSave != texObj->MaxLevel)
337          _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL,
338                                    &blit->maxLevelSave, false);
339 
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.
344           */
345          const GLint param = blit->stencilSamplingSave ?
346             GL_STENCIL_INDEX : GL_DEPTH_COMPONENT;
347 
348          _mesa_texture_parameteriv(ctx, texObj, GL_DEPTH_STENCIL_TEXTURE_MODE,
349                                    &param, false);
350       }
351    }
352 
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);
357 }
358 
359 static struct gl_texture_object *
texture_object_from_renderbuffer(struct gl_context * ctx,struct gl_renderbuffer * rb)360 texture_object_from_renderbuffer(struct gl_context *ctx,
361                                  struct gl_renderbuffer *rb)
362 {
363    struct gl_texture_image *texImage;
364    struct gl_texture_object *texObj;
365    const GLenum target = GL_TEXTURE_2D;
366 
367    texObj = ctx->Driver.NewTextureObject(ctx, 0xDEADBEEF, target);
368    texImage = _mesa_get_tex_image(ctx, texObj, target, 0);
369 
370    if (!ctx->Driver.BindRenderbufferTexImage(ctx, rb, texImage)) {
371       _mesa_delete_nameless_texture(ctx, texObj);
372       return NULL;
373    }
374 
375    if (ctx->Driver.FinishRenderTexture && !rb->NeedsFinishRenderTexture) {
376       rb->NeedsFinishRenderTexture = true;
377       ctx->Driver.FinishRenderTexture(ctx, rb);
378    }
379 
380    return texObj;
381 }
382 
383 static struct gl_sampler_object *
setup_sampler(struct gl_context * ctx,struct gl_texture_object * texObj,GLenum target,GLenum filter,GLuint srcLevel)384 setup_sampler(struct gl_context *ctx, struct gl_texture_object *texObj,
385               GLenum target, GLenum filter, GLuint srcLevel)
386 {
387    struct gl_sampler_object *samp_obj =
388       ctx->Driver.NewSamplerObject(ctx, 0xDEADBEEF);
389 
390    if (samp_obj == NULL)
391       return NULL;
392 
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,
396                           samp_obj->WrapR);
397 
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);
405    }
406 
407    return samp_obj;
408 }
409 
410 /**
411  * Meta implementation of ctx->Driver.BlitFramebuffer() in terms
412  * of texture mapping and polygon rendering.
413  */
414 GLbitfield
_mesa_meta_BlitFramebuffer(struct gl_context * ctx,const struct gl_framebuffer * readFb,const struct gl_framebuffer * drawFb,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)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)
421 {
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;
426 
427    struct {
428       GLint srcX0, srcY0, srcX1, srcY1;
429       GLint dstX0, dstY0, dstX1, dstY1;
430    } clip = {
431       srcX0, srcY0, srcX1, srcY1,
432       dstX0, dstY0, dstX1, dstY1
433    };
434 
435    const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader &&
436                                       ctx->Extensions.ARB_fragment_shader;
437 
438    /* Multisample blit is not supported. */
439    if (readFb->Visual.samples > 0)
440       return mask;
441 
442    /* Clip a copy of the blit coordinates. If these differ from the input
443     * coordinates, then we'll set the scissor.
444     */
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 */
449       return 0;
450    }
451 
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.
454     */
455    _mesa_meta_begin(ctx, MESA_META_ALL &
456                          ~(MESA_META_DRAW_BUFFERS |
457                            MESA_META_FRAMEBUFFER_SRGB));
458 
459    /* Dithering shouldn't be performed for glBlitFramebuffer */
460    _mesa_set_enable(ctx, GL_DITHER, GL_FALSE);
461 
462    /* If the clipping earlier changed the destination rect at all, then
463     * enable the scissor to clip to it.
464     */
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));
472    }
473 
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;
482       }
483    }
484 
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;
492       }
493    }
494 
495    if (mask & GL_STENCIL_BUFFER_BIT) {
496       /* XXX can't easily do stencil */
497    }
498 
499    _mesa_meta_end(ctx);
500 
501    return mask;
502 }
503 
504 void
_mesa_meta_glsl_blit_cleanup(struct gl_context * ctx,struct blit_state * blit)505 _mesa_meta_glsl_blit_cleanup(struct gl_context *ctx, struct blit_state *blit)
506 {
507    if (blit->VAO) {
508       _mesa_DeleteVertexArrays(1, &blit->VAO);
509       blit->VAO = 0;
510       _mesa_reference_buffer_object(ctx, &blit->buf_obj, NULL);
511    }
512 
513    _mesa_meta_blit_shader_table_cleanup(ctx, &blit->shaders_with_depth);
514    _mesa_meta_blit_shader_table_cleanup(ctx, &blit->shaders_without_depth);
515 
516    if (blit->depthTex.tex_obj != NULL) {
517       _mesa_delete_nameless_texture(ctx, blit->depthTex.tex_obj);
518       blit->depthTex.tex_obj = NULL;
519    }
520 }
521 
522 void
_mesa_meta_and_swrast_BlitFramebuffer(struct gl_context * ctx,struct gl_framebuffer * readFb,struct gl_framebuffer * drawFb,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)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)
531 {
532    mask = _mesa_meta_BlitFramebuffer(ctx, readFb, drawFb,
533                                      srcX0, srcY0, srcX1, srcY1,
534                                      dstX0, dstY0, dstX1, dstY1,
535                                      mask, filter);
536    if (mask == 0x0)
537       return;
538 
539    _swrast_BlitFramebuffer(ctx, readFb, drawFb,
540                            srcX0, srcY0, srcX1, srcY1,
541                            dstX0, dstY0, dstX1, dstY1,
542                            mask, filter);
543 }
544