mesa: add EXT_dsa (Named)Framebuffer functions
[mesa.git] / src / mesa / main / buffers.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26 /**
27 * \file buffers.c
28 * glReadBuffer, DrawBuffer functions.
29 */
30
31
32
33 #include "glheader.h"
34 #include "buffers.h"
35 #include "context.h"
36 #include "enums.h"
37 #include "fbobject.h"
38 #include "hash.h"
39 #include "mtypes.h"
40 #include "util/bitscan.h"
41 #include "util/u_math.h"
42
43
44 #define BAD_MASK ~0u
45
46
47 /**
48 * Return bitmask of BUFFER_BIT_* flags indicating which color buffers are
49 * available to the rendering context (for drawing or reading).
50 * This depends on the type of framebuffer. For window system framebuffers
51 * we look at the framebuffer's visual. But for user-create framebuffers we
52 * look at the number of supported color attachments.
53 * \param fb the framebuffer to draw to, or read from
54 * \return bitmask of BUFFER_BIT_* flags
55 */
56 static GLbitfield
57 supported_buffer_bitmask(const struct gl_context *ctx,
58 const struct gl_framebuffer *fb)
59 {
60 GLbitfield mask = 0x0;
61
62 if (_mesa_is_user_fbo(fb)) {
63 /* A user-created renderbuffer */
64 mask = ((1 << ctx->Const.MaxColorAttachments) - 1) << BUFFER_COLOR0;
65 }
66 else {
67 /* A window system framebuffer */
68 GLint i;
69 mask = BUFFER_BIT_FRONT_LEFT; /* always have this */
70 if (fb->Visual.stereoMode) {
71 mask |= BUFFER_BIT_FRONT_RIGHT;
72 if (fb->Visual.doubleBufferMode) {
73 mask |= BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT;
74 }
75 }
76 else if (fb->Visual.doubleBufferMode) {
77 mask |= BUFFER_BIT_BACK_LEFT;
78 }
79
80 for (i = 0; i < fb->Visual.numAuxBuffers; i++) {
81 mask |= (BUFFER_BIT_AUX0 << i);
82 }
83 }
84
85 return mask;
86 }
87
88 static GLenum
89 back_to_front_if_single_buffered(const struct gl_context *ctx, GLenum buffer)
90 {
91 /* If the front buffer is the only buffer, GL_BACK and all other flags
92 * that include BACK select the front buffer for drawing. There are
93 * several reasons we want to do this.
94 *
95 * 1) OpenGL ES 3.0 requires it:
96 *
97 * Page 181 (page 192 of the PDF) in section 4.2.1 of the OpenGL
98 * ES 3.0.1 specification says:
99 *
100 * "When draw buffer zero is BACK, color values are written
101 * into the sole buffer for single-buffered contexts, or into
102 * the back buffer for double-buffered contexts."
103 *
104 * We also do this for GLES 1 and 2 because those APIs have no
105 * concept of selecting the front and back buffer anyway and it's
106 * convenient to be able to maintain the magic behaviour of
107 * GL_BACK in that case.
108 *
109 * 2) Pbuffers are back buffers from the application point of view,
110 * but they are front buffers from the Mesa point of view,
111 * because they are always single buffered.
112 */
113 if (!ctx->DrawBuffer->Visual.doubleBufferMode) {
114 switch (buffer) {
115 case GL_BACK:
116 buffer = GL_FRONT;
117 break;
118 case GL_BACK_RIGHT:
119 buffer = GL_FRONT_RIGHT;
120 break;
121 case GL_BACK_LEFT:
122 buffer = GL_FRONT_LEFT;
123 break;
124 }
125 }
126
127 return buffer;
128 }
129
130 /**
131 * Helper routine used by glDrawBuffer and glDrawBuffersARB.
132 * Given a GLenum naming one or more color buffers (such as
133 * GL_FRONT_AND_BACK), return the corresponding bitmask of BUFFER_BIT_* flags.
134 */
135 static GLbitfield
136 draw_buffer_enum_to_bitmask(const struct gl_context *ctx, GLenum buffer)
137 {
138 buffer = back_to_front_if_single_buffered(ctx, buffer);
139
140 switch (buffer) {
141 case GL_NONE:
142 return 0;
143 case GL_FRONT:
144 return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT;
145 case GL_BACK:
146 return BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT;
147 case GL_RIGHT:
148 return BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT;
149 case GL_FRONT_RIGHT:
150 return BUFFER_BIT_FRONT_RIGHT;
151 case GL_BACK_RIGHT:
152 return BUFFER_BIT_BACK_RIGHT;
153 case GL_BACK_LEFT:
154 return BUFFER_BIT_BACK_LEFT;
155 case GL_FRONT_AND_BACK:
156 return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT
157 | BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT;
158 case GL_LEFT:
159 return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT;
160 case GL_FRONT_LEFT:
161 return BUFFER_BIT_FRONT_LEFT;
162 case GL_AUX0:
163 return BUFFER_BIT_AUX0;
164 case GL_AUX1:
165 case GL_AUX2:
166 case GL_AUX3:
167 return 1 << BUFFER_COUNT; /* invalid, but not BAD_MASK */
168 case GL_COLOR_ATTACHMENT0_EXT:
169 return BUFFER_BIT_COLOR0;
170 case GL_COLOR_ATTACHMENT1_EXT:
171 return BUFFER_BIT_COLOR1;
172 case GL_COLOR_ATTACHMENT2_EXT:
173 return BUFFER_BIT_COLOR2;
174 case GL_COLOR_ATTACHMENT3_EXT:
175 return BUFFER_BIT_COLOR3;
176 case GL_COLOR_ATTACHMENT4_EXT:
177 return BUFFER_BIT_COLOR4;
178 case GL_COLOR_ATTACHMENT5_EXT:
179 return BUFFER_BIT_COLOR5;
180 case GL_COLOR_ATTACHMENT6_EXT:
181 return BUFFER_BIT_COLOR6;
182 case GL_COLOR_ATTACHMENT7_EXT:
183 return BUFFER_BIT_COLOR7;
184 default:
185 /* not an error, but also not supported */
186 if (buffer >= GL_COLOR_ATTACHMENT8 && buffer <= GL_COLOR_ATTACHMENT31)
187 return 1 << BUFFER_COUNT;
188 /* error */
189 return BAD_MASK;
190 }
191 }
192
193
194 /**
195 * Helper routine used by glReadBuffer.
196 * Given a GLenum naming a color buffer, return the index of the corresponding
197 * renderbuffer (a BUFFER_* value).
198 * return BUFFER_NONE for an invalid buffer.
199 */
200 static gl_buffer_index
201 read_buffer_enum_to_index(const struct gl_context *ctx, GLenum buffer)
202 {
203 buffer = back_to_front_if_single_buffered(ctx, buffer);
204
205 switch (buffer) {
206 case GL_FRONT:
207 return BUFFER_FRONT_LEFT;
208 case GL_BACK:
209 return BUFFER_BACK_LEFT;
210 case GL_RIGHT:
211 return BUFFER_FRONT_RIGHT;
212 case GL_FRONT_RIGHT:
213 return BUFFER_FRONT_RIGHT;
214 case GL_BACK_RIGHT:
215 return BUFFER_BACK_RIGHT;
216 case GL_BACK_LEFT:
217 return BUFFER_BACK_LEFT;
218 case GL_LEFT:
219 return BUFFER_FRONT_LEFT;
220 case GL_FRONT_LEFT:
221 return BUFFER_FRONT_LEFT;
222 case GL_AUX0:
223 return BUFFER_AUX0;
224 case GL_FRONT_AND_BACK:
225 return BUFFER_FRONT_LEFT;
226 case GL_AUX1:
227 case GL_AUX2:
228 case GL_AUX3:
229 return BUFFER_COUNT; /* invalid, but not -1 */
230 case GL_COLOR_ATTACHMENT0_EXT:
231 return BUFFER_COLOR0;
232 case GL_COLOR_ATTACHMENT1_EXT:
233 return BUFFER_COLOR1;
234 case GL_COLOR_ATTACHMENT2_EXT:
235 return BUFFER_COLOR2;
236 case GL_COLOR_ATTACHMENT3_EXT:
237 return BUFFER_COLOR3;
238 case GL_COLOR_ATTACHMENT4_EXT:
239 return BUFFER_COLOR4;
240 case GL_COLOR_ATTACHMENT5_EXT:
241 return BUFFER_COLOR5;
242 case GL_COLOR_ATTACHMENT6_EXT:
243 return BUFFER_COLOR6;
244 case GL_COLOR_ATTACHMENT7_EXT:
245 return BUFFER_COLOR7;
246 default:
247 /* not an error, but also not supported */
248 if (buffer >= GL_COLOR_ATTACHMENT8 && buffer <= GL_COLOR_ATTACHMENT31)
249 return BUFFER_COUNT;
250 /* error */
251 return BUFFER_NONE;
252 }
253 }
254
255 static bool
256 is_legal_es3_readbuffer_enum(GLenum buf)
257 {
258 return buf == GL_BACK || buf == GL_NONE ||
259 (buf >= GL_COLOR_ATTACHMENT0 && buf <= GL_COLOR_ATTACHMENT31);
260 }
261
262 /**
263 * Called by glDrawBuffer() and glNamedFramebufferDrawBuffer().
264 * Specify which renderbuffer(s) to draw into for the first color output.
265 * <buffer> can name zero, one, two or four renderbuffers!
266 * \sa _mesa_DrawBuffers
267 *
268 * \param buffer buffer token such as GL_LEFT or GL_FRONT_AND_BACK, etc.
269 *
270 * Note that the behaviour of this function depends on whether the
271 * current ctx->DrawBuffer is a window-system framebuffer or a user-created
272 * framebuffer object.
273 * In the former case, we update the per-context ctx->Color.DrawBuffer
274 * state var _and_ the FB's ColorDrawBuffer state.
275 * In the later case, we update the FB's ColorDrawBuffer state only.
276 *
277 * Furthermore, upon a MakeCurrent() or BindFramebuffer() call, if the
278 * new FB is a window system FB, we need to re-update the FB's
279 * ColorDrawBuffer state to match the context. This is handled in
280 * _mesa_update_framebuffer().
281 *
282 * See the GL_EXT_framebuffer_object spec for more info.
283 */
284 static ALWAYS_INLINE void
285 draw_buffer(struct gl_context *ctx, struct gl_framebuffer *fb,
286 GLenum buffer, const char *caller, bool no_error)
287 {
288 GLbitfield destMask;
289
290 FLUSH_VERTICES(ctx, 0);
291
292 if (MESA_VERBOSE & VERBOSE_API) {
293 _mesa_debug(ctx, "%s %s\n", caller, _mesa_enum_to_string(buffer));
294 }
295
296 if (buffer == GL_NONE) {
297 destMask = 0x0;
298 }
299 else {
300 const GLbitfield supportedMask
301 = supported_buffer_bitmask(ctx, fb);
302 destMask = draw_buffer_enum_to_bitmask(ctx, buffer);
303 if (!no_error && destMask == BAD_MASK) {
304 /* totally bogus buffer */
305 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)", caller,
306 _mesa_enum_to_string(buffer));
307 return;
308 }
309 destMask &= supportedMask;
310 if (!no_error && destMask == 0x0) {
311 /* none of the named color buffers exist! */
312 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid buffer %s)",
313 caller, _mesa_enum_to_string(buffer));
314 return;
315 }
316 }
317
318 /* if we get here, there's no error so set new state */
319 const GLenum16 buffer16 = buffer;
320 _mesa_drawbuffers(ctx, fb, 1, &buffer16, &destMask);
321
322 /* Call device driver function only if fb is the bound draw buffer */
323 if (fb == ctx->DrawBuffer) {
324 if (ctx->Driver.DrawBuffer)
325 ctx->Driver.DrawBuffer(ctx);
326 if (ctx->Driver.DrawBufferAllocate)
327 ctx->Driver.DrawBufferAllocate(ctx);
328 }
329 }
330
331
332 static void
333 draw_buffer_error(struct gl_context *ctx, struct gl_framebuffer *fb,
334 GLenum buffer, const char *caller)
335 {
336 draw_buffer(ctx, fb, buffer, caller, false);
337 }
338
339
340 static void
341 draw_buffer_no_error(struct gl_context *ctx, struct gl_framebuffer *fb,
342 GLenum buffer, const char *caller)
343 {
344 draw_buffer(ctx, fb, buffer, caller, true);
345 }
346
347
348 void GLAPIENTRY
349 _mesa_DrawBuffer_no_error(GLenum buffer)
350 {
351 GET_CURRENT_CONTEXT(ctx);
352 draw_buffer_no_error(ctx, ctx->DrawBuffer, buffer, "glDrawBuffer");
353 }
354
355
356 void GLAPIENTRY
357 _mesa_DrawBuffer(GLenum buffer)
358 {
359 GET_CURRENT_CONTEXT(ctx);
360 draw_buffer_error(ctx, ctx->DrawBuffer, buffer, "glDrawBuffer");
361 }
362
363
364 void GLAPIENTRY
365 _mesa_NamedFramebufferDrawBuffer_no_error(GLuint framebuffer, GLenum buf)
366 {
367 GET_CURRENT_CONTEXT(ctx);
368 struct gl_framebuffer *fb;
369
370 if (framebuffer) {
371 fb = _mesa_lookup_framebuffer(ctx, framebuffer);
372 } else {
373 fb = ctx->WinSysDrawBuffer;
374 }
375
376 draw_buffer_no_error(ctx, fb, buf, "glNamedFramebufferDrawBuffer");
377 }
378
379
380 void GLAPIENTRY
381 _mesa_FramebufferDrawBufferEXT(GLuint framebuffer, GLenum buf)
382 {
383 GET_CURRENT_CONTEXT(ctx);
384 struct gl_framebuffer *fb;
385
386 if (framebuffer) {
387 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
388 "glFramebufferDrawBufferEXT");
389 if (!fb)
390 return;
391 }
392 else
393 fb = ctx->WinSysDrawBuffer;
394
395 draw_buffer_error(ctx, fb, buf, "glFramebufferDrawBufferEXT");
396 }
397
398
399 void GLAPIENTRY
400 _mesa_NamedFramebufferDrawBuffer(GLuint framebuffer, GLenum buf)
401 {
402 GET_CURRENT_CONTEXT(ctx);
403 struct gl_framebuffer *fb;
404
405 if (framebuffer) {
406 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
407 "glNamedFramebufferDrawBuffer");
408 if (!fb)
409 return;
410 }
411 else
412 fb = ctx->WinSysDrawBuffer;
413
414 draw_buffer_error(ctx, fb, buf, "glNamedFramebufferDrawBuffer");
415 }
416
417
418 /**
419 * Called by glDrawBuffersARB() and glNamedFramebufferDrawBuffers() to specify
420 * the destination color renderbuffers for N fragment program color outputs.
421 * \sa _mesa_DrawBuffer
422 * \param n number of outputs
423 * \param buffers array [n] of renderbuffer names. Unlike glDrawBuffer, the
424 * names cannot specify more than one buffer. For example,
425 * GL_FRONT_AND_BACK is illegal. The only exception is GL_BACK
426 * that is considered special and allowed as far as n is one
427 * since 4.5.
428 */
429 static ALWAYS_INLINE void
430 draw_buffers(struct gl_context *ctx, struct gl_framebuffer *fb, GLsizei n,
431 const GLenum *buffers, const char *caller, bool no_error)
432 {
433 GLuint output;
434 GLbitfield usedBufferMask, supportedMask;
435 GLbitfield destMask[MAX_DRAW_BUFFERS];
436
437 FLUSH_VERTICES(ctx, 0);
438
439 if (!no_error) {
440 /* Turns out n==0 is a valid input that should not produce an error.
441 * The remaining code below correctly handles the n==0 case.
442 *
443 * From the OpenGL 3.0 specification, page 258:
444 * "An INVALID_VALUE error is generated if n is greater than
445 * MAX_DRAW_BUFFERS."
446 */
447 if (n < 0) {
448 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", caller);
449 return;
450 }
451
452 if (n > (GLsizei) ctx->Const.MaxDrawBuffers) {
453 _mesa_error(ctx, GL_INVALID_VALUE,
454 "%s(n > maximum number of draw buffers)", caller);
455 return;
456 }
457
458 /* From the ES 3.0 specification, page 180:
459 * "If the GL is bound to the default framebuffer, then n must be 1
460 * and the constant must be BACK or NONE."
461 * (same restriction applies with GL_EXT_draw_buffers specification)
462 */
463 if (ctx->API == API_OPENGLES2 && _mesa_is_winsys_fbo(fb) &&
464 (n != 1 || (buffers[0] != GL_NONE && buffers[0] != GL_BACK))) {
465 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid buffers)", caller);
466 return;
467 }
468 }
469
470 supportedMask = supported_buffer_bitmask(ctx, fb);
471 usedBufferMask = 0x0;
472
473 /* complicated error checking... */
474 for (output = 0; output < n; output++) {
475 if (!no_error) {
476 /* From the OpenGL 4.5 specification, page 493 (page 515 of the PDF)
477 * "An INVALID_ENUM error is generated if any value in bufs is FRONT,
478 * LEFT, RIGHT, or FRONT_AND_BACK . This restriction applies to both
479 * the default framebuffer and framebuffer objects, and exists because
480 * these constants may themselves refer to multiple buffers, as shown
481 * in table 17.4."
482 *
483 * From the OpenGL 4.5 specification, page 492 (page 514 of the PDF):
484 * "If the default framebuffer is affected, then each of the constants
485 * must be one of the values listed in table 17.6 or the special value
486 * BACK. When BACK is used, n must be 1 and color values are written
487 * into the left buffer for single-buffered contexts, or into the back
488 * left buffer for double-buffered contexts."
489 *
490 * Note "special value BACK". GL_BACK also refers to multiple buffers,
491 * but it is consider a special case here. This is a change on 4.5.
492 * For OpenGL 4.x we check that behaviour. For any previous version we
493 * keep considering it wrong (as INVALID_ENUM).
494 */
495 if (buffers[output] == GL_BACK &&
496 _mesa_is_winsys_fbo(fb) &&
497 _mesa_is_desktop_gl(ctx) &&
498 ctx->Version >= 40) {
499 if (n != 1) {
500 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(with GL_BACK n must be 1)",
501 caller);
502 return;
503 }
504 } else if (buffers[output] == GL_FRONT ||
505 buffers[output] == GL_LEFT ||
506 buffers[output] == GL_RIGHT ||
507 buffers[output] == GL_FRONT_AND_BACK ||
508 (buffers[output] == GL_BACK &&
509 _mesa_is_desktop_gl(ctx))) {
510 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)",
511 caller, _mesa_enum_to_string(buffers[output]));
512 return;
513 }
514 }
515
516 destMask[output] = draw_buffer_enum_to_bitmask(ctx, buffers[output]);
517
518 if (!no_error) {
519 /* From the OpenGL 3.0 specification, page 258:
520 * "Each buffer listed in bufs must be one of the values from tables
521 * 4.5 or 4.6. Otherwise, an INVALID_ENUM error is generated.
522 */
523 if (destMask[output] == BAD_MASK) {
524 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)",
525 caller, _mesa_enum_to_string(buffers[output]));
526 return;
527 }
528
529 /* Section 4.2 (Whole Framebuffer Operations) of the OpenGL ES 3.0
530 * specification says:
531 *
532 * "If the GL is bound to a draw framebuffer object, the ith
533 * buffer listed in bufs must be COLOR_ATTACHMENTi or NONE .
534 * Specifying a buffer out of order, BACK , or COLOR_ATTACHMENTm
535 * where m is greater than or equal to the value of MAX_-
536 * COLOR_ATTACHMENTS , will generate the error INVALID_OPERATION .
537 */
538 if (_mesa_is_gles3(ctx) && _mesa_is_user_fbo(fb) &&
539 buffers[output] != GL_NONE &&
540 (buffers[output] < GL_COLOR_ATTACHMENT0 ||
541 buffers[output] >= GL_COLOR_ATTACHMENT0 + ctx->Const.MaxColorAttachments)) {
542 _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)");
543 return;
544 }
545 }
546
547 if (buffers[output] == GL_NONE) {
548 destMask[output] = 0x0;
549 }
550 else {
551 /* Page 259 (page 275 of the PDF) in section 4.2.1 of the OpenGL 3.0
552 * spec (20080923) says:
553 *
554 * "If the GL is bound to a framebuffer object and DrawBuffers is
555 * supplied with [...] COLOR_ATTACHMENTm where m is greater than
556 * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error
557 * INVALID_OPERATION results."
558 */
559 if (!no_error && _mesa_is_user_fbo(fb) && buffers[output] >=
560 GL_COLOR_ATTACHMENT0 + ctx->Const.MaxDrawBuffers) {
561 _mesa_error(ctx, GL_INVALID_OPERATION,
562 "%s(buffers[%d] >= maximum number of draw buffers)",
563 caller, output);
564 return;
565 }
566
567 /* From the OpenGL 3.0 specification, page 259:
568 * "If the GL is bound to the default framebuffer and DrawBuffers is
569 * supplied with a constant (other than NONE) that does not indicate
570 * any of the color buffers allocated to the GL context by the window
571 * system, the error INVALID_OPERATION will be generated.
572 *
573 * If the GL is bound to a framebuffer object and DrawBuffers is
574 * supplied with a constant from table 4.6 [...] then the error
575 * INVALID_OPERATION results."
576 */
577 destMask[output] &= supportedMask;
578 if (!no_error) {
579 if (destMask[output] == 0) {
580 _mesa_error(ctx, GL_INVALID_OPERATION,
581 "%s(unsupported buffer %s)",
582 caller, _mesa_enum_to_string(buffers[output]));
583 return;
584 }
585
586 /* ES 3.0 is even more restrictive. From the ES 3.0 spec, page 180:
587 * "If the GL is bound to a framebuffer object, the ith buffer
588 * listed in bufs must be COLOR_ATTACHMENTi or NONE. [...]
589 * INVALID_OPERATION." (same restriction applies with
590 * GL_EXT_draw_buffers specification)
591 */
592 if (ctx->API == API_OPENGLES2 && _mesa_is_user_fbo(fb) &&
593 buffers[output] != GL_NONE &&
594 buffers[output] != GL_COLOR_ATTACHMENT0 + output) {
595 _mesa_error(ctx, GL_INVALID_OPERATION,
596 "%s(unsupported buffer %s)",
597 caller, _mesa_enum_to_string(buffers[output]));
598 return;
599 }
600
601 /* From the OpenGL 3.0 specification, page 258:
602 * "Except for NONE, a buffer may not appear more than once in the
603 * array pointed to by bufs. Specifying a buffer more then once
604 * will result in the error INVALID_OPERATION."
605 */
606 if (destMask[output] & usedBufferMask) {
607 _mesa_error(ctx, GL_INVALID_OPERATION,
608 "%s(duplicated buffer %s)",
609 caller, _mesa_enum_to_string(buffers[output]));
610 return;
611 }
612 }
613
614 /* update bitmask */
615 usedBufferMask |= destMask[output];
616 }
617 }
618
619 /* OK, if we get here, there were no errors so set the new state */
620 GLenum16 buffers16[MAX_DRAW_BUFFERS];
621 for (int i = 0; i < n; i++)
622 buffers16[i] = buffers[i];
623
624 _mesa_drawbuffers(ctx, fb, n, buffers16, destMask);
625
626 /*
627 * Call device driver function if fb is the bound draw buffer.
628 * Note that n can be equal to 0,
629 * in which case we don't want to reference buffers[0], which
630 * may not be valid.
631 */
632 if (fb == ctx->DrawBuffer) {
633 if (ctx->Driver.DrawBuffer)
634 ctx->Driver.DrawBuffer(ctx);
635 if (ctx->Driver.DrawBufferAllocate)
636 ctx->Driver.DrawBufferAllocate(ctx);
637 }
638 }
639
640
641 static void
642 draw_buffers_error(struct gl_context *ctx, struct gl_framebuffer *fb, GLsizei n,
643 const GLenum *buffers, const char *caller)
644 {
645 draw_buffers(ctx, fb, n, buffers, caller, false);
646 }
647
648
649 static void
650 draw_buffers_no_error(struct gl_context *ctx, struct gl_framebuffer *fb,
651 GLsizei n, const GLenum *buffers, const char *caller)
652 {
653 draw_buffers(ctx, fb, n, buffers, caller, true);
654 }
655
656
657 void GLAPIENTRY
658 _mesa_DrawBuffers_no_error(GLsizei n, const GLenum *buffers)
659 {
660 GET_CURRENT_CONTEXT(ctx);
661 draw_buffers_no_error(ctx, ctx->DrawBuffer, n, buffers, "glDrawBuffers");
662 }
663
664
665 void GLAPIENTRY
666 _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
667 {
668 GET_CURRENT_CONTEXT(ctx);
669 draw_buffers_error(ctx, ctx->DrawBuffer, n, buffers, "glDrawBuffers");
670 }
671
672 void GLAPIENTRY
673 _mesa_FramebufferDrawBuffersEXT(GLuint framebuffer, GLsizei n,
674 const GLenum *bufs)
675 {
676 GET_CURRENT_CONTEXT(ctx);
677 struct gl_framebuffer *fb;
678
679 if (framebuffer) {
680 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
681 "glFramebufferDrawBuffersEXT");
682 if (!fb)
683 return;
684 }
685 else
686 fb = ctx->WinSysDrawBuffer;
687
688 draw_buffers_error(ctx, fb, n, bufs, "glFramebufferDrawBuffersEXT");
689 }
690
691 void GLAPIENTRY
692 _mesa_NamedFramebufferDrawBuffers_no_error(GLuint framebuffer, GLsizei n,
693 const GLenum *bufs)
694 {
695 GET_CURRENT_CONTEXT(ctx);
696 struct gl_framebuffer *fb;
697
698 if (framebuffer) {
699 fb = _mesa_lookup_framebuffer(ctx, framebuffer);
700 } else {
701 fb = ctx->WinSysDrawBuffer;
702 }
703
704 draw_buffers_no_error(ctx, fb, n, bufs, "glNamedFramebufferDrawBuffers");
705 }
706
707
708 void GLAPIENTRY
709 _mesa_NamedFramebufferDrawBuffers(GLuint framebuffer, GLsizei n,
710 const GLenum *bufs)
711 {
712 GET_CURRENT_CONTEXT(ctx);
713 struct gl_framebuffer *fb;
714
715 if (framebuffer) {
716 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
717 "glNamedFramebufferDrawBuffers");
718 if (!fb)
719 return;
720 }
721 else
722 fb = ctx->WinSysDrawBuffer;
723
724 draw_buffers_error(ctx, fb, n, bufs, "glNamedFramebufferDrawBuffers");
725 }
726
727
728 /**
729 * Performs necessary state updates when _mesa_drawbuffers makes an
730 * actual change.
731 */
732 static void
733 updated_drawbuffers(struct gl_context *ctx, struct gl_framebuffer *fb)
734 {
735 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
736
737 if (ctx->API == API_OPENGL_COMPAT && !ctx->Extensions.ARB_ES2_compatibility) {
738 /* Flag the FBO as requiring validation. */
739 if (_mesa_is_user_fbo(fb)) {
740 fb->_Status = 0;
741 }
742 }
743 }
744
745
746 /**
747 * Helper function to set the GL_DRAW_BUFFER state for the given context and
748 * FBO. Called via glDrawBuffer(), glDrawBuffersARB()
749 *
750 * All error checking will have been done prior to calling this function
751 * so nothing should go wrong at this point.
752 *
753 * \param ctx current context
754 * \param fb the desired draw buffer
755 * \param n number of color outputs to set
756 * \param buffers array[n] of colorbuffer names, like GL_LEFT.
757 * \param destMask array[n] of BUFFER_BIT_* bitmasks which correspond to the
758 * colorbuffer names. (i.e. GL_FRONT_AND_BACK =>
759 * BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT).
760 */
761 void
762 _mesa_drawbuffers(struct gl_context *ctx, struct gl_framebuffer *fb,
763 GLuint n, const GLenum16 *buffers,
764 const GLbitfield *destMask)
765 {
766 GLbitfield mask[MAX_DRAW_BUFFERS];
767 GLuint buf;
768
769 if (!destMask) {
770 /* compute destMask values now */
771 const GLbitfield supportedMask = supported_buffer_bitmask(ctx, fb);
772 GLuint output;
773 for (output = 0; output < n; output++) {
774 mask[output] = draw_buffer_enum_to_bitmask(ctx, buffers[output]);
775 assert(mask[output] != BAD_MASK);
776 mask[output] &= supportedMask;
777 }
778 destMask = mask;
779 }
780
781 /*
782 * destMask[0] may have up to four bits set
783 * (ex: glDrawBuffer(GL_FRONT_AND_BACK)).
784 * Otherwise, destMask[x] can only have one bit set.
785 */
786 if (n > 0 && util_bitcount(destMask[0]) > 1) {
787 GLuint count = 0, destMask0 = destMask[0];
788 while (destMask0) {
789 const gl_buffer_index bufIndex = u_bit_scan(&destMask0);
790 if (fb->_ColorDrawBufferIndexes[count] != bufIndex) {
791 updated_drawbuffers(ctx, fb);
792 fb->_ColorDrawBufferIndexes[count] = bufIndex;
793 }
794 count++;
795 }
796 fb->ColorDrawBuffer[0] = buffers[0];
797 fb->_NumColorDrawBuffers = count;
798 }
799 else {
800 GLuint count = 0;
801 for (buf = 0; buf < n; buf++ ) {
802 if (destMask[buf]) {
803 gl_buffer_index bufIndex = ffs(destMask[buf]) - 1;
804 /* only one bit should be set in the destMask[buf] field */
805 assert(util_bitcount(destMask[buf]) == 1);
806 if (fb->_ColorDrawBufferIndexes[buf] != bufIndex) {
807 updated_drawbuffers(ctx, fb);
808 fb->_ColorDrawBufferIndexes[buf] = bufIndex;
809 }
810 count = buf + 1;
811 }
812 else {
813 if (fb->_ColorDrawBufferIndexes[buf] != BUFFER_NONE) {
814 updated_drawbuffers(ctx, fb);
815 fb->_ColorDrawBufferIndexes[buf] = BUFFER_NONE;
816 }
817 }
818 fb->ColorDrawBuffer[buf] = buffers[buf];
819 }
820 fb->_NumColorDrawBuffers = count;
821 }
822
823 /* set remaining outputs to BUFFER_NONE */
824 for (buf = fb->_NumColorDrawBuffers; buf < ctx->Const.MaxDrawBuffers; buf++) {
825 if (fb->_ColorDrawBufferIndexes[buf] != BUFFER_NONE) {
826 updated_drawbuffers(ctx, fb);
827 fb->_ColorDrawBufferIndexes[buf] = BUFFER_NONE;
828 }
829 }
830 for (buf = n; buf < ctx->Const.MaxDrawBuffers; buf++) {
831 fb->ColorDrawBuffer[buf] = GL_NONE;
832 }
833
834 if (_mesa_is_winsys_fbo(fb)) {
835 /* also set context drawbuffer state */
836 for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) {
837 if (ctx->Color.DrawBuffer[buf] != fb->ColorDrawBuffer[buf]) {
838 updated_drawbuffers(ctx, fb);
839 ctx->Color.DrawBuffer[buf] = fb->ColorDrawBuffer[buf];
840 }
841 }
842 }
843 }
844
845
846 /**
847 * Update the current drawbuffer's _ColorDrawBufferIndex[] list, etc.
848 * from the context's Color.DrawBuffer[] state.
849 * Use when changing contexts.
850 */
851 void
852 _mesa_update_draw_buffers(struct gl_context *ctx)
853 {
854 /* should be a window system FBO */
855 assert(_mesa_is_winsys_fbo(ctx->DrawBuffer));
856
857 _mesa_drawbuffers(ctx, ctx->DrawBuffer, ctx->Const.MaxDrawBuffers,
858 ctx->Color.DrawBuffer, NULL);
859 }
860
861
862 /**
863 * Like \sa _mesa_drawbuffers(), this is a helper function for setting
864 * GL_READ_BUFFER state for the given context and FBO.
865 * Note that all error checking should have been done before calling
866 * this function.
867 * \param ctx the rendering context
868 * \param fb the framebuffer object to update
869 * \param buffer GL_FRONT, GL_BACK, GL_COLOR_ATTACHMENT0, etc.
870 * \param bufferIndex the numerical index corresponding to 'buffer'
871 */
872 void
873 _mesa_readbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
874 GLenum buffer, gl_buffer_index bufferIndex)
875 {
876 if ((fb == ctx->ReadBuffer) && _mesa_is_winsys_fbo(fb)) {
877 /* Only update the per-context READ_BUFFER state if we're bound to
878 * a window-system framebuffer.
879 */
880 ctx->Pixel.ReadBuffer = buffer;
881 }
882
883 fb->ColorReadBuffer = buffer;
884 fb->_ColorReadBufferIndex = bufferIndex;
885
886 ctx->NewState |= _NEW_BUFFERS;
887 }
888
889
890
891 /**
892 * Called by glReadBuffer and glNamedFramebufferReadBuffer to set the source
893 * renderbuffer for reading pixels.
894 * \param mode color buffer such as GL_FRONT, GL_BACK, etc.
895 */
896 static ALWAYS_INLINE void
897 read_buffer(struct gl_context *ctx, struct gl_framebuffer *fb,
898 GLenum buffer, const char *caller, bool no_error)
899 {
900 gl_buffer_index srcBuffer;
901
902 FLUSH_VERTICES(ctx, 0);
903
904 if (MESA_VERBOSE & VERBOSE_API)
905 _mesa_debug(ctx, "%s %s\n", caller, _mesa_enum_to_string(buffer));
906
907 if (buffer == GL_NONE) {
908 /* This is legal--it means that no buffer should be bound for reading. */
909 srcBuffer = BUFFER_NONE;
910 }
911 else {
912 /* general case / window-system framebuffer */
913 if (!no_error &&_mesa_is_gles3(ctx) &&
914 !is_legal_es3_readbuffer_enum(buffer))
915 srcBuffer = BUFFER_NONE;
916 else
917 srcBuffer = read_buffer_enum_to_index(ctx, buffer);
918
919 if (!no_error) {
920 GLbitfield supportedMask;
921
922 if (srcBuffer == BUFFER_NONE) {
923 _mesa_error(ctx, GL_INVALID_ENUM,
924 "%s(invalid buffer %s)", caller,
925 _mesa_enum_to_string(buffer));
926 return;
927 }
928
929 supportedMask = supported_buffer_bitmask(ctx, fb);
930 if (((1 << srcBuffer) & supportedMask) == 0) {
931 _mesa_error(ctx, GL_INVALID_OPERATION,
932 "%s(invalid buffer %s)", caller,
933 _mesa_enum_to_string(buffer));
934 return;
935 }
936 }
937 }
938
939 /* OK, all error checking has been completed now */
940
941 _mesa_readbuffer(ctx, fb, buffer, srcBuffer);
942
943 /* Call the device driver function only if fb is the bound read buffer */
944 if (fb == ctx->ReadBuffer) {
945 if (ctx->Driver.ReadBuffer)
946 ctx->Driver.ReadBuffer(ctx, buffer);
947 }
948 }
949
950
951 static void
952 read_buffer_err(struct gl_context *ctx, struct gl_framebuffer *fb,
953 GLenum buffer, const char *caller)
954 {
955 read_buffer(ctx, fb, buffer, caller, false);
956 }
957
958
959 static void
960 read_buffer_no_error(struct gl_context *ctx, struct gl_framebuffer *fb,
961 GLenum buffer, const char *caller)
962 {
963 read_buffer(ctx, fb, buffer, caller, true);
964 }
965
966
967 void GLAPIENTRY
968 _mesa_ReadBuffer_no_error(GLenum buffer)
969 {
970 GET_CURRENT_CONTEXT(ctx);
971 read_buffer_no_error(ctx, ctx->ReadBuffer, buffer, "glReadBuffer");
972 }
973
974
975 void GLAPIENTRY
976 _mesa_ReadBuffer(GLenum buffer)
977 {
978 GET_CURRENT_CONTEXT(ctx);
979 read_buffer_err(ctx, ctx->ReadBuffer, buffer, "glReadBuffer");
980 }
981
982
983 void GLAPIENTRY
984 _mesa_NamedFramebufferReadBuffer_no_error(GLuint framebuffer, GLenum src)
985 {
986 GET_CURRENT_CONTEXT(ctx);
987
988 struct gl_framebuffer *fb;
989
990 if (framebuffer) {
991 fb = _mesa_lookup_framebuffer(ctx, framebuffer);
992 } else {
993 fb = ctx->WinSysReadBuffer;
994 }
995
996 read_buffer_no_error(ctx, fb, src, "glNamedFramebufferReadBuffer");
997 }
998
999
1000 void GLAPIENTRY
1001 _mesa_FramebufferReadBufferEXT(GLuint framebuffer, GLenum buf)
1002 {
1003 GET_CURRENT_CONTEXT(ctx);
1004 struct gl_framebuffer *fb;
1005
1006 if (framebuffer) {
1007 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
1008 "glFramebufferReadBufferEXT");
1009 if (!fb)
1010 return;
1011 }
1012 else
1013 fb = ctx->WinSysDrawBuffer;
1014
1015 read_buffer_err(ctx, fb, buf, "glFramebufferReadBufferEXT");
1016 }
1017
1018
1019 void GLAPIENTRY
1020 _mesa_NamedFramebufferReadBuffer(GLuint framebuffer, GLenum src)
1021 {
1022 GET_CURRENT_CONTEXT(ctx);
1023 struct gl_framebuffer *fb;
1024
1025 if (framebuffer) {
1026 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
1027 "glNamedFramebufferReadBuffer");
1028 if (!fb)
1029 return;
1030 }
1031 else
1032 fb = ctx->WinSysReadBuffer;
1033
1034 read_buffer_err(ctx, fb, src, "glNamedFramebufferReadBuffer");
1035 }