mesa/blit: Don't require the same format for mulitisample blits
[mesa.git] / src / mesa / main / blit.c
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 <stdbool.h>
31 #include <stdio.h>
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 "macros.h"
41 #include "state.h"
42
43
44 /** Set this to 1 to debug/log glBlitFramebuffer() calls */
45 #define DEBUG_BLIT 0
46
47
48
49 static const struct gl_renderbuffer_attachment *
50 find_attachment(const struct gl_framebuffer *fb,
51 const struct gl_renderbuffer *rb)
52 {
53 GLuint i;
54 for (i = 0; i < ARRAY_SIZE(fb->Attachment); i++) {
55 if (fb->Attachment[i].Renderbuffer == rb)
56 return &fb->Attachment[i];
57 }
58 return NULL;
59 }
60
61
62 /**
63 * \return true if two regions overlap, false otherwise
64 */
65 bool
66 _mesa_regions_overlap(int srcX0, int srcY0,
67 int srcX1, int srcY1,
68 int dstX0, int dstY0,
69 int dstX1, int dstY1)
70 {
71 if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1))
72 return false; /* dst completely right of src */
73
74 if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1))
75 return false; /* dst completely left of src */
76
77 if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1))
78 return false; /* dst completely above src */
79
80 if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1))
81 return false; /* dst completely below src */
82
83 return true; /* some overlap */
84 }
85
86
87 /**
88 * Helper function for checking if the datatypes of color buffers are
89 * compatible for glBlitFramebuffer. From the 3.1 spec, page 198:
90 *
91 * "GL_INVALID_OPERATION is generated if mask contains GL_COLOR_BUFFER_BIT
92 * and any of the following conditions hold:
93 * - The read buffer contains fixed-point or floating-point values and any
94 * draw buffer contains neither fixed-point nor floating-point values.
95 * - The read buffer contains unsigned integer values and any draw buffer
96 * does not contain unsigned integer values.
97 * - The read buffer contains signed integer values and any draw buffer
98 * does not contain signed integer values."
99 */
100 static GLboolean
101 compatible_color_datatypes(mesa_format srcFormat, mesa_format dstFormat)
102 {
103 GLenum srcType = _mesa_get_format_datatype(srcFormat);
104 GLenum dstType = _mesa_get_format_datatype(dstFormat);
105
106 if (srcType != GL_INT && srcType != GL_UNSIGNED_INT) {
107 assert(srcType == GL_UNSIGNED_NORMALIZED ||
108 srcType == GL_SIGNED_NORMALIZED ||
109 srcType == GL_FLOAT);
110 /* Boil any of those types down to GL_FLOAT */
111 srcType = GL_FLOAT;
112 }
113
114 if (dstType != GL_INT && dstType != GL_UNSIGNED_INT) {
115 assert(dstType == GL_UNSIGNED_NORMALIZED ||
116 dstType == GL_SIGNED_NORMALIZED ||
117 dstType == GL_FLOAT);
118 /* Boil any of those types down to GL_FLOAT */
119 dstType = GL_FLOAT;
120 }
121
122 return srcType == dstType;
123 }
124
125
126 static GLboolean
127 compatible_resolve_formats(const struct gl_renderbuffer *readRb,
128 const struct gl_renderbuffer *drawRb)
129 {
130 GLenum readFormat, drawFormat;
131
132 /* This checks whether the internal formats are compatible rather than the
133 * Mesa format for two reasons:
134 *
135 * • Under some circumstances, the user may request e.g. two GL_RGBA8
136 * textures and get two entirely different Mesa formats like RGBA8888 and
137 * ARGB8888. Drivers behaving like that should be able to cope with
138 * non-matching formats by themselves, because it's not the user's fault.
139 *
140 * • Picking two different internal formats can end up with the same Mesa
141 * format. For example the driver might be simulating GL_RGB textures
142 * with GL_RGBA internally and in that case both internal formats would
143 * end up with RGBA8888.
144 *
145 * This function is used to generate a GL error according to the spec so in
146 * both cases we want to be looking at the application-level format, which
147 * is InternalFormat.
148 *
149 * Blits between linear and sRGB formats are also allowed.
150 */
151 readFormat = _mesa_get_nongeneric_internalformat(readRb->InternalFormat);
152 drawFormat = _mesa_get_nongeneric_internalformat(drawRb->InternalFormat);
153 readFormat = _mesa_get_linear_internalformat(readFormat);
154 drawFormat = _mesa_get_linear_internalformat(drawFormat);
155
156 if (readFormat == drawFormat) {
157 return GL_TRUE;
158 }
159
160 return GL_FALSE;
161 }
162
163
164 static GLboolean
165 is_valid_blit_filter(const struct gl_context *ctx, GLenum filter)
166 {
167 switch (filter) {
168 case GL_NEAREST:
169 case GL_LINEAR:
170 return true;
171 case GL_SCALED_RESOLVE_FASTEST_EXT:
172 case GL_SCALED_RESOLVE_NICEST_EXT:
173 return ctx->Extensions.EXT_framebuffer_multisample_blit_scaled;
174 default:
175 return false;
176 }
177 }
178
179
180 void
181 _mesa_blit_framebuffer(struct gl_context *ctx,
182 struct gl_framebuffer *readFb,
183 struct gl_framebuffer *drawFb,
184 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
185 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
186 GLbitfield mask, GLenum filter, const char *func)
187 {
188 const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
189 GL_DEPTH_BUFFER_BIT |
190 GL_STENCIL_BUFFER_BIT);
191
192 FLUSH_VERTICES(ctx, 0);
193
194 /* Update completeness status of readFb and drawFb. */
195 _mesa_update_framebuffer(ctx, readFb, drawFb);
196
197 /* Make sure drawFb has an initialized bounding box. */
198 _mesa_update_draw_buffer_bounds(ctx, drawFb);
199
200 if (!readFb || !drawFb) {
201 /* This will normally never happen but someday we may want to
202 * support MakeCurrent() with no drawables.
203 */
204 return;
205 }
206
207 /* check for complete framebuffers */
208 if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
209 readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
210 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
211 "%s(incomplete draw/read buffers)", func);
212 return;
213 }
214
215 if (!is_valid_blit_filter(ctx, filter)) {
216 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid filter %s)", func,
217 _mesa_enum_to_string(filter));
218 return;
219 }
220
221 if ((filter == GL_SCALED_RESOLVE_FASTEST_EXT ||
222 filter == GL_SCALED_RESOLVE_NICEST_EXT) &&
223 (readFb->Visual.samples == 0 || drawFb->Visual.samples > 0)) {
224 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s: invalid samples)", func,
225 _mesa_enum_to_string(filter));
226 return;
227 }
228
229 if (mask & ~legalMaskBits) {
230 _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid mask bits set)", func);
231 return;
232 }
233
234 /* depth/stencil must be blitted with nearest filtering */
235 if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
236 && filter != GL_NEAREST) {
237 _mesa_error(ctx, GL_INVALID_OPERATION,
238 "%s(depth/stencil requires GL_NEAREST filter)", func);
239 return;
240 }
241
242 /* get color read/draw renderbuffers */
243 if (mask & GL_COLOR_BUFFER_BIT) {
244 const GLuint numColorDrawBuffers = drawFb->_NumColorDrawBuffers;
245 const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
246 const struct gl_renderbuffer *colorDrawRb = NULL;
247 GLuint i;
248
249 /* From the EXT_framebuffer_object spec:
250 *
251 * "If a buffer is specified in <mask> and does not exist in both
252 * the read and draw framebuffers, the corresponding bit is silently
253 * ignored."
254 */
255 if (!colorReadRb || numColorDrawBuffers == 0) {
256 mask &= ~GL_COLOR_BUFFER_BIT;
257 }
258 else {
259 for (i = 0; i < numColorDrawBuffers; i++) {
260 colorDrawRb = drawFb->_ColorDrawBuffers[i];
261 if (!colorDrawRb)
262 continue;
263
264 /* Page 193 (page 205 of the PDF) in section 4.3.2 of the OpenGL
265 * ES 3.0.1 spec says:
266 *
267 * "If the source and destination buffers are identical, an
268 * INVALID_OPERATION error is generated. Different mipmap
269 * levels of a texture, different layers of a three-
270 * dimensional texture or two-dimensional array texture, and
271 * different faces of a cube map texture do not constitute
272 * identical buffers."
273 */
274 if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) {
275 _mesa_error(ctx, GL_INVALID_OPERATION,
276 "%s(source and destination color "
277 "buffer cannot be the same)", func);
278 return;
279 }
280
281 if (!compatible_color_datatypes(colorReadRb->Format,
282 colorDrawRb->Format)) {
283 _mesa_error(ctx, GL_INVALID_OPERATION,
284 "%s(color buffer datatypes mismatch)", func);
285 return;
286 }
287 /* extra checks for multisample copies... */
288 if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
289 /* color formats must match on GLES. This isn't checked on
290 * desktop GL because the GL 4.4 spec was changed to allow it.
291 * In the section entitled “Changes in the released
292 * Specification of July 22, 2013” it says:
293 *
294 * “Relax BlitFramebuffer in section 18.3.1 so that format
295 * conversion can take place during multisample blits, since
296 * drivers already allow this and some apps depend on it.”
297 */
298 if (_mesa_is_gles(ctx) &&
299 !compatible_resolve_formats(colorReadRb, colorDrawRb)) {
300 _mesa_error(ctx, GL_INVALID_OPERATION,
301 "%s(bad src/dst multisample pixel formats)", func);
302 return;
303 }
304 }
305 }
306 if (filter != GL_NEAREST) {
307 /* From EXT_framebuffer_multisample_blit_scaled specification:
308 * "Calling BlitFramebuffer will result in an INVALID_OPERATION error
309 * if filter is not NEAREST and read buffer contains integer data."
310 */
311 GLenum type = _mesa_get_format_datatype(colorReadRb->Format);
312 if (type == GL_INT || type == GL_UNSIGNED_INT) {
313 _mesa_error(ctx, GL_INVALID_OPERATION,
314 "%s(integer color type)", func);
315 return;
316 }
317 }
318 }
319 }
320
321 if (mask & GL_STENCIL_BUFFER_BIT) {
322 struct gl_renderbuffer *readRb =
323 readFb->Attachment[BUFFER_STENCIL].Renderbuffer;
324 struct gl_renderbuffer *drawRb =
325 drawFb->Attachment[BUFFER_STENCIL].Renderbuffer;
326
327 /* From the EXT_framebuffer_object spec:
328 *
329 * "If a buffer is specified in <mask> and does not exist in both
330 * the read and draw framebuffers, the corresponding bit is silently
331 * ignored."
332 */
333 if ((readRb == NULL) || (drawRb == NULL)) {
334 mask &= ~GL_STENCIL_BUFFER_BIT;
335 }
336 else {
337 int read_z_bits, draw_z_bits;
338
339 if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
340 _mesa_error(ctx, GL_INVALID_OPERATION,
341 "%s(source and destination stencil "
342 "buffer cannot be the same)", func);
343 return;
344 }
345
346 if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) !=
347 _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {
348 /* There is no need to check the stencil datatype here, because
349 * there is only one: GL_UNSIGNED_INT.
350 */
351 _mesa_error(ctx, GL_INVALID_OPERATION,
352 "%s(stencil attachment format mismatch)", func);
353 return;
354 }
355
356 read_z_bits = _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS);
357 draw_z_bits = _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS);
358
359 /* If both buffers also have depth data, the depth formats must match
360 * as well. If one doesn't have depth, it's not blitted, so we should
361 * ignore the depth format check.
362 */
363 if (read_z_bits > 0 && draw_z_bits > 0 &&
364 (read_z_bits != draw_z_bits ||
365 _mesa_get_format_datatype(readRb->Format) !=
366 _mesa_get_format_datatype(drawRb->Format))) {
367
368 _mesa_error(ctx, GL_INVALID_OPERATION,
369 "%s(stencil attachment depth format mismatch)", func);
370 return;
371 }
372 }
373 }
374
375 if (mask & GL_DEPTH_BUFFER_BIT) {
376 struct gl_renderbuffer *readRb =
377 readFb->Attachment[BUFFER_DEPTH].Renderbuffer;
378 struct gl_renderbuffer *drawRb =
379 drawFb->Attachment[BUFFER_DEPTH].Renderbuffer;
380
381 /* From the EXT_framebuffer_object spec:
382 *
383 * "If a buffer is specified in <mask> and does not exist in both
384 * the read and draw framebuffers, the corresponding bit is silently
385 * ignored."
386 */
387 if ((readRb == NULL) || (drawRb == NULL)) {
388 mask &= ~GL_DEPTH_BUFFER_BIT;
389 }
390 else {
391 int read_s_bit, draw_s_bit;
392
393 if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
394 _mesa_error(ctx, GL_INVALID_OPERATION,
395 "%s(source and destination depth "
396 "buffer cannot be the same)", func);
397 return;
398 }
399
400 if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) !=
401 _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) ||
402 (_mesa_get_format_datatype(readRb->Format) !=
403 _mesa_get_format_datatype(drawRb->Format))) {
404 _mesa_error(ctx, GL_INVALID_OPERATION,
405 "%s(depth attachment format mismatch)", func);
406 return;
407 }
408
409 read_s_bit = _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS);
410 draw_s_bit = _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS);
411
412 /* If both buffers also have stencil data, the stencil formats must
413 * match as well. If one doesn't have stencil, it's not blitted, so
414 * we should ignore the stencil format check.
415 */
416 if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) {
417 _mesa_error(ctx, GL_INVALID_OPERATION,
418 "%s(depth attachment stencil bits mismatch)", func);
419 return;
420 }
421 }
422 }
423
424
425 if (_mesa_is_gles3(ctx)) {
426 /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
427 * 3.0.1 spec says:
428 *
429 * "If SAMPLE_BUFFERS for the draw framebuffer is greater than zero,
430 * an INVALID_OPERATION error is generated."
431 */
432 if (drawFb->Visual.samples > 0) {
433 _mesa_error(ctx, GL_INVALID_OPERATION,
434 "%s(destination samples must be 0)", func);
435 return;
436 }
437
438 /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
439 * 3.0.1 spec says:
440 *
441 * "If SAMPLE_BUFFERS for the read framebuffer is greater than zero,
442 * no copy is performed and an INVALID_OPERATION error is generated
443 * if the formats of the read and draw framebuffers are not
444 * identical or if the source and destination rectangles are not
445 * defined with the same (X0, Y0) and (X1, Y1) bounds."
446 *
447 * The format check was made above because desktop OpenGL has the same
448 * requirement.
449 */
450 if (readFb->Visual.samples > 0
451 && (srcX0 != dstX0 || srcY0 != dstY0
452 || srcX1 != dstX1 || srcY1 != dstY1)) {
453 _mesa_error(ctx, GL_INVALID_OPERATION,
454 "%s(bad src/dst multisample region)", func);
455 return;
456 }
457 } else {
458 if (readFb->Visual.samples > 0 &&
459 drawFb->Visual.samples > 0 &&
460 readFb->Visual.samples != drawFb->Visual.samples) {
461 _mesa_error(ctx, GL_INVALID_OPERATION,
462 "%s(mismatched samples)", func);
463 return;
464 }
465
466 /* extra checks for multisample copies... */
467 if ((readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) &&
468 (filter == GL_NEAREST || filter == GL_LINEAR)) {
469 /* src and dest region sizes must be the same */
470 if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) ||
471 abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) {
472 _mesa_error(ctx, GL_INVALID_OPERATION,
473 "%s(bad src/dst multisample region sizes)", func);
474 return;
475 }
476 }
477 }
478
479 /* Debug code */
480 if (DEBUG_BLIT) {
481 const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
482 const struct gl_renderbuffer *colorDrawRb = NULL;
483 GLuint i = 0;
484
485 printf("%s(%d, %d, %d, %d, %d, %d, %d, %d,"
486 " 0x%x, 0x%x)\n", func,
487 srcX0, srcY0, srcX1, srcY1,
488 dstX0, dstY0, dstX1, dstY1,
489 mask, filter);
490
491 if (colorReadRb) {
492 const struct gl_renderbuffer_attachment *att;
493
494 att = find_attachment(readFb, colorReadRb);
495 printf(" Src FBO %u RB %u (%dx%d) ",
496 readFb->Name, colorReadRb->Name,
497 colorReadRb->Width, colorReadRb->Height);
498 if (att && att->Texture) {
499 printf("Tex %u tgt 0x%x level %u face %u",
500 att->Texture->Name,
501 att->Texture->Target,
502 att->TextureLevel,
503 att->CubeMapFace);
504 }
505 printf("\n");
506
507 /* Print all active color render buffers */
508 for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) {
509 colorDrawRb = drawFb->_ColorDrawBuffers[i];
510 if (!colorDrawRb)
511 continue;
512
513 att = find_attachment(drawFb, colorDrawRb);
514 printf(" Dst FBO %u RB %u (%dx%d) ",
515 drawFb->Name, colorDrawRb->Name,
516 colorDrawRb->Width, colorDrawRb->Height);
517 if (att && att->Texture) {
518 printf("Tex %u tgt 0x%x level %u face %u",
519 att->Texture->Name,
520 att->Texture->Target,
521 att->TextureLevel,
522 att->CubeMapFace);
523 }
524 printf("\n");
525 }
526 }
527 }
528
529 if (!mask ||
530 (srcX1 - srcX0) == 0 || (srcY1 - srcY0) == 0 ||
531 (dstX1 - dstX0) == 0 || (dstY1 - dstY0) == 0) {
532 return;
533 }
534
535 assert(ctx->Driver.BlitFramebuffer);
536 ctx->Driver.BlitFramebuffer(ctx, readFb, drawFb,
537 srcX0, srcY0, srcX1, srcY1,
538 dstX0, dstY0, dstX1, dstY1,
539 mask, filter);
540 }
541
542
543 /**
544 * Blit rectangular region, optionally from one framebuffer to another.
545 *
546 * Note, if the src buffer is multisampled and the dest is not, this is
547 * when the samples must be resolved to a single color.
548 */
549 void GLAPIENTRY
550 _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
551 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
552 GLbitfield mask, GLenum filter)
553 {
554 GET_CURRENT_CONTEXT(ctx);
555
556 if (MESA_VERBOSE & VERBOSE_API)
557 _mesa_debug(ctx,
558 "glBlitFramebuffer(%d, %d, %d, %d, "
559 " %d, %d, %d, %d, 0x%x, %s)\n",
560 srcX0, srcY0, srcX1, srcY1,
561 dstX0, dstY0, dstX1, dstY1,
562 mask, _mesa_enum_to_string(filter));
563
564 _mesa_blit_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
565 srcX0, srcY0, srcX1, srcY1,
566 dstX0, dstY0, dstX1, dstY1,
567 mask, filter, "glBlitFramebuffer");
568 }
569
570
571 void GLAPIENTRY
572 _mesa_BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer,
573 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
574 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
575 GLbitfield mask, GLenum filter)
576 {
577 GET_CURRENT_CONTEXT(ctx);
578 struct gl_framebuffer *readFb, *drawFb;
579
580 if (MESA_VERBOSE & VERBOSE_API)
581 _mesa_debug(ctx,
582 "glBlitNamedFramebuffer(%u %u %d, %d, %d, %d, "
583 " %d, %d, %d, %d, 0x%x, %s)\n",
584 readFramebuffer, drawFramebuffer,
585 srcX0, srcY0, srcX1, srcY1,
586 dstX0, dstY0, dstX1, dstY1,
587 mask, _mesa_enum_to_string(filter));
588
589 /*
590 * According to PDF page 533 of the OpenGL 4.5 core spec (30.10.2014,
591 * Section 18.3 Copying Pixels):
592 * "... if readFramebuffer or drawFramebuffer is zero (for
593 * BlitNamedFramebuffer), then the default read or draw framebuffer is
594 * used as the corresponding source or destination framebuffer,
595 * respectively."
596 */
597 if (readFramebuffer) {
598 readFb = _mesa_lookup_framebuffer_err(ctx, readFramebuffer,
599 "glBlitNamedFramebuffer");
600 if (!readFb)
601 return;
602 }
603 else
604 readFb = ctx->WinSysReadBuffer;
605
606 if (drawFramebuffer) {
607 drawFb = _mesa_lookup_framebuffer_err(ctx, drawFramebuffer,
608 "glBlitNamedFramebuffer");
609 if (!drawFb)
610 return;
611 }
612 else
613 drawFb = ctx->WinSysDrawBuffer;
614
615 _mesa_blit_framebuffer(ctx, readFb, drawFb,
616 srcX0, srcY0, srcX1, srcY1,
617 dstX0, dstY0, dstX1, dstY1,
618 mask, filter, "glBlitNamedFramebuffer");
619 }