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