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