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