Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/*
2
 * Mesa 3-D graphics library
3
 *
4
 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5
 * Copyright (C) 1999-2013  VMware, Inc.  All Rights Reserved.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 * copy of this software and associated documentation files (the "Software"),
9
 * to deal in the Software without restriction, including without limitation
10
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
 * and/or sell copies of the Software, and to permit persons to whom the
12
 * Software is furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included
15
 * in all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 * OTHER DEALINGS IN THE SOFTWARE.
24
 */
25
 
26
/*
27
 * glBlitFramebuffer functions.
28
 */
29
 
30
#include 
31
#include 
32
 
33
#include "context.h"
34
#include "enums.h"
35
#include "blit.h"
36
#include "fbobject.h"
37
#include "framebuffer.h"
38
#include "glformats.h"
39
#include "mtypes.h"
40
#include "state.h"
41
 
42
 
43
/** Set this to 1 to debug/log glBlitFramebuffer() calls */
44
#define DEBUG_BLIT 0
45
 
46
 
47
 
48
static const struct gl_renderbuffer_attachment *
49
find_attachment(const struct gl_framebuffer *fb,
50
                const struct gl_renderbuffer *rb)
51
{
52
   GLuint i;
53
   for (i = 0; i < ARRAY_SIZE(fb->Attachment); i++) {
54
      if (fb->Attachment[i].Renderbuffer == rb)
55
         return &fb->Attachment[i];
56
   }
57
   return NULL;
58
}
59
 
60
 
61
/**
62
 * Helper function for checking if the datatypes of color buffers are
63
 * compatible for glBlitFramebuffer.  From the 3.1 spec, page 198:
64
 *
65
 * "GL_INVALID_OPERATION is generated if mask contains GL_COLOR_BUFFER_BIT
66
 *  and any of the following conditions hold:
67
 *   - The read buffer contains fixed-point or floating-point values and any
68
 *     draw buffer contains neither fixed-point nor floating-point values.
69
 *   - The read buffer contains unsigned integer values and any draw buffer
70
 *     does not contain unsigned integer values.
71
 *   - The read buffer contains signed integer values and any draw buffer
72
 *     does not contain signed integer values."
73
 */
74
static GLboolean
75
compatible_color_datatypes(mesa_format srcFormat, mesa_format dstFormat)
76
{
77
   GLenum srcType = _mesa_get_format_datatype(srcFormat);
78
   GLenum dstType = _mesa_get_format_datatype(dstFormat);
79
 
80
   if (srcType != GL_INT && srcType != GL_UNSIGNED_INT) {
81
      assert(srcType == GL_UNSIGNED_NORMALIZED ||
82
             srcType == GL_SIGNED_NORMALIZED ||
83
             srcType == GL_FLOAT);
84
      /* Boil any of those types down to GL_FLOAT */
85
      srcType = GL_FLOAT;
86
   }
87
 
88
   if (dstType != GL_INT && dstType != GL_UNSIGNED_INT) {
89
      assert(dstType == GL_UNSIGNED_NORMALIZED ||
90
             dstType == GL_SIGNED_NORMALIZED ||
91
             dstType == GL_FLOAT);
92
      /* Boil any of those types down to GL_FLOAT */
93
      dstType = GL_FLOAT;
94
   }
95
 
96
   return srcType == dstType;
97
}
98
 
99
 
100
static GLboolean
101
compatible_resolve_formats(const struct gl_renderbuffer *readRb,
102
                           const struct gl_renderbuffer *drawRb)
103
{
104
   GLenum readFormat, drawFormat;
105
 
106
   /* The simple case where we know the backing Mesa formats are the same.
107
    */
108
   if (_mesa_get_srgb_format_linear(readRb->Format) ==
109
       _mesa_get_srgb_format_linear(drawRb->Format)) {
110
      return GL_TRUE;
111
   }
112
 
113
   /* The Mesa formats are different, so we must check whether the internal
114
    * formats are compatible.
115
    *
116
    * Under some circumstances, the user may request e.g. two GL_RGBA8
117
    * textures and get two entirely different Mesa formats like RGBA8888 and
118
    * ARGB8888. Drivers behaving like that should be able to cope with
119
    * non-matching formats by themselves, because it's not the user's fault.
120
    *
121
    * Blits between linear and sRGB formats are also allowed.
122
    */
123
   readFormat = _mesa_get_nongeneric_internalformat(readRb->InternalFormat);
124
   drawFormat = _mesa_get_nongeneric_internalformat(drawRb->InternalFormat);
125
   readFormat = _mesa_get_linear_internalformat(readFormat);
126
   drawFormat = _mesa_get_linear_internalformat(drawFormat);
127
 
128
   if (readFormat == drawFormat) {
129
      return GL_TRUE;
130
   }
131
 
132
   return GL_FALSE;
133
}
134
 
135
 
136
static GLboolean
137
is_valid_blit_filter(const struct gl_context *ctx, GLenum filter)
138
{
139
   switch (filter) {
140
   case GL_NEAREST:
141
   case GL_LINEAR:
142
      return true;
143
   case GL_SCALED_RESOLVE_FASTEST_EXT:
144
   case GL_SCALED_RESOLVE_NICEST_EXT:
145
      return ctx->Extensions.EXT_framebuffer_multisample_blit_scaled;
146
   default:
147
      return false;
148
   }
149
}
150
 
151
 
152
void
153
_mesa_blit_framebuffer(struct gl_context *ctx,
154
                       struct gl_framebuffer *readFb,
155
                       struct gl_framebuffer *drawFb,
156
                       GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
157
                       GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
158
                       GLbitfield mask, GLenum filter, const char *func)
159
{
160
   const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
161
                                     GL_DEPTH_BUFFER_BIT |
162
                                     GL_STENCIL_BUFFER_BIT);
163
 
164
   FLUSH_VERTICES(ctx, 0);
165
 
166
   /* Update completeness status of readFb and drawFb. */
167
   _mesa_update_framebuffer(ctx, readFb, drawFb);
168
 
169
   /* Make sure drawFb has an initialized bounding box. */
170
   _mesa_update_draw_buffer_bounds(ctx, drawFb);
171
 
172
   if (!readFb || !drawFb) {
173
      /* This will normally never happen but someday we may want to
174
       * support MakeCurrent() with no drawables.
175
       */
176
      return;
177
   }
178
 
179
   /* check for complete framebuffers */
180
   if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
181
       readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
182
      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
183
                  "%s(incomplete draw/read buffers)", func);
184
      return;
185
   }
186
 
187
   if (!is_valid_blit_filter(ctx, filter)) {
188
      _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid filter %s)", func,
189
                  _mesa_lookup_enum_by_nr(filter));
190
      return;
191
   }
192
 
193
   if ((filter == GL_SCALED_RESOLVE_FASTEST_EXT ||
194
        filter == GL_SCALED_RESOLVE_NICEST_EXT) &&
195
        (readFb->Visual.samples == 0 || drawFb->Visual.samples > 0)) {
196
      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s: invalid samples)", func,
197
                  _mesa_lookup_enum_by_nr(filter));
198
      return;
199
   }
200
 
201
   if (mask & ~legalMaskBits) {
202
      _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid mask bits set)", func);
203
      return;
204
   }
205
 
206
   /* depth/stencil must be blitted with nearest filtering */
207
   if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
208
        && filter != GL_NEAREST) {
209
      _mesa_error(ctx, GL_INVALID_OPERATION,
210
             "%s(depth/stencil requires GL_NEAREST filter)", func);
211
      return;
212
   }
213
 
214
   /* get color read/draw renderbuffers */
215
   if (mask & GL_COLOR_BUFFER_BIT) {
216
      const GLuint numColorDrawBuffers = drawFb->_NumColorDrawBuffers;
217
      const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
218
      const struct gl_renderbuffer *colorDrawRb = NULL;
219
      GLuint i;
220
 
221
      /* From the EXT_framebuffer_object spec:
222
       *
223
       *     "If a buffer is specified in  and does not exist in both
224
       *     the read and draw framebuffers, the corresponding bit is silently
225
       *     ignored."
226
       */
227
      if (!colorReadRb || numColorDrawBuffers == 0) {
228
         mask &= ~GL_COLOR_BUFFER_BIT;
229
      }
230
      else {
231
         for (i = 0; i < numColorDrawBuffers; i++) {
232
            colorDrawRb = drawFb->_ColorDrawBuffers[i];
233
            if (!colorDrawRb)
234
               continue;
235
 
236
            /* Page 193 (page 205 of the PDF) in section 4.3.2 of the OpenGL
237
             * ES 3.0.1 spec says:
238
             *
239
             *     "If the source and destination buffers are identical, an
240
             *     INVALID_OPERATION error is generated. Different mipmap
241
             *     levels of a texture, different layers of a three-
242
             *     dimensional texture or two-dimensional array texture, and
243
             *     different faces of a cube map texture do not constitute
244
             *     identical buffers."
245
             */
246
            if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) {
247
               _mesa_error(ctx, GL_INVALID_OPERATION,
248
                           "%s(source and destination color "
249
                           "buffer cannot be the same)", func);
250
               return;
251
            }
252
 
253
            if (!compatible_color_datatypes(colorReadRb->Format,
254
                                            colorDrawRb->Format)) {
255
               _mesa_error(ctx, GL_INVALID_OPERATION,
256
                           "%s(color buffer datatypes mismatch)", func);
257
               return;
258
            }
259
            /* extra checks for multisample copies... */
260
            if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
261
               /* color formats must match */
262
               if (!compatible_resolve_formats(colorReadRb, colorDrawRb)) {
263
                  _mesa_error(ctx, GL_INVALID_OPERATION,
264
                         "%s(bad src/dst multisample pixel formats)", func);
265
                  return;
266
               }
267
            }
268
         }
269
         if (filter != GL_NEAREST) {
270
            /* From EXT_framebuffer_multisample_blit_scaled specification:
271
             * "Calling BlitFramebuffer will result in an INVALID_OPERATION error
272
             * if filter is not NEAREST and read buffer contains integer data."
273
             */
274
            GLenum type = _mesa_get_format_datatype(colorReadRb->Format);
275
            if (type == GL_INT || type == GL_UNSIGNED_INT) {
276
               _mesa_error(ctx, GL_INVALID_OPERATION,
277
                           "%s(integer color type)", func);
278
               return;
279
            }
280
         }
281
      }
282
   }
283
 
284
   if (mask & GL_STENCIL_BUFFER_BIT) {
285
      struct gl_renderbuffer *readRb =
286
         readFb->Attachment[BUFFER_STENCIL].Renderbuffer;
287
      struct gl_renderbuffer *drawRb =
288
         drawFb->Attachment[BUFFER_STENCIL].Renderbuffer;
289
 
290
      /* From the EXT_framebuffer_object spec:
291
       *
292
       *     "If a buffer is specified in  and does not exist in both
293
       *     the read and draw framebuffers, the corresponding bit is silently
294
       *     ignored."
295
       */
296
      if ((readRb == NULL) || (drawRb == NULL)) {
297
         mask &= ~GL_STENCIL_BUFFER_BIT;
298
      }
299
      else {
300
         int read_z_bits, draw_z_bits;
301
 
302
         if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
303
            _mesa_error(ctx, GL_INVALID_OPERATION,
304
                        "%s(source and destination stencil "
305
                        "buffer cannot be the same)", func);
306
            return;
307
         }
308
 
309
         if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) !=
310
             _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {
311
            /* There is no need to check the stencil datatype here, because
312
             * there is only one: GL_UNSIGNED_INT.
313
             */
314
            _mesa_error(ctx, GL_INVALID_OPERATION,
315
                        "%s(stencil attachment format mismatch)", func);
316
            return;
317
         }
318
 
319
         read_z_bits = _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS);
320
         draw_z_bits = _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS);
321
 
322
         /* If both buffers also have depth data, the depth formats must match
323
          * as well.  If one doesn't have depth, it's not blitted, so we should
324
          * ignore the depth format check.
325
          */
326
         if (read_z_bits > 0 && draw_z_bits > 0 &&
327
             (read_z_bits != draw_z_bits ||
328
              _mesa_get_format_datatype(readRb->Format) !=
329
              _mesa_get_format_datatype(drawRb->Format))) {
330
 
331
            _mesa_error(ctx, GL_INVALID_OPERATION,
332
                        "%s(stencil attachment depth format mismatch)", func);
333
            return;
334
         }
335
      }
336
   }
337
 
338
   if (mask & GL_DEPTH_BUFFER_BIT) {
339
      struct gl_renderbuffer *readRb =
340
         readFb->Attachment[BUFFER_DEPTH].Renderbuffer;
341
      struct gl_renderbuffer *drawRb =
342
         drawFb->Attachment[BUFFER_DEPTH].Renderbuffer;
343
 
344
      /* From the EXT_framebuffer_object spec:
345
       *
346
       *     "If a buffer is specified in  and does not exist in both
347
       *     the read and draw framebuffers, the corresponding bit is silently
348
       *     ignored."
349
       */
350
      if ((readRb == NULL) || (drawRb == NULL)) {
351
         mask &= ~GL_DEPTH_BUFFER_BIT;
352
      }
353
      else {
354
         int read_s_bit, draw_s_bit;
355
 
356
         if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
357
            _mesa_error(ctx, GL_INVALID_OPERATION,
358
                        "%s(source and destination depth "
359
                        "buffer cannot be the same)", func);
360
            return;
361
         }
362
 
363
         if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) !=
364
              _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) ||
365
             (_mesa_get_format_datatype(readRb->Format) !=
366
              _mesa_get_format_datatype(drawRb->Format))) {
367
            _mesa_error(ctx, GL_INVALID_OPERATION,
368
                        "%s(depth attachment format mismatch)", func);
369
            return;
370
         }
371
 
372
         read_s_bit = _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS);
373
         draw_s_bit = _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS);
374
 
375
         /* If both buffers also have stencil data, the stencil formats must
376
          * match as well.  If one doesn't have stencil, it's not blitted, so
377
          * we should ignore the stencil format check.
378
          */
379
         if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) {
380
            _mesa_error(ctx, GL_INVALID_OPERATION,
381
                        "%s(depth attachment stencil bits mismatch)", func);
382
            return;
383
         }
384
      }
385
   }
386
 
387
 
388
   if (_mesa_is_gles3(ctx)) {
389
      /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
390
       * 3.0.1 spec says:
391
       *
392
       *     "If SAMPLE_BUFFERS for the draw framebuffer is greater than zero,
393
       *     an INVALID_OPERATION error is generated."
394
       */
395
      if (drawFb->Visual.samples > 0) {
396
         _mesa_error(ctx, GL_INVALID_OPERATION,
397
                     "%s(destination samples must be 0)", func);
398
         return;
399
      }
400
 
401
      /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
402
       * 3.0.1 spec says:
403
       *
404
       *     "If SAMPLE_BUFFERS for the read framebuffer is greater than zero,
405
       *     no copy is performed and an INVALID_OPERATION error is generated
406
       *     if the formats of the read and draw framebuffers are not
407
       *     identical or if the source and destination rectangles are not
408
       *     defined with the same (X0, Y0) and (X1, Y1) bounds."
409
       *
410
       * The format check was made above because desktop OpenGL has the same
411
       * requirement.
412
       */
413
      if (readFb->Visual.samples > 0
414
          && (srcX0 != dstX0 || srcY0 != dstY0
415
              || srcX1 != dstX1 || srcY1 != dstY1)) {
416
         _mesa_error(ctx, GL_INVALID_OPERATION,
417
                     "%s(bad src/dst multisample region)", func);
418
         return;
419
      }
420
   } else {
421
      if (readFb->Visual.samples > 0 &&
422
          drawFb->Visual.samples > 0 &&
423
          readFb->Visual.samples != drawFb->Visual.samples) {
424
         _mesa_error(ctx, GL_INVALID_OPERATION,
425
                     "%s(mismatched samples)", func);
426
         return;
427
      }
428
 
429
      /* extra checks for multisample copies... */
430
      if ((readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) &&
431
          (filter == GL_NEAREST || filter == GL_LINEAR)) {
432
         /* src and dest region sizes must be the same */
433
         if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) ||
434
             abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) {
435
            _mesa_error(ctx, GL_INVALID_OPERATION,
436
                        "%s(bad src/dst multisample region sizes)", func);
437
            return;
438
         }
439
      }
440
   }
441
 
442
   /* Debug code */
443
   if (DEBUG_BLIT) {
444
      const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
445
      const struct gl_renderbuffer *colorDrawRb = NULL;
446
      GLuint i = 0;
447
 
448
      printf("%s(%d, %d, %d, %d,  %d, %d, %d, %d,"
449
             " 0x%x, 0x%x)\n", func,
450
             srcX0, srcY0, srcX1, srcY1,
451
             dstX0, dstY0, dstX1, dstY1,
452
             mask, filter);
453
 
454
      if (colorReadRb) {
455
         const struct gl_renderbuffer_attachment *att;
456
 
457
         att = find_attachment(readFb, colorReadRb);
458
         printf("  Src FBO %u  RB %u (%dx%d)  ",
459
                readFb->Name, colorReadRb->Name,
460
                colorReadRb->Width, colorReadRb->Height);
461
         if (att && att->Texture) {
462
            printf("Tex %u  tgt 0x%x  level %u  face %u",
463
                   att->Texture->Name,
464
                   att->Texture->Target,
465
                   att->TextureLevel,
466
                   att->CubeMapFace);
467
         }
468
         printf("\n");
469
 
470
         /* Print all active color render buffers */
471
         for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) {
472
            colorDrawRb = drawFb->_ColorDrawBuffers[i];
473
            if (!colorDrawRb)
474
               continue;
475
 
476
            att = find_attachment(drawFb, colorDrawRb);
477
            printf("  Dst FBO %u  RB %u (%dx%d)  ",
478
                   drawFb->Name, colorDrawRb->Name,
479
                   colorDrawRb->Width, colorDrawRb->Height);
480
            if (att && att->Texture) {
481
               printf("Tex %u  tgt 0x%x  level %u  face %u",
482
                      att->Texture->Name,
483
                      att->Texture->Target,
484
                      att->TextureLevel,
485
                      att->CubeMapFace);
486
            }
487
            printf("\n");
488
         }
489
      }
490
   }
491
 
492
   if (!mask ||
493
       (srcX1 - srcX0) == 0 || (srcY1 - srcY0) == 0 ||
494
       (dstX1 - dstX0) == 0 || (dstY1 - dstY0) == 0) {
495
      return;
496
   }
497
 
498
   assert(ctx->Driver.BlitFramebuffer);
499
   ctx->Driver.BlitFramebuffer(ctx, readFb, drawFb,
500
                               srcX0, srcY0, srcX1, srcY1,
501
                               dstX0, dstY0, dstX1, dstY1,
502
                               mask, filter);
503
}
504
 
505
 
506
/**
507
 * Blit rectangular region, optionally from one framebuffer to another.
508
 *
509
 * Note, if the src buffer is multisampled and the dest is not, this is
510
 * when the samples must be resolved to a single color.
511
 */
512
void GLAPIENTRY
513
_mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
514
                      GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
515
                      GLbitfield mask, GLenum filter)
516
{
517
   GET_CURRENT_CONTEXT(ctx);
518
 
519
   if (MESA_VERBOSE & VERBOSE_API)
520
      _mesa_debug(ctx,
521
                  "glBlitFramebuffer(%d, %d, %d, %d, "
522
                  " %d, %d, %d, %d, 0x%x, %s)\n",
523
                  srcX0, srcY0, srcX1, srcY1,
524
                  dstX0, dstY0, dstX1, dstY1,
525
                  mask, _mesa_lookup_enum_by_nr(filter));
526
 
527
   _mesa_blit_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
528
                          srcX0, srcY0, srcX1, srcY1,
529
                          dstX0, dstY0, dstX1, dstY1,
530
                          mask, filter, "glBlitFramebuffer");
531
}
532
 
533
 
534
void GLAPIENTRY
535
_mesa_BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer,
536
                           GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
537
                           GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
538
                           GLbitfield mask, GLenum filter)
539
{
540
   GET_CURRENT_CONTEXT(ctx);
541
   struct gl_framebuffer *readFb, *drawFb;
542
 
543
   if (!ctx->Extensions.ARB_direct_state_access) {
544
      _mesa_error(ctx, GL_INVALID_OPERATION,
545
                  "glBlitNamedFramebuffer(GL_ARB_direct_state_access "
546
                  "is not supported)");
547
      return;
548
   }
549
 
550
   if (MESA_VERBOSE & VERBOSE_API)
551
      _mesa_debug(ctx,
552
                  "glBlitNamedFramebuffer(%u %u %d, %d, %d, %d, "
553
                  " %d, %d, %d, %d, 0x%x, %s)\n",
554
                  readFramebuffer, drawFramebuffer,
555
                  srcX0, srcY0, srcX1, srcY1,
556
                  dstX0, dstY0, dstX1, dstY1,
557
                  mask, _mesa_lookup_enum_by_nr(filter));
558
 
559
   /*
560
    * According to PDF page 533 of the OpenGL 4.5 core spec (30.10.2014,
561
    * Section 18.3 Copying Pixels):
562
    *   "... if readFramebuffer or drawFramebuffer is zero (for
563
    *   BlitNamedFramebuffer), then the default read or draw framebuffer is
564
    *   used as the corresponding source or destination framebuffer,
565
    *   respectively."
566
    */
567
   if (readFramebuffer) {
568
      readFb = _mesa_lookup_framebuffer_err(ctx, readFramebuffer,
569
                                            "glBlitNamedFramebuffer");
570
      if (!readFb)
571
         return;
572
   }
573
   else
574
      readFb = ctx->WinSysReadBuffer;
575
 
576
   if (drawFramebuffer) {
577
      drawFb = _mesa_lookup_framebuffer_err(ctx, drawFramebuffer,
578
                                            "glBlitNamedFramebuffer");
579
      if (!drawFb)
580
         return;
581
   }
582
   else
583
      drawFb = ctx->WinSysDrawBuffer;
584
 
585
   _mesa_blit_framebuffer(ctx, readFb, drawFb,
586
                          srcX0, srcY0, srcX1, srcY1,
587
                          dstX0, dstY0, dstX1, dstY1,
588
                          mask, filter, "glBlitNamedFramebuffer");
589
}