Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1901 | serge | 1 | /* |
2 | * Mesa 3-D graphics library |
||
3 | * Version: 7.1 |
||
4 | * |
||
5 | * Copyright (C) 1999-2007 Brian Paul 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 | * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
||
21 | * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
||
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR 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 | |||
39 | |||
40 | #define BAD_MASK ~0u |
||
41 | |||
42 | |||
43 | /** |
||
44 | * Return bitmask of BUFFER_BIT_* flags indicating which color buffers are |
||
45 | * available to the rendering context (for drawing or reading). |
||
46 | * This depends on the type of framebuffer. For window system framebuffers |
||
47 | * we look at the framebuffer's visual. But for user-create framebuffers we |
||
48 | * look at the number of supported color attachments. |
||
49 | * \param fb the framebuffer to draw to, or read from |
||
50 | * \return bitmask of BUFFER_BIT_* flags |
||
51 | */ |
||
52 | static GLbitfield |
||
53 | supported_buffer_bitmask(const struct gl_context *ctx, const struct gl_framebuffer *fb) |
||
54 | { |
||
55 | GLbitfield mask = 0x0; |
||
56 | |||
57 | if (fb->Name > 0) { |
||
58 | /* A user-created renderbuffer */ |
||
59 | GLuint i; |
||
60 | ASSERT(ctx->Extensions.EXT_framebuffer_object); |
||
61 | for (i = 0; i < ctx->Const.MaxColorAttachments; i++) { |
||
62 | mask |= (BUFFER_BIT_COLOR0 << i); |
||
63 | } |
||
64 | } |
||
65 | else { |
||
66 | /* A window system framebuffer */ |
||
67 | GLint i; |
||
68 | mask = BUFFER_BIT_FRONT_LEFT; /* always have this */ |
||
69 | if (fb->Visual.stereoMode) { |
||
70 | mask |= BUFFER_BIT_FRONT_RIGHT; |
||
71 | if (fb->Visual.doubleBufferMode) { |
||
72 | mask |= BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; |
||
73 | } |
||
74 | } |
||
75 | else if (fb->Visual.doubleBufferMode) { |
||
76 | mask |= BUFFER_BIT_BACK_LEFT; |
||
77 | } |
||
78 | |||
79 | for (i = 0; i < fb->Visual.numAuxBuffers; i++) { |
||
80 | mask |= (BUFFER_BIT_AUX0 << i); |
||
81 | } |
||
82 | } |
||
83 | |||
84 | return mask; |
||
85 | } |
||
86 | |||
87 | |||
88 | /** |
||
89 | * Helper routine used by glDrawBuffer and glDrawBuffersARB. |
||
90 | * Given a GLenum naming one or more color buffers (such as |
||
91 | * GL_FRONT_AND_BACK), return the corresponding bitmask of BUFFER_BIT_* flags. |
||
92 | */ |
||
93 | static GLbitfield |
||
94 | draw_buffer_enum_to_bitmask(GLenum buffer) |
||
95 | { |
||
96 | switch (buffer) { |
||
97 | case GL_NONE: |
||
98 | return 0; |
||
99 | case GL_FRONT: |
||
100 | return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT; |
||
101 | case GL_BACK: |
||
102 | return BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; |
||
103 | case GL_RIGHT: |
||
104 | return BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; |
||
105 | case GL_FRONT_RIGHT: |
||
106 | return BUFFER_BIT_FRONT_RIGHT; |
||
107 | case GL_BACK_RIGHT: |
||
108 | return BUFFER_BIT_BACK_RIGHT; |
||
109 | case GL_BACK_LEFT: |
||
110 | return BUFFER_BIT_BACK_LEFT; |
||
111 | case GL_FRONT_AND_BACK: |
||
112 | return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT |
||
113 | | BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; |
||
114 | case GL_LEFT: |
||
115 | return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT; |
||
116 | case GL_FRONT_LEFT: |
||
117 | return BUFFER_BIT_FRONT_LEFT; |
||
118 | case GL_AUX0: |
||
119 | return BUFFER_BIT_AUX0; |
||
120 | case GL_AUX1: |
||
121 | case GL_AUX2: |
||
122 | case GL_AUX3: |
||
123 | return 1 << BUFFER_COUNT; /* invalid, but not BAD_MASK */ |
||
124 | case GL_COLOR_ATTACHMENT0_EXT: |
||
125 | return BUFFER_BIT_COLOR0; |
||
126 | case GL_COLOR_ATTACHMENT1_EXT: |
||
127 | return BUFFER_BIT_COLOR1; |
||
128 | case GL_COLOR_ATTACHMENT2_EXT: |
||
129 | return BUFFER_BIT_COLOR2; |
||
130 | case GL_COLOR_ATTACHMENT3_EXT: |
||
131 | return BUFFER_BIT_COLOR3; |
||
132 | case GL_COLOR_ATTACHMENT4_EXT: |
||
133 | return BUFFER_BIT_COLOR4; |
||
134 | case GL_COLOR_ATTACHMENT5_EXT: |
||
135 | return BUFFER_BIT_COLOR5; |
||
136 | case GL_COLOR_ATTACHMENT6_EXT: |
||
137 | return BUFFER_BIT_COLOR6; |
||
138 | case GL_COLOR_ATTACHMENT7_EXT: |
||
139 | return BUFFER_BIT_COLOR7; |
||
140 | default: |
||
141 | /* error */ |
||
142 | return BAD_MASK; |
||
143 | } |
||
144 | } |
||
145 | |||
146 | |||
147 | /** |
||
148 | * Helper routine used by glReadBuffer. |
||
149 | * Given a GLenum naming a color buffer, return the index of the corresponding |
||
150 | * renderbuffer (a BUFFER_* value). |
||
151 | * return -1 for an invalid buffer. |
||
152 | */ |
||
153 | static GLint |
||
154 | read_buffer_enum_to_index(GLenum buffer) |
||
155 | { |
||
156 | switch (buffer) { |
||
157 | case GL_FRONT: |
||
158 | return BUFFER_FRONT_LEFT; |
||
159 | case GL_BACK: |
||
160 | return BUFFER_BACK_LEFT; |
||
161 | case GL_RIGHT: |
||
162 | return BUFFER_FRONT_RIGHT; |
||
163 | case GL_FRONT_RIGHT: |
||
164 | return BUFFER_FRONT_RIGHT; |
||
165 | case GL_BACK_RIGHT: |
||
166 | return BUFFER_BACK_RIGHT; |
||
167 | case GL_BACK_LEFT: |
||
168 | return BUFFER_BACK_LEFT; |
||
169 | case GL_LEFT: |
||
170 | return BUFFER_FRONT_LEFT; |
||
171 | case GL_FRONT_LEFT: |
||
172 | return BUFFER_FRONT_LEFT; |
||
173 | case GL_AUX0: |
||
174 | return BUFFER_AUX0; |
||
175 | case GL_AUX1: |
||
176 | case GL_AUX2: |
||
177 | case GL_AUX3: |
||
178 | return BUFFER_COUNT; /* invalid, but not -1 */ |
||
179 | case GL_COLOR_ATTACHMENT0_EXT: |
||
180 | return BUFFER_COLOR0; |
||
181 | case GL_COLOR_ATTACHMENT1_EXT: |
||
182 | return BUFFER_COLOR1; |
||
183 | case GL_COLOR_ATTACHMENT2_EXT: |
||
184 | return BUFFER_COLOR2; |
||
185 | case GL_COLOR_ATTACHMENT3_EXT: |
||
186 | return BUFFER_COLOR3; |
||
187 | case GL_COLOR_ATTACHMENT4_EXT: |
||
188 | return BUFFER_COLOR4; |
||
189 | case GL_COLOR_ATTACHMENT5_EXT: |
||
190 | return BUFFER_COLOR5; |
||
191 | case GL_COLOR_ATTACHMENT6_EXT: |
||
192 | return BUFFER_COLOR6; |
||
193 | case GL_COLOR_ATTACHMENT7_EXT: |
||
194 | return BUFFER_COLOR7; |
||
195 | default: |
||
196 | /* error */ |
||
197 | return -1; |
||
198 | } |
||
199 | } |
||
200 | |||
201 | |||
202 | /** |
||
203 | * Called by glDrawBuffer(). |
||
204 | * Specify which renderbuffer(s) to draw into for the first color output. |
||
205 | * |
||
206 | * \sa _mesa_DrawBuffersARB |
||
207 | * |
||
208 | * \param buffer buffer token such as GL_LEFT or GL_FRONT_AND_BACK, etc. |
||
209 | * |
||
210 | * Note that the behaviour of this function depends on whether the |
||
211 | * current ctx->DrawBuffer is a window-system framebuffer (Name=0) or |
||
212 | * a user-created framebuffer object (Name!=0). |
||
213 | * In the former case, we update the per-context ctx->Color.DrawBuffer |
||
214 | * state var _and_ the FB's ColorDrawBuffer state. |
||
215 | * In the later case, we update the FB's ColorDrawBuffer state only. |
||
216 | * |
||
217 | * Furthermore, upon a MakeCurrent() or BindFramebuffer() call, if the |
||
218 | * new FB is a window system FB, we need to re-update the FB's |
||
219 | * ColorDrawBuffer state to match the context. This is handled in |
||
220 | * _mesa_update_framebuffer(). |
||
221 | * |
||
222 | * See the GL_EXT_framebuffer_object spec for more info. |
||
223 | */ |
||
224 | void GLAPIENTRY |
||
225 | _mesa_DrawBuffer(GLenum buffer) |
||
226 | { |
||
227 | GLbitfield destMask; |
||
228 | GET_CURRENT_CONTEXT(ctx); |
||
229 | ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex... */ |
||
230 | |||
231 | if (MESA_VERBOSE & VERBOSE_API) { |
||
232 | _mesa_debug(ctx, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); |
||
233 | } |
||
234 | |||
235 | if (buffer == GL_NONE) { |
||
236 | destMask = 0x0; |
||
237 | } |
||
238 | else { |
||
239 | const GLbitfield supportedMask |
||
240 | = supported_buffer_bitmask(ctx, ctx->DrawBuffer); |
||
241 | destMask = draw_buffer_enum_to_bitmask(buffer); |
||
242 | if (destMask == BAD_MASK) { |
||
243 | /* totally bogus buffer */ |
||
244 | _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffer(buffer=0x%x)", buffer); |
||
245 | return; |
||
246 | } |
||
247 | destMask &= supportedMask; |
||
248 | if (destMask == 0x0) { |
||
249 | /* none of the named color buffers exist! */ |
||
250 | _mesa_error(ctx, GL_INVALID_OPERATION, |
||
251 | "glDrawBuffer(buffer=0x%x)", buffer); |
||
252 | return; |
||
253 | } |
||
254 | } |
||
255 | |||
256 | /* if we get here, there's no error so set new state */ |
||
257 | _mesa_drawbuffers(ctx, 1, &buffer, &destMask); |
||
258 | |||
259 | /* |
||
260 | * Call device driver function. |
||
261 | */ |
||
262 | if (ctx->Driver.DrawBuffers) |
||
263 | ctx->Driver.DrawBuffers(ctx, 1, &buffer); |
||
264 | else if (ctx->Driver.DrawBuffer) |
||
265 | ctx->Driver.DrawBuffer(ctx, buffer); |
||
266 | } |
||
267 | |||
268 | |||
269 | /** |
||
270 | * Called by glDrawBuffersARB; specifies the destination color renderbuffers |
||
271 | * for N fragment program color outputs. |
||
272 | * \sa _mesa_DrawBuffer |
||
273 | * \param n number of outputs |
||
274 | * \param buffers array [n] of renderbuffer names. Unlike glDrawBuffer, the |
||
275 | * names cannot specify more than one buffer. For example, |
||
276 | * GL_FRONT_AND_BACK is illegal. |
||
277 | */ |
||
278 | void GLAPIENTRY |
||
279 | _mesa_DrawBuffersARB(GLsizei n, const GLenum *buffers) |
||
280 | { |
||
281 | GLint output; |
||
282 | GLbitfield usedBufferMask, supportedMask; |
||
283 | GLbitfield destMask[MAX_DRAW_BUFFERS]; |
||
284 | GET_CURRENT_CONTEXT(ctx); |
||
285 | ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); |
||
286 | |||
287 | /* Turns out n==0 is a valid input that should not produce an error. |
||
288 | * The remaining code below correctly handles the n==0 case. |
||
289 | */ |
||
290 | if (n < 0 || n > (GLsizei) ctx->Const.MaxDrawBuffers) { |
||
291 | _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)"); |
||
292 | return; |
||
293 | } |
||
294 | |||
295 | supportedMask = supported_buffer_bitmask(ctx, ctx->DrawBuffer); |
||
296 | usedBufferMask = 0x0; |
||
297 | |||
298 | /* complicated error checking... */ |
||
299 | for (output = 0; output < n; output++) { |
||
300 | if (buffers[output] == GL_NONE) { |
||
301 | destMask[output] = 0x0; |
||
302 | } |
||
303 | else { |
||
304 | destMask[output] = draw_buffer_enum_to_bitmask(buffers[output]); |
||
305 | if (destMask[output] == BAD_MASK |
||
306 | || _mesa_bitcount(destMask[output]) > 1) { |
||
307 | _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)"); |
||
308 | return; |
||
309 | } |
||
310 | destMask[output] &= supportedMask; |
||
311 | if (destMask[output] == 0) { |
||
312 | _mesa_error(ctx, GL_INVALID_OPERATION, |
||
313 | "glDrawBuffersARB(unsupported buffer)"); |
||
314 | return; |
||
315 | } |
||
316 | if (destMask[output] & usedBufferMask) { |
||
317 | /* can't specify a dest buffer more than once! */ |
||
318 | _mesa_error(ctx, GL_INVALID_OPERATION, |
||
319 | "glDrawBuffersARB(duplicated buffer)"); |
||
320 | return; |
||
321 | } |
||
322 | |||
323 | /* update bitmask */ |
||
324 | usedBufferMask |= destMask[output]; |
||
325 | } |
||
326 | } |
||
327 | |||
328 | /* OK, if we get here, there were no errors so set the new state */ |
||
329 | _mesa_drawbuffers(ctx, n, buffers, destMask); |
||
330 | |||
331 | /* |
||
332 | * Call device driver function. Note that n can be equal to 0, |
||
333 | * in which case we don't want to reference buffers[0], which |
||
334 | * may not be valid. |
||
335 | */ |
||
336 | if (ctx->Driver.DrawBuffers) |
||
337 | ctx->Driver.DrawBuffers(ctx, n, buffers); |
||
338 | else if (ctx->Driver.DrawBuffer) |
||
339 | ctx->Driver.DrawBuffer(ctx, n > 0 ? buffers[0] : GL_NONE); |
||
340 | } |
||
341 | |||
342 | |||
343 | /** |
||
344 | * Helper function to set the GL_DRAW_BUFFER state in the context and |
||
345 | * current FBO. Called via glDrawBuffer(), glDrawBuffersARB() |
||
346 | * |
||
347 | * All error checking will have been done prior to calling this function |
||
348 | * so nothing should go wrong at this point. |
||
349 | * |
||
350 | * \param ctx current context |
||
351 | * \param n number of color outputs to set |
||
352 | * \param buffers array[n] of colorbuffer names, like GL_LEFT. |
||
353 | * \param destMask array[n] of BUFFER_BIT_* bitmasks which correspond to the |
||
354 | * colorbuffer names. (i.e. GL_FRONT_AND_BACK => |
||
355 | * BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT). |
||
356 | */ |
||
357 | void |
||
358 | _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, |
||
359 | const GLbitfield *destMask) |
||
360 | { |
||
361 | struct gl_framebuffer *fb = ctx->DrawBuffer; |
||
362 | GLbitfield mask[MAX_DRAW_BUFFERS]; |
||
363 | GLboolean newState = GL_FALSE; |
||
364 | |||
365 | if (!destMask) { |
||
366 | /* compute destMask values now */ |
||
367 | const GLbitfield supportedMask = supported_buffer_bitmask(ctx, fb); |
||
368 | GLuint output; |
||
369 | for (output = 0; output < n; output++) { |
||
370 | mask[output] = draw_buffer_enum_to_bitmask(buffers[output]); |
||
371 | ASSERT(mask[output] != BAD_MASK); |
||
372 | mask[output] &= supportedMask; |
||
373 | } |
||
374 | destMask = mask; |
||
375 | } |
||
376 | |||
377 | /* |
||
378 | * If n==1, destMask[0] may have up to four bits set. |
||
379 | * Otherwise, destMask[x] can only have one bit set. |
||
380 | */ |
||
381 | if (n == 1) { |
||
382 | GLuint count = 0, destMask0 = destMask[0]; |
||
383 | while (destMask0) { |
||
384 | GLint bufIndex = _mesa_ffs(destMask0) - 1; |
||
385 | if (fb->_ColorDrawBufferIndexes[count] != bufIndex) { |
||
386 | fb->_ColorDrawBufferIndexes[count] = bufIndex; |
||
387 | newState = GL_TRUE; |
||
388 | } |
||
389 | count++; |
||
390 | destMask0 &= ~(1 << bufIndex); |
||
391 | } |
||
392 | fb->ColorDrawBuffer[0] = buffers[0]; |
||
393 | if (fb->_NumColorDrawBuffers != count) { |
||
394 | fb->_NumColorDrawBuffers = count; |
||
395 | newState = GL_TRUE; |
||
396 | } |
||
397 | } |
||
398 | else { |
||
399 | GLuint buf, count = 0; |
||
400 | for (buf = 0; buf < n; buf++ ) { |
||
401 | if (destMask[buf]) { |
||
402 | GLint bufIndex = _mesa_ffs(destMask[buf]) - 1; |
||
403 | /* only one bit should be set in the destMask[buf] field */ |
||
404 | ASSERT(_mesa_bitcount(destMask[buf]) == 1); |
||
405 | if (fb->_ColorDrawBufferIndexes[buf] != bufIndex) { |
||
406 | fb->_ColorDrawBufferIndexes[buf] = bufIndex; |
||
407 | newState = GL_TRUE; |
||
408 | } |
||
409 | fb->ColorDrawBuffer[buf] = buffers[buf]; |
||
410 | count = buf + 1; |
||
411 | } |
||
412 | else { |
||
413 | if (fb->_ColorDrawBufferIndexes[buf] != -1) { |
||
414 | fb->_ColorDrawBufferIndexes[buf] = -1; |
||
415 | newState = GL_TRUE; |
||
416 | } |
||
417 | } |
||
418 | } |
||
419 | /* set remaining outputs to -1 (GL_NONE) */ |
||
420 | while (buf < ctx->Const.MaxDrawBuffers) { |
||
421 | if (fb->_ColorDrawBufferIndexes[buf] != -1) { |
||
422 | fb->_ColorDrawBufferIndexes[buf] = -1; |
||
423 | newState = GL_TRUE; |
||
424 | } |
||
425 | fb->ColorDrawBuffer[buf] = GL_NONE; |
||
426 | buf++; |
||
427 | } |
||
428 | fb->_NumColorDrawBuffers = count; |
||
429 | } |
||
430 | |||
431 | if (fb->Name == 0) { |
||
432 | /* also set context drawbuffer state */ |
||
433 | GLuint buf; |
||
434 | for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) { |
||
435 | if (ctx->Color.DrawBuffer[buf] != fb->ColorDrawBuffer[buf]) { |
||
436 | ctx->Color.DrawBuffer[buf] = fb->ColorDrawBuffer[buf]; |
||
437 | newState = GL_TRUE; |
||
438 | } |
||
439 | } |
||
440 | } |
||
441 | |||
442 | if (newState) |
||
443 | FLUSH_VERTICES(ctx, _NEW_BUFFERS); |
||
444 | } |
||
445 | |||
446 | |||
447 | /** |
||
448 | * Like \sa _mesa_drawbuffers(), this is a helper function for setting |
||
449 | * GL_READ_BUFFER state in the context and current FBO. |
||
450 | * \param ctx the rendering context |
||
451 | * \param buffer GL_FRONT, GL_BACK, GL_COLOR_ATTACHMENT0, etc. |
||
452 | * \param bufferIndex the numerical index corresponding to 'buffer' |
||
453 | */ |
||
454 | void |
||
455 | _mesa_readbuffer(struct gl_context *ctx, GLenum buffer, GLint bufferIndex) |
||
456 | { |
||
457 | struct gl_framebuffer *fb = ctx->ReadBuffer; |
||
458 | |||
459 | if (fb->Name == 0) { |
||
460 | /* Only update the per-context READ_BUFFER state if we're bound to |
||
461 | * a window-system framebuffer. |
||
462 | */ |
||
463 | ctx->Pixel.ReadBuffer = buffer; |
||
464 | } |
||
465 | |||
466 | fb->ColorReadBuffer = buffer; |
||
467 | fb->_ColorReadBufferIndex = bufferIndex; |
||
468 | |||
469 | ctx->NewState |= _NEW_BUFFERS; |
||
470 | } |
||
471 | |||
472 | |||
473 | |||
474 | /** |
||
475 | * Called by glReadBuffer to set the source renderbuffer for reading pixels. |
||
476 | * \param mode color buffer such as GL_FRONT, GL_BACK, etc. |
||
477 | */ |
||
478 | void GLAPIENTRY |
||
479 | _mesa_ReadBuffer(GLenum buffer) |
||
480 | { |
||
481 | struct gl_framebuffer *fb; |
||
482 | GLbitfield supportedMask; |
||
483 | GLint srcBuffer; |
||
484 | GET_CURRENT_CONTEXT(ctx); |
||
485 | ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); |
||
486 | |||
487 | if (MESA_VERBOSE & VERBOSE_API) |
||
488 | _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); |
||
489 | |||
490 | fb = ctx->ReadBuffer; |
||
491 | |||
492 | if (MESA_VERBOSE & VERBOSE_API) |
||
493 | _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); |
||
494 | |||
495 | if (fb->Name > 0 && buffer == GL_NONE) { |
||
496 | /* This is legal for user-created framebuffer objects */ |
||
497 | srcBuffer = -1; |
||
498 | } |
||
499 | else { |
||
500 | /* general case / window-system framebuffer */ |
||
501 | srcBuffer = read_buffer_enum_to_index(buffer); |
||
502 | if (srcBuffer == -1) { |
||
503 | _mesa_error(ctx, GL_INVALID_ENUM, |
||
504 | "glReadBuffer(buffer=0x%x)", buffer); |
||
505 | return; |
||
506 | } |
||
507 | supportedMask = supported_buffer_bitmask(ctx, fb); |
||
508 | if (((1 << srcBuffer) & supportedMask) == 0) { |
||
509 | _mesa_error(ctx, GL_INVALID_OPERATION, |
||
510 | "glReadBuffer(buffer=0x%x)", buffer); |
||
511 | return; |
||
512 | } |
||
513 | } |
||
514 | |||
515 | /* OK, all error checking has been completed now */ |
||
516 | |||
517 | _mesa_readbuffer(ctx, buffer, srcBuffer); |
||
518 | ctx->NewState |= _NEW_BUFFERS; |
||
519 | |||
520 | /* |
||
521 | * Call device driver function. |
||
522 | */ |
||
523 | if (ctx->Driver.ReadBuffer) |
||
524 | (*ctx->Driver.ReadBuffer)(ctx, buffer); |
||
525 | }><>>>>><>>>>><>><>>><>> |