1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
5 * Copyright (C) 1999-2009 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 /*
28 * GL_EXT/ARB_framebuffer_object extensions
29 *
30 * Authors:
31 * Brian Paul
32 */
33
34 #include <stdbool.h>
35
36 #include "buffers.h"
37 #include "context.h"
38 #include "debug_output.h"
39 #include "draw_validate.h"
40 #include "enums.h"
41 #include "fbobject.h"
42 #include "formats.h"
43 #include "framebuffer.h"
44 #include "glformats.h"
45 #include "hash.h"
46 #include "macros.h"
47 #include "multisample.h"
48 #include "mtypes.h"
49 #include "renderbuffer.h"
50 #include "state.h"
51 #include "teximage.h"
52 #include "texobj.h"
53
54
55 /**
56 * Notes:
57 *
58 * None of the GL_EXT_framebuffer_object functions are compiled into
59 * display lists.
60 */
61
62
63
64 static void
delete_dummy_renderbuffer(struct gl_context * ctx,struct gl_renderbuffer * rb)65 delete_dummy_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
66 {
67 /* no op */
68 }
69
70 static void
delete_dummy_framebuffer(struct gl_framebuffer * fb)71 delete_dummy_framebuffer(struct gl_framebuffer *fb)
72 {
73 /* no op */
74 }
75
76
77 /*
78 * When glGenRender/FramebuffersEXT() is called we insert pointers to
79 * these placeholder objects into the hash table.
80 * Later, when the object ID is first bound, we replace the placeholder
81 * with the real frame/renderbuffer.
82 */
83 static struct gl_framebuffer DummyFramebuffer = {
84 .Mutex = _SIMPLE_MTX_INITIALIZER_NP,
85 .Delete = delete_dummy_framebuffer,
86 };
87 static struct gl_renderbuffer DummyRenderbuffer = {
88 .Delete = delete_dummy_renderbuffer,
89 };
90
91 /* We bind this framebuffer when applications pass a NULL
92 * drawable/surface in make current. */
93 static struct gl_framebuffer IncompleteFramebuffer = {
94 .Mutex = _SIMPLE_MTX_INITIALIZER_NP,
95 .Delete = delete_dummy_framebuffer,
96 };
97
98
99 struct gl_framebuffer *
_mesa_get_incomplete_framebuffer(void)100 _mesa_get_incomplete_framebuffer(void)
101 {
102 return &IncompleteFramebuffer;
103 }
104
105 /**
106 * Helper routine for getting a gl_renderbuffer.
107 */
108 struct gl_renderbuffer *
_mesa_lookup_renderbuffer(struct gl_context * ctx,GLuint id)109 _mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id)
110 {
111 struct gl_renderbuffer *rb;
112
113 if (id == 0)
114 return NULL;
115
116 rb = (struct gl_renderbuffer *)
117 _mesa_HashLookup(ctx->Shared->RenderBuffers, id);
118 return rb;
119 }
120
121
122 /**
123 * A convenience function for direct state access that throws
124 * GL_INVALID_OPERATION if the renderbuffer doesn't exist.
125 */
126 struct gl_renderbuffer *
_mesa_lookup_renderbuffer_err(struct gl_context * ctx,GLuint id,const char * func)127 _mesa_lookup_renderbuffer_err(struct gl_context *ctx, GLuint id,
128 const char *func)
129 {
130 struct gl_renderbuffer *rb;
131
132 rb = _mesa_lookup_renderbuffer(ctx, id);
133 if (!rb || rb == &DummyRenderbuffer) {
134 _mesa_error(ctx, GL_INVALID_OPERATION,
135 "%s(non-existent renderbuffer %u)", func, id);
136 return NULL;
137 }
138
139 return rb;
140 }
141
142
143 /**
144 * Helper routine for getting a gl_framebuffer.
145 */
146 struct gl_framebuffer *
_mesa_lookup_framebuffer(struct gl_context * ctx,GLuint id)147 _mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id)
148 {
149 struct gl_framebuffer *fb;
150
151 if (id == 0)
152 return NULL;
153
154 fb = (struct gl_framebuffer *)
155 _mesa_HashLookup(ctx->Shared->FrameBuffers, id);
156
157 return fb;
158 }
159
160
161 struct gl_framebuffer *
_mesa_lookup_framebuffer_dsa(struct gl_context * ctx,GLuint id,const char * func)162 _mesa_lookup_framebuffer_dsa(struct gl_context *ctx, GLuint id,
163 const char* func)
164 {
165 struct gl_framebuffer *fb;
166
167 if (id == 0)
168 return NULL;
169
170 fb = _mesa_lookup_framebuffer(ctx, id);
171
172 /* Name exists but buffer is not initialized */
173 if (fb == &DummyFramebuffer) {
174 fb = ctx->Driver.NewFramebuffer(ctx, id);
175 _mesa_HashInsert(ctx->Shared->FrameBuffers, id, fb, true);
176 }
177 /* Name doesn't exist */
178 else if (!fb) {
179 fb = ctx->Driver.NewFramebuffer(ctx, id);
180 if (!fb) {
181 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
182 return NULL;
183 }
184 _mesa_HashInsert(ctx->Shared->FrameBuffers, id, fb, false);
185 }
186 return fb;
187 }
188
189
190 /**
191 * A convenience function for direct state access that throws
192 * GL_INVALID_OPERATION if the framebuffer doesn't exist.
193 */
194 struct gl_framebuffer *
_mesa_lookup_framebuffer_err(struct gl_context * ctx,GLuint id,const char * func)195 _mesa_lookup_framebuffer_err(struct gl_context *ctx, GLuint id,
196 const char *func)
197 {
198 struct gl_framebuffer *fb;
199
200 fb = _mesa_lookup_framebuffer(ctx, id);
201 if (!fb || fb == &DummyFramebuffer) {
202 _mesa_error(ctx, GL_INVALID_OPERATION,
203 "%s(non-existent framebuffer %u)", func, id);
204 return NULL;
205 }
206
207 return fb;
208 }
209
210
211 /**
212 * Mark the given framebuffer as invalid. This will force the
213 * test for framebuffer completeness to be done before the framebuffer
214 * is used.
215 */
216 static void
invalidate_framebuffer(struct gl_framebuffer * fb)217 invalidate_framebuffer(struct gl_framebuffer *fb)
218 {
219 fb->_Status = 0; /* "indeterminate" */
220 }
221
222
223 /**
224 * Return the gl_framebuffer object which corresponds to the given
225 * framebuffer target, such as GL_DRAW_FRAMEBUFFER.
226 * Check support for GL_EXT_framebuffer_blit to determine if certain
227 * targets are legal.
228 * \return gl_framebuffer pointer or NULL if target is illegal
229 */
230 static struct gl_framebuffer *
get_framebuffer_target(struct gl_context * ctx,GLenum target)231 get_framebuffer_target(struct gl_context *ctx, GLenum target)
232 {
233 bool have_fb_blit = _mesa_is_gles3(ctx) || _mesa_is_desktop_gl(ctx);
234 switch (target) {
235 case GL_DRAW_FRAMEBUFFER:
236 return have_fb_blit ? ctx->DrawBuffer : NULL;
237 case GL_READ_FRAMEBUFFER:
238 return have_fb_blit ? ctx->ReadBuffer : NULL;
239 case GL_FRAMEBUFFER_EXT:
240 return ctx->DrawBuffer;
241 default:
242 return NULL;
243 }
244 }
245
246
247 /**
248 * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding
249 * gl_renderbuffer_attachment object.
250 * This function is only used for user-created FB objects, not the
251 * default / window-system FB object.
252 * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to
253 * the depth buffer attachment point.
254 * Returns if the attachment is a GL_COLOR_ATTACHMENTm_EXT on
255 * is_color_attachment, because several callers would return different errors
256 * if they don't find the attachment.
257 */
258 static struct gl_renderbuffer_attachment *
get_attachment(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment,bool * is_color_attachment)259 get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
260 GLenum attachment, bool *is_color_attachment)
261 {
262 GLuint i;
263
264 assert(_mesa_is_user_fbo(fb));
265
266 if (is_color_attachment)
267 *is_color_attachment = false;
268
269 switch (attachment) {
270 case GL_COLOR_ATTACHMENT0_EXT:
271 case GL_COLOR_ATTACHMENT1_EXT:
272 case GL_COLOR_ATTACHMENT2_EXT:
273 case GL_COLOR_ATTACHMENT3_EXT:
274 case GL_COLOR_ATTACHMENT4_EXT:
275 case GL_COLOR_ATTACHMENT5_EXT:
276 case GL_COLOR_ATTACHMENT6_EXT:
277 case GL_COLOR_ATTACHMENT7_EXT:
278 case GL_COLOR_ATTACHMENT8_EXT:
279 case GL_COLOR_ATTACHMENT9_EXT:
280 case GL_COLOR_ATTACHMENT10_EXT:
281 case GL_COLOR_ATTACHMENT11_EXT:
282 case GL_COLOR_ATTACHMENT12_EXT:
283 case GL_COLOR_ATTACHMENT13_EXT:
284 case GL_COLOR_ATTACHMENT14_EXT:
285 case GL_COLOR_ATTACHMENT15_EXT:
286 if (is_color_attachment)
287 *is_color_attachment = true;
288 /* Only OpenGL ES 1.x forbids color attachments other than
289 * GL_COLOR_ATTACHMENT0. For all other APIs the limit set by the
290 * hardware is used.
291 */
292 i = attachment - GL_COLOR_ATTACHMENT0_EXT;
293 if (i >= ctx->Const.MaxColorAttachments
294 || (i > 0 && ctx->API == API_OPENGLES)) {
295 return NULL;
296 }
297 assert(BUFFER_COLOR0 + i < ARRAY_SIZE(fb->Attachment));
298 return &fb->Attachment[BUFFER_COLOR0 + i];
299 case GL_DEPTH_STENCIL_ATTACHMENT:
300 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
301 return NULL;
302 FALLTHROUGH;
303 case GL_DEPTH_ATTACHMENT_EXT:
304 return &fb->Attachment[BUFFER_DEPTH];
305 case GL_STENCIL_ATTACHMENT_EXT:
306 return &fb->Attachment[BUFFER_STENCIL];
307 default:
308 return NULL;
309 }
310 }
311
312
313 /**
314 * As above, but only used for getting attachments of the default /
315 * window-system framebuffer (not user-created framebuffer objects).
316 */
317 static struct gl_renderbuffer_attachment *
get_fb0_attachment(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment)318 get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
319 GLenum attachment)
320 {
321 assert(_mesa_is_winsys_fbo(fb));
322
323 attachment = _mesa_back_to_front_if_single_buffered(fb, attachment);
324
325 if (_mesa_is_gles3(ctx)) {
326 switch (attachment) {
327 case GL_BACK:
328 /* Since there is no stereo rendering in ES 3.0, only return the
329 * LEFT bits.
330 */
331 return &fb->Attachment[BUFFER_BACK_LEFT];
332 case GL_FRONT:
333 /* We might get this if back_to_front triggers above */
334 return &fb->Attachment[BUFFER_FRONT_LEFT];
335 case GL_DEPTH:
336 return &fb->Attachment[BUFFER_DEPTH];
337 case GL_STENCIL:
338 return &fb->Attachment[BUFFER_STENCIL];
339 default:
340 unreachable("invalid attachment");
341 }
342 }
343
344 switch (attachment) {
345 case GL_FRONT:
346 case GL_FRONT_LEFT:
347 /* Front buffers can be allocated on the first use, but
348 * glGetFramebufferAttachmentParameteriv must work even if that
349 * allocation hasn't happened yet. In such case, use the back buffer,
350 * which should be the same.
351 */
352 if (fb->Attachment[BUFFER_FRONT_LEFT].Type == GL_NONE)
353 return &fb->Attachment[BUFFER_BACK_LEFT];
354 else
355 return &fb->Attachment[BUFFER_FRONT_LEFT];
356 case GL_FRONT_RIGHT:
357 /* Same as above. */
358 if (fb->Attachment[BUFFER_FRONT_RIGHT].Type == GL_NONE)
359 return &fb->Attachment[BUFFER_BACK_RIGHT];
360 else
361 return &fb->Attachment[BUFFER_FRONT_RIGHT];
362 case GL_BACK_LEFT:
363 return &fb->Attachment[BUFFER_BACK_LEFT];
364 case GL_BACK_RIGHT:
365 return &fb->Attachment[BUFFER_BACK_RIGHT];
366 case GL_BACK:
367 /* The ARB_ES3_1_compatibility spec says:
368 *
369 * "Since this command can only query a single framebuffer
370 * attachment, BACK is equivalent to BACK_LEFT."
371 */
372 if (ctx->Extensions.ARB_ES3_1_compatibility)
373 return &fb->Attachment[BUFFER_BACK_LEFT];
374 return NULL;
375 case GL_AUX0:
376 return NULL;
377
378 /* Page 336 (page 352 of the PDF) of the OpenGL 3.0 spec says:
379 *
380 * "If the default framebuffer is bound to target, then attachment must
381 * be one of FRONT LEFT, FRONT RIGHT, BACK LEFT, BACK RIGHT, or AUXi,
382 * identifying a color buffer; DEPTH, identifying the depth buffer; or
383 * STENCIL, identifying the stencil buffer."
384 *
385 * Revision #34 of the ARB_framebuffer_object spec has essentially the same
386 * language. However, revision #33 of the ARB_framebuffer_object spec
387 * says:
388 *
389 * "If the default framebuffer is bound to <target>, then <attachment>
390 * must be one of FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, BACK_RIGHT, AUXi,
391 * DEPTH_BUFFER, or STENCIL_BUFFER, identifying a color buffer, the
392 * depth buffer, or the stencil buffer, and <pname> may be
393 * FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE or
394 * FRAMEBUFFER_ATTACHMENT_OBJECT_NAME."
395 *
396 * The enum values for DEPTH_BUFFER and STENCIL_BUFFER have been removed
397 * from glext.h, so shipping apps should not use those values.
398 *
399 * Note that neither EXT_framebuffer_object nor OES_framebuffer_object
400 * support queries of the window system FBO.
401 */
402 case GL_DEPTH:
403 return &fb->Attachment[BUFFER_DEPTH];
404 case GL_STENCIL:
405 return &fb->Attachment[BUFFER_STENCIL];
406 default:
407 return NULL;
408 }
409 }
410
411
412
413 /**
414 * Remove any texture or renderbuffer attached to the given attachment
415 * point. Update reference counts, etc.
416 */
417 static void
remove_attachment(struct gl_context * ctx,struct gl_renderbuffer_attachment * att)418 remove_attachment(struct gl_context *ctx,
419 struct gl_renderbuffer_attachment *att)
420 {
421 struct gl_renderbuffer *rb = att->Renderbuffer;
422
423 /* tell driver that we're done rendering to this texture. */
424 if (rb && rb->NeedsFinishRenderTexture)
425 ctx->Driver.FinishRenderTexture(ctx, rb);
426
427 if (att->Type == GL_TEXTURE) {
428 assert(att->Texture);
429 _mesa_reference_texobj(&att->Texture, NULL); /* unbind */
430 assert(!att->Texture);
431 }
432 if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
433 assert(!att->Texture);
434 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */
435 assert(!att->Renderbuffer);
436 }
437 att->Type = GL_NONE;
438 att->Complete = GL_TRUE;
439 }
440
441 /**
442 * Verify a couple error conditions that will lead to an incomplete FBO and
443 * may cause problems for the driver's RenderTexture path.
444 */
445 static bool
driver_RenderTexture_is_safe(const struct gl_renderbuffer_attachment * att)446 driver_RenderTexture_is_safe(const struct gl_renderbuffer_attachment *att)
447 {
448 const struct gl_texture_image *const texImage =
449 att->Texture->Image[att->CubeMapFace][att->TextureLevel];
450
451 if (!texImage ||
452 texImage->Width == 0 || texImage->Height == 0 || texImage->Depth == 0)
453 return false;
454
455 if ((texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY
456 && att->Zoffset >= texImage->Height)
457 || (texImage->TexObject->Target != GL_TEXTURE_1D_ARRAY
458 && att->Zoffset >= texImage->Depth))
459 return false;
460
461 return true;
462 }
463
464 /**
465 * Create a renderbuffer which will be set up by the driver to wrap the
466 * texture image slice.
467 *
468 * By using a gl_renderbuffer (like user-allocated renderbuffers), drivers get
469 * to share most of their framebuffer rendering code between winsys,
470 * renderbuffer, and texture attachments.
471 *
472 * The allocated renderbuffer uses a non-zero Name so that drivers can check
473 * it for determining vertical orientation, but we use ~0 to make it fairly
474 * unambiguous with actual user (non-texture) renderbuffers.
475 */
476 void
_mesa_update_texture_renderbuffer(struct gl_context * ctx,struct gl_framebuffer * fb,struct gl_renderbuffer_attachment * att)477 _mesa_update_texture_renderbuffer(struct gl_context *ctx,
478 struct gl_framebuffer *fb,
479 struct gl_renderbuffer_attachment *att)
480 {
481 struct gl_texture_image *texImage;
482 struct gl_renderbuffer *rb;
483
484 texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
485
486 rb = att->Renderbuffer;
487 if (!rb) {
488 rb = ctx->Driver.NewRenderbuffer(ctx, ~0);
489 if (!rb) {
490 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
491 return;
492 }
493 att->Renderbuffer = rb;
494
495 /* This can't get called on a texture renderbuffer, so set it to NULL
496 * for clarity compared to user renderbuffers.
497 */
498 rb->AllocStorage = NULL;
499
500 rb->NeedsFinishRenderTexture = ctx->Driver.FinishRenderTexture != NULL;
501 }
502
503 if (!texImage)
504 return;
505
506 rb->_BaseFormat = texImage->_BaseFormat;
507 rb->Format = texImage->TexFormat;
508 rb->InternalFormat = texImage->InternalFormat;
509 rb->Width = texImage->Width2;
510 rb->Height = texImage->Height2;
511 rb->Depth = texImage->Depth2;
512 rb->NumSamples = texImage->NumSamples;
513 rb->NumStorageSamples = texImage->NumSamples;
514 rb->TexImage = texImage;
515
516 if (driver_RenderTexture_is_safe(att))
517 ctx->Driver.RenderTexture(ctx, fb, att);
518 }
519
520 /**
521 * Bind a texture object to an attachment point.
522 * The previous binding, if any, will be removed first.
523 */
524 static void
set_texture_attachment(struct gl_context * ctx,struct gl_framebuffer * fb,struct gl_renderbuffer_attachment * att,struct gl_texture_object * texObj,GLenum texTarget,GLuint level,GLsizei samples,GLuint layer,GLboolean layered)525 set_texture_attachment(struct gl_context *ctx,
526 struct gl_framebuffer *fb,
527 struct gl_renderbuffer_attachment *att,
528 struct gl_texture_object *texObj,
529 GLenum texTarget, GLuint level, GLsizei samples,
530 GLuint layer, GLboolean layered)
531 {
532 struct gl_renderbuffer *rb = att->Renderbuffer;
533
534 if (rb && rb->NeedsFinishRenderTexture)
535 ctx->Driver.FinishRenderTexture(ctx, rb);
536
537 if (att->Texture == texObj) {
538 /* re-attaching same texture */
539 assert(att->Type == GL_TEXTURE);
540 }
541 else {
542 /* new attachment */
543 remove_attachment(ctx, att);
544 att->Type = GL_TEXTURE;
545 assert(!att->Texture);
546 _mesa_reference_texobj(&att->Texture, texObj);
547 }
548 invalidate_framebuffer(fb);
549
550 /* always update these fields */
551 att->TextureLevel = level;
552 att->NumSamples = samples;
553 att->CubeMapFace = _mesa_tex_target_to_face(texTarget);
554 att->Zoffset = layer;
555 att->Layered = layered;
556 att->Complete = GL_FALSE;
557
558 _mesa_update_texture_renderbuffer(ctx, fb, att);
559 }
560
561
562 /**
563 * Bind a renderbuffer to an attachment point.
564 * The previous binding, if any, will be removed first.
565 */
566 static void
set_renderbuffer_attachment(struct gl_context * ctx,struct gl_renderbuffer_attachment * att,struct gl_renderbuffer * rb)567 set_renderbuffer_attachment(struct gl_context *ctx,
568 struct gl_renderbuffer_attachment *att,
569 struct gl_renderbuffer *rb)
570 {
571 /* XXX check if re-doing same attachment, exit early */
572 remove_attachment(ctx, att);
573 att->Type = GL_RENDERBUFFER_EXT;
574 att->Texture = NULL; /* just to be safe */
575 att->Layered = GL_FALSE;
576 att->Complete = GL_FALSE;
577 _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
578 }
579
580
581 /**
582 * Fallback for ctx->Driver.FramebufferRenderbuffer()
583 * Attach a renderbuffer object to a framebuffer object.
584 */
585 void
_mesa_FramebufferRenderbuffer_sw(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment,struct gl_renderbuffer * rb)586 _mesa_FramebufferRenderbuffer_sw(struct gl_context *ctx,
587 struct gl_framebuffer *fb,
588 GLenum attachment,
589 struct gl_renderbuffer *rb)
590 {
591 struct gl_renderbuffer_attachment *att;
592
593 simple_mtx_lock(&fb->Mutex);
594
595 att = get_attachment(ctx, fb, attachment, NULL);
596 assert(att);
597 if (rb) {
598 set_renderbuffer_attachment(ctx, att, rb);
599 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
600 /* do stencil attachment here (depth already done above) */
601 att = get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT, NULL);
602 assert(att);
603 set_renderbuffer_attachment(ctx, att, rb);
604 }
605 rb->AttachedAnytime = GL_TRUE;
606 }
607 else {
608 remove_attachment(ctx, att);
609 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
610 /* detach stencil (depth was detached above) */
611 att = get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT, NULL);
612 assert(att);
613 remove_attachment(ctx, att);
614 }
615 }
616
617 invalidate_framebuffer(fb);
618
619 simple_mtx_unlock(&fb->Mutex);
620 }
621
622
623 /**
624 * Fallback for ctx->Driver.ValidateFramebuffer()
625 * Check if the renderbuffer's formats are supported by the software
626 * renderer.
627 * Drivers should probably override this.
628 */
629 void
_mesa_validate_framebuffer(struct gl_context * ctx,struct gl_framebuffer * fb)630 _mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
631 {
632 gl_buffer_index buf;
633 for (buf = 0; buf < BUFFER_COUNT; buf++) {
634 const struct gl_renderbuffer *rb = fb->Attachment[buf].Renderbuffer;
635 if (rb) {
636 switch (rb->_BaseFormat) {
637 case GL_ALPHA:
638 case GL_LUMINANCE_ALPHA:
639 case GL_LUMINANCE:
640 case GL_INTENSITY:
641 case GL_RED:
642 case GL_RG:
643 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
644 return;
645
646 default:
647 switch (rb->Format) {
648 /* XXX This list is likely incomplete. */
649 case MESA_FORMAT_R9G9B9E5_FLOAT:
650 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
651 return;
652 default:;
653 /* render buffer format is supported by software rendering */
654 }
655 }
656 }
657 }
658 }
659
660
661 /**
662 * Return true if the framebuffer has a combined depth/stencil
663 * renderbuffer attached.
664 */
665 GLboolean
_mesa_has_depthstencil_combined(const struct gl_framebuffer * fb)666 _mesa_has_depthstencil_combined(const struct gl_framebuffer *fb)
667 {
668 const struct gl_renderbuffer_attachment *depth =
669 &fb->Attachment[BUFFER_DEPTH];
670 const struct gl_renderbuffer_attachment *stencil =
671 &fb->Attachment[BUFFER_STENCIL];
672
673 if (depth->Type == stencil->Type) {
674 if (depth->Type == GL_RENDERBUFFER_EXT &&
675 depth->Renderbuffer == stencil->Renderbuffer)
676 return GL_TRUE;
677
678 if (depth->Type == GL_TEXTURE &&
679 depth->Texture == stencil->Texture)
680 return GL_TRUE;
681 }
682
683 return GL_FALSE;
684 }
685
686
687 /**
688 * For debug only.
689 */
690 static void
att_incomplete(const char * msg)691 att_incomplete(const char *msg)
692 {
693 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
694 _mesa_debug(NULL, "attachment incomplete: %s\n", msg);
695 }
696 }
697
698
699 /**
700 * For debug only.
701 */
702 static void
fbo_incomplete(struct gl_context * ctx,const char * msg,int index)703 fbo_incomplete(struct gl_context *ctx, const char *msg, int index)
704 {
705 static GLuint msg_id;
706
707 _mesa_gl_debugf(ctx, &msg_id,
708 MESA_DEBUG_SOURCE_API,
709 MESA_DEBUG_TYPE_OTHER,
710 MESA_DEBUG_SEVERITY_MEDIUM,
711 "FBO incomplete: %s [%d]\n", msg, index);
712
713 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
714 _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index);
715 }
716
717 _mesa_update_valid_to_render_state(ctx);
718 }
719
720
721 /**
722 * Is the given base format a legal format for a color renderbuffer?
723 */
724 GLboolean
_mesa_is_legal_color_format(const struct gl_context * ctx,GLenum baseFormat)725 _mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat)
726 {
727 switch (baseFormat) {
728 case GL_RGB:
729 case GL_RGBA:
730 return GL_TRUE;
731 case GL_LUMINANCE:
732 case GL_LUMINANCE_ALPHA:
733 case GL_INTENSITY:
734 case GL_ALPHA:
735 return ctx->API == API_OPENGL_COMPAT &&
736 ctx->Extensions.ARB_framebuffer_object;
737 case GL_RED:
738 case GL_RG:
739 return ctx->Extensions.ARB_texture_rg;
740 default:
741 return GL_FALSE;
742 }
743 }
744
745 static GLboolean
is_float_format(GLenum internalFormat)746 is_float_format(GLenum internalFormat)
747 {
748 switch (internalFormat) {
749 case GL_R16F:
750 case GL_RG16F:
751 case GL_RGB16F:
752 case GL_RGBA16F:
753 case GL_R32F:
754 case GL_RG32F:
755 case GL_RGB32F:
756 case GL_RGBA32F:
757 return true;
758 default:
759 return false;
760 }
761 }
762
763 /**
764 * Is the given base format a legal format for a color renderbuffer?
765 */
766 static GLboolean
is_format_color_renderable(const struct gl_context * ctx,mesa_format format,GLenum internalFormat)767 is_format_color_renderable(const struct gl_context *ctx, mesa_format format,
768 GLenum internalFormat)
769 {
770 const GLenum baseFormat =
771 _mesa_get_format_base_format(format);
772 GLboolean valid;
773
774 valid = _mesa_is_legal_color_format(ctx, baseFormat);
775 if (!valid || _mesa_is_desktop_gl(ctx)) {
776 return valid;
777 }
778
779 /* Reject additional cases for GLES */
780 switch (internalFormat) {
781 case GL_R8_SNORM:
782 case GL_RG8_SNORM:
783 case GL_RGBA8_SNORM:
784 return _mesa_has_EXT_render_snorm(ctx);
785 case GL_R16_SNORM:
786 case GL_RG16_SNORM:
787 case GL_RGBA16_SNORM:
788 return _mesa_has_EXT_texture_norm16(ctx) &&
789 _mesa_has_EXT_render_snorm(ctx);
790 case GL_R:
791 case GL_RG:
792 return _mesa_has_EXT_texture_rg(ctx);
793 case GL_R16F:
794 case GL_RG16F:
795 return _mesa_is_gles3(ctx) ||
796 (_mesa_has_EXT_color_buffer_half_float(ctx) &&
797 _mesa_has_EXT_texture_rg(ctx));
798 case GL_RGBA16F:
799 return _mesa_is_gles3(ctx) ||
800 _mesa_has_EXT_color_buffer_half_float(ctx);
801 case GL_RGBA32F:
802 return _mesa_has_EXT_color_buffer_float(ctx);
803 case GL_RGB16F:
804 return _mesa_has_EXT_color_buffer_half_float(ctx);
805 case GL_RGB10_A2:
806 return _mesa_is_gles3(ctx);
807 case GL_RGB32F:
808 case GL_RGB32I:
809 case GL_RGB32UI:
810 case GL_RGB16I:
811 case GL_RGB16UI:
812 case GL_RGB8_SNORM:
813 case GL_RGB8I:
814 case GL_RGB8UI:
815 case GL_SRGB8:
816 case GL_RGB10:
817 case GL_RGB9_E5:
818 case GL_SR8_EXT:
819 case GL_SRG8_EXT:
820 return GL_FALSE;
821 default:
822 break;
823 }
824
825 if (internalFormat != GL_RGB10_A2 &&
826 (format == MESA_FORMAT_B10G10R10A2_UNORM ||
827 format == MESA_FORMAT_B10G10R10X2_UNORM ||
828 format == MESA_FORMAT_R10G10B10A2_UNORM ||
829 format == MESA_FORMAT_R10G10B10X2_UNORM)) {
830 return GL_FALSE;
831 }
832
833 return GL_TRUE;
834 }
835
836 /**
837 * Check that implements various limitations of floating point
838 * rendering extensions on OpenGL ES.
839 *
840 * Check passes if texture format is not floating point or
841 * is floating point and is color renderable.
842 *
843 * Check fails if texture format is floating point and cannot
844 * be rendered to with current context and set of supported
845 * extensions.
846 */
847 static GLboolean
gles_check_float_renderable(const struct gl_context * ctx,struct gl_renderbuffer_attachment * att)848 gles_check_float_renderable(const struct gl_context *ctx,
849 struct gl_renderbuffer_attachment *att)
850 {
851 /* Only check floating point texture cases. */
852 if (!att->Texture || !is_float_format(att->Renderbuffer->InternalFormat))
853 return true;
854
855 /* GL_RGBA with unsized GL_FLOAT type, no extension can make this
856 * color renderable.
857 */
858 if (att->Texture->_IsFloat && att->Renderbuffer->_BaseFormat == GL_RGBA)
859 return false;
860
861 /* Unsized GL_HALF_FLOAT supported only with EXT_color_buffer_half_float. */
862 if (att->Texture->_IsHalfFloat && !_mesa_has_EXT_color_buffer_half_float(ctx))
863 return false;
864
865 const struct gl_texture_object *texObj = att->Texture;
866 const struct gl_texture_image *texImage =
867 texObj->Image[att->CubeMapFace][att->TextureLevel];
868
869 return is_format_color_renderable(ctx, texImage->TexFormat,
870 att->Renderbuffer->InternalFormat);
871 }
872
873 /**
874 * Is the given base format a legal format for a depth/stencil renderbuffer?
875 */
876 static GLboolean
is_legal_depth_format(const struct gl_context * ctx,GLenum baseFormat)877 is_legal_depth_format(const struct gl_context *ctx, GLenum baseFormat)
878 {
879 switch (baseFormat) {
880 case GL_DEPTH_COMPONENT:
881 case GL_DEPTH_STENCIL_EXT:
882 return GL_TRUE;
883 default:
884 return GL_FALSE;
885 }
886 }
887
888
889 /**
890 * Test if an attachment point is complete and update its Complete field.
891 * \param format if GL_COLOR, this is a color attachment point,
892 * if GL_DEPTH, this is a depth component attachment point,
893 * if GL_STENCIL, this is a stencil component attachment point.
894 */
895 static void
test_attachment_completeness(const struct gl_context * ctx,GLenum format,struct gl_renderbuffer_attachment * att)896 test_attachment_completeness(const struct gl_context *ctx, GLenum format,
897 struct gl_renderbuffer_attachment *att)
898 {
899 assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL);
900
901 /* assume complete */
902 att->Complete = GL_TRUE;
903
904 /* Look for reasons why the attachment might be incomplete */
905 if (att->Type == GL_TEXTURE) {
906 const struct gl_texture_object *texObj = att->Texture;
907 const struct gl_texture_image *texImage;
908 GLenum baseFormat;
909
910 if (!texObj) {
911 att_incomplete("no texobj");
912 att->Complete = GL_FALSE;
913 return;
914 }
915
916 texImage = texObj->Image[att->CubeMapFace][att->TextureLevel];
917 if (!texImage) {
918 att_incomplete("no teximage");
919 att->Complete = GL_FALSE;
920 return;
921 }
922
923 /* Mutable non base level texture as framebuffer attachment
924 * must be mipmap complete.
925 */
926 if (texImage->Level > texObj->Attrib.BaseLevel &&
927 !texObj->_MipmapComplete) {
928 /* Test if texture has become mipmap complete meanwhile. */
929 _mesa_test_texobj_completeness(ctx, att->Texture);
930 if (!texObj->_MipmapComplete) {
931 att_incomplete("texture attachment not mipmap complete");
932 att->Complete = GL_FALSE;
933 return;
934 }
935 }
936
937 if (texImage->Width < 1 || texImage->Height < 1) {
938 att_incomplete("teximage width/height=0");
939 att->Complete = GL_FALSE;
940 return;
941 }
942
943 switch (texObj->Target) {
944 case GL_TEXTURE_3D:
945 if (att->Zoffset >= texImage->Depth) {
946 att_incomplete("bad z offset");
947 att->Complete = GL_FALSE;
948 return;
949 }
950 break;
951 case GL_TEXTURE_1D_ARRAY:
952 if (att->Zoffset >= texImage->Height) {
953 att_incomplete("bad 1D-array layer");
954 att->Complete = GL_FALSE;
955 return;
956 }
957 break;
958 case GL_TEXTURE_2D_ARRAY:
959 if (att->Zoffset >= texImage->Depth) {
960 att_incomplete("bad 2D-array layer");
961 att->Complete = GL_FALSE;
962 return;
963 }
964 break;
965 case GL_TEXTURE_CUBE_MAP_ARRAY:
966 if (att->Zoffset >= texImage->Depth) {
967 att_incomplete("bad cube-array layer");
968 att->Complete = GL_FALSE;
969 return;
970 }
971 break;
972 }
973
974 baseFormat = texImage->_BaseFormat;
975
976 if (format == GL_COLOR) {
977 if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
978 att_incomplete("bad format");
979 att->Complete = GL_FALSE;
980 return;
981 }
982 if (_mesa_is_format_compressed(texImage->TexFormat)) {
983 att_incomplete("compressed internalformat");
984 att->Complete = GL_FALSE;
985 return;
986 }
987
988 /* OES_texture_float allows creation and use of floating point
989 * textures with GL_FLOAT, GL_HALF_FLOAT but it does not allow
990 * these textures to be used as a render target, this is done via
991 * GL_EXT_color_buffer(_half)_float with set of new sized types.
992 */
993 if (_mesa_is_gles(ctx) && !gles_check_float_renderable(ctx, att)) {
994 att_incomplete("bad internal format");
995 att->Complete = GL_FALSE;
996 return;
997 }
998 }
999 else if (format == GL_DEPTH) {
1000 if (baseFormat == GL_DEPTH_COMPONENT) {
1001 /* OK */
1002 }
1003 else if (ctx->Extensions.ARB_depth_texture &&
1004 baseFormat == GL_DEPTH_STENCIL) {
1005 /* OK */
1006 }
1007 else {
1008 att->Complete = GL_FALSE;
1009 att_incomplete("bad depth format");
1010 return;
1011 }
1012 }
1013 else {
1014 assert(format == GL_STENCIL);
1015 if (ctx->Extensions.ARB_depth_texture &&
1016 baseFormat == GL_DEPTH_STENCIL) {
1017 /* OK */
1018 } else if (ctx->Extensions.ARB_texture_stencil8 &&
1019 baseFormat == GL_STENCIL_INDEX) {
1020 /* OK */
1021 } else {
1022 /* no such thing as stencil-only textures */
1023 att_incomplete("illegal stencil texture");
1024 att->Complete = GL_FALSE;
1025 return;
1026 }
1027 }
1028 }
1029 else if (att->Type == GL_RENDERBUFFER_EXT) {
1030 const GLenum baseFormat = att->Renderbuffer->_BaseFormat;
1031
1032 assert(att->Renderbuffer);
1033 if (!att->Renderbuffer->InternalFormat ||
1034 att->Renderbuffer->Width < 1 ||
1035 att->Renderbuffer->Height < 1) {
1036 att_incomplete("0x0 renderbuffer");
1037 att->Complete = GL_FALSE;
1038 return;
1039 }
1040 if (format == GL_COLOR) {
1041 if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
1042 att_incomplete("bad renderbuffer color format");
1043 att->Complete = GL_FALSE;
1044 return;
1045 }
1046 }
1047 else if (format == GL_DEPTH) {
1048 if (baseFormat == GL_DEPTH_COMPONENT) {
1049 /* OK */
1050 }
1051 else if (baseFormat == GL_DEPTH_STENCIL) {
1052 /* OK */
1053 }
1054 else {
1055 att_incomplete("bad renderbuffer depth format");
1056 att->Complete = GL_FALSE;
1057 return;
1058 }
1059 }
1060 else {
1061 assert(format == GL_STENCIL);
1062 if (baseFormat == GL_STENCIL_INDEX ||
1063 baseFormat == GL_DEPTH_STENCIL) {
1064 /* OK */
1065 }
1066 else {
1067 att->Complete = GL_FALSE;
1068 att_incomplete("bad renderbuffer stencil format");
1069 return;
1070 }
1071 }
1072 }
1073 else {
1074 assert(att->Type == GL_NONE);
1075 /* complete */
1076 return;
1077 }
1078 }
1079
1080
1081 /**
1082 * Test if the given framebuffer object is complete and update its
1083 * Status field with the results.
1084 * Calls the ctx->Driver.ValidateFramebuffer() function to allow the
1085 * driver to make hardware-specific validation/completeness checks.
1086 * Also update the framebuffer's Width and Height fields if the
1087 * framebuffer is complete.
1088 */
1089 void
_mesa_test_framebuffer_completeness(struct gl_context * ctx,struct gl_framebuffer * fb)1090 _mesa_test_framebuffer_completeness(struct gl_context *ctx,
1091 struct gl_framebuffer *fb)
1092 {
1093 GLuint numImages;
1094 GLenum intFormat = GL_NONE; /* color buffers' internal format */
1095 GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0;
1096 GLint numColorSamples = -1;
1097 GLint numColorStorageSamples = -1;
1098 GLint numDepthSamples = -1;
1099 GLint fixedSampleLocations = -1;
1100 GLint i;
1101 GLuint j;
1102 /* Covers max_layer_count, is_layered, and layer_tex_target */
1103 bool layer_info_valid = false;
1104 GLuint max_layer_count = 0, att_layer_count;
1105 bool is_layered = false;
1106 GLenum layer_tex_target = 0;
1107 bool has_depth_attachment = false;
1108 bool has_stencil_attachment = false;
1109
1110 assert(_mesa_is_user_fbo(fb));
1111
1112 /* we're changing framebuffer fields here */
1113 FLUSH_VERTICES(ctx, _NEW_BUFFERS, 0);
1114
1115 numImages = 0;
1116 fb->Width = 0;
1117 fb->Height = 0;
1118 fb->_AllColorBuffersFixedPoint = GL_TRUE;
1119 fb->_HasSNormOrFloatColorBuffer = GL_FALSE;
1120 fb->_HasAttachments = true;
1121 fb->_IntegerBuffers = 0;
1122 fb->_RGBBuffers = 0;
1123 fb->_FP32Buffers = 0;
1124
1125 /* Start at -2 to more easily loop over all attachment points.
1126 * -2: depth buffer
1127 * -1: stencil buffer
1128 * >=0: color buffer
1129 */
1130 for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
1131 struct gl_renderbuffer_attachment *att;
1132 GLenum f;
1133 GLenum baseFormat;
1134 mesa_format attFormat;
1135 GLenum att_tex_target = GL_NONE;
1136
1137 /*
1138 * XXX for ARB_fbo, only check color buffers that are named by
1139 * GL_READ_BUFFER and GL_DRAW_BUFFERi.
1140 */
1141
1142 /* check for attachment completeness
1143 */
1144 if (i == -2) {
1145 att = &fb->Attachment[BUFFER_DEPTH];
1146 test_attachment_completeness(ctx, GL_DEPTH, att);
1147 if (!att->Complete) {
1148 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
1149 fbo_incomplete(ctx, "depth attachment incomplete", -1);
1150 return;
1151 } else if (att->Type != GL_NONE) {
1152 has_depth_attachment = true;
1153 }
1154 }
1155 else if (i == -1) {
1156 att = &fb->Attachment[BUFFER_STENCIL];
1157 test_attachment_completeness(ctx, GL_STENCIL, att);
1158 if (!att->Complete) {
1159 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
1160 fbo_incomplete(ctx, "stencil attachment incomplete", -1);
1161 return;
1162 } else if (att->Type != GL_NONE) {
1163 has_stencil_attachment = true;
1164 }
1165 }
1166 else {
1167 att = &fb->Attachment[BUFFER_COLOR0 + i];
1168 test_attachment_completeness(ctx, GL_COLOR, att);
1169 if (!att->Complete) {
1170 /* With EXT_color_buffer_half_float, check if attachment was incomplete
1171 * due to invalid format. This is special case for the extension where
1172 * CTS tests expect unsupported framebuffer status instead of incomplete.
1173 */
1174 if ((_mesa_is_gles(ctx) && _mesa_has_EXT_color_buffer_half_float(ctx)) &&
1175 !gles_check_float_renderable(ctx, att)) {
1176 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
1177 return;
1178 }
1179
1180 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
1181 fbo_incomplete(ctx, "color attachment incomplete", i);
1182 return;
1183 }
1184 }
1185
1186 /* get width, height, format of the renderbuffer/texture
1187 */
1188 unsigned attNumSamples, attNumStorageSamples;
1189
1190 if (att->Type == GL_TEXTURE) {
1191 const struct gl_texture_image *texImg = att->Renderbuffer->TexImage;
1192 att_tex_target = att->Texture->Target;
1193 minWidth = MIN2(minWidth, texImg->Width);
1194 maxWidth = MAX2(maxWidth, texImg->Width);
1195 minHeight = MIN2(minHeight, texImg->Height);
1196 maxHeight = MAX2(maxHeight, texImg->Height);
1197 f = texImg->_BaseFormat;
1198 baseFormat = f;
1199 attFormat = texImg->TexFormat;
1200 numImages++;
1201
1202 if (!is_format_color_renderable(ctx, attFormat,
1203 texImg->InternalFormat) &&
1204 !is_legal_depth_format(ctx, f) &&
1205 f != GL_STENCIL_INDEX) {
1206 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1207 fbo_incomplete(ctx, "texture attachment incomplete", -1);
1208 return;
1209 }
1210
1211 if (fixedSampleLocations < 0)
1212 fixedSampleLocations = texImg->FixedSampleLocations;
1213 else if (fixedSampleLocations != texImg->FixedSampleLocations) {
1214 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1215 fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
1216 return;
1217 }
1218
1219 if (att->NumSamples > 0)
1220 attNumSamples = att->NumSamples;
1221 else
1222 attNumSamples = texImg->NumSamples;
1223 attNumStorageSamples = attNumSamples;
1224 }
1225 else if (att->Type == GL_RENDERBUFFER_EXT) {
1226 minWidth = MIN2(minWidth, att->Renderbuffer->Width);
1227 maxWidth = MAX2(maxWidth, att->Renderbuffer->Width);
1228 minHeight = MIN2(minHeight, att->Renderbuffer->Height);
1229 maxHeight = MAX2(maxHeight, att->Renderbuffer->Height);
1230 f = att->Renderbuffer->InternalFormat;
1231 baseFormat = att->Renderbuffer->_BaseFormat;
1232 attFormat = att->Renderbuffer->Format;
1233 numImages++;
1234
1235 /* RENDERBUFFER has fixedSampleLocations implicitly true */
1236 if (fixedSampleLocations < 0)
1237 fixedSampleLocations = GL_TRUE;
1238 else if (fixedSampleLocations != GL_TRUE) {
1239 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1240 fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
1241 return;
1242 }
1243
1244 attNumSamples = att->Renderbuffer->NumSamples;
1245 attNumStorageSamples = att->Renderbuffer->NumStorageSamples;
1246 }
1247 else {
1248 assert(att->Type == GL_NONE);
1249 continue;
1250 }
1251
1252 if (i >= 0) {
1253 /* Color buffers. */
1254 if (numColorSamples < 0) {
1255 assert(numColorStorageSamples < 0);
1256 numColorSamples = attNumSamples;
1257 numColorStorageSamples = attNumStorageSamples;
1258 } else if (numColorSamples != attNumSamples ||
1259 numColorStorageSamples != attNumStorageSamples) {
1260 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1261 fbo_incomplete(ctx, "inconsistent sample counts", -1);
1262 return;
1263 }
1264 } else {
1265 /* Depth/stencil buffers. */
1266 if (numDepthSamples < 0) {
1267 numDepthSamples = attNumSamples;
1268 } else if (numDepthSamples != attNumSamples) {
1269 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1270 fbo_incomplete(ctx, "inconsistent sample counts", -1);
1271 return;
1272 }
1273 }
1274
1275 /* Update flags describing color buffer datatypes */
1276 if (i >= 0) {
1277 GLenum type = _mesa_get_format_datatype(attFormat);
1278
1279 /* check if integer color */
1280 if (_mesa_is_format_integer_color(attFormat))
1281 fb->_IntegerBuffers |= (1 << i);
1282
1283 if (baseFormat == GL_RGB)
1284 fb->_RGBBuffers |= (1 << i);
1285
1286 if (type == GL_FLOAT && _mesa_get_format_max_bits(attFormat) > 16)
1287 fb->_FP32Buffers |= (1 << i);
1288
1289 fb->_AllColorBuffersFixedPoint =
1290 fb->_AllColorBuffersFixedPoint &&
1291 (type == GL_UNSIGNED_NORMALIZED || type == GL_SIGNED_NORMALIZED);
1292
1293 fb->_HasSNormOrFloatColorBuffer =
1294 fb->_HasSNormOrFloatColorBuffer ||
1295 type == GL_SIGNED_NORMALIZED || type == GL_FLOAT;
1296 }
1297
1298 /* Error-check width, height, format */
1299 if (numImages == 1) {
1300 /* save format */
1301 if (i >= 0) {
1302 intFormat = f;
1303 }
1304 }
1305 else {
1306 if (!_mesa_has_ARB_framebuffer_object(ctx) &&
1307 !_mesa_is_gles3(ctx)) {
1308 /* check that width, height, format are same */
1309 if (minWidth != maxWidth || minHeight != maxHeight) {
1310 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
1311 fbo_incomplete(ctx, "width or height mismatch", -1);
1312 return;
1313 }
1314 /* check that all color buffers are the same format */
1315 if (ctx->API != API_OPENGLES2 && intFormat != GL_NONE && f != intFormat) {
1316 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
1317 fbo_incomplete(ctx, "format mismatch", -1);
1318 return;
1319 }
1320 }
1321 }
1322
1323 /* Check that the format is valid. (MESA_FORMAT_NONE means unsupported)
1324 */
1325 if (att->Type == GL_RENDERBUFFER &&
1326 att->Renderbuffer->Format == MESA_FORMAT_NONE) {
1327 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
1328 fbo_incomplete(ctx, "unsupported renderbuffer format", i);
1329 return;
1330 }
1331
1332 /* Check that layered rendering is consistent. */
1333 if (att->Layered) {
1334 if (att_tex_target == GL_TEXTURE_CUBE_MAP) {
1335 /* Each layer's format and size must match to the base layer. */
1336 if (!_mesa_cube_complete(att->Texture)) {
1337 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1338 fbo_incomplete(ctx, "attachment not cube complete", i);
1339 return;
1340 }
1341 att_layer_count = 6;
1342 } else if (att_tex_target == GL_TEXTURE_1D_ARRAY)
1343 att_layer_count = att->Renderbuffer->Height;
1344 else
1345 att_layer_count = att->Renderbuffer->Depth;
1346
1347 /* From OpenGL ES 3.2 spec, chapter 9.4. FRAMEBUFFER COMPLETENESS:
1348 *
1349 * "If any framebuffer attachment is layered, all populated
1350 * attachments must be layered. Additionally, all populated color
1351 * attachments must be from textures of the same target
1352 * (three-dimensional, one- or two-dimensional array, cube map, or
1353 * cube map array textures)."
1354 *
1355 * Same text can be found from OpenGL 4.6 spec.
1356 *
1357 * Setup the checked layer target with first color attachment here
1358 * so that mismatch check below will not trigger between depth,
1359 * stencil, only between color attachments.
1360 */
1361 if (i == 0)
1362 layer_tex_target = att_tex_target;
1363
1364 } else {
1365 att_layer_count = 0;
1366 }
1367 if (!layer_info_valid) {
1368 is_layered = att->Layered;
1369 max_layer_count = att_layer_count;
1370 layer_info_valid = true;
1371 } else if (max_layer_count > 0 && layer_tex_target &&
1372 layer_tex_target != att_tex_target) {
1373 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS;
1374 fbo_incomplete(ctx, "layered framebuffer has mismatched targets", i);
1375 return;
1376 } else if (is_layered != att->Layered) {
1377 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS;
1378 fbo_incomplete(ctx,
1379 "framebuffer attachment layer mode is inconsistent",
1380 i);
1381 return;
1382 } else if (att_layer_count > max_layer_count) {
1383 max_layer_count = att_layer_count;
1384 }
1385
1386 /*
1387 * The extension GL_ARB_framebuffer_no_attachments places additional
1388 * requirement on each attachment. Those additional requirements are
1389 * tighter that those of previous versions of GL. In interest of better
1390 * compatibility, we will not enforce these restrictions. For the record
1391 * those additional restrictions are quoted below:
1392 *
1393 * "The width and height of image are greater than zero and less than or
1394 * equal to the values of the implementation-dependent limits
1395 * MAX_FRAMEBUFFER_WIDTH and MAX_FRAMEBUFFER_HEIGHT, respectively."
1396 *
1397 * "If <image> is a three-dimensional texture or a one- or two-dimensional
1398 * array texture and the attachment is layered, the depth or layer count
1399 * of the texture is less than or equal to the implementation-dependent
1400 * limit MAX_FRAMEBUFFER_LAYERS."
1401 *
1402 * "If image has multiple samples, its sample count is less than or equal
1403 * to the value of the implementation-dependent limit
1404 * MAX_FRAMEBUFFER_SAMPLES."
1405 *
1406 * The same requirements are also in place for GL 4.5,
1407 * Section 9.4.1 "Framebuffer Attachment Completeness", pg 310-311
1408 */
1409 }
1410
1411 if (ctx->Extensions.AMD_framebuffer_multisample_advanced) {
1412 /* See if non-matching sample counts are supported. */
1413 if (numColorSamples >= 0 && numDepthSamples >= 0) {
1414 bool found = false;
1415
1416 assert(numColorStorageSamples != -1);
1417
1418 numColorSamples = MAX2(numColorSamples, 1);
1419 numColorStorageSamples = MAX2(numColorStorageSamples, 1);
1420 numDepthSamples = MAX2(numDepthSamples, 1);
1421
1422 if (numColorSamples == 1 && numColorStorageSamples == 1 &&
1423 numDepthSamples == 1) {
1424 found = true;
1425 } else {
1426 for (i = 0; i < ctx->Const.NumSupportedMultisampleModes; i++) {
1427 GLint *counts =
1428 &ctx->Const.SupportedMultisampleModes[i].NumColorSamples;
1429
1430 if (counts[0] == numColorSamples &&
1431 counts[1] == numColorStorageSamples &&
1432 counts[2] == numDepthSamples) {
1433 found = true;
1434 break;
1435 }
1436 }
1437 }
1438
1439 if (!found) {
1440 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1441 fbo_incomplete(ctx, "unsupported sample counts", -1);
1442 return;
1443 }
1444 }
1445 } else {
1446 /* If the extension is unsupported, all sample counts must be equal. */
1447 if (numColorSamples >= 0 &&
1448 (numColorSamples != numColorStorageSamples ||
1449 (numDepthSamples >= 0 && numColorSamples != numDepthSamples))) {
1450 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1451 fbo_incomplete(ctx, "inconsistent sample counts", -1);
1452 return;
1453 }
1454 }
1455
1456 fb->MaxNumLayers = max_layer_count;
1457
1458 if (numImages == 0) {
1459 fb->_HasAttachments = false;
1460
1461 if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
1462 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
1463 fbo_incomplete(ctx, "no attachments", -1);
1464 return;
1465 }
1466
1467 if (fb->DefaultGeometry.Width == 0 || fb->DefaultGeometry.Height == 0) {
1468 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
1469 fbo_incomplete(ctx, "no attachments and default width or height is 0", -1);
1470 return;
1471 }
1472 }
1473
1474 if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) {
1475 /* Check that all DrawBuffers are present */
1476 for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
1477 if (fb->ColorDrawBuffer[j] != GL_NONE) {
1478 const struct gl_renderbuffer_attachment *att
1479 = get_attachment(ctx, fb, fb->ColorDrawBuffer[j], NULL);
1480 assert(att);
1481 if (att->Type == GL_NONE) {
1482 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
1483 fbo_incomplete(ctx, "missing drawbuffer", j);
1484 return;
1485 }
1486 }
1487 }
1488
1489 /* Check that the ReadBuffer is present */
1490 if (fb->ColorReadBuffer != GL_NONE) {
1491 const struct gl_renderbuffer_attachment *att
1492 = get_attachment(ctx, fb, fb->ColorReadBuffer, NULL);
1493 assert(att);
1494 if (att->Type == GL_NONE) {
1495 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
1496 fbo_incomplete(ctx, "missing readbuffer", -1);
1497 return;
1498 }
1499 }
1500 }
1501
1502 /* The OpenGL ES3 spec, in chapter 9.4. FRAMEBUFFER COMPLETENESS, says:
1503 *
1504 * "Depth and stencil attachments, if present, are the same image."
1505 *
1506 * This restriction is not present in the OpenGL ES2 spec.
1507 */
1508 if (_mesa_is_gles3(ctx) &&
1509 has_stencil_attachment && has_depth_attachment &&
1510 !_mesa_has_depthstencil_combined(fb)) {
1511 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
1512 fbo_incomplete(ctx, "Depth and stencil attachments must be the same image", -1);
1513 return;
1514 }
1515
1516 /* Provisionally set status = COMPLETE ... */
1517 fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
1518
1519 /* ... but the driver may say the FB is incomplete.
1520 * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED
1521 * if anything.
1522 */
1523 if (ctx->Driver.ValidateFramebuffer) {
1524 ctx->Driver.ValidateFramebuffer(ctx, fb);
1525 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1526 fbo_incomplete(ctx, "driver marked FBO as incomplete", -1);
1527 return;
1528 }
1529 }
1530
1531 /*
1532 * Note that if ARB_framebuffer_object is supported and the attached
1533 * renderbuffers/textures are different sizes, the framebuffer
1534 * width/height will be set to the smallest width/height.
1535 */
1536 if (numImages != 0) {
1537 fb->Width = minWidth;
1538 fb->Height = minHeight;
1539 }
1540
1541 /* finally, update the visual info for the framebuffer */
1542 _mesa_update_framebuffer_visual(ctx, fb);
1543 }
1544
1545
1546 GLboolean GLAPIENTRY
_mesa_IsRenderbuffer(GLuint renderbuffer)1547 _mesa_IsRenderbuffer(GLuint renderbuffer)
1548 {
1549 struct gl_renderbuffer *rb;
1550
1551 GET_CURRENT_CONTEXT(ctx);
1552
1553 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1554
1555 rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
1556 return rb != NULL && rb != &DummyRenderbuffer;
1557 }
1558
1559
1560 static struct gl_renderbuffer *
allocate_renderbuffer_locked(struct gl_context * ctx,GLuint renderbuffer,bool isGenName,const char * func)1561 allocate_renderbuffer_locked(struct gl_context *ctx, GLuint renderbuffer,
1562 bool isGenName,
1563 const char *func)
1564 {
1565 struct gl_renderbuffer *newRb;
1566
1567 /* create new renderbuffer object */
1568 newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
1569 if (!newRb) {
1570 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
1571 return NULL;
1572 }
1573 assert(newRb->AllocStorage);
1574 _mesa_HashInsertLocked(ctx->Shared->RenderBuffers, renderbuffer,
1575 newRb, isGenName);
1576
1577 return newRb;
1578 }
1579
1580
1581 static void
bind_renderbuffer(GLenum target,GLuint renderbuffer)1582 bind_renderbuffer(GLenum target, GLuint renderbuffer)
1583 {
1584 struct gl_renderbuffer *newRb;
1585 GET_CURRENT_CONTEXT(ctx);
1586
1587 if (target != GL_RENDERBUFFER_EXT) {
1588 _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)");
1589 return;
1590 }
1591
1592 /* No need to flush here since the render buffer binding has no
1593 * effect on rendering state.
1594 */
1595
1596 if (renderbuffer) {
1597 bool isGenName = false;
1598 newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
1599 if (newRb == &DummyRenderbuffer) {
1600 /* ID was reserved, but no real renderbuffer object made yet */
1601 newRb = NULL;
1602 isGenName = true;
1603 }
1604 else if (!newRb && ctx->API == API_OPENGL_CORE) {
1605 /* All RB IDs must be Gen'd */
1606 _mesa_error(ctx, GL_INVALID_OPERATION,
1607 "glBindRenderbuffer(non-gen name)");
1608 return;
1609 }
1610
1611 if (!newRb) {
1612 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
1613 newRb = allocate_renderbuffer_locked(ctx, renderbuffer,
1614 isGenName, "glBindRenderbufferEXT");
1615 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
1616 }
1617 }
1618 else {
1619 newRb = NULL;
1620 }
1621
1622 assert(newRb != &DummyRenderbuffer);
1623
1624 _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb);
1625 }
1626
1627 void GLAPIENTRY
_mesa_BindRenderbuffer(GLenum target,GLuint renderbuffer)1628 _mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer)
1629 {
1630 /* OpenGL ES glBindRenderbuffer and glBindRenderbufferOES use this same
1631 * entry point, but they allow the use of user-generated names.
1632 */
1633 bind_renderbuffer(target, renderbuffer);
1634 }
1635
1636 void GLAPIENTRY
_mesa_BindRenderbufferEXT(GLenum target,GLuint renderbuffer)1637 _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
1638 {
1639 bind_renderbuffer(target, renderbuffer);
1640 }
1641
1642 /**
1643 * ARB_framebuffer_no_attachment and ARB_sample_locations - Application passes
1644 * requested param's here. NOTE: NumSamples requested need not be _NumSamples
1645 * which is what the hw supports.
1646 */
1647 static void
framebuffer_parameteri(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum pname,GLint param,const char * func)1648 framebuffer_parameteri(struct gl_context *ctx, struct gl_framebuffer *fb,
1649 GLenum pname, GLint param, const char *func)
1650 {
1651 bool cannot_be_winsys_fbo = false;
1652
1653 switch (pname) {
1654 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1655 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1656 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
1657 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1658 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1659 if (!ctx->Extensions.ARB_framebuffer_no_attachments)
1660 goto invalid_pname_enum;
1661 cannot_be_winsys_fbo = true;
1662 break;
1663 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1664 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1665 if (!ctx->Extensions.ARB_sample_locations)
1666 goto invalid_pname_enum;
1667 break;
1668 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1669 if (!ctx->Extensions.MESA_framebuffer_flip_y)
1670 goto invalid_pname_enum;
1671 cannot_be_winsys_fbo = true;
1672 break;
1673 default:
1674 goto invalid_pname_enum;
1675 }
1676
1677 if (cannot_be_winsys_fbo && _mesa_is_winsys_fbo(fb)) {
1678 _mesa_error(ctx, GL_INVALID_OPERATION,
1679 "%s(invalid pname=0x%x for default framebuffer)", func, pname);
1680 return;
1681 }
1682
1683 switch (pname) {
1684 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1685 if (param < 0 || param > ctx->Const.MaxFramebufferWidth)
1686 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1687 else
1688 fb->DefaultGeometry.Width = param;
1689 break;
1690 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1691 if (param < 0 || param > ctx->Const.MaxFramebufferHeight)
1692 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1693 else
1694 fb->DefaultGeometry.Height = param;
1695 break;
1696 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
1697 /*
1698 * According to the OpenGL ES 3.1 specification section 9.2.1, the
1699 * GL_FRAMEBUFFER_DEFAULT_LAYERS parameter name is not supported.
1700 */
1701 if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader) {
1702 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1703 break;
1704 }
1705 if (param < 0 || param > ctx->Const.MaxFramebufferLayers)
1706 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1707 else
1708 fb->DefaultGeometry.Layers = param;
1709 break;
1710 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1711 if (param < 0 || param > ctx->Const.MaxFramebufferSamples)
1712 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1713 else
1714 fb->DefaultGeometry.NumSamples = param;
1715 break;
1716 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1717 fb->DefaultGeometry.FixedSampleLocations = param;
1718 break;
1719 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1720 fb->ProgrammableSampleLocations = !!param;
1721 break;
1722 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1723 fb->SampleLocationPixelGrid = !!param;
1724 break;
1725 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1726 fb->FlipY = param;
1727 break;
1728 }
1729
1730 switch (pname) {
1731 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1732 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1733 if (fb == ctx->DrawBuffer)
1734 ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
1735 break;
1736 default:
1737 invalidate_framebuffer(fb);
1738 ctx->NewState |= _NEW_BUFFERS;
1739 break;
1740 }
1741
1742 return;
1743
1744 invalid_pname_enum:
1745 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1746 }
1747
1748 static bool
validate_framebuffer_parameter_extensions(GLenum pname,const char * func)1749 validate_framebuffer_parameter_extensions(GLenum pname, const char *func)
1750 {
1751 GET_CURRENT_CONTEXT(ctx);
1752
1753 if (!ctx->Extensions.ARB_framebuffer_no_attachments &&
1754 !ctx->Extensions.ARB_sample_locations &&
1755 !ctx->Extensions.MESA_framebuffer_flip_y) {
1756 _mesa_error(ctx, GL_INVALID_OPERATION,
1757 "%s not supported "
1758 "(none of ARB_framebuffer_no_attachments,"
1759 " ARB_sample_locations, or"
1760 " MESA_framebuffer_flip_y extensions are available)",
1761 func);
1762 return false;
1763 }
1764
1765 /*
1766 * If only the MESA_framebuffer_flip_y extension is enabled
1767 * pname can only be GL_FRAMEBUFFER_FLIP_Y_MESA
1768 */
1769 if (ctx->Extensions.MESA_framebuffer_flip_y &&
1770 pname != GL_FRAMEBUFFER_FLIP_Y_MESA &&
1771 !(ctx->Extensions.ARB_framebuffer_no_attachments ||
1772 ctx->Extensions.ARB_sample_locations)) {
1773 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1774 return false;
1775 }
1776
1777 return true;
1778 }
1779
1780 void GLAPIENTRY
_mesa_FramebufferParameteri(GLenum target,GLenum pname,GLint param)1781 _mesa_FramebufferParameteri(GLenum target, GLenum pname, GLint param)
1782 {
1783 GET_CURRENT_CONTEXT(ctx);
1784 struct gl_framebuffer *fb;
1785
1786 if (!validate_framebuffer_parameter_extensions(pname,
1787 "glFramebufferParameteri")) {
1788 return;
1789 }
1790
1791 fb = get_framebuffer_target(ctx, target);
1792 if (!fb) {
1793 _mesa_error(ctx, GL_INVALID_ENUM,
1794 "glFramebufferParameteri(target=0x%x)", target);
1795 return;
1796 }
1797
1798 framebuffer_parameteri(ctx, fb, pname, param, "glFramebufferParameteri");
1799 }
1800
1801 void GLAPIENTRY
_mesa_FramebufferParameteriMESA(GLenum target,GLenum pname,GLint param)1802 _mesa_FramebufferParameteriMESA(GLenum target, GLenum pname, GLint param)
1803 {
1804 _mesa_FramebufferParameteri(target, pname, param);
1805 }
1806
1807 static bool
validate_get_framebuffer_parameteriv_pname(struct gl_context * ctx,struct gl_framebuffer * fb,GLuint pname,const char * func)1808 validate_get_framebuffer_parameteriv_pname(struct gl_context *ctx,
1809 struct gl_framebuffer *fb,
1810 GLuint pname, const char *func)
1811 {
1812 bool cannot_be_winsys_fbo = true;
1813
1814 switch (pname) {
1815 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
1816 /*
1817 * According to the OpenGL ES 3.1 specification section 9.2.3, the
1818 * GL_FRAMEBUFFER_LAYERS parameter name is not supported.
1819 */
1820 if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader) {
1821 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1822 return false;
1823 }
1824 break;
1825 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1826 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1827 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1828 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1829 break;
1830 case GL_DOUBLEBUFFER:
1831 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1832 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1833 case GL_SAMPLES:
1834 case GL_SAMPLE_BUFFERS:
1835 case GL_STEREO:
1836 /* From OpenGL 4.5 spec, section 9.2.3 "Framebuffer Object Queries:
1837 *
1838 * "An INVALID_OPERATION error is generated by GetFramebufferParameteriv
1839 * if the default framebuffer is bound to target and pname is not one
1840 * of the accepted values from table 23.73, other than
1841 * SAMPLE_POSITION."
1842 *
1843 * For OpenGL ES, using default framebuffer raises INVALID_OPERATION
1844 * for any pname.
1845 */
1846 cannot_be_winsys_fbo = !_mesa_is_desktop_gl(ctx);
1847 break;
1848 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1849 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1850 if (!ctx->Extensions.ARB_sample_locations)
1851 goto invalid_pname_enum;
1852 cannot_be_winsys_fbo = false;
1853 break;
1854 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1855 if (!ctx->Extensions.MESA_framebuffer_flip_y) {
1856 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1857 return false;
1858 }
1859 break;
1860 default:
1861 goto invalid_pname_enum;
1862 }
1863
1864 if (cannot_be_winsys_fbo && _mesa_is_winsys_fbo(fb)) {
1865 _mesa_error(ctx, GL_INVALID_OPERATION,
1866 "%s(invalid pname=0x%x for default framebuffer)", func, pname);
1867 return false;
1868 }
1869
1870 return true;
1871
1872 invalid_pname_enum:
1873 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1874 return false;
1875 }
1876
1877 static void
get_framebuffer_parameteriv(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum pname,GLint * params,const char * func)1878 get_framebuffer_parameteriv(struct gl_context *ctx, struct gl_framebuffer *fb,
1879 GLenum pname, GLint *params, const char *func)
1880 {
1881 if (!validate_get_framebuffer_parameteriv_pname(ctx, fb, pname, func))
1882 return;
1883
1884 switch (pname) {
1885 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1886 *params = fb->DefaultGeometry.Width;
1887 break;
1888 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1889 *params = fb->DefaultGeometry.Height;
1890 break;
1891 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
1892 *params = fb->DefaultGeometry.Layers;
1893 break;
1894 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1895 *params = fb->DefaultGeometry.NumSamples;
1896 break;
1897 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1898 *params = fb->DefaultGeometry.FixedSampleLocations;
1899 break;
1900 case GL_DOUBLEBUFFER:
1901 *params = fb->Visual.doubleBufferMode;
1902 break;
1903 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1904 *params = _mesa_get_color_read_format(ctx, fb, func);
1905 break;
1906 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1907 *params = _mesa_get_color_read_type(ctx, fb, func);
1908 break;
1909 case GL_SAMPLES:
1910 *params = _mesa_geometric_samples(fb);
1911 break;
1912 case GL_SAMPLE_BUFFERS:
1913 *params = _mesa_geometric_samples(fb) > 0;
1914 break;
1915 case GL_STEREO:
1916 *params = fb->Visual.stereoMode;
1917 break;
1918 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1919 *params = fb->ProgrammableSampleLocations;
1920 break;
1921 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1922 *params = fb->SampleLocationPixelGrid;
1923 break;
1924 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1925 *params = fb->FlipY;
1926 break;
1927 }
1928 }
1929
1930 void GLAPIENTRY
_mesa_GetFramebufferParameteriv(GLenum target,GLenum pname,GLint * params)1931 _mesa_GetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params)
1932 {
1933 GET_CURRENT_CONTEXT(ctx);
1934 struct gl_framebuffer *fb;
1935
1936 if (!validate_framebuffer_parameter_extensions(pname,
1937 "glGetFramebufferParameteriv")) {
1938 return;
1939 }
1940
1941 fb = get_framebuffer_target(ctx, target);
1942 if (!fb) {
1943 _mesa_error(ctx, GL_INVALID_ENUM,
1944 "glGetFramebufferParameteriv(target=0x%x)", target);
1945 return;
1946 }
1947
1948 get_framebuffer_parameteriv(ctx, fb, pname, params,
1949 "glGetFramebufferParameteriv");
1950 }
1951
1952 void GLAPIENTRY
_mesa_GetFramebufferParameterivMESA(GLenum target,GLenum pname,GLint * params)1953 _mesa_GetFramebufferParameterivMESA(GLenum target, GLenum pname, GLint *params)
1954 {
1955 _mesa_GetFramebufferParameteriv(target, pname, params);
1956 }
1957
1958 /**
1959 * Remove the specified renderbuffer or texture from any attachment point in
1960 * the framebuffer.
1961 *
1962 * \returns
1963 * \c true if the renderbuffer was detached from an attachment point. \c
1964 * false otherwise.
1965 */
1966 bool
_mesa_detach_renderbuffer(struct gl_context * ctx,struct gl_framebuffer * fb,const void * att)1967 _mesa_detach_renderbuffer(struct gl_context *ctx,
1968 struct gl_framebuffer *fb,
1969 const void *att)
1970 {
1971 unsigned i;
1972 bool progress = false;
1973
1974 for (i = 0; i < BUFFER_COUNT; i++) {
1975 if (fb->Attachment[i].Texture == att
1976 || fb->Attachment[i].Renderbuffer == att) {
1977 remove_attachment(ctx, &fb->Attachment[i]);
1978 progress = true;
1979 }
1980 }
1981
1982 /* Section 4.4.4 (Framebuffer Completeness), subsection "Whole Framebuffer
1983 * Completeness," of the OpenGL 3.1 spec says:
1984 *
1985 * "Performing any of the following actions may change whether the
1986 * framebuffer is considered complete or incomplete:
1987 *
1988 * ...
1989 *
1990 * - Deleting, with DeleteTextures or DeleteRenderbuffers, an object
1991 * containing an image that is attached to a framebuffer object
1992 * that is bound to the framebuffer."
1993 */
1994 if (progress)
1995 invalidate_framebuffer(fb);
1996
1997 return progress;
1998 }
1999
2000
2001 void GLAPIENTRY
_mesa_DeleteRenderbuffers(GLsizei n,const GLuint * renderbuffers)2002 _mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
2003 {
2004 GLint i;
2005 GET_CURRENT_CONTEXT(ctx);
2006
2007 if (n < 0) {
2008 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteRenderbuffers(n < 0)");
2009 return;
2010 }
2011
2012 FLUSH_VERTICES(ctx, _NEW_BUFFERS, 0);
2013
2014 for (i = 0; i < n; i++) {
2015 if (renderbuffers[i] > 0) {
2016 struct gl_renderbuffer *rb;
2017 rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
2018 if (rb) {
2019 /* check if deleting currently bound renderbuffer object */
2020 if (rb == ctx->CurrentRenderbuffer) {
2021 /* bind default */
2022 assert(rb->RefCount >= 2);
2023 _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
2024 }
2025
2026 /* Section 4.4.2 (Attaching Images to Framebuffer Objects),
2027 * subsection "Attaching Renderbuffer Images to a Framebuffer,"
2028 * of the OpenGL 3.1 spec says:
2029 *
2030 * "If a renderbuffer object is deleted while its image is
2031 * attached to one or more attachment points in the currently
2032 * bound framebuffer, then it is as if FramebufferRenderbuffer
2033 * had been called, with a renderbuffer of 0, for each
2034 * attachment point to which this image was attached in the
2035 * currently bound framebuffer. In other words, this
2036 * renderbuffer image is first detached from all attachment
2037 * points in the currently bound framebuffer. Note that the
2038 * renderbuffer image is specifically not detached from any
2039 * non-bound framebuffers. Detaching the image from any
2040 * non-bound framebuffers is the responsibility of the
2041 * application.
2042 */
2043 if (_mesa_is_user_fbo(ctx->DrawBuffer)) {
2044 _mesa_detach_renderbuffer(ctx, ctx->DrawBuffer, rb);
2045 }
2046 if (_mesa_is_user_fbo(ctx->ReadBuffer)
2047 && ctx->ReadBuffer != ctx->DrawBuffer) {
2048 _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
2049 }
2050
2051 /* Remove from hash table immediately, to free the ID.
2052 * But the object will not be freed until it's no longer
2053 * referenced anywhere else.
2054 */
2055 _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
2056
2057 if (rb != &DummyRenderbuffer) {
2058 /* no longer referenced by hash table */
2059 _mesa_reference_renderbuffer(&rb, NULL);
2060 }
2061 }
2062 }
2063 }
2064 }
2065
2066 static void
create_render_buffers(struct gl_context * ctx,GLsizei n,GLuint * renderbuffers,bool dsa)2067 create_render_buffers(struct gl_context *ctx, GLsizei n, GLuint *renderbuffers,
2068 bool dsa)
2069 {
2070 const char *func = dsa ? "glCreateRenderbuffers" : "glGenRenderbuffers";
2071 GLint i;
2072
2073 if (!renderbuffers)
2074 return;
2075
2076 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
2077
2078 _mesa_HashFindFreeKeys(ctx->Shared->RenderBuffers, renderbuffers, n);
2079
2080 for (i = 0; i < n; i++) {
2081 if (dsa) {
2082 allocate_renderbuffer_locked(ctx, renderbuffers[i], true, func);
2083 } else {
2084 /* insert a dummy renderbuffer into the hash table */
2085 _mesa_HashInsertLocked(ctx->Shared->RenderBuffers, renderbuffers[i],
2086 &DummyRenderbuffer, true);
2087 }
2088 }
2089
2090 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
2091 }
2092
2093
2094 static void
create_render_buffers_err(struct gl_context * ctx,GLsizei n,GLuint * renderbuffers,bool dsa)2095 create_render_buffers_err(struct gl_context *ctx, GLsizei n,
2096 GLuint *renderbuffers, bool dsa)
2097 {
2098 const char *func = dsa ? "glCreateRenderbuffers" : "glGenRenderbuffers";
2099
2100 if (n < 0) {
2101 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", func);
2102 return;
2103 }
2104
2105 create_render_buffers(ctx, n, renderbuffers, dsa);
2106 }
2107
2108
2109 void GLAPIENTRY
_mesa_GenRenderbuffers_no_error(GLsizei n,GLuint * renderbuffers)2110 _mesa_GenRenderbuffers_no_error(GLsizei n, GLuint *renderbuffers)
2111 {
2112 GET_CURRENT_CONTEXT(ctx);
2113 create_render_buffers(ctx, n, renderbuffers, false);
2114 }
2115
2116
2117 void GLAPIENTRY
_mesa_GenRenderbuffers(GLsizei n,GLuint * renderbuffers)2118 _mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
2119 {
2120 GET_CURRENT_CONTEXT(ctx);
2121 create_render_buffers_err(ctx, n, renderbuffers, false);
2122 }
2123
2124
2125 void GLAPIENTRY
_mesa_CreateRenderbuffers_no_error(GLsizei n,GLuint * renderbuffers)2126 _mesa_CreateRenderbuffers_no_error(GLsizei n, GLuint *renderbuffers)
2127 {
2128 GET_CURRENT_CONTEXT(ctx);
2129 create_render_buffers(ctx, n, renderbuffers, true);
2130 }
2131
2132
2133 void GLAPIENTRY
_mesa_CreateRenderbuffers(GLsizei n,GLuint * renderbuffers)2134 _mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers)
2135 {
2136 GET_CURRENT_CONTEXT(ctx);
2137 create_render_buffers_err(ctx, n, renderbuffers, true);
2138 }
2139
2140
2141 /**
2142 * Given an internal format token for a render buffer, return the
2143 * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX,
2144 * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE,
2145 * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc).
2146 *
2147 * This is similar to _mesa_base_tex_format() but the set of valid
2148 * internal formats is different.
2149 *
2150 * Note that even if a format is determined to be legal here, validation
2151 * of the FBO may fail if the format is not supported by the driver/GPU.
2152 *
2153 * \param internalFormat as passed to glRenderbufferStorage()
2154 * \return the base internal format, or 0 if internalFormat is illegal
2155 */
2156 GLenum
_mesa_base_fbo_format(const struct gl_context * ctx,GLenum internalFormat)2157 _mesa_base_fbo_format(const struct gl_context *ctx, GLenum internalFormat)
2158 {
2159 /*
2160 * Notes: some formats such as alpha, luminance, etc. were added
2161 * with GL_ARB_framebuffer_object.
2162 */
2163 switch (internalFormat) {
2164 case GL_ALPHA:
2165 case GL_ALPHA4:
2166 case GL_ALPHA8:
2167 case GL_ALPHA12:
2168 case GL_ALPHA16:
2169 return (ctx->API == API_OPENGL_COMPAT &&
2170 ctx->Extensions.ARB_framebuffer_object) ? GL_ALPHA : 0;
2171 case GL_LUMINANCE:
2172 case GL_LUMINANCE4:
2173 case GL_LUMINANCE8:
2174 case GL_LUMINANCE12:
2175 case GL_LUMINANCE16:
2176 return (ctx->API == API_OPENGL_COMPAT &&
2177 ctx->Extensions.ARB_framebuffer_object) ? GL_LUMINANCE : 0;
2178 case GL_LUMINANCE_ALPHA:
2179 case GL_LUMINANCE4_ALPHA4:
2180 case GL_LUMINANCE6_ALPHA2:
2181 case GL_LUMINANCE8_ALPHA8:
2182 case GL_LUMINANCE12_ALPHA4:
2183 case GL_LUMINANCE12_ALPHA12:
2184 case GL_LUMINANCE16_ALPHA16:
2185 return (ctx->API == API_OPENGL_COMPAT &&
2186 ctx->Extensions.ARB_framebuffer_object) ? GL_LUMINANCE_ALPHA : 0;
2187 case GL_INTENSITY:
2188 case GL_INTENSITY4:
2189 case GL_INTENSITY8:
2190 case GL_INTENSITY12:
2191 case GL_INTENSITY16:
2192 return (ctx->API == API_OPENGL_COMPAT &&
2193 ctx->Extensions.ARB_framebuffer_object) ? GL_INTENSITY : 0;
2194 case GL_RGB8:
2195 return GL_RGB;
2196 case GL_RGB:
2197 case GL_R3_G3_B2:
2198 case GL_RGB4:
2199 case GL_RGB5:
2200 case GL_RGB10:
2201 case GL_RGB12:
2202 case GL_RGB16:
2203 return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
2204 case GL_SRGB8_EXT:
2205 return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
2206 case GL_RGBA4:
2207 case GL_RGB5_A1:
2208 case GL_RGBA8:
2209 return GL_RGBA;
2210 case GL_RGBA:
2211 case GL_RGBA2:
2212 case GL_RGBA12:
2213 return _mesa_is_desktop_gl(ctx) ? GL_RGBA : 0;
2214 case GL_RGBA16:
2215 return _mesa_is_desktop_gl(ctx) || _mesa_has_EXT_texture_norm16(ctx)
2216 ? GL_RGBA : 0;
2217 case GL_RGB10_A2:
2218 case GL_SRGB8_ALPHA8_EXT:
2219 return _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
2220 case GL_STENCIL_INDEX:
2221 case GL_STENCIL_INDEX1_EXT:
2222 case GL_STENCIL_INDEX4_EXT:
2223 case GL_STENCIL_INDEX16_EXT:
2224 /* There are extensions for GL_STENCIL_INDEX1 and GL_STENCIL_INDEX4 in
2225 * OpenGL ES, but Mesa does not currently support them.
2226 */
2227 return _mesa_is_desktop_gl(ctx) ? GL_STENCIL_INDEX : 0;
2228 case GL_STENCIL_INDEX8_EXT:
2229 return GL_STENCIL_INDEX;
2230 case GL_DEPTH_COMPONENT:
2231 case GL_DEPTH_COMPONENT32:
2232 return _mesa_is_desktop_gl(ctx) ? GL_DEPTH_COMPONENT : 0;
2233 case GL_DEPTH_COMPONENT16:
2234 case GL_DEPTH_COMPONENT24:
2235 return GL_DEPTH_COMPONENT;
2236 case GL_DEPTH_STENCIL:
2237 return _mesa_is_desktop_gl(ctx) ? GL_DEPTH_STENCIL : 0;
2238 case GL_DEPTH24_STENCIL8:
2239 return GL_DEPTH_STENCIL;
2240 case GL_DEPTH_COMPONENT32F:
2241 return ctx->Version >= 30
2242 || (ctx->API == API_OPENGL_COMPAT &&
2243 ctx->Extensions.ARB_depth_buffer_float)
2244 ? GL_DEPTH_COMPONENT : 0;
2245 case GL_DEPTH32F_STENCIL8:
2246 return ctx->Version >= 30
2247 || (ctx->API == API_OPENGL_COMPAT &&
2248 ctx->Extensions.ARB_depth_buffer_float)
2249 ? GL_DEPTH_STENCIL : 0;
2250 case GL_RED:
2251 return _mesa_has_ARB_texture_rg(ctx) ? GL_RED : 0;
2252 case GL_R16:
2253 return _mesa_has_ARB_texture_rg(ctx) || _mesa_has_EXT_texture_norm16(ctx)
2254 ? GL_RED : 0;
2255 case GL_R8:
2256 return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
2257 ? GL_RED : 0;
2258 case GL_RG:
2259 return _mesa_has_ARB_texture_rg(ctx) ? GL_RG : 0;
2260 case GL_RG16:
2261 return _mesa_has_ARB_texture_rg(ctx) || _mesa_has_EXT_texture_norm16(ctx)
2262 ? GL_RG : 0;
2263 case GL_RG8:
2264 return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
2265 ? GL_RG : 0;
2266 /* signed normalized texture formats */
2267 case GL_R8_SNORM:
2268 return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
2269 ? GL_RED : 0;
2270 case GL_RED_SNORM:
2271 return _mesa_has_EXT_texture_snorm(ctx) ? GL_RED : 0;
2272 case GL_R16_SNORM:
2273 return _mesa_has_EXT_texture_snorm(ctx) ||
2274 (_mesa_has_EXT_render_snorm(ctx) &&
2275 _mesa_has_EXT_texture_norm16(ctx))
2276 ? GL_RED : 0;
2277 case GL_RG8_SNORM:
2278 return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
2279 ? GL_RG : 0;
2280 case GL_RG_SNORM:
2281 return _mesa_has_EXT_texture_snorm(ctx) ? GL_RG : 0;
2282 case GL_RG16_SNORM:
2283 return _mesa_has_EXT_texture_snorm(ctx) ||
2284 (_mesa_has_EXT_render_snorm(ctx) &&
2285 _mesa_has_EXT_texture_norm16(ctx))
2286 ? GL_RG : 0;
2287 case GL_RGB_SNORM:
2288 case GL_RGB8_SNORM:
2289 case GL_RGB16_SNORM:
2290 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2291 ? GL_RGB : 0;
2292 case GL_RGBA8_SNORM:
2293 return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
2294 ? GL_RGBA : 0;
2295 case GL_RGBA_SNORM:
2296 return _mesa_has_EXT_texture_snorm(ctx) ? GL_RGBA : 0;
2297 case GL_RGBA16_SNORM:
2298 return _mesa_has_EXT_texture_snorm(ctx) ||
2299 (_mesa_has_EXT_render_snorm(ctx) &&
2300 _mesa_has_EXT_texture_norm16(ctx))
2301 ? GL_RGBA : 0;
2302 case GL_ALPHA_SNORM:
2303 case GL_ALPHA8_SNORM:
2304 case GL_ALPHA16_SNORM:
2305 return ctx->API == API_OPENGL_COMPAT &&
2306 ctx->Extensions.EXT_texture_snorm &&
2307 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
2308 case GL_LUMINANCE_SNORM:
2309 case GL_LUMINANCE8_SNORM:
2310 case GL_LUMINANCE16_SNORM:
2311 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2312 ? GL_LUMINANCE : 0;
2313 case GL_LUMINANCE_ALPHA_SNORM:
2314 case GL_LUMINANCE8_ALPHA8_SNORM:
2315 case GL_LUMINANCE16_ALPHA16_SNORM:
2316 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2317 ? GL_LUMINANCE_ALPHA : 0;
2318 case GL_INTENSITY_SNORM:
2319 case GL_INTENSITY8_SNORM:
2320 case GL_INTENSITY16_SNORM:
2321 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2322 ? GL_INTENSITY : 0;
2323
2324 case GL_R16F:
2325 return ((_mesa_is_desktop_gl(ctx) &&
2326 ctx->Extensions.ARB_texture_rg &&
2327 ctx->Extensions.ARB_texture_float) ||
2328 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ ||
2329 (_mesa_has_EXT_color_buffer_half_float(ctx) &&
2330 _mesa_has_EXT_texture_rg(ctx)))
2331 ? GL_RED : 0;
2332 case GL_R32F:
2333 return ((_mesa_is_desktop_gl(ctx) &&
2334 ctx->Extensions.ARB_texture_rg &&
2335 ctx->Extensions.ARB_texture_float) ||
2336 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
2337 ? GL_RED : 0;
2338 case GL_RG16F:
2339 return ((_mesa_is_desktop_gl(ctx) &&
2340 ctx->Extensions.ARB_texture_rg &&
2341 ctx->Extensions.ARB_texture_float) ||
2342 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ ||
2343 (_mesa_has_EXT_color_buffer_half_float(ctx) &&
2344 _mesa_has_EXT_texture_rg(ctx)))
2345 ? GL_RG : 0;
2346 case GL_RG32F:
2347 return ((_mesa_is_desktop_gl(ctx) &&
2348 ctx->Extensions.ARB_texture_rg &&
2349 ctx->Extensions.ARB_texture_float) ||
2350 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
2351 ? GL_RG : 0;
2352 case GL_RGB16F:
2353 return (_mesa_has_ARB_texture_float(ctx) ||
2354 _mesa_has_EXT_color_buffer_half_float(ctx))
2355 ? GL_RGB : 0;
2356 case GL_RGB32F:
2357 return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_float)
2358 ? GL_RGB : 0;
2359 case GL_RGBA16F:
2360 return (_mesa_has_ARB_texture_float(ctx) ||
2361 _mesa_is_gles3(ctx) ||
2362 _mesa_has_EXT_color_buffer_half_float(ctx))
2363 ? GL_RGBA : 0;
2364 case GL_RGBA32F:
2365 return ((_mesa_is_desktop_gl(ctx) &&
2366 ctx->Extensions.ARB_texture_float) ||
2367 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
2368 ? GL_RGBA : 0;
2369 case GL_RGB9_E5:
2370 return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_shared_exponent)
2371 ? GL_RGB: 0;
2372 case GL_ALPHA16F_ARB:
2373 case GL_ALPHA32F_ARB:
2374 return ctx->API == API_OPENGL_COMPAT &&
2375 ctx->Extensions.ARB_texture_float &&
2376 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
2377 case GL_LUMINANCE16F_ARB:
2378 case GL_LUMINANCE32F_ARB:
2379 return ctx->API == API_OPENGL_COMPAT &&
2380 ctx->Extensions.ARB_texture_float &&
2381 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
2382 case GL_LUMINANCE_ALPHA16F_ARB:
2383 case GL_LUMINANCE_ALPHA32F_ARB:
2384 return ctx->API == API_OPENGL_COMPAT &&
2385 ctx->Extensions.ARB_texture_float &&
2386 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
2387 case GL_INTENSITY16F_ARB:
2388 case GL_INTENSITY32F_ARB:
2389 return ctx->API == API_OPENGL_COMPAT &&
2390 ctx->Extensions.ARB_texture_float &&
2391 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
2392 case GL_R11F_G11F_B10F:
2393 return ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_packed_float) ||
2394 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
2395 ? GL_RGB : 0;
2396
2397 case GL_RGBA8UI_EXT:
2398 case GL_RGBA16UI_EXT:
2399 case GL_RGBA32UI_EXT:
2400 case GL_RGBA8I_EXT:
2401 case GL_RGBA16I_EXT:
2402 case GL_RGBA32I_EXT:
2403 return ctx->Version >= 30
2404 || (_mesa_is_desktop_gl(ctx) &&
2405 ctx->Extensions.EXT_texture_integer) ? GL_RGBA : 0;
2406
2407 case GL_RGB8UI_EXT:
2408 case GL_RGB16UI_EXT:
2409 case GL_RGB32UI_EXT:
2410 case GL_RGB8I_EXT:
2411 case GL_RGB16I_EXT:
2412 case GL_RGB32I_EXT:
2413 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_integer
2414 ? GL_RGB : 0;
2415 case GL_R8UI:
2416 case GL_R8I:
2417 case GL_R16UI:
2418 case GL_R16I:
2419 case GL_R32UI:
2420 case GL_R32I:
2421 return ctx->Version >= 30
2422 || (_mesa_is_desktop_gl(ctx) &&
2423 ctx->Extensions.ARB_texture_rg &&
2424 ctx->Extensions.EXT_texture_integer) ? GL_RED : 0;
2425
2426 case GL_RG8UI:
2427 case GL_RG8I:
2428 case GL_RG16UI:
2429 case GL_RG16I:
2430 case GL_RG32UI:
2431 case GL_RG32I:
2432 return ctx->Version >= 30
2433 || (_mesa_is_desktop_gl(ctx) &&
2434 ctx->Extensions.ARB_texture_rg &&
2435 ctx->Extensions.EXT_texture_integer) ? GL_RG : 0;
2436
2437 case GL_INTENSITY8I_EXT:
2438 case GL_INTENSITY8UI_EXT:
2439 case GL_INTENSITY16I_EXT:
2440 case GL_INTENSITY16UI_EXT:
2441 case GL_INTENSITY32I_EXT:
2442 case GL_INTENSITY32UI_EXT:
2443 return ctx->API == API_OPENGL_COMPAT &&
2444 ctx->Extensions.EXT_texture_integer &&
2445 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
2446
2447 case GL_LUMINANCE8I_EXT:
2448 case GL_LUMINANCE8UI_EXT:
2449 case GL_LUMINANCE16I_EXT:
2450 case GL_LUMINANCE16UI_EXT:
2451 case GL_LUMINANCE32I_EXT:
2452 case GL_LUMINANCE32UI_EXT:
2453 return ctx->API == API_OPENGL_COMPAT &&
2454 ctx->Extensions.EXT_texture_integer &&
2455 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
2456
2457 case GL_LUMINANCE_ALPHA8I_EXT:
2458 case GL_LUMINANCE_ALPHA8UI_EXT:
2459 case GL_LUMINANCE_ALPHA16I_EXT:
2460 case GL_LUMINANCE_ALPHA16UI_EXT:
2461 case GL_LUMINANCE_ALPHA32I_EXT:
2462 case GL_LUMINANCE_ALPHA32UI_EXT:
2463 return ctx->API == API_OPENGL_COMPAT &&
2464 ctx->Extensions.EXT_texture_integer &&
2465 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
2466
2467 case GL_ALPHA8I_EXT:
2468 case GL_ALPHA8UI_EXT:
2469 case GL_ALPHA16I_EXT:
2470 case GL_ALPHA16UI_EXT:
2471 case GL_ALPHA32I_EXT:
2472 case GL_ALPHA32UI_EXT:
2473 return ctx->API == API_OPENGL_COMPAT &&
2474 ctx->Extensions.EXT_texture_integer &&
2475 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
2476
2477 case GL_RGB10_A2UI:
2478 return (_mesa_is_desktop_gl(ctx) &&
2479 ctx->Extensions.ARB_texture_rgb10_a2ui)
2480 || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
2481
2482 case GL_RGB565:
2483 return _mesa_is_gles(ctx) || ctx->Extensions.ARB_ES2_compatibility
2484 ? GL_RGB : 0;
2485 default:
2486 return 0;
2487 }
2488 }
2489
2490
2491 /**
2492 * Invalidate a renderbuffer attachment. Called from _mesa_HashWalk().
2493 */
2494 static void
invalidate_rb(void * data,void * userData)2495 invalidate_rb(void *data, void *userData)
2496 {
2497 struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
2498 struct gl_renderbuffer *rb = (struct gl_renderbuffer *) userData;
2499
2500 /* If this is a user-created FBO */
2501 if (_mesa_is_user_fbo(fb)) {
2502 GLuint i;
2503 for (i = 0; i < BUFFER_COUNT; i++) {
2504 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
2505 if (att->Type == GL_RENDERBUFFER &&
2506 att->Renderbuffer == rb) {
2507 /* Mark fb status as indeterminate to force re-validation */
2508 fb->_Status = 0;
2509 return;
2510 }
2511 }
2512 }
2513 }
2514
2515
2516 /** sentinal value, see below */
2517 #define NO_SAMPLES 1000
2518
2519 void
_mesa_renderbuffer_storage(struct gl_context * ctx,struct gl_renderbuffer * rb,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei samples,GLsizei storageSamples)2520 _mesa_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
2521 GLenum internalFormat, GLsizei width,
2522 GLsizei height, GLsizei samples,
2523 GLsizei storageSamples)
2524 {
2525 const GLenum baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
2526
2527 assert(baseFormat != 0);
2528 assert(width >= 0 && width <= (GLsizei) ctx->Const.MaxRenderbufferSize);
2529 assert(height >= 0 && height <= (GLsizei) ctx->Const.MaxRenderbufferSize);
2530 assert(samples != NO_SAMPLES);
2531 if (samples != 0) {
2532 assert(samples > 0);
2533 assert(_mesa_check_sample_count(ctx, GL_RENDERBUFFER,
2534 internalFormat, samples,
2535 storageSamples) == GL_NO_ERROR);
2536 }
2537
2538 FLUSH_VERTICES(ctx, _NEW_BUFFERS, 0);
2539
2540 if (rb->InternalFormat == internalFormat &&
2541 rb->Width == (GLuint) width &&
2542 rb->Height == (GLuint) height &&
2543 rb->NumSamples == samples &&
2544 rb->NumStorageSamples == storageSamples) {
2545 /* no change in allocation needed */
2546 return;
2547 }
2548
2549 /* These MUST get set by the AllocStorage func */
2550 rb->Format = MESA_FORMAT_NONE;
2551 rb->NumSamples = samples;
2552 rb->NumStorageSamples = storageSamples;
2553
2554 /* Now allocate the storage */
2555 assert(rb->AllocStorage);
2556 if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
2557 /* No error - check/set fields now */
2558 /* If rb->Format == MESA_FORMAT_NONE, the format is unsupported. */
2559 assert(rb->Width == (GLuint) width);
2560 assert(rb->Height == (GLuint) height);
2561 rb->InternalFormat = internalFormat;
2562 rb->_BaseFormat = baseFormat;
2563 assert(rb->_BaseFormat != 0);
2564 }
2565 else {
2566 /* Probably ran out of memory - clear the fields */
2567 rb->Width = 0;
2568 rb->Height = 0;
2569 rb->Format = MESA_FORMAT_NONE;
2570 rb->InternalFormat = GL_NONE;
2571 rb->_BaseFormat = GL_NONE;
2572 rb->NumSamples = 0;
2573 rb->NumStorageSamples = 0;
2574 }
2575
2576 /* Invalidate the framebuffers the renderbuffer is attached in. */
2577 if (rb->AttachedAnytime) {
2578 _mesa_HashWalk(ctx->Shared->FrameBuffers, invalidate_rb, rb);
2579 }
2580 }
2581
2582 /**
2583 * Helper function used by renderbuffer_storage_direct() and
2584 * renderbuffer_storage_target().
2585 * samples will be NO_SAMPLES if called by a non-multisample function.
2586 */
2587 static void
renderbuffer_storage(struct gl_context * ctx,struct gl_renderbuffer * rb,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei samples,GLsizei storageSamples,const char * func)2588 renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
2589 GLenum internalFormat, GLsizei width,
2590 GLsizei height, GLsizei samples, GLsizei storageSamples,
2591 const char *func)
2592 {
2593 GLenum baseFormat;
2594 GLenum sample_count_error;
2595
2596 baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
2597 if (baseFormat == 0) {
2598 _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat=%s)",
2599 func, _mesa_enum_to_string(internalFormat));
2600 return;
2601 }
2602
2603 if (width < 0 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
2604 _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid width %d)", func,
2605 width);
2606 return;
2607 }
2608
2609 if (height < 0 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
2610 _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid height %d)", func,
2611 height);
2612 return;
2613 }
2614
2615 if (samples == NO_SAMPLES) {
2616 /* NumSamples == 0 indicates non-multisampling */
2617 samples = 0;
2618 storageSamples = 0;
2619 }
2620 else {
2621 /* check the sample count;
2622 * note: driver may choose to use more samples than what's requested
2623 */
2624 sample_count_error = _mesa_check_sample_count(ctx, GL_RENDERBUFFER,
2625 internalFormat, samples, storageSamples);
2626
2627 /* Section 2.5 (GL Errors) of OpenGL 3.0 specification, page 16:
2628 *
2629 * "If a negative number is provided where an argument of type sizei or
2630 * sizeiptr is specified, the error INVALID VALUE is generated."
2631 */
2632 if (samples < 0 || storageSamples < 0) {
2633 sample_count_error = GL_INVALID_VALUE;
2634 }
2635
2636 if (sample_count_error != GL_NO_ERROR) {
2637 _mesa_error(ctx, sample_count_error,
2638 "%s(samples=%d, storageSamples=%d)", func, samples,
2639 storageSamples);
2640 return;
2641 }
2642 }
2643
2644 _mesa_renderbuffer_storage(ctx, rb, internalFormat, width, height, samples,
2645 storageSamples);
2646 }
2647
2648 /**
2649 * Helper function used by _mesa_NamedRenderbufferStorage*().
2650 * samples will be NO_SAMPLES if called by a non-multisample function.
2651 */
2652 static void
renderbuffer_storage_named(GLuint renderbuffer,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei samples,GLsizei storageSamples,const char * func)2653 renderbuffer_storage_named(GLuint renderbuffer, GLenum internalFormat,
2654 GLsizei width, GLsizei height, GLsizei samples,
2655 GLsizei storageSamples, const char *func)
2656 {
2657 GET_CURRENT_CONTEXT(ctx);
2658
2659 if (MESA_VERBOSE & VERBOSE_API) {
2660 if (samples == NO_SAMPLES)
2661 _mesa_debug(ctx, "%s(%u, %s, %d, %d)\n",
2662 func, renderbuffer,
2663 _mesa_enum_to_string(internalFormat),
2664 width, height);
2665 else
2666 _mesa_debug(ctx, "%s(%u, %s, %d, %d, %d)\n",
2667 func, renderbuffer,
2668 _mesa_enum_to_string(internalFormat),
2669 width, height, samples);
2670 }
2671
2672 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2673 if (!rb || rb == &DummyRenderbuffer) {
2674 /* ID was reserved, but no real renderbuffer object made yet */
2675 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid renderbuffer %u)",
2676 func, renderbuffer);
2677 return;
2678 }
2679
2680 renderbuffer_storage(ctx, rb, internalFormat, width, height, samples,
2681 storageSamples, func);
2682 }
2683
2684 /**
2685 * Helper function used by _mesa_RenderbufferStorage() and
2686 * _mesa_RenderbufferStorageMultisample().
2687 * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage().
2688 */
2689 static void
renderbuffer_storage_target(GLenum target,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei samples,GLsizei storageSamples,const char * func)2690 renderbuffer_storage_target(GLenum target, GLenum internalFormat,
2691 GLsizei width, GLsizei height, GLsizei samples,
2692 GLsizei storageSamples, const char *func)
2693 {
2694 GET_CURRENT_CONTEXT(ctx);
2695
2696 if (MESA_VERBOSE & VERBOSE_API) {
2697 if (samples == NO_SAMPLES)
2698 _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n",
2699 func,
2700 _mesa_enum_to_string(target),
2701 _mesa_enum_to_string(internalFormat),
2702 width, height);
2703 else
2704 _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n",
2705 func,
2706 _mesa_enum_to_string(target),
2707 _mesa_enum_to_string(internalFormat),
2708 width, height, samples);
2709 }
2710
2711 if (target != GL_RENDERBUFFER_EXT) {
2712 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
2713 return;
2714 }
2715
2716 if (!ctx->CurrentRenderbuffer) {
2717 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no renderbuffer bound)",
2718 func);
2719 return;
2720 }
2721
2722 renderbuffer_storage(ctx, ctx->CurrentRenderbuffer, internalFormat, width,
2723 height, samples, storageSamples, func);
2724 }
2725
2726
2727 void GLAPIENTRY
_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target,GLeglImageOES image)2728 _mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
2729 {
2730 struct gl_renderbuffer *rb;
2731 GET_CURRENT_CONTEXT(ctx);
2732
2733 if (!ctx->Extensions.OES_EGL_image) {
2734 _mesa_error(ctx, GL_INVALID_OPERATION,
2735 "glEGLImageTargetRenderbufferStorageOES(unsupported)");
2736 return;
2737 }
2738
2739 if (target != GL_RENDERBUFFER) {
2740 _mesa_error(ctx, GL_INVALID_ENUM,
2741 "EGLImageTargetRenderbufferStorageOES");
2742 return;
2743 }
2744
2745 rb = ctx->CurrentRenderbuffer;
2746 if (!rb) {
2747 _mesa_error(ctx, GL_INVALID_OPERATION,
2748 "EGLImageTargetRenderbufferStorageOES");
2749 return;
2750 }
2751
2752 if (!image || (ctx->Driver.ValidateEGLImage &&
2753 !ctx->Driver.ValidateEGLImage(ctx, image))) {
2754 _mesa_error(ctx, GL_INVALID_VALUE,
2755 "EGLImageTargetRenderbufferStorageOES");
2756 return;
2757 }
2758
2759 FLUSH_VERTICES(ctx, _NEW_BUFFERS, 0);
2760
2761 ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image);
2762 }
2763
2764
2765 /**
2766 * Helper function for _mesa_GetRenderbufferParameteriv() and
2767 * _mesa_GetFramebufferAttachmentParameteriv()
2768 * We have to be careful to respect the base format. For example, if a
2769 * renderbuffer/texture was created with internalFormat=GL_RGB but the
2770 * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE
2771 * we need to return zero.
2772 */
2773 static GLint
get_component_bits(GLenum pname,GLenum baseFormat,mesa_format format)2774 get_component_bits(GLenum pname, GLenum baseFormat, mesa_format format)
2775 {
2776 if (_mesa_base_format_has_channel(baseFormat, pname))
2777 return _mesa_get_format_bits(format, pname);
2778 else
2779 return 0;
2780 }
2781
2782
2783
2784 void GLAPIENTRY
_mesa_RenderbufferStorage(GLenum target,GLenum internalFormat,GLsizei width,GLsizei height)2785 _mesa_RenderbufferStorage(GLenum target, GLenum internalFormat,
2786 GLsizei width, GLsizei height)
2787 {
2788 /* GL_ARB_fbo says calling this function is equivalent to calling
2789 * glRenderbufferStorageMultisample() with samples=0. We pass in
2790 * a token value here just for error reporting purposes.
2791 */
2792 renderbuffer_storage_target(target, internalFormat, width, height,
2793 NO_SAMPLES, 0, "glRenderbufferStorage");
2794 }
2795
2796
2797 void GLAPIENTRY
_mesa_RenderbufferStorageMultisample(GLenum target,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height)2798 _mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
2799 GLenum internalFormat,
2800 GLsizei width, GLsizei height)
2801 {
2802 renderbuffer_storage_target(target, internalFormat, width, height,
2803 samples, samples,
2804 "glRenderbufferStorageMultisample");
2805 }
2806
2807
2808 void GLAPIENTRY
_mesa_RenderbufferStorageMultisampleAdvancedAMD(GLenum target,GLsizei samples,GLsizei storageSamples,GLenum internalFormat,GLsizei width,GLsizei height)2809 _mesa_RenderbufferStorageMultisampleAdvancedAMD(
2810 GLenum target, GLsizei samples, GLsizei storageSamples,
2811 GLenum internalFormat, GLsizei width, GLsizei height)
2812 {
2813 renderbuffer_storage_target(target, internalFormat, width, height,
2814 samples, storageSamples,
2815 "glRenderbufferStorageMultisampleAdvancedAMD");
2816 }
2817
2818
2819 /**
2820 * OpenGL ES version of glRenderBufferStorage.
2821 */
2822 void GLAPIENTRY
_es_RenderbufferStorageEXT(GLenum target,GLenum internalFormat,GLsizei width,GLsizei height)2823 _es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
2824 GLsizei width, GLsizei height)
2825 {
2826 switch (internalFormat) {
2827 case GL_RGB565:
2828 /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */
2829 /* choose a closest format */
2830 internalFormat = GL_RGB5;
2831 break;
2832 default:
2833 break;
2834 }
2835
2836 renderbuffer_storage_target(target, internalFormat, width, height, 0, 0,
2837 "glRenderbufferStorageEXT");
2838 }
2839
2840 void GLAPIENTRY
_mesa_NamedRenderbufferStorage(GLuint renderbuffer,GLenum internalformat,GLsizei width,GLsizei height)2841 _mesa_NamedRenderbufferStorage(GLuint renderbuffer, GLenum internalformat,
2842 GLsizei width, GLsizei height)
2843 {
2844 /* GL_ARB_fbo says calling this function is equivalent to calling
2845 * glRenderbufferStorageMultisample() with samples=0. We pass in
2846 * a token value here just for error reporting purposes.
2847 */
2848 renderbuffer_storage_named(renderbuffer, internalformat, width, height,
2849 NO_SAMPLES, 0, "glNamedRenderbufferStorage");
2850 }
2851
2852 void GLAPIENTRY
_mesa_NamedRenderbufferStorageEXT(GLuint renderbuffer,GLenum internalformat,GLsizei width,GLsizei height)2853 _mesa_NamedRenderbufferStorageEXT(GLuint renderbuffer, GLenum internalformat,
2854 GLsizei width, GLsizei height)
2855 {
2856 GET_CURRENT_CONTEXT(ctx);
2857 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2858 if (!rb || rb == &DummyRenderbuffer) {
2859 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
2860 rb = allocate_renderbuffer_locked(ctx, renderbuffer, rb != NULL,
2861 "glNamedRenderbufferStorageEXT");
2862 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
2863 }
2864 renderbuffer_storage(ctx, rb, internalformat, width, height, NO_SAMPLES,
2865 0, "glNamedRenderbufferStorageEXT");
2866 }
2867
2868
2869 void GLAPIENTRY
_mesa_NamedRenderbufferStorageMultisample(GLuint renderbuffer,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)2870 _mesa_NamedRenderbufferStorageMultisample(GLuint renderbuffer, GLsizei samples,
2871 GLenum internalformat,
2872 GLsizei width, GLsizei height)
2873 {
2874 renderbuffer_storage_named(renderbuffer, internalformat, width, height,
2875 samples, samples,
2876 "glNamedRenderbufferStorageMultisample");
2877 }
2878
2879
2880 void GLAPIENTRY
_mesa_NamedRenderbufferStorageMultisampleEXT(GLuint renderbuffer,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)2881 _mesa_NamedRenderbufferStorageMultisampleEXT(GLuint renderbuffer, GLsizei samples,
2882 GLenum internalformat,
2883 GLsizei width, GLsizei height)
2884 {
2885 GET_CURRENT_CONTEXT(ctx);
2886 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2887 if (!rb || rb == &DummyRenderbuffer) {
2888 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
2889 rb = allocate_renderbuffer_locked(ctx, renderbuffer, rb != NULL,
2890 "glNamedRenderbufferStorageMultisampleEXT");
2891 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
2892 }
2893 renderbuffer_storage(ctx, rb, internalformat, width, height,
2894 samples, samples,
2895 "glNamedRenderbufferStorageMultisample");
2896 }
2897
2898
2899 void GLAPIENTRY
_mesa_NamedRenderbufferStorageMultisampleAdvancedAMD(GLuint renderbuffer,GLsizei samples,GLsizei storageSamples,GLenum internalformat,GLsizei width,GLsizei height)2900 _mesa_NamedRenderbufferStorageMultisampleAdvancedAMD(
2901 GLuint renderbuffer, GLsizei samples, GLsizei storageSamples,
2902 GLenum internalformat, GLsizei width, GLsizei height)
2903 {
2904 renderbuffer_storage_named(renderbuffer, internalformat, width, height,
2905 samples, storageSamples,
2906 "glNamedRenderbufferStorageMultisampleAdvancedAMD");
2907 }
2908
2909
2910 static void
get_render_buffer_parameteriv(struct gl_context * ctx,struct gl_renderbuffer * rb,GLenum pname,GLint * params,const char * func)2911 get_render_buffer_parameteriv(struct gl_context *ctx,
2912 struct gl_renderbuffer *rb, GLenum pname,
2913 GLint *params, const char *func)
2914 {
2915 /* No need to flush here since we're just quering state which is
2916 * not effected by rendering.
2917 */
2918
2919 switch (pname) {
2920 case GL_RENDERBUFFER_WIDTH_EXT:
2921 *params = rb->Width;
2922 return;
2923 case GL_RENDERBUFFER_HEIGHT_EXT:
2924 *params = rb->Height;
2925 return;
2926 case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
2927 *params = rb->InternalFormat;
2928 return;
2929 case GL_RENDERBUFFER_RED_SIZE_EXT:
2930 case GL_RENDERBUFFER_GREEN_SIZE_EXT:
2931 case GL_RENDERBUFFER_BLUE_SIZE_EXT:
2932 case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
2933 case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
2934 case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
2935 *params = get_component_bits(pname, rb->_BaseFormat, rb->Format);
2936 return;
2937 case GL_RENDERBUFFER_SAMPLES:
2938 if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_framebuffer_object)
2939 || _mesa_is_gles3(ctx)) {
2940 *params = rb->NumSamples;
2941 return;
2942 }
2943 break;
2944 case GL_RENDERBUFFER_STORAGE_SAMPLES_AMD:
2945 if (ctx->Extensions.AMD_framebuffer_multisample_advanced) {
2946 *params = rb->NumStorageSamples;
2947 return;
2948 }
2949 break;
2950 }
2951
2952 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname=%s)", func,
2953 _mesa_enum_to_string(pname));
2954 }
2955
2956
2957 void GLAPIENTRY
_mesa_GetRenderbufferParameteriv(GLenum target,GLenum pname,GLint * params)2958 _mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
2959 {
2960 GET_CURRENT_CONTEXT(ctx);
2961
2962 if (target != GL_RENDERBUFFER_EXT) {
2963 _mesa_error(ctx, GL_INVALID_ENUM,
2964 "glGetRenderbufferParameterivEXT(target)");
2965 return;
2966 }
2967
2968 if (!ctx->CurrentRenderbuffer) {
2969 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetRenderbufferParameterivEXT"
2970 "(no renderbuffer bound)");
2971 return;
2972 }
2973
2974 get_render_buffer_parameteriv(ctx, ctx->CurrentRenderbuffer, pname,
2975 params, "glGetRenderbufferParameteriv");
2976 }
2977
2978
2979 void GLAPIENTRY
_mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer,GLenum pname,GLint * params)2980 _mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname,
2981 GLint *params)
2982 {
2983 GET_CURRENT_CONTEXT(ctx);
2984
2985 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2986 if (!rb || rb == &DummyRenderbuffer) {
2987 /* ID was reserved, but no real renderbuffer object made yet */
2988 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetNamedRenderbufferParameteriv"
2989 "(invalid renderbuffer %i)", renderbuffer);
2990 return;
2991 }
2992
2993 get_render_buffer_parameteriv(ctx, rb, pname, params,
2994 "glGetNamedRenderbufferParameteriv");
2995 }
2996
2997
2998 void GLAPIENTRY
_mesa_GetNamedRenderbufferParameterivEXT(GLuint renderbuffer,GLenum pname,GLint * params)2999 _mesa_GetNamedRenderbufferParameterivEXT(GLuint renderbuffer, GLenum pname,
3000 GLint *params)
3001 {
3002 GET_CURRENT_CONTEXT(ctx);
3003
3004 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
3005 if (!rb || rb == &DummyRenderbuffer) {
3006 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
3007 rb = allocate_renderbuffer_locked(ctx, renderbuffer, rb != NULL,
3008 "glGetNamedRenderbufferParameterivEXT");
3009 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
3010 }
3011
3012 get_render_buffer_parameteriv(ctx, rb, pname, params,
3013 "glGetNamedRenderbufferParameterivEXT");
3014 }
3015
3016
3017 GLboolean GLAPIENTRY
_mesa_IsFramebuffer(GLuint framebuffer)3018 _mesa_IsFramebuffer(GLuint framebuffer)
3019 {
3020 GET_CURRENT_CONTEXT(ctx);
3021 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
3022 if (framebuffer) {
3023 struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
3024 if (rb != NULL && rb != &DummyFramebuffer)
3025 return GL_TRUE;
3026 }
3027 return GL_FALSE;
3028 }
3029
3030
3031 /**
3032 * Check if any of the attachments of the given framebuffer are textures
3033 * (render to texture). Call ctx->Driver.RenderTexture() for such
3034 * attachments.
3035 */
3036 static void
check_begin_texture_render(struct gl_context * ctx,struct gl_framebuffer * fb)3037 check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
3038 {
3039 GLuint i;
3040 assert(ctx->Driver.RenderTexture);
3041
3042 if (_mesa_is_winsys_fbo(fb))
3043 return; /* can't render to texture with winsys framebuffers */
3044
3045 for (i = 0; i < BUFFER_COUNT; i++) {
3046 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
3047 if (att->Texture && att->Renderbuffer->TexImage
3048 && driver_RenderTexture_is_safe(att)) {
3049 ctx->Driver.RenderTexture(ctx, fb, att);
3050 }
3051 }
3052 }
3053
3054
3055 /**
3056 * Examine all the framebuffer's attachments to see if any are textures.
3057 * If so, call ctx->Driver.FinishRenderTexture() for each texture to
3058 * notify the device driver that the texture image may have changed.
3059 */
3060 static void
check_end_texture_render(struct gl_context * ctx,struct gl_framebuffer * fb)3061 check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
3062 {
3063 /* Skip if we know NeedsFinishRenderTexture won't be set. */
3064 if (_mesa_is_winsys_fbo(fb) && !ctx->Driver.BindRenderbufferTexImage)
3065 return;
3066
3067 if (ctx->Driver.FinishRenderTexture) {
3068 GLuint i;
3069 for (i = 0; i < BUFFER_COUNT; i++) {
3070 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
3071 struct gl_renderbuffer *rb = att->Renderbuffer;
3072 if (rb && rb->NeedsFinishRenderTexture) {
3073 ctx->Driver.FinishRenderTexture(ctx, rb);
3074 }
3075 }
3076 }
3077 }
3078
3079
3080 static void
bind_framebuffer(GLenum target,GLuint framebuffer)3081 bind_framebuffer(GLenum target, GLuint framebuffer)
3082 {
3083 struct gl_framebuffer *newDrawFb, *newReadFb;
3084 GLboolean bindReadBuf, bindDrawBuf;
3085 GET_CURRENT_CONTEXT(ctx);
3086
3087 switch (target) {
3088 case GL_DRAW_FRAMEBUFFER_EXT:
3089 bindDrawBuf = GL_TRUE;
3090 bindReadBuf = GL_FALSE;
3091 break;
3092 case GL_READ_FRAMEBUFFER_EXT:
3093 bindDrawBuf = GL_FALSE;
3094 bindReadBuf = GL_TRUE;
3095 break;
3096 case GL_FRAMEBUFFER_EXT:
3097 bindDrawBuf = GL_TRUE;
3098 bindReadBuf = GL_TRUE;
3099 break;
3100 default:
3101 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
3102 return;
3103 }
3104
3105 if (framebuffer) {
3106 bool isGenName = false;
3107 /* Binding a user-created framebuffer object */
3108 newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer);
3109 if (newDrawFb == &DummyFramebuffer) {
3110 /* ID was reserved, but no real framebuffer object made yet */
3111 newDrawFb = NULL;
3112 isGenName = true;
3113 }
3114 else if (!newDrawFb && ctx->API == API_OPENGL_CORE) {
3115 /* All FBO IDs must be Gen'd */
3116 _mesa_error(ctx, GL_INVALID_OPERATION,
3117 "glBindFramebuffer(non-gen name)");
3118 return;
3119 }
3120
3121 if (!newDrawFb) {
3122 /* create new framebuffer object */
3123 newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
3124 if (!newDrawFb) {
3125 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
3126 return;
3127 }
3128 _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb, isGenName);
3129 }
3130 newReadFb = newDrawFb;
3131 }
3132 else {
3133 /* Binding the window system framebuffer (which was originally set
3134 * with MakeCurrent).
3135 */
3136 newDrawFb = ctx->WinSysDrawBuffer;
3137 newReadFb = ctx->WinSysReadBuffer;
3138 }
3139
3140 _mesa_bind_framebuffers(ctx,
3141 bindDrawBuf ? newDrawFb : ctx->DrawBuffer,
3142 bindReadBuf ? newReadFb : ctx->ReadBuffer);
3143 }
3144
3145 void
_mesa_bind_framebuffers(struct gl_context * ctx,struct gl_framebuffer * newDrawFb,struct gl_framebuffer * newReadFb)3146 _mesa_bind_framebuffers(struct gl_context *ctx,
3147 struct gl_framebuffer *newDrawFb,
3148 struct gl_framebuffer *newReadFb)
3149 {
3150 struct gl_framebuffer *const oldDrawFb = ctx->DrawBuffer;
3151 struct gl_framebuffer *const oldReadFb = ctx->ReadBuffer;
3152 const bool bindDrawBuf = oldDrawFb != newDrawFb;
3153 const bool bindReadBuf = oldReadFb != newReadFb;
3154
3155 assert(newDrawFb);
3156 assert(newDrawFb != &DummyFramebuffer);
3157
3158 /*
3159 * OK, now bind the new Draw/Read framebuffers, if they're changing.
3160 *
3161 * We also check if we're beginning and/or ending render-to-texture.
3162 * When a framebuffer with texture attachments is unbound, call
3163 * ctx->Driver.FinishRenderTexture().
3164 * When a framebuffer with texture attachments is bound, call
3165 * ctx->Driver.RenderTexture().
3166 *
3167 * Note that if the ReadBuffer has texture attachments we don't consider
3168 * that a render-to-texture case.
3169 */
3170 if (bindReadBuf) {
3171 FLUSH_VERTICES(ctx, _NEW_BUFFERS, 0);
3172
3173 _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb);
3174 }
3175
3176 if (bindDrawBuf) {
3177 FLUSH_VERTICES(ctx, _NEW_BUFFERS, 0);
3178 ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
3179
3180 /* check if old framebuffer had any texture attachments */
3181 if (oldDrawFb)
3182 check_end_texture_render(ctx, oldDrawFb);
3183
3184 /* check if newly bound framebuffer has any texture attachments */
3185 check_begin_texture_render(ctx, newDrawFb);
3186
3187 _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb);
3188 _mesa_update_allow_draw_out_of_order(ctx);
3189 _mesa_update_valid_to_render_state(ctx);
3190 }
3191
3192 if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) {
3193 /* The few classic drivers that actually hook this function really only
3194 * want to know if the draw framebuffer changed.
3195 */
3196 ctx->Driver.BindFramebuffer(ctx,
3197 bindDrawBuf ? GL_FRAMEBUFFER : GL_READ_FRAMEBUFFER,
3198 newDrawFb, newReadFb);
3199 }
3200 }
3201
3202 void GLAPIENTRY
_mesa_BindFramebuffer(GLenum target,GLuint framebuffer)3203 _mesa_BindFramebuffer(GLenum target, GLuint framebuffer)
3204 {
3205 /* OpenGL ES glBindFramebuffer and glBindFramebufferOES use this same entry
3206 * point, but they allow the use of user-generated names.
3207 */
3208 bind_framebuffer(target, framebuffer);
3209 }
3210
3211
3212 void GLAPIENTRY
_mesa_BindFramebufferEXT(GLenum target,GLuint framebuffer)3213 _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
3214 {
3215 bind_framebuffer(target, framebuffer);
3216 }
3217
3218
3219 void GLAPIENTRY
_mesa_DeleteFramebuffers(GLsizei n,const GLuint * framebuffers)3220 _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
3221 {
3222 GLint i;
3223 GET_CURRENT_CONTEXT(ctx);
3224
3225 if (n < 0) {
3226 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteFramebuffers(n < 0)");
3227 return;
3228 }
3229
3230 FLUSH_VERTICES(ctx, _NEW_BUFFERS, 0);
3231
3232 for (i = 0; i < n; i++) {
3233 if (framebuffers[i] > 0) {
3234 struct gl_framebuffer *fb;
3235 fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
3236 if (fb) {
3237 assert(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
3238
3239 /* check if deleting currently bound framebuffer object */
3240 if (fb == ctx->DrawBuffer) {
3241 /* bind default */
3242 assert(fb->RefCount >= 2);
3243 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
3244 }
3245 if (fb == ctx->ReadBuffer) {
3246 /* bind default */
3247 assert(fb->RefCount >= 2);
3248 _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
3249 }
3250
3251 /* remove from hash table immediately, to free the ID */
3252 _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
3253
3254 if (fb != &DummyFramebuffer) {
3255 /* But the object will not be freed until it's no longer
3256 * bound in any context.
3257 */
3258 _mesa_reference_framebuffer(&fb, NULL);
3259 }
3260 }
3261 }
3262 }
3263 }
3264
3265
3266 /**
3267 * This is the implementation for glGenFramebuffers and glCreateFramebuffers.
3268 * It is not exposed to the rest of Mesa to encourage the use of
3269 * nameless buffers in driver internals.
3270 */
3271 static void
create_framebuffers(GLsizei n,GLuint * framebuffers,bool dsa)3272 create_framebuffers(GLsizei n, GLuint *framebuffers, bool dsa)
3273 {
3274 GET_CURRENT_CONTEXT(ctx);
3275 GLint i;
3276 struct gl_framebuffer *fb;
3277
3278 const char *func = dsa ? "glCreateFramebuffers" : "glGenFramebuffers";
3279
3280 if (n < 0) {
3281 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
3282 return;
3283 }
3284
3285 if (!framebuffers)
3286 return;
3287
3288 _mesa_HashLockMutex(ctx->Shared->FrameBuffers);
3289
3290 _mesa_HashFindFreeKeys(ctx->Shared->FrameBuffers, framebuffers, n);
3291
3292 for (i = 0; i < n; i++) {
3293 if (dsa) {
3294 fb = ctx->Driver.NewFramebuffer(ctx, framebuffers[i]);
3295 if (!fb) {
3296 _mesa_HashUnlockMutex(ctx->Shared->FrameBuffers);
3297 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
3298 return;
3299 }
3300 }
3301 else
3302 fb = &DummyFramebuffer;
3303
3304 _mesa_HashInsertLocked(ctx->Shared->FrameBuffers, framebuffers[i],
3305 fb, true);
3306 }
3307
3308 _mesa_HashUnlockMutex(ctx->Shared->FrameBuffers);
3309 }
3310
3311
3312 void GLAPIENTRY
_mesa_GenFramebuffers(GLsizei n,GLuint * framebuffers)3313 _mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers)
3314 {
3315 create_framebuffers(n, framebuffers, false);
3316 }
3317
3318
3319 void GLAPIENTRY
_mesa_CreateFramebuffers(GLsizei n,GLuint * framebuffers)3320 _mesa_CreateFramebuffers(GLsizei n, GLuint *framebuffers)
3321 {
3322 create_framebuffers(n, framebuffers, true);
3323 }
3324
3325
3326 GLenum
_mesa_check_framebuffer_status(struct gl_context * ctx,struct gl_framebuffer * buffer)3327 _mesa_check_framebuffer_status(struct gl_context *ctx,
3328 struct gl_framebuffer *buffer)
3329 {
3330 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
3331
3332 if (_mesa_is_winsys_fbo(buffer)) {
3333 /* EGL_KHR_surfaceless_context allows the winsys FBO to be incomplete. */
3334 if (buffer != &IncompleteFramebuffer) {
3335 return GL_FRAMEBUFFER_COMPLETE_EXT;
3336 } else {
3337 return GL_FRAMEBUFFER_UNDEFINED;
3338 }
3339 }
3340
3341 /* No need to flush here */
3342
3343 if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
3344 _mesa_test_framebuffer_completeness(ctx, buffer);
3345 }
3346
3347 return buffer->_Status;
3348 }
3349
3350
3351 GLenum GLAPIENTRY
_mesa_CheckFramebufferStatus_no_error(GLenum target)3352 _mesa_CheckFramebufferStatus_no_error(GLenum target)
3353 {
3354 GET_CURRENT_CONTEXT(ctx);
3355
3356 struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
3357 return _mesa_check_framebuffer_status(ctx, fb);
3358 }
3359
3360
3361 GLenum GLAPIENTRY
_mesa_CheckFramebufferStatus(GLenum target)3362 _mesa_CheckFramebufferStatus(GLenum target)
3363 {
3364 struct gl_framebuffer *fb;
3365 GET_CURRENT_CONTEXT(ctx);
3366
3367 if (MESA_VERBOSE & VERBOSE_API)
3368 _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n",
3369 _mesa_enum_to_string(target));
3370
3371 fb = get_framebuffer_target(ctx, target);
3372 if (!fb) {
3373 _mesa_error(ctx, GL_INVALID_ENUM,
3374 "glCheckFramebufferStatus(invalid target %s)",
3375 _mesa_enum_to_string(target));
3376 return 0;
3377 }
3378
3379 return _mesa_check_framebuffer_status(ctx, fb);
3380 }
3381
3382
3383 GLenum GLAPIENTRY
_mesa_CheckNamedFramebufferStatus(GLuint framebuffer,GLenum target)3384 _mesa_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target)
3385 {
3386 struct gl_framebuffer *fb;
3387 GET_CURRENT_CONTEXT(ctx);
3388
3389 /* Validate the target (for conformance's sake) and grab a reference to the
3390 * default framebuffer in case framebuffer = 0.
3391 * Section 9.4 Framebuffer Completeness of the OpenGL 4.5 core spec
3392 * (30.10.2014, PDF page 336) says:
3393 * "If framebuffer is zero, then the status of the default read or
3394 * draw framebuffer (as determined by target) is returned."
3395 */
3396 switch (target) {
3397 case GL_DRAW_FRAMEBUFFER:
3398 case GL_FRAMEBUFFER:
3399 fb = ctx->WinSysDrawBuffer;
3400 break;
3401 case GL_READ_FRAMEBUFFER:
3402 fb = ctx->WinSysReadBuffer;
3403 break;
3404 default:
3405 _mesa_error(ctx, GL_INVALID_ENUM,
3406 "glCheckNamedFramebufferStatus(invalid target %s)",
3407 _mesa_enum_to_string(target));
3408 return 0;
3409 }
3410
3411 if (framebuffer) {
3412 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
3413 "glCheckNamedFramebufferStatus");
3414 if (!fb)
3415 return 0;
3416 }
3417
3418 return _mesa_check_framebuffer_status(ctx, fb);
3419 }
3420
3421
3422 GLenum GLAPIENTRY
_mesa_CheckNamedFramebufferStatusEXT(GLuint framebuffer,GLenum target)3423 _mesa_CheckNamedFramebufferStatusEXT(GLuint framebuffer, GLenum target)
3424 {
3425 struct gl_framebuffer *fb;
3426 GET_CURRENT_CONTEXT(ctx);
3427
3428 switch (target) {
3429 case GL_DRAW_FRAMEBUFFER:
3430 case GL_FRAMEBUFFER:
3431 case GL_READ_FRAMEBUFFER:
3432 break;
3433 default:
3434 _mesa_error(ctx, GL_INVALID_ENUM,
3435 "glCheckNamedFramebufferStatusEXT(invalid target %s)",
3436 _mesa_enum_to_string(target));
3437 return 0;
3438 }
3439
3440 if (framebuffer == 0) {
3441 return _mesa_CheckNamedFramebufferStatus(0, target);
3442 }
3443
3444 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
3445 "glCheckNamedFramebufferStatusEXT");
3446 if (!fb)
3447 return 0;
3448
3449 return _mesa_check_framebuffer_status(ctx, fb);
3450 }
3451
3452
3453 /**
3454 * Replicate the src attachment point. Used by framebuffer_texture() when
3455 * the same texture is attached at GL_DEPTH_ATTACHMENT and
3456 * GL_STENCIL_ATTACHMENT.
3457 */
3458 static void
reuse_framebuffer_texture_attachment(struct gl_framebuffer * fb,gl_buffer_index dst,gl_buffer_index src)3459 reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb,
3460 gl_buffer_index dst,
3461 gl_buffer_index src)
3462 {
3463 struct gl_renderbuffer_attachment *dst_att = &fb->Attachment[dst];
3464 struct gl_renderbuffer_attachment *src_att = &fb->Attachment[src];
3465
3466 assert(src_att->Texture != NULL);
3467 assert(src_att->Renderbuffer != NULL);
3468
3469 _mesa_reference_texobj(&dst_att->Texture, src_att->Texture);
3470 _mesa_reference_renderbuffer(&dst_att->Renderbuffer, src_att->Renderbuffer);
3471 dst_att->Type = src_att->Type;
3472 dst_att->Complete = src_att->Complete;
3473 dst_att->TextureLevel = src_att->TextureLevel;
3474 dst_att->CubeMapFace = src_att->CubeMapFace;
3475 dst_att->Zoffset = src_att->Zoffset;
3476 dst_att->Layered = src_att->Layered;
3477 }
3478
3479
3480 static struct gl_texture_object *
get_texture_for_framebuffer(struct gl_context * ctx,GLuint texture)3481 get_texture_for_framebuffer(struct gl_context *ctx, GLuint texture)
3482 {
3483 if (!texture)
3484 return NULL;
3485
3486 return _mesa_lookup_texture(ctx, texture);
3487 }
3488
3489
3490 /**
3491 * Common code called by gl*FramebufferTexture*() to retrieve the correct
3492 * texture object pointer.
3493 *
3494 * \param texObj where the pointer to the texture object is returned. Note
3495 * that a successful call may return texObj = NULL.
3496 *
3497 * \return true if no errors, false if errors
3498 */
3499 static bool
get_texture_for_framebuffer_err(struct gl_context * ctx,GLuint texture,bool layered,const char * caller,struct gl_texture_object ** texObj)3500 get_texture_for_framebuffer_err(struct gl_context *ctx, GLuint texture,
3501 bool layered, const char *caller,
3502 struct gl_texture_object **texObj)
3503 {
3504 *texObj = NULL; /* This will get returned if texture = 0. */
3505
3506 if (!texture)
3507 return true;
3508
3509 *texObj = _mesa_lookup_texture(ctx, texture);
3510 if (*texObj == NULL || (*texObj)->Target == 0) {
3511 /* Can't render to a non-existent texture object.
3512 *
3513 * The OpenGL 4.5 core spec (02.02.2015) in Section 9.2 Binding and
3514 * Managing Framebuffer Objects specifies a different error
3515 * depending upon the calling function (PDF pages 325-328).
3516 * *FramebufferTexture (where layered = GL_TRUE) throws invalid
3517 * value, while the other commands throw invalid operation (where
3518 * layered = GL_FALSE).
3519 */
3520 const GLenum error = layered ? GL_INVALID_VALUE :
3521 GL_INVALID_OPERATION;
3522 _mesa_error(ctx, error,
3523 "%s(non-existent texture %u)", caller, texture);
3524 return false;
3525 }
3526
3527 return true;
3528 }
3529
3530
3531 /**
3532 * Common code called by gl*FramebufferTexture() to verify the texture target
3533 * and decide whether or not the attachment should truly be considered
3534 * layered.
3535 *
3536 * \param layered true if attachment should be considered layered, false if
3537 * not
3538 *
3539 * \return true if no errors, false if errors
3540 */
3541 static bool
check_layered_texture_target(struct gl_context * ctx,GLenum target,const char * caller,GLboolean * layered)3542 check_layered_texture_target(struct gl_context *ctx, GLenum target,
3543 const char *caller, GLboolean *layered)
3544 {
3545 *layered = GL_TRUE;
3546
3547 switch (target) {
3548 case GL_TEXTURE_3D:
3549 case GL_TEXTURE_1D_ARRAY_EXT:
3550 case GL_TEXTURE_2D_ARRAY_EXT:
3551 case GL_TEXTURE_CUBE_MAP:
3552 case GL_TEXTURE_CUBE_MAP_ARRAY:
3553 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3554 return true;
3555 case GL_TEXTURE_1D:
3556 case GL_TEXTURE_2D:
3557 case GL_TEXTURE_RECTANGLE:
3558 case GL_TEXTURE_2D_MULTISAMPLE:
3559 /* These texture types are valid to pass to
3560 * glFramebufferTexture(), but since they aren't layered, it
3561 * is equivalent to calling glFramebufferTexture{1D,2D}().
3562 */
3563 *layered = GL_FALSE;
3564 return true;
3565 }
3566
3567 _mesa_error(ctx, GL_INVALID_OPERATION,
3568 "%s(invalid texture target %s)", caller,
3569 _mesa_enum_to_string(target));
3570 return false;
3571 }
3572
3573
3574 /**
3575 * Common code called by gl*FramebufferTextureLayer() to verify the texture
3576 * target.
3577 *
3578 * \return true if no errors, false if errors
3579 */
3580 static bool
check_texture_target(struct gl_context * ctx,GLenum target,const char * caller)3581 check_texture_target(struct gl_context *ctx, GLenum target,
3582 const char *caller)
3583 {
3584 /* We're being called by glFramebufferTextureLayer().
3585 * The only legal texture types for that function are 3D,
3586 * cube-map, and 1D/2D/cube-map array textures.
3587 *
3588 * We don't need to check for GL_ARB_texture_cube_map_array because the
3589 * application wouldn't have been able to create a texture with a
3590 * GL_TEXTURE_CUBE_MAP_ARRAY target if the extension were not enabled.
3591 */
3592 switch (target) {
3593 case GL_TEXTURE_3D:
3594 case GL_TEXTURE_1D_ARRAY:
3595 case GL_TEXTURE_2D_ARRAY:
3596 case GL_TEXTURE_CUBE_MAP_ARRAY:
3597 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3598 return true;
3599 case GL_TEXTURE_CUBE_MAP:
3600 /* GL_TEXTURE_CUBE_MAP is only allowed by OpenGL 4.5 here, which
3601 * includes the DSA API.
3602 *
3603 * Because DSA is only enabled for GL 3.1+ and this can be called
3604 * from _mesa_FramebufferTextureLayer in compatibility profile,
3605 * we need to check the version.
3606 */
3607 return _mesa_is_desktop_gl(ctx) && ctx->Version >= 31;
3608 }
3609
3610 _mesa_error(ctx, GL_INVALID_OPERATION,
3611 "%s(invalid texture target %s)", caller,
3612 _mesa_enum_to_string(target));
3613 return false;
3614 }
3615
3616
3617 /**
3618 * Common code called by glFramebufferTexture*D() to verify the texture
3619 * target.
3620 *
3621 * \return true if no errors, false if errors
3622 */
3623 static bool
check_textarget(struct gl_context * ctx,int dims,GLenum target,GLenum textarget,const char * caller)3624 check_textarget(struct gl_context *ctx, int dims, GLenum target,
3625 GLenum textarget, const char *caller)
3626 {
3627 bool err = false;
3628
3629 switch (textarget) {
3630 case GL_TEXTURE_1D:
3631 err = dims != 1;
3632 break;
3633 case GL_TEXTURE_1D_ARRAY:
3634 err = dims != 1 || !ctx->Extensions.EXT_texture_array;
3635 break;
3636 case GL_TEXTURE_2D:
3637 err = dims != 2;
3638 break;
3639 case GL_TEXTURE_2D_ARRAY:
3640 err = dims != 2 || !ctx->Extensions.EXT_texture_array ||
3641 (_mesa_is_gles(ctx) && ctx->Version < 30);
3642 break;
3643 case GL_TEXTURE_2D_MULTISAMPLE:
3644 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3645 err = dims != 2 ||
3646 !ctx->Extensions.ARB_texture_multisample ||
3647 (_mesa_is_gles(ctx) && ctx->Version < 31);
3648 break;
3649 case GL_TEXTURE_RECTANGLE:
3650 err = dims != 2 || _mesa_is_gles(ctx) ||
3651 !ctx->Extensions.NV_texture_rectangle;
3652 break;
3653 case GL_TEXTURE_CUBE_MAP:
3654 case GL_TEXTURE_CUBE_MAP_ARRAY:
3655 err = true;
3656 break;
3657 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3658 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3659 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3660 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3661 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3662 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3663 err = dims != 2 || !ctx->Extensions.ARB_texture_cube_map;
3664 break;
3665 case GL_TEXTURE_3D:
3666 err = dims != 3;
3667 break;
3668 default:
3669 _mesa_error(ctx, GL_INVALID_ENUM,
3670 "%s(unknown textarget 0x%x)", caller, textarget);
3671 return false;
3672 }
3673
3674 if (err) {
3675 _mesa_error(ctx, GL_INVALID_OPERATION,
3676 "%s(invalid textarget %s)",
3677 caller, _mesa_enum_to_string(textarget));
3678 return false;
3679 }
3680
3681 /* Make sure textarget is consistent with the texture's type */
3682 err = (target == GL_TEXTURE_CUBE_MAP) ?
3683 !_mesa_is_cube_face(textarget): (target != textarget);
3684
3685 if (err) {
3686 _mesa_error(ctx, GL_INVALID_OPERATION,
3687 "%s(mismatched texture target)", caller);
3688 return false;
3689 }
3690
3691 return true;
3692 }
3693
3694
3695 /**
3696 * Common code called by gl*FramebufferTextureLayer() and
3697 * glFramebufferTexture3D() to validate the layer.
3698 *
3699 * \return true if no errors, false if errors
3700 */
3701 static bool
check_layer(struct gl_context * ctx,GLenum target,GLint layer,const char * caller)3702 check_layer(struct gl_context *ctx, GLenum target, GLint layer,
3703 const char *caller)
3704 {
3705 /* Page 306 (page 328 of the PDF) of the OpenGL 4.5 (Core Profile)
3706 * spec says:
3707 *
3708 * "An INVALID_VALUE error is generated if texture is non-zero
3709 * and layer is negative."
3710 */
3711 if (layer < 0) {
3712 _mesa_error(ctx, GL_INVALID_VALUE, "%s(layer %d < 0)", caller, layer);
3713 return false;
3714 }
3715
3716 if (target == GL_TEXTURE_3D) {
3717 const GLuint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
3718 if (layer >= maxSize) {
3719 _mesa_error(ctx, GL_INVALID_VALUE,
3720 "%s(invalid layer %u)", caller, layer);
3721 return false;
3722 }
3723 }
3724 else if ((target == GL_TEXTURE_1D_ARRAY) ||
3725 (target == GL_TEXTURE_2D_ARRAY) ||
3726 (target == GL_TEXTURE_CUBE_MAP_ARRAY) ||
3727 (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) {
3728 if (layer >= ctx->Const.MaxArrayTextureLayers) {
3729 _mesa_error(ctx, GL_INVALID_VALUE,
3730 "%s(layer %u >= GL_MAX_ARRAY_TEXTURE_LAYERS)",
3731 caller, layer);
3732 return false;
3733 }
3734 }
3735 else if (target == GL_TEXTURE_CUBE_MAP) {
3736 if (layer >= 6) {
3737 _mesa_error(ctx, GL_INVALID_VALUE,
3738 "%s(layer %u >= 6)", caller, layer);
3739 return false;
3740 }
3741 }
3742
3743 return true;
3744 }
3745
3746
3747 /**
3748 * Common code called by all gl*FramebufferTexture*() entry points to verify
3749 * the level.
3750 *
3751 * \return true if no errors, false if errors
3752 */
3753 static bool
check_level(struct gl_context * ctx,struct gl_texture_object * texObj,GLenum target,GLint level,const char * caller)3754 check_level(struct gl_context *ctx, struct gl_texture_object *texObj,
3755 GLenum target, GLint level, const char *caller)
3756 {
3757 /* Section 9.2.8 of the OpenGL 4.6 specification says:
3758 *
3759 * "If texture refers to an immutable-format texture, level must be
3760 * greater than or equal to zero and smaller than the value of
3761 * TEXTURE_VIEW_NUM_LEVELS for texture."
3762 */
3763 const int max_levels = texObj->Immutable ? texObj->Attrib.ImmutableLevels :
3764 _mesa_max_texture_levels(ctx, target);
3765
3766 if (level < 0 || level >= max_levels) {
3767 _mesa_error(ctx, GL_INVALID_VALUE,
3768 "%s(invalid level %d)", caller, level);
3769 return false;
3770 }
3771
3772 return true;
3773 }
3774
3775
3776 struct gl_renderbuffer_attachment *
_mesa_get_and_validate_attachment(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment,const char * caller)3777 _mesa_get_and_validate_attachment(struct gl_context *ctx,
3778 struct gl_framebuffer *fb,
3779 GLenum attachment, const char *caller)
3780 {
3781 /* The window-system framebuffer object is immutable */
3782 if (_mesa_is_winsys_fbo(fb)) {
3783 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(window-system framebuffer)",
3784 caller);
3785 return NULL;
3786 }
3787
3788 /* Not a hash lookup, so we can afford to get the attachment here. */
3789 bool is_color_attachment;
3790 struct gl_renderbuffer_attachment *att =
3791 get_attachment(ctx, fb, attachment, &is_color_attachment);
3792 if (att == NULL) {
3793 if (is_color_attachment) {
3794 _mesa_error(ctx, GL_INVALID_OPERATION,
3795 "%s(invalid color attachment %s)", caller,
3796 _mesa_enum_to_string(attachment));
3797 } else {
3798 _mesa_error(ctx, GL_INVALID_ENUM,
3799 "%s(invalid attachment %s)", caller,
3800 _mesa_enum_to_string(attachment));
3801 }
3802 return NULL;
3803 }
3804
3805 return att;
3806 }
3807
3808
3809 void
_mesa_framebuffer_texture(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment,struct gl_renderbuffer_attachment * att,struct gl_texture_object * texObj,GLenum textarget,GLint level,GLsizei samples,GLuint layer,GLboolean layered)3810 _mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
3811 GLenum attachment,
3812 struct gl_renderbuffer_attachment *att,
3813 struct gl_texture_object *texObj, GLenum textarget,
3814 GLint level, GLsizei samples,
3815 GLuint layer, GLboolean layered)
3816 {
3817 FLUSH_VERTICES(ctx, _NEW_BUFFERS, 0);
3818
3819 simple_mtx_lock(&fb->Mutex);
3820 if (texObj) {
3821 if (attachment == GL_DEPTH_ATTACHMENT &&
3822 texObj == fb->Attachment[BUFFER_STENCIL].Texture &&
3823 level == fb->Attachment[BUFFER_STENCIL].TextureLevel &&
3824 _mesa_tex_target_to_face(textarget) ==
3825 fb->Attachment[BUFFER_STENCIL].CubeMapFace &&
3826 samples == fb->Attachment[BUFFER_STENCIL].NumSamples &&
3827 layer == fb->Attachment[BUFFER_STENCIL].Zoffset) {
3828 /* The texture object is already attached to the stencil attachment
3829 * point. Don't create a new renderbuffer; just reuse the stencil
3830 * attachment's. This is required to prevent a GL error in
3831 * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL).
3832 */
3833 reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH,
3834 BUFFER_STENCIL);
3835 } else if (attachment == GL_STENCIL_ATTACHMENT &&
3836 texObj == fb->Attachment[BUFFER_DEPTH].Texture &&
3837 level == fb->Attachment[BUFFER_DEPTH].TextureLevel &&
3838 _mesa_tex_target_to_face(textarget) ==
3839 fb->Attachment[BUFFER_DEPTH].CubeMapFace &&
3840 samples == fb->Attachment[BUFFER_DEPTH].NumSamples &&
3841 layer == fb->Attachment[BUFFER_DEPTH].Zoffset) {
3842 /* As above, but with depth and stencil transposed. */
3843 reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
3844 BUFFER_DEPTH);
3845 } else {
3846 set_texture_attachment(ctx, fb, att, texObj, textarget,
3847 level, samples, layer, layered);
3848
3849 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
3850 /* Above we created a new renderbuffer and attached it to the
3851 * depth attachment point. Now attach it to the stencil attachment
3852 * point too.
3853 */
3854 assert(att == &fb->Attachment[BUFFER_DEPTH]);
3855 reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL,
3856 BUFFER_DEPTH);
3857 }
3858 }
3859
3860 /* Set the render-to-texture flag. We'll check this flag in
3861 * glTexImage() and friends to determine if we need to revalidate
3862 * any FBOs that might be rendering into this texture.
3863 * This flag never gets cleared since it's non-trivial to determine
3864 * when all FBOs might be done rendering to this texture. That's OK
3865 * though since it's uncommon to render to a texture then repeatedly
3866 * call glTexImage() to change images in the texture.
3867 */
3868 texObj->_RenderToTexture = GL_TRUE;
3869 }
3870 else {
3871 remove_attachment(ctx, att);
3872 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
3873 assert(att == &fb->Attachment[BUFFER_DEPTH]);
3874 remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]);
3875 }
3876 }
3877
3878 invalidate_framebuffer(fb);
3879
3880 simple_mtx_unlock(&fb->Mutex);
3881 }
3882
3883
3884 static void
framebuffer_texture_with_dims_no_error(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level,GLint layer)3885 framebuffer_texture_with_dims_no_error(GLenum target, GLenum attachment,
3886 GLenum textarget, GLuint texture,
3887 GLint level, GLint layer)
3888 {
3889 GET_CURRENT_CONTEXT(ctx);
3890
3891 /* Get the framebuffer object */
3892 struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
3893
3894 /* Get the texture object */
3895 struct gl_texture_object *texObj =
3896 get_texture_for_framebuffer(ctx, texture);
3897
3898 struct gl_renderbuffer_attachment *att =
3899 get_attachment(ctx, fb, attachment, NULL);
3900
3901 _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
3902 level, 0, layer, GL_FALSE);
3903 }
3904
3905
3906 static void
framebuffer_texture_with_dims(int dims,GLenum target,GLuint framebuffer,GLenum attachment,GLenum textarget,GLuint texture,GLint level,GLsizei samples,GLint layer,const char * caller,bool dsa)3907 framebuffer_texture_with_dims(int dims, GLenum target, GLuint framebuffer,
3908 GLenum attachment, GLenum textarget,
3909 GLuint texture, GLint level, GLsizei samples,
3910 GLint layer, const char *caller, bool dsa)
3911 {
3912 GET_CURRENT_CONTEXT(ctx);
3913 struct gl_framebuffer *fb;
3914 struct gl_texture_object *texObj;
3915
3916 /* Get the framebuffer object */
3917 if (dsa) {
3918 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer, caller);
3919 } else {
3920 fb = get_framebuffer_target(ctx, target);
3921 }
3922 if (!fb) {
3923 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", caller,
3924 _mesa_enum_to_string(target));
3925 return;
3926 }
3927
3928 /* Get the texture object */
3929 if (!get_texture_for_framebuffer_err(ctx, texture, false, caller, &texObj))
3930 return;
3931
3932 if (texObj) {
3933 if (!check_textarget(ctx, dims, texObj->Target, textarget, caller))
3934 return;
3935
3936 if ((dims == 3) && !check_layer(ctx, texObj->Target, layer, caller))
3937 return;
3938
3939 if (!check_level(ctx, texObj, textarget, level, caller))
3940 return;
3941 }
3942
3943 struct gl_renderbuffer_attachment *att =
3944 _mesa_get_and_validate_attachment(ctx, fb, attachment, caller);
3945 if (!att)
3946 return;
3947
3948 _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
3949 level, samples, layer, GL_FALSE);
3950 }
3951
3952
3953 void GLAPIENTRY
_mesa_FramebufferTexture1D_no_error(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level)3954 _mesa_FramebufferTexture1D_no_error(GLenum target, GLenum attachment,
3955 GLenum textarget, GLuint texture,
3956 GLint level)
3957 {
3958 framebuffer_texture_with_dims_no_error(target, attachment, textarget,
3959 texture, level, 0);
3960 }
3961
3962
3963 void GLAPIENTRY
_mesa_FramebufferTexture1D(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level)3964 _mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
3965 GLenum textarget, GLuint texture, GLint level)
3966 {
3967 framebuffer_texture_with_dims(1, target, 0, attachment, textarget, texture,
3968 level, 0, 0, "glFramebufferTexture1D", false);
3969 }
3970
3971
3972 void GLAPIENTRY
_mesa_FramebufferTexture2D_no_error(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level)3973 _mesa_FramebufferTexture2D_no_error(GLenum target, GLenum attachment,
3974 GLenum textarget, GLuint texture,
3975 GLint level)
3976 {
3977 framebuffer_texture_with_dims_no_error(target, attachment, textarget,
3978 texture, level, 0);
3979 }
3980
3981
3982 void GLAPIENTRY
_mesa_FramebufferTexture2D(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level)3983 _mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
3984 GLenum textarget, GLuint texture, GLint level)
3985 {
3986 framebuffer_texture_with_dims(2, target, 0, attachment, textarget, texture,
3987 level, 0, 0, "glFramebufferTexture2D", false);
3988 }
3989
3990
3991 void GLAPIENTRY
_mesa_FramebufferTexture2DMultisampleEXT(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level,GLsizei samples)3992 _mesa_FramebufferTexture2DMultisampleEXT(GLenum target, GLenum attachment,
3993 GLenum textarget, GLuint texture,
3994 GLint level, GLsizei samples)
3995 {
3996 framebuffer_texture_with_dims(2, target, 0, attachment, textarget, texture,
3997 level, samples, 0,
3998 "glFramebufferTexture2DMultisampleEXT",
3999 false);
4000 }
4001
4002
4003 void GLAPIENTRY
_mesa_FramebufferTexture3D_no_error(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level,GLint layer)4004 _mesa_FramebufferTexture3D_no_error(GLenum target, GLenum attachment,
4005 GLenum textarget, GLuint texture,
4006 GLint level, GLint layer)
4007 {
4008 framebuffer_texture_with_dims_no_error(target, attachment, textarget,
4009 texture, level, layer);
4010 }
4011
4012
4013 void GLAPIENTRY
_mesa_FramebufferTexture3D(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level,GLint layer)4014 _mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
4015 GLenum textarget, GLuint texture,
4016 GLint level, GLint layer)
4017 {
4018 framebuffer_texture_with_dims(3, target, 0, attachment, textarget, texture,
4019 level, 0, layer, "glFramebufferTexture3D", false);
4020 }
4021
4022
4023 static ALWAYS_INLINE void
frame_buffer_texture(GLuint framebuffer,GLenum target,GLenum attachment,GLuint texture,GLint level,GLint layer,const char * func,bool dsa,bool no_error,bool check_layered)4024 frame_buffer_texture(GLuint framebuffer, GLenum target,
4025 GLenum attachment, GLuint texture,
4026 GLint level, GLint layer, const char *func,
4027 bool dsa, bool no_error, bool check_layered)
4028 {
4029 GET_CURRENT_CONTEXT(ctx);
4030 GLboolean layered = GL_FALSE;
4031
4032 if (!no_error && check_layered) {
4033 if (!_mesa_has_geometry_shaders(ctx)) {
4034 _mesa_error(ctx, GL_INVALID_OPERATION,
4035 "unsupported function (%s) called", func);
4036 return;
4037 }
4038 }
4039
4040 /* Get the framebuffer object */
4041 struct gl_framebuffer *fb;
4042 if (no_error) {
4043 if (dsa) {
4044 fb = _mesa_lookup_framebuffer(ctx, framebuffer);
4045 } else {
4046 fb = get_framebuffer_target(ctx, target);
4047 }
4048 } else {
4049 if (dsa) {
4050 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func);
4051 if (!fb)
4052 return;
4053 } else {
4054 fb = get_framebuffer_target(ctx, target);
4055 if (!fb) {
4056 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)",
4057 func, _mesa_enum_to_string(target));
4058 return;
4059 }
4060 }
4061 }
4062
4063 /* Get the texture object and framebuffer attachment*/
4064 struct gl_renderbuffer_attachment *att;
4065 struct gl_texture_object *texObj;
4066 if (no_error) {
4067 texObj = get_texture_for_framebuffer(ctx, texture);
4068 att = get_attachment(ctx, fb, attachment, NULL);
4069 } else {
4070 if (!get_texture_for_framebuffer_err(ctx, texture, check_layered, func,
4071 &texObj))
4072 return;
4073
4074 att = _mesa_get_and_validate_attachment(ctx, fb, attachment, func);
4075 if (!att)
4076 return;
4077 }
4078
4079 GLenum textarget = 0;
4080 if (texObj) {
4081 if (check_layered) {
4082 /* We do this regardless of no_error because this sets layered */
4083 if (!check_layered_texture_target(ctx, texObj->Target, func,
4084 &layered))
4085 return;
4086 }
4087
4088 if (!no_error) {
4089 if (!check_layered) {
4090 if (!check_texture_target(ctx, texObj->Target, func))
4091 return;
4092
4093 if (!check_layer(ctx, texObj->Target, layer, func))
4094 return;
4095 }
4096
4097 if (!check_level(ctx, texObj, texObj->Target, level, func))
4098 return;
4099 }
4100
4101 if (!check_layered && texObj->Target == GL_TEXTURE_CUBE_MAP) {
4102 assert(layer >= 0 && layer < 6);
4103 textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
4104 layer = 0;
4105 }
4106 }
4107
4108 _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
4109 level, 0, layer, layered);
4110 }
4111
4112 void GLAPIENTRY
_mesa_FramebufferTextureLayer_no_error(GLenum target,GLenum attachment,GLuint texture,GLint level,GLint layer)4113 _mesa_FramebufferTextureLayer_no_error(GLenum target, GLenum attachment,
4114 GLuint texture, GLint level,
4115 GLint layer)
4116 {
4117 frame_buffer_texture(0, target, attachment, texture, level, layer,
4118 "glFramebufferTextureLayer", false, true, false);
4119 }
4120
4121
4122 void GLAPIENTRY
_mesa_FramebufferTextureLayer(GLenum target,GLenum attachment,GLuint texture,GLint level,GLint layer)4123 _mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
4124 GLuint texture, GLint level, GLint layer)
4125 {
4126 frame_buffer_texture(0, target, attachment, texture, level, layer,
4127 "glFramebufferTextureLayer", false, false, false);
4128 }
4129
4130
4131 void GLAPIENTRY
_mesa_NamedFramebufferTextureLayer_no_error(GLuint framebuffer,GLenum attachment,GLuint texture,GLint level,GLint layer)4132 _mesa_NamedFramebufferTextureLayer_no_error(GLuint framebuffer,
4133 GLenum attachment,
4134 GLuint texture, GLint level,
4135 GLint layer)
4136 {
4137 frame_buffer_texture(framebuffer, 0, attachment, texture, level, layer,
4138 "glNamedFramebufferTextureLayer", true, true, false);
4139 }
4140
4141
4142 void GLAPIENTRY
_mesa_NamedFramebufferTextureLayer(GLuint framebuffer,GLenum attachment,GLuint texture,GLint level,GLint layer)4143 _mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment,
4144 GLuint texture, GLint level, GLint layer)
4145 {
4146 frame_buffer_texture(framebuffer, 0, attachment, texture, level, layer,
4147 "glNamedFramebufferTextureLayer", true, false, false);
4148 }
4149
4150
4151 void GLAPIENTRY
_mesa_FramebufferTexture_no_error(GLenum target,GLenum attachment,GLuint texture,GLint level)4152 _mesa_FramebufferTexture_no_error(GLenum target, GLenum attachment,
4153 GLuint texture, GLint level)
4154 {
4155 frame_buffer_texture(0, target, attachment, texture, level, 0,
4156 "glFramebufferTexture", false, true, true);
4157 }
4158
4159
4160 void GLAPIENTRY
_mesa_FramebufferTexture(GLenum target,GLenum attachment,GLuint texture,GLint level)4161 _mesa_FramebufferTexture(GLenum target, GLenum attachment,
4162 GLuint texture, GLint level)
4163 {
4164 frame_buffer_texture(0, target, attachment, texture, level, 0,
4165 "glFramebufferTexture", false, false, true);
4166 }
4167
4168 void GLAPIENTRY
_mesa_NamedFramebufferTexture_no_error(GLuint framebuffer,GLenum attachment,GLuint texture,GLint level)4169 _mesa_NamedFramebufferTexture_no_error(GLuint framebuffer, GLenum attachment,
4170 GLuint texture, GLint level)
4171 {
4172 frame_buffer_texture(framebuffer, 0, attachment, texture, level, 0,
4173 "glNamedFramebufferTexture", true, true, true);
4174 }
4175
4176
4177 void GLAPIENTRY
_mesa_NamedFramebufferTexture(GLuint framebuffer,GLenum attachment,GLuint texture,GLint level)4178 _mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment,
4179 GLuint texture, GLint level)
4180 {
4181 frame_buffer_texture(framebuffer, 0, attachment, texture, level, 0,
4182 "glNamedFramebufferTexture", true, false, true);
4183 }
4184
4185
4186 void GLAPIENTRY
_mesa_NamedFramebufferTexture1DEXT(GLuint framebuffer,GLenum attachment,GLenum textarget,GLuint texture,GLint level)4187 _mesa_NamedFramebufferTexture1DEXT(GLuint framebuffer, GLenum attachment,
4188 GLenum textarget, GLuint texture, GLint level)
4189 {
4190 framebuffer_texture_with_dims(1, GL_FRAMEBUFFER, framebuffer, attachment,
4191 textarget, texture, level, 0, 0,
4192 "glNamedFramebufferTexture1DEXT", true);
4193 }
4194
4195
4196 void GLAPIENTRY
_mesa_NamedFramebufferTexture2DEXT(GLuint framebuffer,GLenum attachment,GLenum textarget,GLuint texture,GLint level)4197 _mesa_NamedFramebufferTexture2DEXT(GLuint framebuffer, GLenum attachment,
4198 GLenum textarget, GLuint texture, GLint level)
4199 {
4200 framebuffer_texture_with_dims(2, GL_FRAMEBUFFER, framebuffer, attachment,
4201 textarget, texture, level, 0, 0,
4202 "glNamedFramebufferTexture2DEXT", true);
4203 }
4204
4205
4206 void GLAPIENTRY
_mesa_NamedFramebufferTexture3DEXT(GLuint framebuffer,GLenum attachment,GLenum textarget,GLuint texture,GLint level,GLint zoffset)4207 _mesa_NamedFramebufferTexture3DEXT(GLuint framebuffer, GLenum attachment,
4208 GLenum textarget, GLuint texture,
4209 GLint level, GLint zoffset)
4210 {
4211 framebuffer_texture_with_dims(3, GL_FRAMEBUFFER, framebuffer, attachment,
4212 textarget, texture, level, 0, zoffset,
4213 "glNamedFramebufferTexture3DEXT", true);
4214 }
4215
4216
4217 void
_mesa_framebuffer_renderbuffer(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment,struct gl_renderbuffer * rb)4218 _mesa_framebuffer_renderbuffer(struct gl_context *ctx,
4219 struct gl_framebuffer *fb,
4220 GLenum attachment,
4221 struct gl_renderbuffer *rb)
4222 {
4223 assert(!_mesa_is_winsys_fbo(fb));
4224
4225 FLUSH_VERTICES(ctx, _NEW_BUFFERS, 0);
4226
4227 assert(ctx->Driver.FramebufferRenderbuffer);
4228 ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
4229
4230 /* Some subsequent GL commands may depend on the framebuffer's visual
4231 * after the binding is updated. Update visual info now.
4232 */
4233 _mesa_update_framebuffer_visual(ctx, fb);
4234 }
4235
4236 static ALWAYS_INLINE void
framebuffer_renderbuffer(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer,const char * func,bool no_error)4237 framebuffer_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
4238 GLenum attachment, GLenum renderbuffertarget,
4239 GLuint renderbuffer, const char *func, bool no_error)
4240 {
4241 struct gl_renderbuffer_attachment *att;
4242 struct gl_renderbuffer *rb;
4243 bool is_color_attachment;
4244
4245 if (!no_error && renderbuffertarget != GL_RENDERBUFFER) {
4246 _mesa_error(ctx, GL_INVALID_ENUM,
4247 "%s(renderbuffertarget is not GL_RENDERBUFFER)", func);
4248 return;
4249 }
4250
4251 if (renderbuffer) {
4252 if (!no_error) {
4253 rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer, func);
4254 if (!rb)
4255 return;
4256 } else {
4257 rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
4258 }
4259 } else {
4260 /* remove renderbuffer attachment */
4261 rb = NULL;
4262 }
4263
4264 if (!no_error) {
4265 if (_mesa_is_winsys_fbo(fb)) {
4266 /* Can't attach new renderbuffers to a window system framebuffer */
4267 _mesa_error(ctx, GL_INVALID_OPERATION,
4268 "%s(window-system framebuffer)", func);
4269 return;
4270 }
4271
4272 att = get_attachment(ctx, fb, attachment, &is_color_attachment);
4273 if (att == NULL) {
4274 /*
4275 * From OpenGL 4.5 spec, section 9.2.7 "Attaching Renderbuffer Images
4276 * to a Framebuffer":
4277 *
4278 * "An INVALID_OPERATION error is generated if attachment is
4279 * COLOR_- ATTACHMENTm where m is greater than or equal to the
4280 * value of MAX_COLOR_- ATTACHMENTS ."
4281 *
4282 * If we are at this point, is because the attachment is not valid, so
4283 * if is_color_attachment is true, is because of the previous reason.
4284 */
4285 if (is_color_attachment) {
4286 _mesa_error(ctx, GL_INVALID_OPERATION,
4287 "%s(invalid color attachment %s)", func,
4288 _mesa_enum_to_string(attachment));
4289 } else {
4290 _mesa_error(ctx, GL_INVALID_ENUM,
4291 "%s(invalid attachment %s)", func,
4292 _mesa_enum_to_string(attachment));
4293 }
4294
4295 return;
4296 }
4297
4298 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
4299 rb && rb->Format != MESA_FORMAT_NONE) {
4300 /* make sure the renderbuffer is a depth/stencil format */
4301 const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
4302 if (baseFormat != GL_DEPTH_STENCIL) {
4303 _mesa_error(ctx, GL_INVALID_OPERATION,
4304 "%s(renderbuffer is not DEPTH_STENCIL format)", func);
4305 return;
4306 }
4307 }
4308 }
4309
4310 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
4311 }
4312
4313 static void
framebuffer_renderbuffer_error(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer,const char * func)4314 framebuffer_renderbuffer_error(struct gl_context *ctx,
4315 struct gl_framebuffer *fb, GLenum attachment,
4316 GLenum renderbuffertarget,
4317 GLuint renderbuffer, const char *func)
4318 {
4319 framebuffer_renderbuffer(ctx, fb, attachment, renderbuffertarget,
4320 renderbuffer, func, false);
4321 }
4322
4323 static void
framebuffer_renderbuffer_no_error(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer,const char * func)4324 framebuffer_renderbuffer_no_error(struct gl_context *ctx,
4325 struct gl_framebuffer *fb, GLenum attachment,
4326 GLenum renderbuffertarget,
4327 GLuint renderbuffer, const char *func)
4328 {
4329 framebuffer_renderbuffer(ctx, fb, attachment, renderbuffertarget,
4330 renderbuffer, func, true);
4331 }
4332
4333 void GLAPIENTRY
_mesa_FramebufferRenderbuffer_no_error(GLenum target,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer)4334 _mesa_FramebufferRenderbuffer_no_error(GLenum target, GLenum attachment,
4335 GLenum renderbuffertarget,
4336 GLuint renderbuffer)
4337 {
4338 GET_CURRENT_CONTEXT(ctx);
4339
4340 struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
4341 framebuffer_renderbuffer_no_error(ctx, fb, attachment, renderbuffertarget,
4342 renderbuffer, "glFramebufferRenderbuffer");
4343 }
4344
4345 void GLAPIENTRY
_mesa_FramebufferRenderbuffer(GLenum target,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer)4346 _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
4347 GLenum renderbuffertarget,
4348 GLuint renderbuffer)
4349 {
4350 struct gl_framebuffer *fb;
4351 GET_CURRENT_CONTEXT(ctx);
4352
4353 fb = get_framebuffer_target(ctx, target);
4354 if (!fb) {
4355 _mesa_error(ctx, GL_INVALID_ENUM,
4356 "glFramebufferRenderbuffer(invalid target %s)",
4357 _mesa_enum_to_string(target));
4358 return;
4359 }
4360
4361 framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
4362 renderbuffer, "glFramebufferRenderbuffer");
4363 }
4364
4365 void GLAPIENTRY
_mesa_NamedFramebufferRenderbuffer_no_error(GLuint framebuffer,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer)4366 _mesa_NamedFramebufferRenderbuffer_no_error(GLuint framebuffer,
4367 GLenum attachment,
4368 GLenum renderbuffertarget,
4369 GLuint renderbuffer)
4370 {
4371 GET_CURRENT_CONTEXT(ctx);
4372
4373 struct gl_framebuffer *fb = _mesa_lookup_framebuffer(ctx, framebuffer);
4374 framebuffer_renderbuffer_no_error(ctx, fb, attachment, renderbuffertarget,
4375 renderbuffer,
4376 "glNamedFramebufferRenderbuffer");
4377 }
4378
4379 void GLAPIENTRY
_mesa_NamedFramebufferRenderbuffer(GLuint framebuffer,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer)4380 _mesa_NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment,
4381 GLenum renderbuffertarget,
4382 GLuint renderbuffer)
4383 {
4384 struct gl_framebuffer *fb;
4385 GET_CURRENT_CONTEXT(ctx);
4386
4387 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4388 "glNamedFramebufferRenderbuffer");
4389 if (!fb)
4390 return;
4391
4392 framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
4393 renderbuffer,
4394 "glNamedFramebufferRenderbuffer");
4395 }
4396
4397
4398 void GLAPIENTRY
_mesa_NamedFramebufferRenderbufferEXT(GLuint framebuffer,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer)4399 _mesa_NamedFramebufferRenderbufferEXT(GLuint framebuffer, GLenum attachment,
4400 GLenum renderbuffertarget,
4401 GLuint renderbuffer)
4402 {
4403 struct gl_framebuffer *fb;
4404 GET_CURRENT_CONTEXT(ctx);
4405
4406 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
4407 "glNamedFramebufferRenderbufferEXT");
4408 if (!fb)
4409 return;
4410
4411 framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
4412 renderbuffer,
4413 "glNamedFramebufferRenderbuffer");
4414 }
4415
4416
4417 static void
get_framebuffer_attachment_parameter(struct gl_context * ctx,struct gl_framebuffer * buffer,GLenum attachment,GLenum pname,GLint * params,const char * caller)4418 get_framebuffer_attachment_parameter(struct gl_context *ctx,
4419 struct gl_framebuffer *buffer,
4420 GLenum attachment, GLenum pname,
4421 GLint *params, const char *caller)
4422 {
4423 const struct gl_renderbuffer_attachment *att;
4424 bool is_color_attachment = false;
4425 GLenum err;
4426
4427 /* The error code for an attachment type of GL_NONE differs between APIs.
4428 *
4429 * From the ES 2.0.25 specification, page 127:
4430 * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, then
4431 * querying any other pname will generate INVALID_ENUM."
4432 *
4433 * From the OpenGL 3.0 specification, page 337, or identically,
4434 * the OpenGL ES 3.0.4 specification, page 240:
4435 *
4436 * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, no
4437 * framebuffer is bound to target. In this case querying pname
4438 * FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero, and all other
4439 * queries will generate an INVALID_OPERATION error."
4440 */
4441 err = ctx->API == API_OPENGLES2 && ctx->Version < 30 ?
4442 GL_INVALID_ENUM : GL_INVALID_OPERATION;
4443
4444 if (_mesa_is_winsys_fbo(buffer)) {
4445 /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec
4446 * says:
4447 *
4448 * "If the framebuffer currently bound to target is zero, then
4449 * INVALID_OPERATION is generated."
4450 *
4451 * The EXT_framebuffer_object spec has the same wording, and the
4452 * OES_framebuffer_object spec refers to the EXT_framebuffer_object
4453 * spec.
4454 */
4455 if ((!_mesa_is_desktop_gl(ctx) ||
4456 !ctx->Extensions.ARB_framebuffer_object)
4457 && !_mesa_is_gles3(ctx)) {
4458 _mesa_error(ctx, GL_INVALID_OPERATION,
4459 "%s(window-system framebuffer)", caller);
4460 return;
4461 }
4462
4463 if (_mesa_is_gles3(ctx) && attachment != GL_BACK &&
4464 attachment != GL_DEPTH && attachment != GL_STENCIL) {
4465 _mesa_error(ctx, GL_INVALID_ENUM,
4466 "%s(invalid attachment %s)", caller,
4467 _mesa_enum_to_string(attachment));
4468 return;
4469 }
4470
4471 /* The specs are not clear about how to handle
4472 * GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME with the default framebuffer,
4473 * but dEQP-GLES3 expects an INVALID_ENUM error. This has also been
4474 * discussed in:
4475 *
4476 * https://cvs.khronos.org/bugzilla/show_bug.cgi?id=12928#c1
4477 * and https://bugs.freedesktop.org/show_bug.cgi?id=31947
4478 */
4479 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4480 _mesa_error(ctx, GL_INVALID_ENUM,
4481 "%s(requesting GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME "
4482 "when GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is "
4483 "GL_FRAMEBUFFER_DEFAULT is not allowed)", caller);
4484 return;
4485 }
4486
4487 /* the default / window-system FBO */
4488 att = get_fb0_attachment(ctx, buffer, attachment);
4489 }
4490 else {
4491 /* user-created framebuffer FBO */
4492 att = get_attachment(ctx, buffer, attachment, &is_color_attachment);
4493 }
4494
4495 if (att == NULL) {
4496 /*
4497 * From OpenGL 4.5 spec, section 9.2.3 "Framebuffer Object Queries":
4498 *
4499 * "An INVALID_OPERATION error is generated if a framebuffer object
4500 * is bound to target and attachment is COLOR_ATTACHMENTm where m is
4501 * greater than or equal to the value of MAX_COLOR_ATTACHMENTS."
4502 *
4503 * If we are at this point, is because the attachment is not valid, so
4504 * if is_color_attachment is true, is because of the previous reason.
4505 */
4506 if (is_color_attachment) {
4507 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid color attachment %s)",
4508 caller, _mesa_enum_to_string(attachment));
4509 } else {
4510 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller,
4511 _mesa_enum_to_string(attachment));
4512 }
4513 return;
4514 }
4515
4516 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
4517 const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt;
4518 if (pname == GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE) {
4519 /* This behavior is first specified in OpenGL 4.4 specification.
4520 *
4521 * From the OpenGL 4.4 spec page 275:
4522 * "This query cannot be performed for a combined depth+stencil
4523 * attachment, since it does not have a single format."
4524 */
4525 _mesa_error(ctx, GL_INVALID_OPERATION,
4526 "%s(GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"
4527 " is invalid for depth+stencil attachment)", caller);
4528 return;
4529 }
4530 /* the depth and stencil attachments must point to the same buffer */
4531 depthAtt = get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT, NULL);
4532 stencilAtt = get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT, NULL);
4533 if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
4534 _mesa_error(ctx, GL_INVALID_OPERATION,
4535 "%s(DEPTH/STENCIL attachments differ)", caller);
4536 return;
4537 }
4538 }
4539
4540 /* No need to flush here */
4541
4542 switch (pname) {
4543 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
4544 /* From the OpenGL spec, 9.2. Binding and Managing Framebuffer Objects:
4545 *
4546 * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, then
4547 * either no framebuffer is bound to target; or the default framebuffer
4548 * is bound, attachment is DEPTH or STENCIL, and the number of depth or
4549 * stencil bits, respectively, is zero."
4550 *
4551 * Note that we don't need explicit checks on DEPTH and STENCIL, because
4552 * on the case the spec is pointing, att->Type is already NONE, so we
4553 * just need to check att->Type.
4554 */
4555 *params = (_mesa_is_winsys_fbo(buffer) && att->Type != GL_NONE) ?
4556 GL_FRAMEBUFFER_DEFAULT : att->Type;
4557 return;
4558 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
4559 if (att->Type == GL_RENDERBUFFER_EXT) {
4560 *params = att->Renderbuffer->Name;
4561 }
4562 else if (att->Type == GL_TEXTURE) {
4563 *params = att->Texture->Name;
4564 }
4565 else {
4566 assert(att->Type == GL_NONE);
4567 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
4568 *params = 0;
4569 } else {
4570 goto invalid_pname_enum;
4571 }
4572 }
4573 return;
4574 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
4575 if (att->Type == GL_TEXTURE) {
4576 *params = att->TextureLevel;
4577 }
4578 else if (att->Type == GL_NONE) {
4579 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4580 _mesa_enum_to_string(pname));
4581 }
4582 else {
4583 goto invalid_pname_enum;
4584 }
4585 return;
4586 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
4587 if (att->Type == GL_TEXTURE) {
4588 if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) {
4589 *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace;
4590 }
4591 else {
4592 *params = 0;
4593 }
4594 }
4595 else if (att->Type == GL_NONE) {
4596 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4597 _mesa_enum_to_string(pname));
4598 }
4599 else {
4600 goto invalid_pname_enum;
4601 }
4602 return;
4603 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
4604 if (ctx->API == API_OPENGLES) {
4605 goto invalid_pname_enum;
4606 } else if (att->Type == GL_NONE) {
4607 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4608 _mesa_enum_to_string(pname));
4609 } else if (att->Type == GL_TEXTURE) {
4610 if (att->Texture && (att->Texture->Target == GL_TEXTURE_3D ||
4611 att->Texture->Target == GL_TEXTURE_2D_ARRAY)) {
4612 *params = att->Zoffset;
4613 }
4614 else {
4615 *params = 0;
4616 }
4617 }
4618 else {
4619 goto invalid_pname_enum;
4620 }
4621 return;
4622 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4623 if ((!_mesa_is_desktop_gl(ctx) ||
4624 !ctx->Extensions.ARB_framebuffer_object)
4625 && !_mesa_is_gles3(ctx)) {
4626 goto invalid_pname_enum;
4627 }
4628 else if (att->Type == GL_NONE) {
4629 if (_mesa_is_winsys_fbo(buffer) &&
4630 (attachment == GL_DEPTH || attachment == GL_STENCIL)) {
4631 *params = GL_LINEAR;
4632 } else {
4633 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4634 _mesa_enum_to_string(pname));
4635 }
4636 }
4637 else {
4638 if (ctx->Extensions.EXT_sRGB) {
4639 *params = (_mesa_is_format_srgb(att->Renderbuffer->Format) ?
4640 GL_SRGB : GL_LINEAR);
4641 }
4642 else {
4643 /* According to ARB_framebuffer_sRGB, we should return LINEAR
4644 * if the sRGB conversion is unsupported. */
4645 *params = GL_LINEAR;
4646 }
4647 }
4648 return;
4649 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4650 if ((ctx->API != API_OPENGL_COMPAT ||
4651 !ctx->Extensions.ARB_framebuffer_object)
4652 && ctx->API != API_OPENGL_CORE
4653 && !_mesa_is_gles3(ctx)) {
4654 goto invalid_pname_enum;
4655 }
4656 else if (att->Type == GL_NONE) {
4657 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4658 _mesa_enum_to_string(pname));
4659 }
4660 else {
4661 mesa_format format = att->Renderbuffer->Format;
4662
4663 /* Page 235 (page 247 of the PDF) in section 6.1.13 of the OpenGL ES
4664 * 3.0.1 spec says:
4665 *
4666 * "If pname is FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE.... If
4667 * attachment is DEPTH_STENCIL_ATTACHMENT the query will fail and
4668 * generate an INVALID_OPERATION error.
4669 */
4670 if (_mesa_is_gles3(ctx) &&
4671 attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
4672 _mesa_error(ctx, GL_INVALID_OPERATION,
4673 "%s(cannot query "
4674 "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE of "
4675 "GL_DEPTH_STENCIL_ATTACHMENT)", caller);
4676 return;
4677 }
4678
4679 if (format == MESA_FORMAT_S_UINT8) {
4680 /* special cases */
4681 *params = GL_INDEX;
4682 }
4683 else if (format == MESA_FORMAT_Z32_FLOAT_S8X24_UINT) {
4684 /* depends on the attachment parameter */
4685 if (attachment == GL_STENCIL_ATTACHMENT) {
4686 *params = GL_INDEX;
4687 }
4688 else {
4689 *params = GL_FLOAT;
4690 }
4691 }
4692 else {
4693 *params = _mesa_get_format_datatype(format);
4694 }
4695 }
4696 return;
4697 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4698 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4699 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4700 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4701 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4702 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4703 if ((!_mesa_is_desktop_gl(ctx) ||
4704 !ctx->Extensions.ARB_framebuffer_object)
4705 && !_mesa_is_gles3(ctx)) {
4706 goto invalid_pname_enum;
4707 }
4708 else if (att->Texture) {
4709 const struct gl_texture_image *texImage =
4710 _mesa_select_tex_image(att->Texture, att->Texture->Target,
4711 att->TextureLevel);
4712 if (texImage) {
4713 *params = get_component_bits(pname, texImage->_BaseFormat,
4714 texImage->TexFormat);
4715 }
4716 else {
4717 *params = 0;
4718 }
4719 }
4720 else if (att->Renderbuffer) {
4721 *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat,
4722 att->Renderbuffer->Format);
4723 }
4724 else {
4725 assert(att->Type == GL_NONE);
4726 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4727 _mesa_enum_to_string(pname));
4728 }
4729 return;
4730 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED:
4731 if (!_mesa_has_geometry_shaders(ctx)) {
4732 goto invalid_pname_enum;
4733 } else if (att->Type == GL_TEXTURE) {
4734 *params = att->Layered;
4735 } else if (att->Type == GL_NONE) {
4736 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4737 _mesa_enum_to_string(pname));
4738 } else {
4739 goto invalid_pname_enum;
4740 }
4741 return;
4742 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT:
4743 if (!ctx->Extensions.EXT_multisampled_render_to_texture) {
4744 goto invalid_pname_enum;
4745 } else if (att->Type == GL_TEXTURE) {
4746 *params = att->NumSamples;
4747 } else if (att->Type == GL_NONE) {
4748 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4749 _mesa_enum_to_string(pname));
4750 } else {
4751 goto invalid_pname_enum;
4752 }
4753 return;
4754 default:
4755 goto invalid_pname_enum;
4756 }
4757
4758 return;
4759
4760 invalid_pname_enum:
4761 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname %s)", caller,
4762 _mesa_enum_to_string(pname));
4763 return;
4764 }
4765
4766
4767 void GLAPIENTRY
_mesa_GetFramebufferAttachmentParameteriv(GLenum target,GLenum attachment,GLenum pname,GLint * params)4768 _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
4769 GLenum pname, GLint *params)
4770 {
4771 GET_CURRENT_CONTEXT(ctx);
4772 struct gl_framebuffer *buffer;
4773
4774 buffer = get_framebuffer_target(ctx, target);
4775 if (!buffer) {
4776 _mesa_error(ctx, GL_INVALID_ENUM,
4777 "glGetFramebufferAttachmentParameteriv(invalid target %s)",
4778 _mesa_enum_to_string(target));
4779 return;
4780 }
4781
4782 get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
4783 params,
4784 "glGetFramebufferAttachmentParameteriv");
4785 }
4786
4787
4788 void GLAPIENTRY
_mesa_GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer,GLenum attachment,GLenum pname,GLint * params)4789 _mesa_GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer,
4790 GLenum attachment,
4791 GLenum pname, GLint *params)
4792 {
4793 GET_CURRENT_CONTEXT(ctx);
4794 struct gl_framebuffer *buffer;
4795
4796 if (framebuffer) {
4797 buffer = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4798 "glGetNamedFramebufferAttachmentParameteriv");
4799 if (!buffer)
4800 return;
4801 }
4802 else {
4803 /*
4804 * Section 9.2 Binding and Managing Framebuffer Objects of the OpenGL
4805 * 4.5 core spec (30.10.2014, PDF page 314):
4806 * "If framebuffer is zero, then the default draw framebuffer is
4807 * queried."
4808 */
4809 buffer = ctx->WinSysDrawBuffer;
4810 }
4811
4812 get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
4813 params,
4814 "glGetNamedFramebufferAttachmentParameteriv");
4815 }
4816
4817
4818 void GLAPIENTRY
_mesa_GetNamedFramebufferAttachmentParameterivEXT(GLuint framebuffer,GLenum attachment,GLenum pname,GLint * params)4819 _mesa_GetNamedFramebufferAttachmentParameterivEXT(GLuint framebuffer,
4820 GLenum attachment,
4821 GLenum pname, GLint *params)
4822 {
4823 GET_CURRENT_CONTEXT(ctx);
4824 struct gl_framebuffer *buffer;
4825
4826 if (framebuffer) {
4827 buffer = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
4828 "glGetNamedFramebufferAttachmentParameterivEXT");
4829 if (!buffer)
4830 return;
4831 }
4832 else {
4833 /*
4834 * Section 9.2 Binding and Managing Framebuffer Objects of the OpenGL
4835 * 4.5 core spec (30.10.2014, PDF page 314):
4836 * "If framebuffer is zero, then the default draw framebuffer is
4837 * queried."
4838 */
4839 buffer = ctx->WinSysDrawBuffer;
4840 }
4841
4842 get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
4843 params,
4844 "glGetNamedFramebufferAttachmentParameterivEXT");
4845 }
4846
4847
4848 void GLAPIENTRY
_mesa_NamedFramebufferParameteri(GLuint framebuffer,GLenum pname,GLint param)4849 _mesa_NamedFramebufferParameteri(GLuint framebuffer, GLenum pname,
4850 GLint param)
4851 {
4852 GET_CURRENT_CONTEXT(ctx);
4853 struct gl_framebuffer *fb = NULL;
4854
4855 if (!ctx->Extensions.ARB_framebuffer_no_attachments &&
4856 !ctx->Extensions.ARB_sample_locations) {
4857 _mesa_error(ctx, GL_INVALID_OPERATION,
4858 "glNamedFramebufferParameteri("
4859 "neither ARB_framebuffer_no_attachments nor "
4860 "ARB_sample_locations is available)");
4861 return;
4862 }
4863
4864 if (framebuffer) {
4865 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4866 "glNamedFramebufferParameteri");
4867 } else {
4868 fb = ctx->WinSysDrawBuffer;
4869 }
4870
4871 if (fb) {
4872 framebuffer_parameteri(ctx, fb, pname, param,
4873 "glNamedFramebufferParameteriv");
4874 }
4875 }
4876
4877
4878 /* Helper function for ARB_framebuffer_no_attachments functions interacting with EXT_direct_state_access */
4879 static struct gl_framebuffer *
lookup_named_framebuffer_ext_dsa(struct gl_context * ctx,GLuint framebuffer,const char * caller)4880 lookup_named_framebuffer_ext_dsa(struct gl_context *ctx, GLuint framebuffer, const char* caller)
4881 {
4882 struct gl_framebuffer *fb = NULL;
4883
4884 if (framebuffer) {
4885 /* The ARB_framebuffer_no_attachments spec says:
4886 *
4887 * "The error INVALID_VALUE is generated if <framebuffer> is not
4888 * a name returned by GenFramebuffers. If a framebuffer object
4889 * named <framebuffer> does not yet exist, it will be created."
4890 *
4891 * This is different from the EXT_direct_state_access spec which says:
4892 *
4893 * "If the framebuffer object named by the framebuffer parameter has not
4894 * been previously bound or has been deleted since the last binding,
4895 * the GL first creates a new state vector in the same manner as when
4896 * BindFramebuffer creates a new framebuffer object"
4897 *
4898 * So first we verify that the name exists.
4899 */
4900 fb = _mesa_lookup_framebuffer(ctx, framebuffer);
4901 if (!fb) {
4902 _mesa_error(ctx, GL_INVALID_VALUE, "%s(frameBuffer)", caller);
4903 return NULL;
4904 }
4905 /* Then, make sure it's initialized */
4906 if (fb == &DummyFramebuffer) {
4907 fb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
4908 _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, fb, true);
4909 }
4910 }
4911 else
4912 fb = ctx->WinSysDrawBuffer;
4913
4914 return fb;
4915 }
4916
4917
4918 void GLAPIENTRY
_mesa_NamedFramebufferParameteriEXT(GLuint framebuffer,GLenum pname,GLint param)4919 _mesa_NamedFramebufferParameteriEXT(GLuint framebuffer, GLenum pname,
4920 GLint param)
4921 {
4922 GET_CURRENT_CONTEXT(ctx);
4923 struct gl_framebuffer *fb =
4924 lookup_named_framebuffer_ext_dsa(ctx, framebuffer,
4925 "glNamedFramebufferParameteriEXT");
4926
4927 if (!fb)
4928 return;
4929
4930 framebuffer_parameteri(ctx, fb, pname, param,
4931 "glNamedFramebufferParameteriEXT");
4932 }
4933
4934
4935 void GLAPIENTRY
_mesa_GetFramebufferParameterivEXT(GLuint framebuffer,GLenum pname,GLint * param)4936 _mesa_GetFramebufferParameterivEXT(GLuint framebuffer, GLenum pname,
4937 GLint *param)
4938 {
4939 GET_CURRENT_CONTEXT(ctx);
4940 struct gl_framebuffer *fb;
4941
4942 if (framebuffer)
4943 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
4944 "glGetFramebufferParameterivEXT");
4945 else
4946 fb = ctx->WinSysDrawBuffer;
4947
4948 if (fb) {
4949 /* The GL_EXT_direct_state_access says:
4950 *
4951 * The pname parameter must be one of framebuffer dependent values
4952 * listed in either table 4.nnn (namely DRAW_BUFFER, READ_BUFFER,
4953 * or DRAW_BUFFER0 through DRAW_BUFFER15).
4954 */
4955 if (pname == GL_DRAW_BUFFER) {
4956 *param = fb->ColorDrawBuffer[0];
4957
4958 }
4959 else if (pname == GL_READ_BUFFER) {
4960 *param = fb->ColorReadBuffer;
4961 }
4962 else if (GL_DRAW_BUFFER0 <= pname && pname <= GL_DRAW_BUFFER15) {
4963 unsigned buffer = pname - GL_DRAW_BUFFER0;
4964 if (buffer < ARRAY_SIZE(fb->ColorDrawBuffer))
4965 *param = fb->ColorDrawBuffer[buffer];
4966 else
4967 _mesa_error(ctx, GL_INVALID_ENUM, "glGetFramebufferParameterivEXT(pname)");
4968 }
4969 else {
4970 _mesa_error(ctx, GL_INVALID_ENUM, "glGetFramebufferParameterivEXT(pname)");
4971 }
4972 }
4973 }
4974
4975
4976 void GLAPIENTRY
_mesa_GetNamedFramebufferParameteriv(GLuint framebuffer,GLenum pname,GLint * param)4977 _mesa_GetNamedFramebufferParameteriv(GLuint framebuffer, GLenum pname,
4978 GLint *param)
4979 {
4980 GET_CURRENT_CONTEXT(ctx);
4981 struct gl_framebuffer *fb;
4982
4983 if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
4984 _mesa_error(ctx, GL_INVALID_OPERATION,
4985 "glNamedFramebufferParameteriv("
4986 "neither ARB_framebuffer_no_attachments nor ARB_sample_locations"
4987 " is available)");
4988 return;
4989 }
4990
4991 if (framebuffer)
4992 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4993 "glGetNamedFramebufferParameteriv");
4994 else
4995 fb = ctx->WinSysDrawBuffer;
4996
4997 if (fb) {
4998 get_framebuffer_parameteriv(ctx, fb, pname, param,
4999 "glGetNamedFramebufferParameteriv");
5000 }
5001 }
5002
5003
5004 void GLAPIENTRY
_mesa_GetNamedFramebufferParameterivEXT(GLuint framebuffer,GLenum pname,GLint * param)5005 _mesa_GetNamedFramebufferParameterivEXT(GLuint framebuffer, GLenum pname,
5006 GLint *param)
5007 {
5008 GET_CURRENT_CONTEXT(ctx);
5009 struct gl_framebuffer *fb =
5010 lookup_named_framebuffer_ext_dsa(ctx, framebuffer,
5011 "glGetNamedFramebufferParameterivEXT");
5012
5013 if (!fb)
5014 return;
5015
5016 get_framebuffer_parameteriv(ctx, fb, pname, param,
5017 "glGetNamedFramebufferParameterivEXT");
5018 }
5019
5020
5021 static void
invalidate_framebuffer_storage(struct gl_context * ctx,struct gl_framebuffer * fb,GLsizei numAttachments,const GLenum * attachments,GLint x,GLint y,GLsizei width,GLsizei height,const char * name)5022 invalidate_framebuffer_storage(struct gl_context *ctx,
5023 struct gl_framebuffer *fb,
5024 GLsizei numAttachments,
5025 const GLenum *attachments, GLint x, GLint y,
5026 GLsizei width, GLsizei height, const char *name)
5027 {
5028 int i;
5029
5030 /* Section 17.4 Whole Framebuffer Operations of the OpenGL 4.5 Core
5031 * Spec (2.2.2015, PDF page 522) says:
5032 * "An INVALID_VALUE error is generated if numAttachments, width, or
5033 * height is negative."
5034 */
5035 if (numAttachments < 0) {
5036 _mesa_error(ctx, GL_INVALID_VALUE,
5037 "%s(numAttachments < 0)", name);
5038 return;
5039 }
5040
5041 if (width < 0) {
5042 _mesa_error(ctx, GL_INVALID_VALUE,
5043 "%s(width < 0)", name);
5044 return;
5045 }
5046
5047 if (height < 0) {
5048 _mesa_error(ctx, GL_INVALID_VALUE,
5049 "%s(height < 0)", name);
5050 return;
5051 }
5052
5053 /* The GL_ARB_invalidate_subdata spec says:
5054 *
5055 * "If an attachment is specified that does not exist in the
5056 * framebuffer bound to <target>, it is ignored."
5057 *
5058 * It also says:
5059 *
5060 * "If <attachments> contains COLOR_ATTACHMENTm and m is greater than
5061 * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error
5062 * INVALID_OPERATION is generated."
5063 *
5064 * No mention is made of GL_AUXi being out of range. Therefore, we allow
5065 * any enum that can be allowed by the API (OpenGL ES 3.0 has a different
5066 * set of retrictions).
5067 */
5068 for (i = 0; i < numAttachments; i++) {
5069 if (_mesa_is_winsys_fbo(fb)) {
5070 switch (attachments[i]) {
5071 case GL_ACCUM:
5072 case GL_AUX0:
5073 case GL_AUX1:
5074 case GL_AUX2:
5075 case GL_AUX3:
5076 /* Accumulation buffers and auxilary buffers were removed in
5077 * OpenGL 3.1, and they never existed in OpenGL ES.
5078 */
5079 if (ctx->API != API_OPENGL_COMPAT)
5080 goto invalid_enum;
5081 break;
5082 case GL_COLOR:
5083 case GL_DEPTH:
5084 case GL_STENCIL:
5085 break;
5086 case GL_BACK_LEFT:
5087 case GL_BACK_RIGHT:
5088 case GL_FRONT_LEFT:
5089 case GL_FRONT_RIGHT:
5090 if (!_mesa_is_desktop_gl(ctx))
5091 goto invalid_enum;
5092 break;
5093 default:
5094 goto invalid_enum;
5095 }
5096 } else {
5097 switch (attachments[i]) {
5098 case GL_DEPTH_ATTACHMENT:
5099 case GL_STENCIL_ATTACHMENT:
5100 break;
5101 case GL_DEPTH_STENCIL_ATTACHMENT:
5102 /* GL_DEPTH_STENCIL_ATTACHMENT is a valid attachment point only
5103 * in desktop and ES 3.0 profiles. Note that OES_packed_depth_stencil
5104 * extension does not make this attachment point valid on ES 2.0.
5105 */
5106 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx))
5107 break;
5108 FALLTHROUGH;
5109 case GL_COLOR_ATTACHMENT0:
5110 case GL_COLOR_ATTACHMENT1:
5111 case GL_COLOR_ATTACHMENT2:
5112 case GL_COLOR_ATTACHMENT3:
5113 case GL_COLOR_ATTACHMENT4:
5114 case GL_COLOR_ATTACHMENT5:
5115 case GL_COLOR_ATTACHMENT6:
5116 case GL_COLOR_ATTACHMENT7:
5117 case GL_COLOR_ATTACHMENT8:
5118 case GL_COLOR_ATTACHMENT9:
5119 case GL_COLOR_ATTACHMENT10:
5120 case GL_COLOR_ATTACHMENT11:
5121 case GL_COLOR_ATTACHMENT12:
5122 case GL_COLOR_ATTACHMENT13:
5123 case GL_COLOR_ATTACHMENT14:
5124 case GL_COLOR_ATTACHMENT15: {
5125 unsigned k = attachments[i] - GL_COLOR_ATTACHMENT0;
5126 if (k >= ctx->Const.MaxColorAttachments) {
5127 _mesa_error(ctx, GL_INVALID_OPERATION,
5128 "%s(attachment >= max. color attachments)", name);
5129 return;
5130 }
5131 break;
5132 }
5133 default:
5134 goto invalid_enum;
5135 }
5136 }
5137 }
5138
5139 /* We don't actually do anything for this yet. Just return after
5140 * validating the parameters and generating the required errors.
5141 */
5142 return;
5143
5144 invalid_enum:
5145 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", name,
5146 _mesa_enum_to_string(attachments[i]));
5147 return;
5148 }
5149
5150 static struct gl_renderbuffer_attachment *
get_fb_attachment(struct gl_context * ctx,struct gl_framebuffer * fb,const GLenum attachment)5151 get_fb_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
5152 const GLenum attachment)
5153 {
5154 switch (attachment) {
5155 case GL_COLOR:
5156 return &fb->Attachment[BUFFER_BACK_LEFT];
5157 case GL_COLOR_ATTACHMENT0:
5158 case GL_COLOR_ATTACHMENT1:
5159 case GL_COLOR_ATTACHMENT2:
5160 case GL_COLOR_ATTACHMENT3:
5161 case GL_COLOR_ATTACHMENT4:
5162 case GL_COLOR_ATTACHMENT5:
5163 case GL_COLOR_ATTACHMENT6:
5164 case GL_COLOR_ATTACHMENT7:
5165 case GL_COLOR_ATTACHMENT8:
5166 case GL_COLOR_ATTACHMENT9:
5167 case GL_COLOR_ATTACHMENT10:
5168 case GL_COLOR_ATTACHMENT11:
5169 case GL_COLOR_ATTACHMENT12:
5170 case GL_COLOR_ATTACHMENT13:
5171 case GL_COLOR_ATTACHMENT14:
5172 case GL_COLOR_ATTACHMENT15: {
5173 const unsigned i = attachment - GL_COLOR_ATTACHMENT0;
5174 if (i >= ctx->Const.MaxColorAttachments)
5175 return NULL;
5176 assert(BUFFER_COLOR0 + i < ARRAY_SIZE(fb->Attachment));
5177 return &fb->Attachment[BUFFER_COLOR0 + i];
5178 }
5179 case GL_DEPTH:
5180 case GL_DEPTH_ATTACHMENT:
5181 case GL_DEPTH_STENCIL_ATTACHMENT:
5182 return &fb->Attachment[BUFFER_DEPTH];
5183 case GL_STENCIL:
5184 case GL_STENCIL_ATTACHMENT:
5185 return &fb->Attachment[BUFFER_STENCIL];
5186 default:
5187 return NULL;
5188 }
5189 }
5190
5191 static void
discard_framebuffer(struct gl_context * ctx,struct gl_framebuffer * fb,GLsizei numAttachments,const GLenum * attachments)5192 discard_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
5193 GLsizei numAttachments, const GLenum *attachments)
5194 {
5195 if (!ctx->Driver.DiscardFramebuffer)
5196 return;
5197
5198 for (int i = 0; i < numAttachments; i++) {
5199 struct gl_renderbuffer_attachment *att =
5200 get_fb_attachment(ctx, fb, attachments[i]);
5201
5202 if (!att)
5203 continue;
5204
5205 /* If we're asked to invalidate just depth or just stencil, but the
5206 * attachment is packed depth/stencil, then we can only use
5207 * Driver.DiscardFramebuffer if the attachments list includes both depth
5208 * and stencil and they both point at the same renderbuffer.
5209 */
5210 if ((attachments[i] == GL_DEPTH_ATTACHMENT ||
5211 attachments[i] == GL_STENCIL_ATTACHMENT) &&
5212 (!att->Renderbuffer ||
5213 att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL)) {
5214 GLenum other_format = (attachments[i] == GL_DEPTH_ATTACHMENT ?
5215 GL_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT);
5216 bool has_both = false;
5217 for (int j = 0; j < numAttachments; j++) {
5218 if (attachments[j] == other_format) {
5219 has_both = true;
5220 break;
5221 }
5222 }
5223
5224 if (fb->Attachment[BUFFER_DEPTH].Renderbuffer !=
5225 fb->Attachment[BUFFER_STENCIL].Renderbuffer || !has_both)
5226 continue;
5227 }
5228
5229 ctx->Driver.DiscardFramebuffer(ctx, fb, att);
5230 }
5231 }
5232
5233 void GLAPIENTRY
_mesa_InvalidateSubFramebuffer_no_error(GLenum target,GLsizei numAttachments,const GLenum * attachments,GLint x,GLint y,GLsizei width,GLsizei height)5234 _mesa_InvalidateSubFramebuffer_no_error(GLenum target, GLsizei numAttachments,
5235 const GLenum *attachments, GLint x,
5236 GLint y, GLsizei width, GLsizei height)
5237 {
5238 /* no-op */
5239 }
5240
5241
5242 void GLAPIENTRY
_mesa_InvalidateSubFramebuffer(GLenum target,GLsizei numAttachments,const GLenum * attachments,GLint x,GLint y,GLsizei width,GLsizei height)5243 _mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
5244 const GLenum *attachments, GLint x, GLint y,
5245 GLsizei width, GLsizei height)
5246 {
5247 struct gl_framebuffer *fb;
5248 GET_CURRENT_CONTEXT(ctx);
5249
5250 fb = get_framebuffer_target(ctx, target);
5251 if (!fb) {
5252 _mesa_error(ctx, GL_INVALID_ENUM,
5253 "glInvalidateSubFramebuffer(invalid target %s)",
5254 _mesa_enum_to_string(target));
5255 return;
5256 }
5257
5258 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
5259 x, y, width, height,
5260 "glInvalidateSubFramebuffer");
5261 }
5262
5263
5264 void GLAPIENTRY
_mesa_InvalidateNamedFramebufferSubData(GLuint framebuffer,GLsizei numAttachments,const GLenum * attachments,GLint x,GLint y,GLsizei width,GLsizei height)5265 _mesa_InvalidateNamedFramebufferSubData(GLuint framebuffer,
5266 GLsizei numAttachments,
5267 const GLenum *attachments,
5268 GLint x, GLint y,
5269 GLsizei width, GLsizei height)
5270 {
5271 struct gl_framebuffer *fb;
5272 GET_CURRENT_CONTEXT(ctx);
5273
5274 /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
5275 * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
5276 * default draw framebuffer is affected."
5277 */
5278 if (framebuffer) {
5279 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
5280 "glInvalidateNamedFramebufferSubData");
5281 if (!fb)
5282 return;
5283 }
5284 else
5285 fb = ctx->WinSysDrawBuffer;
5286
5287 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
5288 x, y, width, height,
5289 "glInvalidateNamedFramebufferSubData");
5290 }
5291
5292 void GLAPIENTRY
_mesa_InvalidateFramebuffer_no_error(GLenum target,GLsizei numAttachments,const GLenum * attachments)5293 _mesa_InvalidateFramebuffer_no_error(GLenum target, GLsizei numAttachments,
5294 const GLenum *attachments)
5295 {
5296 struct gl_framebuffer *fb;
5297 GET_CURRENT_CONTEXT(ctx);
5298
5299 fb = get_framebuffer_target(ctx, target);
5300 if (!fb)
5301 return;
5302
5303 discard_framebuffer(ctx, fb, numAttachments, attachments);
5304 }
5305
5306
5307 void GLAPIENTRY
_mesa_InvalidateFramebuffer(GLenum target,GLsizei numAttachments,const GLenum * attachments)5308 _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
5309 const GLenum *attachments)
5310 {
5311 struct gl_framebuffer *fb;
5312 GET_CURRENT_CONTEXT(ctx);
5313
5314 fb = get_framebuffer_target(ctx, target);
5315 if (!fb) {
5316 _mesa_error(ctx, GL_INVALID_ENUM,
5317 "glInvalidateFramebuffer(invalid target %s)",
5318 _mesa_enum_to_string(target));
5319 return;
5320 }
5321
5322 /* The GL_ARB_invalidate_subdata spec says:
5323 *
5324 * "The command
5325 *
5326 * void InvalidateFramebuffer(enum target,
5327 * sizei numAttachments,
5328 * const enum *attachments);
5329 *
5330 * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
5331 * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
5332 * <MAX_VIEWPORT_DIMS[1]> respectively."
5333 */
5334 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
5335 0, 0,
5336 ctx->Const.MaxViewportWidth,
5337 ctx->Const.MaxViewportHeight,
5338 "glInvalidateFramebuffer");
5339
5340 discard_framebuffer(ctx, fb, numAttachments, attachments);
5341 }
5342
5343
5344 void GLAPIENTRY
_mesa_InvalidateNamedFramebufferData(GLuint framebuffer,GLsizei numAttachments,const GLenum * attachments)5345 _mesa_InvalidateNamedFramebufferData(GLuint framebuffer,
5346 GLsizei numAttachments,
5347 const GLenum *attachments)
5348 {
5349 struct gl_framebuffer *fb;
5350 GET_CURRENT_CONTEXT(ctx);
5351
5352 /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
5353 * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
5354 * default draw framebuffer is affected."
5355 */
5356 if (framebuffer) {
5357 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
5358 "glInvalidateNamedFramebufferData");
5359 if (!fb)
5360 return;
5361 }
5362 else
5363 fb = ctx->WinSysDrawBuffer;
5364
5365 /* The GL_ARB_invalidate_subdata spec says:
5366 *
5367 * "The command
5368 *
5369 * void InvalidateFramebuffer(enum target,
5370 * sizei numAttachments,
5371 * const enum *attachments);
5372 *
5373 * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
5374 * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
5375 * <MAX_VIEWPORT_DIMS[1]> respectively."
5376 */
5377 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
5378 0, 0,
5379 ctx->Const.MaxViewportWidth,
5380 ctx->Const.MaxViewportHeight,
5381 "glInvalidateNamedFramebufferData");
5382 }
5383
5384
5385 void GLAPIENTRY
_mesa_DiscardFramebufferEXT(GLenum target,GLsizei numAttachments,const GLenum * attachments)5386 _mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments,
5387 const GLenum *attachments)
5388 {
5389 struct gl_framebuffer *fb;
5390 GLint i;
5391
5392 GET_CURRENT_CONTEXT(ctx);
5393
5394 fb = get_framebuffer_target(ctx, target);
5395 if (!fb) {
5396 _mesa_error(ctx, GL_INVALID_ENUM,
5397 "glDiscardFramebufferEXT(target %s)",
5398 _mesa_enum_to_string(target));
5399 return;
5400 }
5401
5402 if (numAttachments < 0) {
5403 _mesa_error(ctx, GL_INVALID_VALUE,
5404 "glDiscardFramebufferEXT(numAttachments < 0)");
5405 return;
5406 }
5407
5408 for (i = 0; i < numAttachments; i++) {
5409 switch (attachments[i]) {
5410 case GL_COLOR:
5411 case GL_DEPTH:
5412 case GL_STENCIL:
5413 if (_mesa_is_user_fbo(fb))
5414 goto invalid_enum;
5415 break;
5416 case GL_COLOR_ATTACHMENT0:
5417 case GL_DEPTH_ATTACHMENT:
5418 case GL_STENCIL_ATTACHMENT:
5419 if (_mesa_is_winsys_fbo(fb))
5420 goto invalid_enum;
5421 break;
5422 default:
5423 goto invalid_enum;
5424 }
5425 }
5426
5427 discard_framebuffer(ctx, fb, numAttachments, attachments);
5428
5429 return;
5430
5431 invalid_enum:
5432 _mesa_error(ctx, GL_INVALID_ENUM,
5433 "glDiscardFramebufferEXT(attachment %s)",
5434 _mesa_enum_to_string(attachments[i]));
5435 }
5436
5437 static void
sample_locations(struct gl_context * ctx,struct gl_framebuffer * fb,GLuint start,GLsizei count,const GLfloat * v,bool no_error,const char * name)5438 sample_locations(struct gl_context *ctx, struct gl_framebuffer *fb,
5439 GLuint start, GLsizei count, const GLfloat *v, bool no_error,
5440 const char *name)
5441 {
5442 GLsizei i;
5443
5444 if (!no_error) {
5445 if (!ctx->Extensions.ARB_sample_locations) {
5446 _mesa_error(ctx, GL_INVALID_OPERATION,
5447 "%s not supported "
5448 "(ARB_sample_locations not available)", name);
5449 return;
5450 }
5451
5452 if (start + count > MAX_SAMPLE_LOCATION_TABLE_SIZE) {
5453 _mesa_error(ctx, GL_INVALID_VALUE,
5454 "%s(start+size > sample location table size)", name);
5455 return;
5456 }
5457 }
5458
5459 if (!fb->SampleLocationTable) {
5460 size_t size = MAX_SAMPLE_LOCATION_TABLE_SIZE * 2 * sizeof(GLfloat);
5461 fb->SampleLocationTable = malloc(size);
5462 if (!fb->SampleLocationTable) {
5463 _mesa_error(ctx, GL_OUT_OF_MEMORY,
5464 "Cannot allocate sample location table");
5465 return;
5466 }
5467 for (i = 0; i < MAX_SAMPLE_LOCATION_TABLE_SIZE * 2; i++)
5468 fb->SampleLocationTable[i] = 0.5f;
5469 }
5470
5471 for (i = 0; i < count * 2; i++) {
5472 /* The ARB_sample_locations spec says:
5473 *
5474 * Sample locations outside of [0,1] result in undefined
5475 * behavior.
5476 *
5477 * To simplify driver implementations, we choose to clamp to
5478 * [0,1] and change NaN into 0.5.
5479 */
5480 if (isnan(v[i]) || v[i] < 0.0f || v[i] > 1.0f) {
5481 static GLuint msg_id = 0;
5482 static const char* msg = "Invalid sample location specified";
5483 _mesa_debug_get_id(&msg_id);
5484
5485 _mesa_log_msg(ctx, MESA_DEBUG_SOURCE_API, MESA_DEBUG_TYPE_UNDEFINED,
5486 msg_id, MESA_DEBUG_SEVERITY_HIGH, strlen(msg), msg);
5487 }
5488
5489 if (isnan(v[i]))
5490 fb->SampleLocationTable[start * 2 + i] = 0.5f;
5491 else
5492 fb->SampleLocationTable[start * 2 + i] = SATURATE(v[i]);
5493 }
5494
5495 if (fb == ctx->DrawBuffer)
5496 ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
5497 }
5498
5499 void GLAPIENTRY
_mesa_FramebufferSampleLocationsfvARB(GLenum target,GLuint start,GLsizei count,const GLfloat * v)5500 _mesa_FramebufferSampleLocationsfvARB(GLenum target, GLuint start,
5501 GLsizei count, const GLfloat *v)
5502 {
5503 struct gl_framebuffer *fb;
5504
5505 GET_CURRENT_CONTEXT(ctx);
5506
5507 fb = get_framebuffer_target(ctx, target);
5508 if (!fb) {
5509 _mesa_error(ctx, GL_INVALID_ENUM,
5510 "glFramebufferSampleLocationsfvARB(target %s)",
5511 _mesa_enum_to_string(target));
5512 return;
5513 }
5514
5515 sample_locations(ctx, fb, start, count, v, false,
5516 "glFramebufferSampleLocationsfvARB");
5517 }
5518
5519 void GLAPIENTRY
_mesa_NamedFramebufferSampleLocationsfvARB(GLuint framebuffer,GLuint start,GLsizei count,const GLfloat * v)5520 _mesa_NamedFramebufferSampleLocationsfvARB(GLuint framebuffer, GLuint start,
5521 GLsizei count, const GLfloat *v)
5522 {
5523 struct gl_framebuffer *fb;
5524
5525 GET_CURRENT_CONTEXT(ctx);
5526
5527 if (framebuffer) {
5528 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
5529 "glNamedFramebufferSampleLocationsfvARB");
5530 if (!fb)
5531 return;
5532 }
5533 else
5534 fb = ctx->WinSysDrawBuffer;
5535
5536 sample_locations(ctx, fb, start, count, v, false,
5537 "glNamedFramebufferSampleLocationsfvARB");
5538 }
5539
5540 void GLAPIENTRY
_mesa_FramebufferSampleLocationsfvARB_no_error(GLenum target,GLuint start,GLsizei count,const GLfloat * v)5541 _mesa_FramebufferSampleLocationsfvARB_no_error(GLenum target, GLuint start,
5542 GLsizei count, const GLfloat *v)
5543 {
5544 GET_CURRENT_CONTEXT(ctx);
5545 sample_locations(ctx, get_framebuffer_target(ctx, target), start,
5546 count, v, true, "glFramebufferSampleLocationsfvARB");
5547 }
5548
5549 void GLAPIENTRY
_mesa_NamedFramebufferSampleLocationsfvARB_no_error(GLuint framebuffer,GLuint start,GLsizei count,const GLfloat * v)5550 _mesa_NamedFramebufferSampleLocationsfvARB_no_error(GLuint framebuffer,
5551 GLuint start, GLsizei count,
5552 const GLfloat *v)
5553 {
5554 GET_CURRENT_CONTEXT(ctx);
5555 sample_locations(ctx, _mesa_lookup_framebuffer(ctx, framebuffer), start,
5556 count, v, true, "glNamedFramebufferSampleLocationsfvARB");
5557 }
5558
5559 void GLAPIENTRY
_mesa_EvaluateDepthValuesARB(void)5560 _mesa_EvaluateDepthValuesARB(void)
5561 {
5562 GET_CURRENT_CONTEXT(ctx);
5563
5564 if (!ctx->Extensions.ARB_sample_locations) {
5565 _mesa_error(ctx, GL_INVALID_OPERATION,
5566 "EvaluateDepthValuesARB not supported (neither "
5567 "ARB_sample_locations nor NV_sample_locations is available)");
5568 return;
5569 }
5570
5571 if (ctx->Driver.EvaluateDepthValues)
5572 ctx->Driver.EvaluateDepthValues(ctx);
5573 }
5574