DD: Refactor BlitFramebuffer.
[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
32 #include "context.h"
33 #include "enums.h"
34 #include "blit.h"
35 #include "fbobject.h"
36 #include "glformats.h"
37 #include "mtypes.h"
38 #include "state.h"
39
40
41 /** Set this to 1 to debug/log glBlitFramebuffer() calls */
42 #define DEBUG_BLIT 0
43
44
45
46 static const struct gl_renderbuffer_attachment *
47 find_attachment(const struct gl_framebuffer *fb,
48 const struct gl_renderbuffer *rb)
49 {
50 GLuint i;
51 for (i = 0; i < Elements(fb->Attachment); i++) {
52 if (fb->Attachment[i].Renderbuffer == rb)
53 return &fb->Attachment[i];
54 }
55 return NULL;
56 }
57
58
59 /**
60 * Helper function for checking if the datatypes of color buffers are
61 * compatible for glBlitFramebuffer. From the 3.1 spec, page 198:
62 *
63 * "GL_INVALID_OPERATION is generated if mask contains GL_COLOR_BUFFER_BIT
64 * and any of the following conditions hold:
65 * - The read buffer contains fixed-point or floating-point values and any
66 * draw buffer contains neither fixed-point nor floating-point values.
67 * - The read buffer contains unsigned integer values and any draw buffer
68 * does not contain unsigned integer values.
69 * - The read buffer contains signed integer values and any draw buffer
70 * does not contain signed integer values."
71 */
72 static GLboolean
73 compatible_color_datatypes(mesa_format srcFormat, mesa_format dstFormat)
74 {
75 GLenum srcType = _mesa_get_format_datatype(srcFormat);
76 GLenum dstType = _mesa_get_format_datatype(dstFormat);
77
78 if (srcType != GL_INT && srcType != GL_UNSIGNED_INT) {
79 assert(srcType == GL_UNSIGNED_NORMALIZED ||
80 srcType == GL_SIGNED_NORMALIZED ||
81 srcType == GL_FLOAT);
82 /* Boil any of those types down to GL_FLOAT */
83 srcType = GL_FLOAT;
84 }
85
86 if (dstType != GL_INT && dstType != GL_UNSIGNED_INT) {
87 assert(dstType == GL_UNSIGNED_NORMALIZED ||
88 dstType == GL_SIGNED_NORMALIZED ||
89 dstType == GL_FLOAT);
90 /* Boil any of those types down to GL_FLOAT */
91 dstType = GL_FLOAT;
92 }
93
94 return srcType == dstType;
95 }
96
97
98 static GLboolean
99 compatible_resolve_formats(const struct gl_renderbuffer *readRb,
100 const struct gl_renderbuffer *drawRb)
101 {
102 GLenum readFormat, drawFormat;
103
104 /* The simple case where we know the backing Mesa formats are the same.
105 */
106 if (_mesa_get_srgb_format_linear(readRb->Format) ==
107 _mesa_get_srgb_format_linear(drawRb->Format)) {
108 return GL_TRUE;
109 }
110
111 /* The Mesa formats are different, so we must check whether the internal
112 * formats are compatible.
113 *
114 * Under some circumstances, the user may request e.g. two GL_RGBA8
115 * textures and get two entirely different Mesa formats like RGBA8888 and
116 * ARGB8888. Drivers behaving like that should be able to cope with
117 * non-matching formats by themselves, because it's not the user's fault.
118 *
119 * Blits between linear and sRGB formats are also allowed.
120 */
121 readFormat = _mesa_get_nongeneric_internalformat(readRb->InternalFormat);
122 drawFormat = _mesa_get_nongeneric_internalformat(drawRb->InternalFormat);
123 readFormat = _mesa_get_linear_internalformat(readFormat);
124 drawFormat = _mesa_get_linear_internalformat(drawFormat);
125
126 if (readFormat == drawFormat) {
127 return GL_TRUE;
128 }
129
130 return GL_FALSE;
131 }
132
133
134 static GLboolean
135 is_valid_blit_filter(const struct gl_context *ctx, GLenum filter)
136 {
137 switch (filter) {
138 case GL_NEAREST:
139 case GL_LINEAR:
140 return true;
141 case GL_SCALED_RESOLVE_FASTEST_EXT:
142 case GL_SCALED_RESOLVE_NICEST_EXT:
143 return ctx->Extensions.EXT_framebuffer_multisample_blit_scaled;
144 default:
145 return false;
146 }
147 }
148
149
150 /**
151 * Blit rectangular region, optionally from one framebuffer to another.
152 *
153 * Note, if the src buffer is multisampled and the dest is not, this is
154 * when the samples must be resolved to a single color.
155 */
156 void GLAPIENTRY
157 _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
158 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
159 GLbitfield mask, GLenum filter)
160 {
161 const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
162 GL_DEPTH_BUFFER_BIT |
163 GL_STENCIL_BUFFER_BIT);
164 const struct gl_framebuffer *readFb, *drawFb;
165 GET_CURRENT_CONTEXT(ctx);
166
167 FLUSH_VERTICES(ctx, 0);
168
169 if (MESA_VERBOSE & VERBOSE_API)
170 _mesa_debug(ctx,
171 "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n",
172 srcX0, srcY0, srcX1, srcY1,
173 dstX0, dstY0, dstX1, dstY1,
174 mask, _mesa_lookup_enum_by_nr(filter));
175
176 if (ctx->NewState) {
177 _mesa_update_state(ctx);
178 }
179
180 readFb = ctx->ReadBuffer;
181 drawFb = ctx->DrawBuffer;
182
183 if (!readFb || !drawFb) {
184 /* This will normally never happen but someday we may want to
185 * support MakeCurrent() with no drawables.
186 */
187 return;
188 }
189
190 /* check for complete framebuffers */
191 if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
192 readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
193 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
194 "glBlitFramebufferEXT(incomplete draw/read buffers)");
195 return;
196 }
197
198 if (!is_valid_blit_filter(ctx, filter)) {
199 _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(%s)",
200 _mesa_lookup_enum_by_nr(filter));
201 return;
202 }
203
204 if ((filter == GL_SCALED_RESOLVE_FASTEST_EXT ||
205 filter == GL_SCALED_RESOLVE_NICEST_EXT) &&
206 (readFb->Visual.samples == 0 || drawFb->Visual.samples > 0)) {
207 _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT(%s)",
208 _mesa_lookup_enum_by_nr(filter));
209 return;
210 }
211
212 if (mask & ~legalMaskBits) {
213 _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
214 return;
215 }
216
217 /* depth/stencil must be blitted with nearest filtering */
218 if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
219 && filter != GL_NEAREST) {
220 _mesa_error(ctx, GL_INVALID_OPERATION,
221 "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)");
222 return;
223 }
224
225 /* get color read/draw renderbuffers */
226 if (mask & GL_COLOR_BUFFER_BIT) {
227 const GLuint numColorDrawBuffers = ctx->DrawBuffer->_NumColorDrawBuffers;
228 const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
229 const struct gl_renderbuffer *colorDrawRb = NULL;
230 GLuint i;
231
232 /* From the EXT_framebuffer_object spec:
233 *
234 * "If a buffer is specified in <mask> and does not exist in both
235 * the read and draw framebuffers, the corresponding bit is silently
236 * ignored."
237 */
238 if (!colorReadRb || numColorDrawBuffers == 0) {
239 mask &= ~GL_COLOR_BUFFER_BIT;
240 }
241 else {
242 for (i = 0; i < numColorDrawBuffers; i++) {
243 colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
244 if (!colorDrawRb)
245 continue;
246
247 /* Page 193 (page 205 of the PDF) in section 4.3.2 of the OpenGL
248 * ES 3.0.1 spec says:
249 *
250 * "If the source and destination buffers are identical, an
251 * INVALID_OPERATION error is generated. Different mipmap
252 * levels of a texture, different layers of a three-
253 * dimensional texture or two-dimensional array texture, and
254 * different faces of a cube map texture do not constitute
255 * identical buffers."
256 */
257 if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) {
258 _mesa_error(ctx, GL_INVALID_OPERATION,
259 "glBlitFramebuffer(source and destination color "
260 "buffer cannot be the same)");
261 return;
262 }
263
264 if (!compatible_color_datatypes(colorReadRb->Format,
265 colorDrawRb->Format)) {
266 _mesa_error(ctx, GL_INVALID_OPERATION,
267 "glBlitFramebufferEXT(color buffer datatypes mismatch)");
268 return;
269 }
270 /* extra checks for multisample copies... */
271 if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
272 /* color formats must match */
273 if (!compatible_resolve_formats(colorReadRb, colorDrawRb)) {
274 _mesa_error(ctx, GL_INVALID_OPERATION,
275 "glBlitFramebufferEXT(bad src/dst multisample pixel formats)");
276 return;
277 }
278 }
279 }
280 if (filter != GL_NEAREST) {
281 /* From EXT_framebuffer_multisample_blit_scaled specification:
282 * "Calling BlitFramebuffer will result in an INVALID_OPERATION error
283 * if filter is not NEAREST and read buffer contains integer data."
284 */
285 GLenum type = _mesa_get_format_datatype(colorReadRb->Format);
286 if (type == GL_INT || type == GL_UNSIGNED_INT) {
287 _mesa_error(ctx, GL_INVALID_OPERATION,
288 "glBlitFramebufferEXT(integer color type)");
289 return;
290 }
291 }
292 }
293 }
294
295 if (mask & GL_STENCIL_BUFFER_BIT) {
296 struct gl_renderbuffer *readRb =
297 readFb->Attachment[BUFFER_STENCIL].Renderbuffer;
298 struct gl_renderbuffer *drawRb =
299 drawFb->Attachment[BUFFER_STENCIL].Renderbuffer;
300
301 /* From the EXT_framebuffer_object spec:
302 *
303 * "If a buffer is specified in <mask> and does not exist in both
304 * the read and draw framebuffers, the corresponding bit is silently
305 * ignored."
306 */
307 if ((readRb == NULL) || (drawRb == NULL)) {
308 mask &= ~GL_STENCIL_BUFFER_BIT;
309 }
310 else {
311 int read_z_bits, draw_z_bits;
312
313 if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
314 _mesa_error(ctx, GL_INVALID_OPERATION,
315 "glBlitFramebuffer(source and destination stencil "
316 "buffer cannot be the same)");
317 return;
318 }
319
320 if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) !=
321 _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {
322 /* There is no need to check the stencil datatype here, because
323 * there is only one: GL_UNSIGNED_INT.
324 */
325 _mesa_error(ctx, GL_INVALID_OPERATION,
326 "glBlitFramebuffer(stencil attachment format mismatch)");
327 return;
328 }
329
330 read_z_bits = _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS);
331 draw_z_bits = _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS);
332
333 /* If both buffers also have depth data, the depth formats must match
334 * as well. If one doesn't have depth, it's not blitted, so we should
335 * ignore the depth format check.
336 */
337 if (read_z_bits > 0 && draw_z_bits > 0 &&
338 (read_z_bits != draw_z_bits ||
339 _mesa_get_format_datatype(readRb->Format) !=
340 _mesa_get_format_datatype(drawRb->Format))) {
341
342 _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer"
343 "(stencil attachment depth format mismatch)");
344 return;
345 }
346 }
347 }
348
349 if (mask & GL_DEPTH_BUFFER_BIT) {
350 struct gl_renderbuffer *readRb =
351 readFb->Attachment[BUFFER_DEPTH].Renderbuffer;
352 struct gl_renderbuffer *drawRb =
353 drawFb->Attachment[BUFFER_DEPTH].Renderbuffer;
354
355 /* From the EXT_framebuffer_object spec:
356 *
357 * "If a buffer is specified in <mask> and does not exist in both
358 * the read and draw framebuffers, the corresponding bit is silently
359 * ignored."
360 */
361 if ((readRb == NULL) || (drawRb == NULL)) {
362 mask &= ~GL_DEPTH_BUFFER_BIT;
363 }
364 else {
365 int read_s_bit, draw_s_bit;
366
367 if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
368 _mesa_error(ctx, GL_INVALID_OPERATION,
369 "glBlitFramebuffer(source and destination depth "
370 "buffer cannot be the same)");
371 return;
372 }
373
374 if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) !=
375 _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) ||
376 (_mesa_get_format_datatype(readRb->Format) !=
377 _mesa_get_format_datatype(drawRb->Format))) {
378 _mesa_error(ctx, GL_INVALID_OPERATION,
379 "glBlitFramebuffer(depth attachment format mismatch)");
380 return;
381 }
382
383 read_s_bit = _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS);
384 draw_s_bit = _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS);
385
386 /* If both buffers also have stencil data, the stencil formats must
387 * match as well. If one doesn't have stencil, it's not blitted, so
388 * we should ignore the stencil format check.
389 */
390 if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) {
391 _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer"
392 "(depth attachment stencil bits mismatch)");
393 return;
394 }
395 }
396 }
397
398
399 if (_mesa_is_gles3(ctx)) {
400 /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
401 * 3.0.1 spec says:
402 *
403 * "If SAMPLE_BUFFERS for the draw framebuffer is greater than zero,
404 * an INVALID_OPERATION error is generated."
405 */
406 if (drawFb->Visual.samples > 0) {
407 _mesa_error(ctx, GL_INVALID_OPERATION,
408 "glBlitFramebuffer(destination samples must be 0)");
409 return;
410 }
411
412 /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
413 * 3.0.1 spec says:
414 *
415 * "If SAMPLE_BUFFERS for the read framebuffer is greater than zero,
416 * no copy is performed and an INVALID_OPERATION error is generated
417 * if the formats of the read and draw framebuffers are not
418 * identical or if the source and destination rectangles are not
419 * defined with the same (X0, Y0) and (X1, Y1) bounds."
420 *
421 * The format check was made above because desktop OpenGL has the same
422 * requirement.
423 */
424 if (readFb->Visual.samples > 0
425 && (srcX0 != dstX0 || srcY0 != dstY0
426 || srcX1 != dstX1 || srcY1 != dstY1)) {
427 _mesa_error(ctx, GL_INVALID_OPERATION,
428 "glBlitFramebuffer(bad src/dst multisample region)");
429 return;
430 }
431 } else {
432 if (readFb->Visual.samples > 0 &&
433 drawFb->Visual.samples > 0 &&
434 readFb->Visual.samples != drawFb->Visual.samples) {
435 _mesa_error(ctx, GL_INVALID_OPERATION,
436 "glBlitFramebufferEXT(mismatched samples)");
437 return;
438 }
439
440 /* extra checks for multisample copies... */
441 if ((readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) &&
442 (filter == GL_NEAREST || filter == GL_LINEAR)) {
443 /* src and dest region sizes must be the same */
444 if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) ||
445 abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) {
446 _mesa_error(ctx, GL_INVALID_OPERATION,
447 "glBlitFramebufferEXT(bad src/dst multisample region sizes)");
448 return;
449 }
450 }
451 }
452
453 /* Debug code */
454 if (DEBUG_BLIT) {
455 const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
456 const struct gl_renderbuffer *colorDrawRb = NULL;
457 GLuint i = 0;
458
459 printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d,"
460 " 0x%x, 0x%x)\n",
461 srcX0, srcY0, srcX1, srcY1,
462 dstX0, dstY0, dstX1, dstY1,
463 mask, filter);
464 if (colorReadRb) {
465 const struct gl_renderbuffer_attachment *att;
466
467 att = find_attachment(readFb, colorReadRb);
468 printf(" Src FBO %u RB %u (%dx%d) ",
469 readFb->Name, colorReadRb->Name,
470 colorReadRb->Width, colorReadRb->Height);
471 if (att && att->Texture) {
472 printf("Tex %u tgt 0x%x level %u face %u",
473 att->Texture->Name,
474 att->Texture->Target,
475 att->TextureLevel,
476 att->CubeMapFace);
477 }
478 printf("\n");
479
480 /* Print all active color render buffers */
481 for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
482 colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
483 if (!colorDrawRb)
484 continue;
485
486 att = find_attachment(drawFb, colorDrawRb);
487 printf(" Dst FBO %u RB %u (%dx%d) ",
488 drawFb->Name, colorDrawRb->Name,
489 colorDrawRb->Width, colorDrawRb->Height);
490 if (att && att->Texture) {
491 printf("Tex %u tgt 0x%x level %u face %u",
492 att->Texture->Name,
493 att->Texture->Target,
494 att->TextureLevel,
495 att->CubeMapFace);
496 }
497 printf("\n");
498 }
499 }
500 }
501
502 if (!mask ||
503 (srcX1 - srcX0) == 0 || (srcY1 - srcY0) == 0 ||
504 (dstX1 - dstX0) == 0 || (dstY1 - dstY0) == 0) {
505 return;
506 }
507
508 ASSERT(ctx->Driver.BlitFramebuffer);
509 ctx->Driver.BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
510 srcX0, srcY0, srcX1, srcY1,
511 dstX0, dstY0, dstX1, dstY1,
512 mask, filter);
513 }