2 * Mesa 3-D graphics library
4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
5 * Copyright (C) 1999-2013 VMware, Inc. All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
27 * glBlitFramebuffer functions.
37 #include "glformats.h"
42 /** Set this to 1 to debug/log glBlitFramebuffer() calls */
47 static const struct gl_renderbuffer_attachment
*
48 find_attachment(const struct gl_framebuffer
*fb
,
49 const struct gl_renderbuffer
*rb
)
52 for (i
= 0; i
< ARRAY_SIZE(fb
->Attachment
); i
++) {
53 if (fb
->Attachment
[i
].Renderbuffer
== rb
)
54 return &fb
->Attachment
[i
];
61 * Helper function for checking if the datatypes of color buffers are
62 * compatible for glBlitFramebuffer. From the 3.1 spec, page 198:
64 * "GL_INVALID_OPERATION is generated if mask contains GL_COLOR_BUFFER_BIT
65 * and any of the following conditions hold:
66 * - The read buffer contains fixed-point or floating-point values and any
67 * draw buffer contains neither fixed-point nor floating-point values.
68 * - The read buffer contains unsigned integer values and any draw buffer
69 * does not contain unsigned integer values.
70 * - The read buffer contains signed integer values and any draw buffer
71 * does not contain signed integer values."
74 compatible_color_datatypes(mesa_format srcFormat
, mesa_format dstFormat
)
76 GLenum srcType
= _mesa_get_format_datatype(srcFormat
);
77 GLenum dstType
= _mesa_get_format_datatype(dstFormat
);
79 if (srcType
!= GL_INT
&& srcType
!= GL_UNSIGNED_INT
) {
80 assert(srcType
== GL_UNSIGNED_NORMALIZED
||
81 srcType
== GL_SIGNED_NORMALIZED
||
83 /* Boil any of those types down to GL_FLOAT */
87 if (dstType
!= GL_INT
&& dstType
!= GL_UNSIGNED_INT
) {
88 assert(dstType
== GL_UNSIGNED_NORMALIZED
||
89 dstType
== GL_SIGNED_NORMALIZED
||
91 /* Boil any of those types down to GL_FLOAT */
95 return srcType
== dstType
;
100 compatible_resolve_formats(const struct gl_renderbuffer
*readRb
,
101 const struct gl_renderbuffer
*drawRb
)
103 GLenum readFormat
, drawFormat
;
105 /* The simple case where we know the backing Mesa formats are the same.
107 if (_mesa_get_srgb_format_linear(readRb
->Format
) ==
108 _mesa_get_srgb_format_linear(drawRb
->Format
)) {
112 /* The Mesa formats are different, so we must check whether the internal
113 * formats are compatible.
115 * Under some circumstances, the user may request e.g. two GL_RGBA8
116 * textures and get two entirely different Mesa formats like RGBA8888 and
117 * ARGB8888. Drivers behaving like that should be able to cope with
118 * non-matching formats by themselves, because it's not the user's fault.
120 * Blits between linear and sRGB formats are also allowed.
122 readFormat
= _mesa_get_nongeneric_internalformat(readRb
->InternalFormat
);
123 drawFormat
= _mesa_get_nongeneric_internalformat(drawRb
->InternalFormat
);
124 readFormat
= _mesa_get_linear_internalformat(readFormat
);
125 drawFormat
= _mesa_get_linear_internalformat(drawFormat
);
127 if (readFormat
== drawFormat
) {
136 is_valid_blit_filter(const struct gl_context
*ctx
, GLenum filter
)
142 case GL_SCALED_RESOLVE_FASTEST_EXT
:
143 case GL_SCALED_RESOLVE_NICEST_EXT
:
144 return ctx
->Extensions
.EXT_framebuffer_multisample_blit_scaled
;
152 * Blit rectangular region, optionally from one framebuffer to another.
154 * Note, if the src buffer is multisampled and the dest is not, this is
155 * when the samples must be resolved to a single color.
158 _mesa_BlitFramebuffer(GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
159 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
160 GLbitfield mask
, GLenum filter
)
162 const GLbitfield legalMaskBits
= (GL_COLOR_BUFFER_BIT
|
163 GL_DEPTH_BUFFER_BIT
|
164 GL_STENCIL_BUFFER_BIT
);
165 const struct gl_framebuffer
*readFb
, *drawFb
;
166 GET_CURRENT_CONTEXT(ctx
);
168 FLUSH_VERTICES(ctx
, 0);
170 if (MESA_VERBOSE
& VERBOSE_API
)
172 "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n",
173 srcX0
, srcY0
, srcX1
, srcY1
,
174 dstX0
, dstY0
, dstX1
, dstY1
,
175 mask
, _mesa_lookup_enum_by_nr(filter
));
178 _mesa_update_state(ctx
);
181 readFb
= ctx
->ReadBuffer
;
182 drawFb
= ctx
->DrawBuffer
;
184 if (!readFb
|| !drawFb
) {
185 /* This will normally never happen but someday we may want to
186 * support MakeCurrent() with no drawables.
191 /* check for complete framebuffers */
192 if (drawFb
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
||
193 readFb
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
194 _mesa_error(ctx
, GL_INVALID_FRAMEBUFFER_OPERATION_EXT
,
195 "glBlitFramebufferEXT(incomplete draw/read buffers)");
199 if (!is_valid_blit_filter(ctx
, filter
)) {
200 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlitFramebufferEXT(%s)",
201 _mesa_lookup_enum_by_nr(filter
));
205 if ((filter
== GL_SCALED_RESOLVE_FASTEST_EXT
||
206 filter
== GL_SCALED_RESOLVE_NICEST_EXT
) &&
207 (readFb
->Visual
.samples
== 0 || drawFb
->Visual
.samples
> 0)) {
208 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glBlitFramebufferEXT(%s)",
209 _mesa_lookup_enum_by_nr(filter
));
213 if (mask
& ~legalMaskBits
) {
214 _mesa_error( ctx
, GL_INVALID_VALUE
, "glBlitFramebufferEXT(mask)");
218 /* depth/stencil must be blitted with nearest filtering */
219 if ((mask
& (GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
))
220 && filter
!= GL_NEAREST
) {
221 _mesa_error(ctx
, GL_INVALID_OPERATION
,
222 "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)");
226 /* get color read/draw renderbuffers */
227 if (mask
& GL_COLOR_BUFFER_BIT
) {
228 const GLuint numColorDrawBuffers
= ctx
->DrawBuffer
->_NumColorDrawBuffers
;
229 const struct gl_renderbuffer
*colorReadRb
= readFb
->_ColorReadBuffer
;
230 const struct gl_renderbuffer
*colorDrawRb
= NULL
;
233 /* From the EXT_framebuffer_object spec:
235 * "If a buffer is specified in <mask> and does not exist in both
236 * the read and draw framebuffers, the corresponding bit is silently
239 if (!colorReadRb
|| numColorDrawBuffers
== 0) {
240 mask
&= ~GL_COLOR_BUFFER_BIT
;
243 for (i
= 0; i
< numColorDrawBuffers
; i
++) {
244 colorDrawRb
= ctx
->DrawBuffer
->_ColorDrawBuffers
[i
];
248 /* Page 193 (page 205 of the PDF) in section 4.3.2 of the OpenGL
249 * ES 3.0.1 spec says:
251 * "If the source and destination buffers are identical, an
252 * INVALID_OPERATION error is generated. Different mipmap
253 * levels of a texture, different layers of a three-
254 * dimensional texture or two-dimensional array texture, and
255 * different faces of a cube map texture do not constitute
256 * identical buffers."
258 if (_mesa_is_gles3(ctx
) && (colorDrawRb
== colorReadRb
)) {
259 _mesa_error(ctx
, GL_INVALID_OPERATION
,
260 "glBlitFramebuffer(source and destination color "
261 "buffer cannot be the same)");
265 if (!compatible_color_datatypes(colorReadRb
->Format
,
266 colorDrawRb
->Format
)) {
267 _mesa_error(ctx
, GL_INVALID_OPERATION
,
268 "glBlitFramebufferEXT(color buffer datatypes mismatch)");
271 /* extra checks for multisample copies... */
272 if (readFb
->Visual
.samples
> 0 || drawFb
->Visual
.samples
> 0) {
273 /* color formats must match */
274 if (!compatible_resolve_formats(colorReadRb
, colorDrawRb
)) {
275 _mesa_error(ctx
, GL_INVALID_OPERATION
,
276 "glBlitFramebufferEXT(bad src/dst multisample pixel formats)");
281 if (filter
!= GL_NEAREST
) {
282 /* From EXT_framebuffer_multisample_blit_scaled specification:
283 * "Calling BlitFramebuffer will result in an INVALID_OPERATION error
284 * if filter is not NEAREST and read buffer contains integer data."
286 GLenum type
= _mesa_get_format_datatype(colorReadRb
->Format
);
287 if (type
== GL_INT
|| type
== GL_UNSIGNED_INT
) {
288 _mesa_error(ctx
, GL_INVALID_OPERATION
,
289 "glBlitFramebufferEXT(integer color type)");
296 if (mask
& GL_STENCIL_BUFFER_BIT
) {
297 struct gl_renderbuffer
*readRb
=
298 readFb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
299 struct gl_renderbuffer
*drawRb
=
300 drawFb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
302 /* From the EXT_framebuffer_object spec:
304 * "If a buffer is specified in <mask> and does not exist in both
305 * the read and draw framebuffers, the corresponding bit is silently
308 if ((readRb
== NULL
) || (drawRb
== NULL
)) {
309 mask
&= ~GL_STENCIL_BUFFER_BIT
;
312 int read_z_bits
, draw_z_bits
;
314 if (_mesa_is_gles3(ctx
) && (drawRb
== readRb
)) {
315 _mesa_error(ctx
, GL_INVALID_OPERATION
,
316 "glBlitFramebuffer(source and destination stencil "
317 "buffer cannot be the same)");
321 if (_mesa_get_format_bits(readRb
->Format
, GL_STENCIL_BITS
) !=
322 _mesa_get_format_bits(drawRb
->Format
, GL_STENCIL_BITS
)) {
323 /* There is no need to check the stencil datatype here, because
324 * there is only one: GL_UNSIGNED_INT.
326 _mesa_error(ctx
, GL_INVALID_OPERATION
,
327 "glBlitFramebuffer(stencil attachment format mismatch)");
331 read_z_bits
= _mesa_get_format_bits(readRb
->Format
, GL_DEPTH_BITS
);
332 draw_z_bits
= _mesa_get_format_bits(drawRb
->Format
, GL_DEPTH_BITS
);
334 /* If both buffers also have depth data, the depth formats must match
335 * as well. If one doesn't have depth, it's not blitted, so we should
336 * ignore the depth format check.
338 if (read_z_bits
> 0 && draw_z_bits
> 0 &&
339 (read_z_bits
!= draw_z_bits
||
340 _mesa_get_format_datatype(readRb
->Format
) !=
341 _mesa_get_format_datatype(drawRb
->Format
))) {
343 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glBlitFramebuffer"
344 "(stencil attachment depth format mismatch)");
350 if (mask
& GL_DEPTH_BUFFER_BIT
) {
351 struct gl_renderbuffer
*readRb
=
352 readFb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
353 struct gl_renderbuffer
*drawRb
=
354 drawFb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
356 /* From the EXT_framebuffer_object spec:
358 * "If a buffer is specified in <mask> and does not exist in both
359 * the read and draw framebuffers, the corresponding bit is silently
362 if ((readRb
== NULL
) || (drawRb
== NULL
)) {
363 mask
&= ~GL_DEPTH_BUFFER_BIT
;
366 int read_s_bit
, draw_s_bit
;
368 if (_mesa_is_gles3(ctx
) && (drawRb
== readRb
)) {
369 _mesa_error(ctx
, GL_INVALID_OPERATION
,
370 "glBlitFramebuffer(source and destination depth "
371 "buffer cannot be the same)");
375 if ((_mesa_get_format_bits(readRb
->Format
, GL_DEPTH_BITS
) !=
376 _mesa_get_format_bits(drawRb
->Format
, GL_DEPTH_BITS
)) ||
377 (_mesa_get_format_datatype(readRb
->Format
) !=
378 _mesa_get_format_datatype(drawRb
->Format
))) {
379 _mesa_error(ctx
, GL_INVALID_OPERATION
,
380 "glBlitFramebuffer(depth attachment format mismatch)");
384 read_s_bit
= _mesa_get_format_bits(readRb
->Format
, GL_STENCIL_BITS
);
385 draw_s_bit
= _mesa_get_format_bits(drawRb
->Format
, GL_STENCIL_BITS
);
387 /* If both buffers also have stencil data, the stencil formats must
388 * match as well. If one doesn't have stencil, it's not blitted, so
389 * we should ignore the stencil format check.
391 if (read_s_bit
> 0 && draw_s_bit
> 0 && read_s_bit
!= draw_s_bit
) {
392 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glBlitFramebuffer"
393 "(depth attachment stencil bits mismatch)");
400 if (_mesa_is_gles3(ctx
)) {
401 /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
404 * "If SAMPLE_BUFFERS for the draw framebuffer is greater than zero,
405 * an INVALID_OPERATION error is generated."
407 if (drawFb
->Visual
.samples
> 0) {
408 _mesa_error(ctx
, GL_INVALID_OPERATION
,
409 "glBlitFramebuffer(destination samples must be 0)");
413 /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
416 * "If SAMPLE_BUFFERS for the read framebuffer is greater than zero,
417 * no copy is performed and an INVALID_OPERATION error is generated
418 * if the formats of the read and draw framebuffers are not
419 * identical or if the source and destination rectangles are not
420 * defined with the same (X0, Y0) and (X1, Y1) bounds."
422 * The format check was made above because desktop OpenGL has the same
425 if (readFb
->Visual
.samples
> 0
426 && (srcX0
!= dstX0
|| srcY0
!= dstY0
427 || srcX1
!= dstX1
|| srcY1
!= dstY1
)) {
428 _mesa_error(ctx
, GL_INVALID_OPERATION
,
429 "glBlitFramebuffer(bad src/dst multisample region)");
433 if (readFb
->Visual
.samples
> 0 &&
434 drawFb
->Visual
.samples
> 0 &&
435 readFb
->Visual
.samples
!= drawFb
->Visual
.samples
) {
436 _mesa_error(ctx
, GL_INVALID_OPERATION
,
437 "glBlitFramebufferEXT(mismatched samples)");
441 /* extra checks for multisample copies... */
442 if ((readFb
->Visual
.samples
> 0 || drawFb
->Visual
.samples
> 0) &&
443 (filter
== GL_NEAREST
|| filter
== GL_LINEAR
)) {
444 /* src and dest region sizes must be the same */
445 if (abs(srcX1
- srcX0
) != abs(dstX1
- dstX0
) ||
446 abs(srcY1
- srcY0
) != abs(dstY1
- dstY0
)) {
447 _mesa_error(ctx
, GL_INVALID_OPERATION
,
448 "glBlitFramebufferEXT(bad src/dst multisample region sizes)");
456 const struct gl_renderbuffer
*colorReadRb
= readFb
->_ColorReadBuffer
;
457 const struct gl_renderbuffer
*colorDrawRb
= NULL
;
460 printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d,"
462 srcX0
, srcY0
, srcX1
, srcY1
,
463 dstX0
, dstY0
, dstX1
, dstY1
,
466 const struct gl_renderbuffer_attachment
*att
;
468 att
= find_attachment(readFb
, colorReadRb
);
469 printf(" Src FBO %u RB %u (%dx%d) ",
470 readFb
->Name
, colorReadRb
->Name
,
471 colorReadRb
->Width
, colorReadRb
->Height
);
472 if (att
&& att
->Texture
) {
473 printf("Tex %u tgt 0x%x level %u face %u",
475 att
->Texture
->Target
,
481 /* Print all active color render buffers */
482 for (i
= 0; i
< ctx
->DrawBuffer
->_NumColorDrawBuffers
; i
++) {
483 colorDrawRb
= ctx
->DrawBuffer
->_ColorDrawBuffers
[i
];
487 att
= find_attachment(drawFb
, colorDrawRb
);
488 printf(" Dst FBO %u RB %u (%dx%d) ",
489 drawFb
->Name
, colorDrawRb
->Name
,
490 colorDrawRb
->Width
, colorDrawRb
->Height
);
491 if (att
&& att
->Texture
) {
492 printf("Tex %u tgt 0x%x level %u face %u",
494 att
->Texture
->Target
,
504 (srcX1
- srcX0
) == 0 || (srcY1
- srcY0
) == 0 ||
505 (dstX1
- dstX0
) == 0 || (dstY1
- dstY0
) == 0) {
509 assert(ctx
->Driver
.BlitFramebuffer
);
510 ctx
->Driver
.BlitFramebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
,
511 srcX0
, srcY0
, srcX1
, srcY1
,
512 dstX0
, dstY0
, dstX1
, dstY1
,