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