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