blit.c revision 848b8605
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 46static const struct gl_renderbuffer_attachment * 47find_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 */ 72static GLboolean 73compatible_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 98static GLboolean 99compatible_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 134static GLboolean 135is_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 */ 156void 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, 510 srcX0, srcY0, srcX1, srcY1, 511 dstX0, dstY0, dstX1, dstY1, 512 mask, filter); 513} 514