Use the magic behaviour of GL_BACK in GLES 1 and 2 as well as 3
[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 "colormac.h"
36 #include "context.h"
37 #include "enums.h"
38 #include "fbobject.h"
39 #include "mtypes.h"
40
41
42 #define BAD_MASK ~0u
43
44
45 /**
46 * Return bitmask of BUFFER_BIT_* flags indicating which color buffers are
47 * available to the rendering context (for drawing or reading).
48 * This depends on the type of framebuffer. For window system framebuffers
49 * we look at the framebuffer's visual. But for user-create framebuffers we
50 * look at the number of supported color attachments.
51 * \param fb the framebuffer to draw to, or read from
52 * \return bitmask of BUFFER_BIT_* flags
53 */
54 static GLbitfield
55 supported_buffer_bitmask(const struct gl_context *ctx,
56 const struct gl_framebuffer *fb)
57 {
58 GLbitfield mask = 0x0;
59
60 if (_mesa_is_user_fbo(fb)) {
61 /* A user-created renderbuffer */
62 GLuint i;
63 for (i = 0; i < ctx->Const.MaxColorAttachments; i++) {
64 mask |= (BUFFER_BIT_COLOR0 << i);
65 }
66 }
67 else {
68 /* A window system framebuffer */
69 GLint i;
70 mask = BUFFER_BIT_FRONT_LEFT; /* always have this */
71 if (fb->Visual.stereoMode) {
72 mask |= BUFFER_BIT_FRONT_RIGHT;
73 if (fb->Visual.doubleBufferMode) {
74 mask |= BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT;
75 }
76 }
77 else if (fb->Visual.doubleBufferMode) {
78 mask |= BUFFER_BIT_BACK_LEFT;
79 }
80
81 for (i = 0; i < fb->Visual.numAuxBuffers; i++) {
82 mask |= (BUFFER_BIT_AUX0 << i);
83 }
84 }
85
86 return mask;
87 }
88
89
90 /**
91 * Helper routine used by glDrawBuffer and glDrawBuffersARB.
92 * Given a GLenum naming one or more color buffers (such as
93 * GL_FRONT_AND_BACK), return the corresponding bitmask of BUFFER_BIT_* flags.
94 */
95 static GLbitfield
96 draw_buffer_enum_to_bitmask(const struct gl_context *ctx, GLenum buffer)
97 {
98 switch (buffer) {
99 case GL_NONE:
100 return 0;
101 case GL_FRONT:
102 return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT;
103 case GL_BACK:
104 if (_mesa_is_gles(ctx)) {
105 /* Page 181 (page 192 of the PDF) in section 4.2.1 of the OpenGL
106 * ES 3.0.1 specification says:
107 *
108 * "When draw buffer zero is BACK, color values are written
109 * into the sole buffer for single-buffered contexts, or into
110 * the back buffer for double-buffered contexts."
111 *
112 * Since there is no stereo rendering in ES 3.0, only return the
113 * LEFT bits. This also satisfies the "n must be 1" requirement.
114 *
115 * We also do this for GLES 1 and 2 because those APIs have no
116 * concept of selecting the front and back buffer anyway and it's
117 * convenient to be able to maintain the magic behaviour of
118 * GL_BACK in that case.
119 */
120 if (ctx->DrawBuffer->Visual.doubleBufferMode)
121 return BUFFER_BIT_BACK_LEFT;
122 return BUFFER_BIT_FRONT_LEFT;
123 }
124 return BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT;
125 case GL_RIGHT:
126 return BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT;
127 case GL_FRONT_RIGHT:
128 return BUFFER_BIT_FRONT_RIGHT;
129 case GL_BACK_RIGHT:
130 return BUFFER_BIT_BACK_RIGHT;
131 case GL_BACK_LEFT:
132 return BUFFER_BIT_BACK_LEFT;
133 case GL_FRONT_AND_BACK:
134 return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT
135 | BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT;
136 case GL_LEFT:
137 return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT;
138 case GL_FRONT_LEFT:
139 return BUFFER_BIT_FRONT_LEFT;
140 case GL_AUX0:
141 return BUFFER_BIT_AUX0;
142 case GL_AUX1:
143 case GL_AUX2:
144 case GL_AUX3:
145 return 1 << BUFFER_COUNT; /* invalid, but not BAD_MASK */
146 case GL_COLOR_ATTACHMENT0_EXT:
147 return BUFFER_BIT_COLOR0;
148 case GL_COLOR_ATTACHMENT1_EXT:
149 return BUFFER_BIT_COLOR1;
150 case GL_COLOR_ATTACHMENT2_EXT:
151 return BUFFER_BIT_COLOR2;
152 case GL_COLOR_ATTACHMENT3_EXT:
153 return BUFFER_BIT_COLOR3;
154 case GL_COLOR_ATTACHMENT4_EXT:
155 return BUFFER_BIT_COLOR4;
156 case GL_COLOR_ATTACHMENT5_EXT:
157 return BUFFER_BIT_COLOR5;
158 case GL_COLOR_ATTACHMENT6_EXT:
159 return BUFFER_BIT_COLOR6;
160 case GL_COLOR_ATTACHMENT7_EXT:
161 return BUFFER_BIT_COLOR7;
162 default:
163 /* error */
164 return BAD_MASK;
165 }
166 }
167
168
169 /**
170 * Helper routine used by glReadBuffer.
171 * Given a GLenum naming a color buffer, return the index of the corresponding
172 * renderbuffer (a BUFFER_* value).
173 * return -1 for an invalid buffer.
174 */
175 static GLint
176 read_buffer_enum_to_index(GLenum buffer)
177 {
178 switch (buffer) {
179 case GL_FRONT:
180 return BUFFER_FRONT_LEFT;
181 case GL_BACK:
182 return BUFFER_BACK_LEFT;
183 case GL_RIGHT:
184 return BUFFER_FRONT_RIGHT;
185 case GL_FRONT_RIGHT:
186 return BUFFER_FRONT_RIGHT;
187 case GL_BACK_RIGHT:
188 return BUFFER_BACK_RIGHT;
189 case GL_BACK_LEFT:
190 return BUFFER_BACK_LEFT;
191 case GL_LEFT:
192 return BUFFER_FRONT_LEFT;
193 case GL_FRONT_LEFT:
194 return BUFFER_FRONT_LEFT;
195 case GL_AUX0:
196 return BUFFER_AUX0;
197 case GL_AUX1:
198 case GL_AUX2:
199 case GL_AUX3:
200 return BUFFER_COUNT; /* invalid, but not -1 */
201 case GL_COLOR_ATTACHMENT0_EXT:
202 return BUFFER_COLOR0;
203 case GL_COLOR_ATTACHMENT1_EXT:
204 return BUFFER_COLOR1;
205 case GL_COLOR_ATTACHMENT2_EXT:
206 return BUFFER_COLOR2;
207 case GL_COLOR_ATTACHMENT3_EXT:
208 return BUFFER_COLOR3;
209 case GL_COLOR_ATTACHMENT4_EXT:
210 return BUFFER_COLOR4;
211 case GL_COLOR_ATTACHMENT5_EXT:
212 return BUFFER_COLOR5;
213 case GL_COLOR_ATTACHMENT6_EXT:
214 return BUFFER_COLOR6;
215 case GL_COLOR_ATTACHMENT7_EXT:
216 return BUFFER_COLOR7;
217 default:
218 /* error */
219 return -1;
220 }
221 }
222
223
224 /**
225 * Called by glDrawBuffer().
226 * Specify which renderbuffer(s) to draw into for the first color output.
227 * <buffer> can name zero, one, two or four renderbuffers!
228 * \sa _mesa_DrawBuffers
229 *
230 * \param buffer buffer token such as GL_LEFT or GL_FRONT_AND_BACK, etc.
231 *
232 * Note that the behaviour of this function depends on whether the
233 * current ctx->DrawBuffer is a window-system framebuffer or a user-created
234 * framebuffer object.
235 * In the former case, we update the per-context ctx->Color.DrawBuffer
236 * state var _and_ the FB's ColorDrawBuffer state.
237 * In the later case, we update the FB's ColorDrawBuffer state only.
238 *
239 * Furthermore, upon a MakeCurrent() or BindFramebuffer() call, if the
240 * new FB is a window system FB, we need to re-update the FB's
241 * ColorDrawBuffer state to match the context. This is handled in
242 * _mesa_update_framebuffer().
243 *
244 * See the GL_EXT_framebuffer_object spec for more info.
245 */
246 void GLAPIENTRY
247 _mesa_DrawBuffer(GLenum buffer)
248 {
249 GLbitfield destMask;
250 GET_CURRENT_CONTEXT(ctx);
251
252 FLUSH_VERTICES(ctx, 0);
253
254 if (MESA_VERBOSE & VERBOSE_API) {
255 _mesa_debug(ctx, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(buffer));
256 }
257
258 if (buffer == GL_NONE) {
259 destMask = 0x0;
260 }
261 else {
262 const GLbitfield supportedMask
263 = supported_buffer_bitmask(ctx, ctx->DrawBuffer);
264 destMask = draw_buffer_enum_to_bitmask(ctx, buffer);
265 if (destMask == BAD_MASK) {
266 /* totally bogus buffer */
267 _mesa_error(ctx, GL_INVALID_ENUM,
268 "glDrawBuffer(buffer=0x%x)", buffer);
269 return;
270 }
271 destMask &= supportedMask;
272 if (destMask == 0x0) {
273 /* none of the named color buffers exist! */
274 _mesa_error(ctx, GL_INVALID_OPERATION,
275 "glDrawBuffer(buffer=0x%x)", buffer);
276 return;
277 }
278 }
279
280 /* if we get here, there's no error so set new state */
281 _mesa_drawbuffers(ctx, 1, &buffer, &destMask);
282
283 /*
284 * Call device driver function.
285 */
286 if (ctx->Driver.DrawBuffers)
287 ctx->Driver.DrawBuffers(ctx, 1, &buffer);
288 else if (ctx->Driver.DrawBuffer)
289 ctx->Driver.DrawBuffer(ctx, buffer);
290 }
291
292
293 /**
294 * Called by glDrawBuffersARB; specifies the destination color renderbuffers
295 * for N fragment program color outputs.
296 * \sa _mesa_DrawBuffer
297 * \param n number of outputs
298 * \param buffers array [n] of renderbuffer names. Unlike glDrawBuffer, the
299 * names cannot specify more than one buffer. For example,
300 * GL_FRONT_AND_BACK is illegal.
301 */
302 void GLAPIENTRY
303 _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
304 {
305 GLint output;
306 GLbitfield usedBufferMask, supportedMask;
307 GLbitfield destMask[MAX_DRAW_BUFFERS];
308 GET_CURRENT_CONTEXT(ctx);
309
310 FLUSH_VERTICES(ctx, 0);
311
312 /* Turns out n==0 is a valid input that should not produce an error.
313 * The remaining code below correctly handles the n==0 case.
314 *
315 * From the OpenGL 3.0 specification, page 258:
316 * "An INVALID_VALUE error is generated if n is greater than
317 * MAX_DRAW_BUFFERS."
318 */
319 if (n < 0 || n > (GLsizei) ctx->Const.MaxDrawBuffers) {
320 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)");
321 return;
322 }
323
324 supportedMask = supported_buffer_bitmask(ctx, ctx->DrawBuffer);
325 usedBufferMask = 0x0;
326
327 /* From the ES 3.0 specification, page 180:
328 * "If the GL is bound to the default framebuffer, then n must be 1
329 * and the constant must be BACK or NONE."
330 */
331 if (_mesa_is_gles3(ctx) && _mesa_is_winsys_fbo(ctx->DrawBuffer) &&
332 (n != 1 || (buffers[0] != GL_NONE && buffers[0] != GL_BACK))) {
333 _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)");
334 return;
335 }
336
337 /* complicated error checking... */
338 for (output = 0; output < n; output++) {
339 if (buffers[output] == GL_NONE) {
340 destMask[output] = 0x0;
341 }
342 else {
343 /* Page 259 (page 275 of the PDF) in section 4.2.1 of the OpenGL 3.0
344 * spec (20080923) says:
345 *
346 * "If the GL is bound to a framebuffer object and DrawBuffers is
347 * supplied with [...] COLOR_ATTACHMENTm where m is greater than
348 * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error
349 * INVALID_OPERATION results."
350 */
351 if (_mesa_is_user_fbo(ctx->DrawBuffer) && buffers[output] >=
352 GL_COLOR_ATTACHMENT0 + ctx->Const.MaxDrawBuffers) {
353 _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB(buffer)");
354 return;
355 }
356
357 destMask[output] = draw_buffer_enum_to_bitmask(ctx, buffers[output]);
358
359 /* From the OpenGL 3.0 specification, page 258:
360 * "Each buffer listed in bufs must be one of the values from tables
361 * 4.5 or 4.6. Otherwise, an INVALID_ENUM error is generated.
362 */
363 if (destMask[output] == BAD_MASK) {
364 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)");
365 return;
366 }
367
368 /* From the OpenGL 4.0 specification, page 256:
369 * "For both the default framebuffer and framebuffer objects, the
370 * constants FRONT, BACK, LEFT, RIGHT, and FRONT_AND_BACK are not
371 * valid in the bufs array passed to DrawBuffers, and will result in
372 * the error INVALID_ENUM. This restriction is because these
373 * constants may themselves refer to multiple buffers, as shown in
374 * table 4.4."
375 * Previous versions of the OpenGL specification say INVALID_OPERATION,
376 * but the Khronos conformance tests expect INVALID_ENUM.
377 */
378 if (_mesa_bitcount(destMask[output]) > 1) {
379 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)");
380 return;
381 }
382
383 /* From the OpenGL 3.0 specification, page 259:
384 * "If the GL is bound to the default framebuffer and DrawBuffers is
385 * supplied with a constant (other than NONE) that does not indicate
386 * any of the color buffers allocated to the GL context by the window
387 * system, the error INVALID_OPERATION will be generated.
388 *
389 * If the GL is bound to a framebuffer object and DrawBuffers is
390 * supplied with a constant from table 4.6 [...] then the error
391 * INVALID_OPERATION results."
392 */
393 destMask[output] &= supportedMask;
394 if (destMask[output] == 0) {
395 _mesa_error(ctx, GL_INVALID_OPERATION,
396 "glDrawBuffersARB(unsupported buffer)");
397 return;
398 }
399
400 /* ES 3.0 is even more restrictive. From the ES 3.0 spec, page 180:
401 * "If the GL is bound to a framebuffer object, the ith buffer listed
402 * in bufs must be COLOR_ATTACHMENTi or NONE. [...] INVALID_OPERATION."
403 */
404 if (_mesa_is_gles3(ctx) && _mesa_is_user_fbo(ctx->DrawBuffer) &&
405 buffers[output] != GL_NONE &&
406 buffers[output] != GL_COLOR_ATTACHMENT0 + output) {
407 _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)");
408 return;
409 }
410
411 /* From the OpenGL 3.0 specification, page 258:
412 * "Except for NONE, a buffer may not appear more than once in the
413 * array pointed to by bufs. Specifying a buffer more then once will
414 * result in the error INVALID_OPERATION."
415 */
416 if (destMask[output] & usedBufferMask) {
417 _mesa_error(ctx, GL_INVALID_OPERATION,
418 "glDrawBuffersARB(duplicated buffer)");
419 return;
420 }
421
422 /* update bitmask */
423 usedBufferMask |= destMask[output];
424 }
425 }
426
427 /* OK, if we get here, there were no errors so set the new state */
428 _mesa_drawbuffers(ctx, n, buffers, destMask);
429
430 /*
431 * Call device driver function. Note that n can be equal to 0,
432 * in which case we don't want to reference buffers[0], which
433 * may not be valid.
434 */
435 if (ctx->Driver.DrawBuffers)
436 ctx->Driver.DrawBuffers(ctx, n, buffers);
437 else if (ctx->Driver.DrawBuffer)
438 ctx->Driver.DrawBuffer(ctx, n > 0 ? buffers[0] : GL_NONE);
439 }
440
441
442 /**
443 * Performs necessary state updates when _mesa_drawbuffers makes an
444 * actual change.
445 */
446 static void
447 updated_drawbuffers(struct gl_context *ctx)
448 {
449 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
450
451 if (ctx->API == API_OPENGL_COMPAT && !ctx->Extensions.ARB_ES2_compatibility) {
452 struct gl_framebuffer *fb = ctx->DrawBuffer;
453
454 /* Flag the FBO as requiring validation. */
455 if (_mesa_is_user_fbo(fb)) {
456 fb->_Status = 0;
457 }
458 }
459 }
460
461
462 /**
463 * Helper function to set the GL_DRAW_BUFFER state in the context and
464 * current FBO. Called via glDrawBuffer(), glDrawBuffersARB()
465 *
466 * All error checking will have been done prior to calling this function
467 * so nothing should go wrong at this point.
468 *
469 * \param ctx current context
470 * \param n number of color outputs to set
471 * \param buffers array[n] of colorbuffer names, like GL_LEFT.
472 * \param destMask array[n] of BUFFER_BIT_* bitmasks which correspond to the
473 * colorbuffer names. (i.e. GL_FRONT_AND_BACK =>
474 * BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT).
475 */
476 void
477 _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers,
478 const GLbitfield *destMask)
479 {
480 struct gl_framebuffer *fb = ctx->DrawBuffer;
481 GLbitfield mask[MAX_DRAW_BUFFERS];
482 GLuint buf;
483
484 if (!destMask) {
485 /* compute destMask values now */
486 const GLbitfield supportedMask = supported_buffer_bitmask(ctx, fb);
487 GLuint output;
488 for (output = 0; output < n; output++) {
489 mask[output] = draw_buffer_enum_to_bitmask(ctx, buffers[output]);
490 ASSERT(mask[output] != BAD_MASK);
491 mask[output] &= supportedMask;
492 }
493 destMask = mask;
494 }
495
496 /*
497 * If n==1, destMask[0] may have up to four bits set.
498 * Otherwise, destMask[x] can only have one bit set.
499 */
500 if (n == 1) {
501 GLuint count = 0, destMask0 = destMask[0];
502 while (destMask0) {
503 GLint bufIndex = ffs(destMask0) - 1;
504 if (fb->_ColorDrawBufferIndexes[count] != bufIndex) {
505 updated_drawbuffers(ctx);
506 fb->_ColorDrawBufferIndexes[count] = bufIndex;
507 }
508 count++;
509 destMask0 &= ~(1 << bufIndex);
510 }
511 fb->ColorDrawBuffer[0] = buffers[0];
512 fb->_NumColorDrawBuffers = count;
513 }
514 else {
515 GLuint count = 0;
516 for (buf = 0; buf < n; buf++ ) {
517 if (destMask[buf]) {
518 GLint bufIndex = ffs(destMask[buf]) - 1;
519 /* only one bit should be set in the destMask[buf] field */
520 ASSERT(_mesa_bitcount(destMask[buf]) == 1);
521 if (fb->_ColorDrawBufferIndexes[buf] != bufIndex) {
522 updated_drawbuffers(ctx);
523 fb->_ColorDrawBufferIndexes[buf] = bufIndex;
524 }
525 count = buf + 1;
526 }
527 else {
528 if (fb->_ColorDrawBufferIndexes[buf] != -1) {
529 updated_drawbuffers(ctx);
530 fb->_ColorDrawBufferIndexes[buf] = -1;
531 }
532 }
533 fb->ColorDrawBuffer[buf] = buffers[buf];
534 }
535 fb->_NumColorDrawBuffers = count;
536 }
537
538 /* set remaining outputs to -1 (GL_NONE) */
539 for (buf = fb->_NumColorDrawBuffers; buf < ctx->Const.MaxDrawBuffers; buf++) {
540 if (fb->_ColorDrawBufferIndexes[buf] != -1) {
541 updated_drawbuffers(ctx);
542 fb->_ColorDrawBufferIndexes[buf] = -1;
543 }
544 }
545 for (buf = n; buf < ctx->Const.MaxDrawBuffers; buf++) {
546 fb->ColorDrawBuffer[buf] = GL_NONE;
547 }
548
549 if (_mesa_is_winsys_fbo(fb)) {
550 /* also set context drawbuffer state */
551 for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) {
552 if (ctx->Color.DrawBuffer[buf] != fb->ColorDrawBuffer[buf]) {
553 updated_drawbuffers(ctx);
554 ctx->Color.DrawBuffer[buf] = fb->ColorDrawBuffer[buf];
555 }
556 }
557 }
558 }
559
560
561 /**
562 * Update the current drawbuffer's _ColorDrawBufferIndex[] list, etc.
563 * from the context's Color.DrawBuffer[] state.
564 * Use when changing contexts.
565 */
566 void
567 _mesa_update_draw_buffers(struct gl_context *ctx)
568 {
569 GLenum buffers[MAX_DRAW_BUFFERS];
570 GLuint i;
571
572 /* should be a window system FBO */
573 assert(_mesa_is_winsys_fbo(ctx->DrawBuffer));
574
575 for (i = 0; i < ctx->Const.MaxDrawBuffers; i++)
576 buffers[i] = ctx->Color.DrawBuffer[i];
577
578 _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, buffers, NULL);
579 }
580
581
582 /**
583 * Like \sa _mesa_drawbuffers(), this is a helper function for setting
584 * GL_READ_BUFFER state in the context and current FBO.
585 * \param ctx the rendering context
586 * \param buffer GL_FRONT, GL_BACK, GL_COLOR_ATTACHMENT0, etc.
587 * \param bufferIndex the numerical index corresponding to 'buffer'
588 */
589 void
590 _mesa_readbuffer(struct gl_context *ctx, GLenum buffer, GLint bufferIndex)
591 {
592 struct gl_framebuffer *fb = ctx->ReadBuffer;
593
594 if (_mesa_is_winsys_fbo(fb)) {
595 /* Only update the per-context READ_BUFFER state if we're bound to
596 * a window-system framebuffer.
597 */
598 ctx->Pixel.ReadBuffer = buffer;
599 }
600
601 fb->ColorReadBuffer = buffer;
602 fb->_ColorReadBufferIndex = bufferIndex;
603
604 ctx->NewState |= _NEW_BUFFERS;
605 }
606
607
608
609 /**
610 * Called by glReadBuffer to set the source renderbuffer for reading pixels.
611 * \param mode color buffer such as GL_FRONT, GL_BACK, etc.
612 */
613 void GLAPIENTRY
614 _mesa_ReadBuffer(GLenum buffer)
615 {
616 struct gl_framebuffer *fb;
617 GLbitfield supportedMask;
618 GLint srcBuffer;
619 GET_CURRENT_CONTEXT(ctx);
620
621 FLUSH_VERTICES(ctx, 0);
622
623 if (MESA_VERBOSE & VERBOSE_API)
624 _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer));
625
626 fb = ctx->ReadBuffer;
627
628 if (MESA_VERBOSE & VERBOSE_API)
629 _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer));
630
631 if (buffer == GL_NONE) {
632 /* This is legal--it means that no buffer should be bound for reading. */
633 srcBuffer = -1;
634 }
635 else {
636 /* general case / window-system framebuffer */
637 srcBuffer = read_buffer_enum_to_index(buffer);
638 if (srcBuffer == -1) {
639 _mesa_error(ctx, GL_INVALID_ENUM,
640 "glReadBuffer(buffer=0x%x)", buffer);
641 return;
642 }
643 supportedMask = supported_buffer_bitmask(ctx, fb);
644 if (((1 << srcBuffer) & supportedMask) == 0) {
645 _mesa_error(ctx, GL_INVALID_OPERATION,
646 "glReadBuffer(buffer=0x%x)", buffer);
647 return;
648 }
649 }
650
651 /* OK, all error checking has been completed now */
652
653 _mesa_readbuffer(ctx, buffer, srcBuffer);
654
655 /*
656 * Call device driver function.
657 */
658 if (ctx->Driver.ReadBuffer)
659 (*ctx->Driver.ReadBuffer)(ctx, buffer);
660 }