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