mesa: include stdio.h where needed
[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 "glformats.h"
38 #include "mtypes.h"
39 #include "state.h"
40
41
42 /** Set this to 1 to debug/log glBlitFramebuffer() calls */
43 #define DEBUG_BLIT 0
44
45
46
47 static const struct gl_renderbuffer_attachment *
48 find_attachment(const struct gl_framebuffer *fb,
49 const struct gl_renderbuffer *rb)
50 {
51 GLuint i;
52 for (i = 0; i < ARRAY_SIZE(fb->Attachment); i++) {
53 if (fb->Attachment[i].Renderbuffer == rb)
54 return &fb->Attachment[i];
55 }
56 return NULL;
57 }
58
59
60 /**
61 * Helper function for checking if the datatypes of color buffers are
62 * compatible for glBlitFramebuffer. From the 3.1 spec, page 198:
63 *
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."
72 */
73 static GLboolean
74 compatible_color_datatypes(mesa_format srcFormat, mesa_format dstFormat)
75 {
76 GLenum srcType = _mesa_get_format_datatype(srcFormat);
77 GLenum dstType = _mesa_get_format_datatype(dstFormat);
78
79 if (srcType != GL_INT && srcType != GL_UNSIGNED_INT) {
80 assert(srcType == GL_UNSIGNED_NORMALIZED ||
81 srcType == GL_SIGNED_NORMALIZED ||
82 srcType == GL_FLOAT);
83 /* Boil any of those types down to GL_FLOAT */
84 srcType = GL_FLOAT;
85 }
86
87 if (dstType != GL_INT && dstType != GL_UNSIGNED_INT) {
88 assert(dstType == GL_UNSIGNED_NORMALIZED ||
89 dstType == GL_SIGNED_NORMALIZED ||
90 dstType == GL_FLOAT);
91 /* Boil any of those types down to GL_FLOAT */
92 dstType = GL_FLOAT;
93 }
94
95 return srcType == dstType;
96 }
97
98
99 static GLboolean
100 compatible_resolve_formats(const struct gl_renderbuffer *readRb,
101 const struct gl_renderbuffer *drawRb)
102 {
103 GLenum readFormat, drawFormat;
104
105 /* The simple case where we know the backing Mesa formats are the same.
106 */
107 if (_mesa_get_srgb_format_linear(readRb->Format) ==
108 _mesa_get_srgb_format_linear(drawRb->Format)) {
109 return GL_TRUE;
110 }
111
112 /* The Mesa formats are different, so we must check whether the internal
113 * formats are compatible.
114 *
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.
119 *
120 * Blits between linear and sRGB formats are also allowed.
121 */
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);
126
127 if (readFormat == drawFormat) {
128 return GL_TRUE;
129 }
130
131 return GL_FALSE;
132 }
133
134
135 static GLboolean
136 is_valid_blit_filter(const struct gl_context *ctx, GLenum filter)
137 {
138 switch (filter) {
139 case GL_NEAREST:
140 case GL_LINEAR:
141 return true;
142 case GL_SCALED_RESOLVE_FASTEST_EXT:
143 case GL_SCALED_RESOLVE_NICEST_EXT:
144 return ctx->Extensions.EXT_framebuffer_multisample_blit_scaled;
145 default:
146 return false;
147 }
148 }
149
150
151 /**
152 * Blit rectangular region, optionally from one framebuffer to another.
153 *
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.
156 */
157 void GLAPIENTRY
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)
161 {
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);
167
168 FLUSH_VERTICES(ctx, 0);
169
170 if (MESA_VERBOSE & VERBOSE_API)
171 _mesa_debug(ctx,
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));
176
177 if (ctx->NewState) {
178 _mesa_update_state(ctx);
179 }
180
181 readFb = ctx->ReadBuffer;
182 drawFb = ctx->DrawBuffer;
183
184 if (!readFb || !drawFb) {
185 /* This will normally never happen but someday we may want to
186 * support MakeCurrent() with no drawables.
187 */
188 return;
189 }
190
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)");
196 return;
197 }
198
199 if (!is_valid_blit_filter(ctx, filter)) {
200 _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(%s)",
201 _mesa_lookup_enum_by_nr(filter));
202 return;
203 }
204
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));
210 return;
211 }
212
213 if (mask & ~legalMaskBits) {
214 _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
215 return;
216 }
217
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)");
223 return;
224 }
225
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;
231 GLuint i;
232
233 /* From the EXT_framebuffer_object spec:
234 *
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
237 * ignored."
238 */
239 if (!colorReadRb || numColorDrawBuffers == 0) {
240 mask &= ~GL_COLOR_BUFFER_BIT;
241 }
242 else {
243 for (i = 0; i < numColorDrawBuffers; i++) {
244 colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
245 if (!colorDrawRb)
246 continue;
247
248 /* Page 193 (page 205 of the PDF) in section 4.3.2 of the OpenGL
249 * ES 3.0.1 spec says:
250 *
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."
257 */
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)");
262 return;
263 }
264
265 if (!compatible_color_datatypes(colorReadRb->Format,
266 colorDrawRb->Format)) {
267 _mesa_error(ctx, GL_INVALID_OPERATION,
268 "glBlitFramebufferEXT(color buffer datatypes mismatch)");
269 return;
270 }
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)");
277 return;
278 }
279 }
280 }
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."
285 */
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)");
290 return;
291 }
292 }
293 }
294 }
295
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;
301
302 /* From the EXT_framebuffer_object spec:
303 *
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
306 * ignored."
307 */
308 if ((readRb == NULL) || (drawRb == NULL)) {
309 mask &= ~GL_STENCIL_BUFFER_BIT;
310 }
311 else {
312 int read_z_bits, draw_z_bits;
313
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)");
318 return;
319 }
320
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.
325 */
326 _mesa_error(ctx, GL_INVALID_OPERATION,
327 "glBlitFramebuffer(stencil attachment format mismatch)");
328 return;
329 }
330
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);
333
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.
337 */
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))) {
342
343 _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer"
344 "(stencil attachment depth format mismatch)");
345 return;
346 }
347 }
348 }
349
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;
355
356 /* From the EXT_framebuffer_object spec:
357 *
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
360 * ignored."
361 */
362 if ((readRb == NULL) || (drawRb == NULL)) {
363 mask &= ~GL_DEPTH_BUFFER_BIT;
364 }
365 else {
366 int read_s_bit, draw_s_bit;
367
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)");
372 return;
373 }
374
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)");
381 return;
382 }
383
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);
386
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.
390 */
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)");
394 return;
395 }
396 }
397 }
398
399
400 if (_mesa_is_gles3(ctx)) {
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 draw framebuffer is greater than zero,
405 * an INVALID_OPERATION error is generated."
406 */
407 if (drawFb->Visual.samples > 0) {
408 _mesa_error(ctx, GL_INVALID_OPERATION,
409 "glBlitFramebuffer(destination samples must be 0)");
410 return;
411 }
412
413 /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
414 * 3.0.1 spec says:
415 *
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."
421 *
422 * The format check was made above because desktop OpenGL has the same
423 * requirement.
424 */
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)");
430 return;
431 }
432 } else {
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)");
438 return;
439 }
440
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)");
449 return;
450 }
451 }
452 }
453
454 /* Debug code */
455 if (DEBUG_BLIT) {
456 const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
457 const struct gl_renderbuffer *colorDrawRb = NULL;
458 GLuint i = 0;
459
460 printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d,"
461 " 0x%x, 0x%x)\n",
462 srcX0, srcY0, srcX1, srcY1,
463 dstX0, dstY0, dstX1, dstY1,
464 mask, filter);
465 if (colorReadRb) {
466 const struct gl_renderbuffer_attachment *att;
467
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",
474 att->Texture->Name,
475 att->Texture->Target,
476 att->TextureLevel,
477 att->CubeMapFace);
478 }
479 printf("\n");
480
481 /* Print all active color render buffers */
482 for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
483 colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
484 if (!colorDrawRb)
485 continue;
486
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",
493 att->Texture->Name,
494 att->Texture->Target,
495 att->TextureLevel,
496 att->CubeMapFace);
497 }
498 printf("\n");
499 }
500 }
501 }
502
503 if (!mask ||
504 (srcX1 - srcX0) == 0 || (srcY1 - srcY0) == 0 ||
505 (dstX1 - dstX0) == 0 || (dstY1 - dstY0) == 0) {
506 return;
507 }
508
509 assert(ctx->Driver.BlitFramebuffer);
510 ctx->Driver.BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
511 srcX0, srcY0, srcX1, srcY1,
512 dstX0, dstY0, dstX1, dstY1,
513 mask, filter);
514 }