OSDN Git Service

mesa: remove outdated version lines in comments
[android-x86/external-mesa.git] / src / mesa / main / framebuffer.c
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 1999-2008  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  * Functions for allocating/managing framebuffers and renderbuffers.
28  * Also, routines for reading/writing renderbuffer data as ubytes,
29  * ushorts, uints, etc.
30  */
31
32
33 #include "glheader.h"
34 #include "imports.h"
35 #include "blend.h"
36 #include "buffers.h"
37 #include "context.h"
38 #include "enums.h"
39 #include "formats.h"
40 #include "macros.h"
41 #include "mtypes.h"
42 #include "fbobject.h"
43 #include "framebuffer.h"
44 #include "renderbuffer.h"
45 #include "texobj.h"
46 #include "glformats.h"
47
48
49
50 /**
51  * Compute/set the _DepthMax field for the given framebuffer.
52  * This value depends on the Z buffer resolution.
53  */
54 static void
55 compute_depth_max(struct gl_framebuffer *fb)
56 {
57    if (fb->Visual.depthBits == 0) {
58       /* Special case.  Even if we don't have a depth buffer we need
59        * good values for DepthMax for Z vertex transformation purposes
60        * and for per-fragment fog computation.
61        */
62       fb->_DepthMax = (1 << 16) - 1;
63    }
64    else if (fb->Visual.depthBits < 32) {
65       fb->_DepthMax = (1 << fb->Visual.depthBits) - 1;
66    }
67    else {
68       /* Special case since shift values greater than or equal to the
69        * number of bits in the left hand expression's type are undefined.
70        */
71       fb->_DepthMax = 0xffffffff;
72    }
73    fb->_DepthMaxF = (GLfloat) fb->_DepthMax;
74
75    /* Minimum resolvable depth value, for polygon offset */
76    fb->_MRD = (GLfloat)1.0 / fb->_DepthMaxF;
77 }
78
79 /**
80  * Create and initialize a gl_framebuffer object.
81  * This is intended for creating _window_system_ framebuffers, not generic
82  * framebuffer objects ala GL_EXT_framebuffer_object.
83  *
84  * \sa _mesa_new_framebuffer
85  */
86 struct gl_framebuffer *
87 _mesa_create_framebuffer(const struct gl_config *visual)
88 {
89    struct gl_framebuffer *fb = CALLOC_STRUCT(gl_framebuffer);
90    assert(visual);
91    if (fb) {
92       _mesa_initialize_window_framebuffer(fb, visual);
93    }
94    return fb;
95 }
96
97
98 /**
99  * Allocate a new gl_framebuffer object.
100  * This is the default function for ctx->Driver.NewFramebuffer().
101  * This is for allocating user-created framebuffers, not window-system
102  * framebuffers!
103  * \sa _mesa_create_framebuffer
104  */
105 struct gl_framebuffer *
106 _mesa_new_framebuffer(struct gl_context *ctx, GLuint name)
107 {
108    struct gl_framebuffer *fb;
109    (void) ctx;
110    assert(name != 0);
111    fb = CALLOC_STRUCT(gl_framebuffer);
112    if (fb) {
113       _mesa_initialize_user_framebuffer(fb, name);
114    }
115    return fb;
116 }
117
118
119 /**
120  * Initialize a gl_framebuffer object.  Typically used to initialize
121  * window system-created framebuffers, not user-created framebuffers.
122  * \sa _mesa_initialize_user_framebuffer
123  */
124 void
125 _mesa_initialize_window_framebuffer(struct gl_framebuffer *fb,
126                                      const struct gl_config *visual)
127 {
128    assert(fb);
129    assert(visual);
130
131    memset(fb, 0, sizeof(struct gl_framebuffer));
132
133    _glthread_INIT_MUTEX(fb->Mutex);
134
135    fb->RefCount = 1;
136
137    /* save the visual */
138    fb->Visual = *visual;
139
140    /* Init read/draw renderbuffer state */
141    if (visual->doubleBufferMode) {
142       fb->_NumColorDrawBuffers = 1;
143       fb->ColorDrawBuffer[0] = GL_BACK;
144       fb->_ColorDrawBufferIndexes[0] = BUFFER_BACK_LEFT;
145       fb->ColorReadBuffer = GL_BACK;
146       fb->_ColorReadBufferIndex = BUFFER_BACK_LEFT;
147    }
148    else {
149       fb->_NumColorDrawBuffers = 1;
150       fb->ColorDrawBuffer[0] = GL_FRONT;
151       fb->_ColorDrawBufferIndexes[0] = BUFFER_FRONT_LEFT;
152       fb->ColorReadBuffer = GL_FRONT;
153       fb->_ColorReadBufferIndex = BUFFER_FRONT_LEFT;
154    }
155
156    fb->Delete = _mesa_destroy_framebuffer;
157    fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
158    fb->_AllColorBuffersFixedPoint = !visual->floatMode;
159    fb->_HasSNormOrFloatColorBuffer = visual->floatMode;
160
161    compute_depth_max(fb);
162 }
163
164
165 /**
166  * Initialize a user-created gl_framebuffer object.
167  * \sa _mesa_initialize_window_framebuffer
168  */
169 void
170 _mesa_initialize_user_framebuffer(struct gl_framebuffer *fb, GLuint name)
171 {
172    assert(fb);
173    assert(name);
174
175    memset(fb, 0, sizeof(struct gl_framebuffer));
176
177    fb->Name = name;
178    fb->RefCount = 1;
179    fb->_NumColorDrawBuffers = 1;
180    fb->ColorDrawBuffer[0] = GL_COLOR_ATTACHMENT0_EXT;
181    fb->_ColorDrawBufferIndexes[0] = BUFFER_COLOR0;
182    fb->ColorReadBuffer = GL_COLOR_ATTACHMENT0_EXT;
183    fb->_ColorReadBufferIndex = BUFFER_COLOR0;
184    fb->Delete = _mesa_destroy_framebuffer;
185    _glthread_INIT_MUTEX(fb->Mutex);
186 }
187
188
189 /**
190  * Deallocate buffer and everything attached to it.
191  * Typically called via the gl_framebuffer->Delete() method.
192  */
193 void
194 _mesa_destroy_framebuffer(struct gl_framebuffer *fb)
195 {
196    if (fb) {
197       _mesa_free_framebuffer_data(fb);
198       free(fb);
199    }
200 }
201
202
203 /**
204  * Free all the data hanging off the given gl_framebuffer, but don't free
205  * the gl_framebuffer object itself.
206  */
207 void
208 _mesa_free_framebuffer_data(struct gl_framebuffer *fb)
209 {
210    GLuint i;
211
212    assert(fb);
213    assert(fb->RefCount == 0);
214
215    _glthread_DESTROY_MUTEX(fb->Mutex);
216
217    for (i = 0; i < BUFFER_COUNT; i++) {
218       struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
219       if (att->Renderbuffer) {
220          _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
221       }
222       if (att->Texture) {
223          _mesa_reference_texobj(&att->Texture, NULL);
224       }
225       ASSERT(!att->Renderbuffer);
226       ASSERT(!att->Texture);
227       att->Type = GL_NONE;
228    }
229 }
230
231
232 /**
233  * Set *ptr to point to fb, with refcounting and locking.
234  * This is normally only called from the _mesa_reference_framebuffer() macro
235  * when there's a real pointer change.
236  */
237 void
238 _mesa_reference_framebuffer_(struct gl_framebuffer **ptr,
239                              struct gl_framebuffer *fb)
240 {
241    if (*ptr) {
242       /* unreference old renderbuffer */
243       GLboolean deleteFlag = GL_FALSE;
244       struct gl_framebuffer *oldFb = *ptr;
245
246       _glthread_LOCK_MUTEX(oldFb->Mutex);
247       ASSERT(oldFb->RefCount > 0);
248       oldFb->RefCount--;
249       deleteFlag = (oldFb->RefCount == 0);
250       _glthread_UNLOCK_MUTEX(oldFb->Mutex);
251       
252       if (deleteFlag)
253          oldFb->Delete(oldFb);
254
255       *ptr = NULL;
256    }
257    assert(!*ptr);
258
259    if (fb) {
260       _glthread_LOCK_MUTEX(fb->Mutex);
261       fb->RefCount++;
262       _glthread_UNLOCK_MUTEX(fb->Mutex);
263       *ptr = fb;
264    }
265 }
266
267
268 /**
269  * Resize the given framebuffer's renderbuffers to the new width and height.
270  * This should only be used for window-system framebuffers, not
271  * user-created renderbuffers (i.e. made with GL_EXT_framebuffer_object).
272  * This will typically be called via ctx->Driver.ResizeBuffers() or directly
273  * from a device driver.
274  *
275  * \note it's possible for ctx to be null since a window can be resized
276  * without a currently bound rendering context.
277  */
278 void
279 _mesa_resize_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
280                          GLuint width, GLuint height)
281 {
282    GLuint i;
283
284    /* XXX I think we could check if the size is not changing
285     * and return early.
286     */
287
288    /* Can only resize win-sys framebuffer objects */
289    assert(_mesa_is_winsys_fbo(fb));
290
291    for (i = 0; i < BUFFER_COUNT; i++) {
292       struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
293       if (att->Type == GL_RENDERBUFFER_EXT && att->Renderbuffer) {
294          struct gl_renderbuffer *rb = att->Renderbuffer;
295          /* only resize if size is changing */
296          if (rb->Width != width || rb->Height != height) {
297             if (rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) {
298                ASSERT(rb->Width == width);
299                ASSERT(rb->Height == height);
300             }
301             else {
302                _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer");
303                /* no return */
304             }
305          }
306       }
307    }
308
309    fb->Width = width;
310    fb->Height = height;
311
312    if (ctx) {
313       /* update scissor / window bounds */
314       _mesa_update_draw_buffer_bounds(ctx);
315       /* Signal new buffer state so that swrast will update its clipping
316        * info (the CLIP_BIT flag).
317        */
318       ctx->NewState |= _NEW_BUFFERS;
319    }
320 }
321
322
323
324 /**
325  * XXX THIS IS OBSOLETE - drivers should take care of detecting window
326  * size changes and act accordingly, likely calling _mesa_resize_framebuffer().
327  *
328  * GL_MESA_resize_buffers extension.
329  *
330  * When this function is called, we'll ask the window system how large
331  * the current window is.  If it's a new size, we'll call the driver's
332  * ResizeBuffers function.  The driver will then resize its color buffers
333  * as needed, and maybe call the swrast's routine for reallocating
334  * swrast-managed depth/stencil/accum/etc buffers.
335  * \note This function should only be called through the GL API, not
336  * from device drivers (as was done in the past).
337  */
338 void
339 _mesa_resizebuffers( struct gl_context *ctx )
340 {
341    FLUSH_VERTICES(ctx, 0);
342
343    if (MESA_VERBOSE & VERBOSE_API)
344       _mesa_debug(ctx, "glResizeBuffersMESA\n");
345
346    if (!ctx->Driver.GetBufferSize) {
347       return;
348    }
349
350    if (ctx->WinSysDrawBuffer) {
351       GLuint newWidth, newHeight;
352       struct gl_framebuffer *buffer = ctx->WinSysDrawBuffer;
353
354       assert(_mesa_is_winsys_fbo(buffer));
355
356       /* ask device driver for size of output buffer */
357       ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight );
358
359       /* see if size of device driver's color buffer (window) has changed */
360       if (buffer->Width != newWidth || buffer->Height != newHeight) {
361          if (ctx->Driver.ResizeBuffers)
362             ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight );
363       }
364    }
365
366    if (ctx->WinSysReadBuffer
367        && ctx->WinSysReadBuffer != ctx->WinSysDrawBuffer) {
368       GLuint newWidth, newHeight;
369       struct gl_framebuffer *buffer = ctx->WinSysReadBuffer;
370
371       assert(_mesa_is_winsys_fbo(buffer));
372
373       /* ask device driver for size of read buffer */
374       ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight );
375
376       /* see if size of device driver's color buffer (window) has changed */
377       if (buffer->Width != newWidth || buffer->Height != newHeight) {
378          if (ctx->Driver.ResizeBuffers)
379             ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight );
380       }
381    }
382
383    ctx->NewState |= _NEW_BUFFERS;  /* to update scissor / window bounds */
384 }
385
386
387 /*
388  * XXX THIS IS OBSOLETE
389  */
390 void GLAPIENTRY
391 _mesa_ResizeBuffersMESA( void )
392 {
393    GET_CURRENT_CONTEXT(ctx);
394
395    if (ctx->Extensions.MESA_resize_buffers)
396       _mesa_resizebuffers( ctx );
397 }
398
399
400
401 /**
402  * Examine all the framebuffer's renderbuffers to update the Width/Height
403  * fields of the framebuffer.  If we have renderbuffers with different
404  * sizes, set the framebuffer's width and height to the min size.
405  * Note: this is only intended for user-created framebuffers, not
406  * window-system framebuffes.
407  */
408 static void
409 update_framebuffer_size(struct gl_context *ctx, struct gl_framebuffer *fb)
410 {
411    GLuint minWidth = ~0, minHeight = ~0;
412    GLuint i;
413
414    /* user-created framebuffers only */
415    assert(_mesa_is_user_fbo(fb));
416
417    for (i = 0; i < BUFFER_COUNT; i++) {
418       struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
419       const struct gl_renderbuffer *rb = att->Renderbuffer;
420       if (rb) {
421          minWidth = MIN2(minWidth, rb->Width);
422          minHeight = MIN2(minHeight, rb->Height);
423       }
424    }
425
426    if (minWidth != ~0) {
427       fb->Width = minWidth;
428       fb->Height = minHeight;
429    }
430    else {
431       fb->Width = 0;
432       fb->Height = 0;
433    }
434 }
435
436
437 /**
438  * Update the context's current drawing buffer's Xmin, Xmax, Ymin, Ymax fields.
439  * These values are computed from the buffer's width and height and
440  * the scissor box, if it's enabled.
441  * \param ctx  the GL context.
442  */
443 void
444 _mesa_update_draw_buffer_bounds(struct gl_context *ctx)
445 {
446    struct gl_framebuffer *buffer = ctx->DrawBuffer;
447
448    if (!buffer)
449       return;
450
451    if (_mesa_is_user_fbo(buffer)) {
452       /* user-created framebuffer size depends on the renderbuffers */
453       update_framebuffer_size(ctx, buffer);
454    }
455
456    buffer->_Xmin = 0;
457    buffer->_Ymin = 0;
458    buffer->_Xmax = buffer->Width;
459    buffer->_Ymax = buffer->Height;
460
461    if (ctx->Scissor.Enabled) {
462       if (ctx->Scissor.X > buffer->_Xmin) {
463          buffer->_Xmin = ctx->Scissor.X;
464       }
465       if (ctx->Scissor.Y > buffer->_Ymin) {
466          buffer->_Ymin = ctx->Scissor.Y;
467       }
468       if (ctx->Scissor.X + ctx->Scissor.Width < buffer->_Xmax) {
469          buffer->_Xmax = ctx->Scissor.X + ctx->Scissor.Width;
470       }
471       if (ctx->Scissor.Y + ctx->Scissor.Height < buffer->_Ymax) {
472          buffer->_Ymax = ctx->Scissor.Y + ctx->Scissor.Height;
473       }
474       /* finally, check for empty region */
475       if (buffer->_Xmin > buffer->_Xmax) {
476          buffer->_Xmin = buffer->_Xmax;
477       }
478       if (buffer->_Ymin > buffer->_Ymax) {
479          buffer->_Ymin = buffer->_Ymax;
480       }
481    }
482
483    ASSERT(buffer->_Xmin <= buffer->_Xmax);
484    ASSERT(buffer->_Ymin <= buffer->_Ymax);
485 }
486
487
488 /**
489  * The glGet queries of the framebuffer red/green/blue size, stencil size,
490  * etc. are satisfied by the fields of ctx->DrawBuffer->Visual.  These can
491  * change depending on the renderbuffer bindings.  This function updates
492  * the given framebuffer's Visual from the current renderbuffer bindings.
493  *
494  * This may apply to user-created framebuffers or window system framebuffers.
495  *
496  * Also note: ctx->DrawBuffer->Visual.depthBits might not equal
497  * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits.
498  * The former one is used to convert floating point depth values into
499  * integer Z values.
500  */
501 void
502 _mesa_update_framebuffer_visual(struct gl_context *ctx,
503                                 struct gl_framebuffer *fb)
504 {
505    GLuint i;
506
507    memset(&fb->Visual, 0, sizeof(fb->Visual));
508    fb->Visual.rgbMode = GL_TRUE; /* assume this */
509
510 #if 0 /* this _might_ be needed */
511    if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
512       /* leave visual fields zero'd */
513       return;
514    }
515 #endif
516
517    /* find first RGB renderbuffer */
518    for (i = 0; i < BUFFER_COUNT; i++) {
519       if (fb->Attachment[i].Renderbuffer) {
520          const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
521          const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
522          const gl_format fmt = rb->Format;
523
524          /* Grab samples and sampleBuffers from any attachment point (assuming
525           * the framebuffer is complete, we'll get the same answer from all
526           * attachments).
527           */
528          fb->Visual.samples = rb->NumSamples;
529          fb->Visual.sampleBuffers = rb->NumSamples > 0 ? 1 : 0;
530
531          if (_mesa_is_legal_color_format(ctx, baseFormat)) {
532             fb->Visual.redBits = _mesa_get_format_bits(fmt, GL_RED_BITS);
533             fb->Visual.greenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS);
534             fb->Visual.blueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS);
535             fb->Visual.alphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS);
536             fb->Visual.rgbBits = fb->Visual.redBits
537                + fb->Visual.greenBits + fb->Visual.blueBits;
538             if (_mesa_get_format_color_encoding(fmt) == GL_SRGB)
539                 fb->Visual.sRGBCapable = ctx->Extensions.EXT_framebuffer_sRGB;
540             break;
541          }
542       }
543    }
544
545    fb->Visual.floatMode = GL_FALSE;
546    for (i = 0; i < BUFFER_COUNT; i++) {
547       if (fb->Attachment[i].Renderbuffer) {
548          const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
549          const gl_format fmt = rb->Format;
550
551          if (_mesa_get_format_datatype(fmt) == GL_FLOAT) {
552             fb->Visual.floatMode = GL_TRUE;
553             break;
554          }
555       }
556    }
557
558    if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) {
559       const struct gl_renderbuffer *rb =
560          fb->Attachment[BUFFER_DEPTH].Renderbuffer;
561       const gl_format fmt = rb->Format;
562       fb->Visual.haveDepthBuffer = GL_TRUE;
563       fb->Visual.depthBits = _mesa_get_format_bits(fmt, GL_DEPTH_BITS);
564    }
565
566    if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) {
567       const struct gl_renderbuffer *rb =
568          fb->Attachment[BUFFER_STENCIL].Renderbuffer;
569       const gl_format fmt = rb->Format;
570       fb->Visual.haveStencilBuffer = GL_TRUE;
571       fb->Visual.stencilBits = _mesa_get_format_bits(fmt, GL_STENCIL_BITS);
572    }
573
574    if (fb->Attachment[BUFFER_ACCUM].Renderbuffer) {
575       const struct gl_renderbuffer *rb =
576          fb->Attachment[BUFFER_ACCUM].Renderbuffer;
577       const gl_format fmt = rb->Format;
578       fb->Visual.haveAccumBuffer = GL_TRUE;
579       fb->Visual.accumRedBits = _mesa_get_format_bits(fmt, GL_RED_BITS);
580       fb->Visual.accumGreenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS);
581       fb->Visual.accumBlueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS);
582       fb->Visual.accumAlphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS);
583    }
584
585    compute_depth_max(fb);
586 }
587
588
589 /*
590  * Example DrawBuffers scenarios:
591  *
592  * 1. glDrawBuffer(GL_FRONT_AND_BACK), fixed-func or shader writes to
593  * "gl_FragColor" or program writes to the "result.color" register:
594  *
595  *   fragment color output   renderbuffer
596  *   ---------------------   ---------------
597  *   color[0]                Front, Back
598  *
599  *
600  * 2. glDrawBuffers(3, [GL_FRONT, GL_AUX0, GL_AUX1]), shader writes to
601  * gl_FragData[i] or program writes to result.color[i] registers:
602  *
603  *   fragment color output   renderbuffer
604  *   ---------------------   ---------------
605  *   color[0]                Front
606  *   color[1]                Aux0
607  *   color[3]                Aux1
608  *
609  *
610  * 3. glDrawBuffers(3, [GL_FRONT, GL_AUX0, GL_AUX1]) and shader writes to
611  * gl_FragColor, or fixed function:
612  *
613  *   fragment color output   renderbuffer
614  *   ---------------------   ---------------
615  *   color[0]                Front, Aux0, Aux1
616  *
617  *
618  * In either case, the list of renderbuffers is stored in the
619  * framebuffer->_ColorDrawBuffers[] array and
620  * framebuffer->_NumColorDrawBuffers indicates the number of buffers.
621  * The renderer (like swrast) has to look at the current fragment shader
622  * to see if it writes to gl_FragColor vs. gl_FragData[i] to determine
623  * how to map color outputs to renderbuffers.
624  *
625  * Note that these two calls are equivalent (for fixed function fragment
626  * shading anyway):
627  *   a)  glDrawBuffer(GL_FRONT_AND_BACK);  (assuming non-stereo framebuffer)
628  *   b)  glDrawBuffers(2, [GL_FRONT_LEFT, GL_BACK_LEFT]);
629  */
630
631
632
633
634 /**
635  * Update the (derived) list of color drawing renderbuffer pointers.
636  * Later, when we're rendering we'll loop from 0 to _NumColorDrawBuffers
637  * writing colors.
638  */
639 static void
640 update_color_draw_buffers(struct gl_context *ctx, struct gl_framebuffer *fb)
641 {
642    GLuint output;
643
644    /* set 0th buffer to NULL now in case _NumColorDrawBuffers is zero */
645    fb->_ColorDrawBuffers[0] = NULL;
646
647    for (output = 0; output < fb->_NumColorDrawBuffers; output++) {
648       GLint buf = fb->_ColorDrawBufferIndexes[output];
649       if (buf >= 0) {
650          fb->_ColorDrawBuffers[output] = fb->Attachment[buf].Renderbuffer;
651       }
652       else {
653          fb->_ColorDrawBuffers[output] = NULL;
654       }
655    }
656 }
657
658
659 /**
660  * Update the (derived) color read renderbuffer pointer.
661  * Unlike the DrawBuffer, we can only read from one (or zero) color buffers.
662  */
663 static void
664 update_color_read_buffer(struct gl_context *ctx, struct gl_framebuffer *fb)
665 {
666    (void) ctx;
667    if (fb->_ColorReadBufferIndex == -1 ||
668        fb->DeletePending ||
669        fb->Width == 0 ||
670        fb->Height == 0) {
671       fb->_ColorReadBuffer = NULL; /* legal! */
672    }
673    else {
674       ASSERT(fb->_ColorReadBufferIndex >= 0);
675       ASSERT(fb->_ColorReadBufferIndex < BUFFER_COUNT);
676       fb->_ColorReadBuffer
677          = fb->Attachment[fb->_ColorReadBufferIndex].Renderbuffer;
678    }
679 }
680
681
682 /**
683  * Update a gl_framebuffer's derived state.
684  *
685  * Specifically, update these framebuffer fields:
686  *    _ColorDrawBuffers
687  *    _NumColorDrawBuffers
688  *    _ColorReadBuffer
689  *
690  * If the framebuffer is user-created, make sure it's complete.
691  *
692  * The following functions (at least) can effect framebuffer state:
693  * glReadBuffer, glDrawBuffer, glDrawBuffersARB, glFramebufferRenderbufferEXT,
694  * glRenderbufferStorageEXT.
695  */
696 static void
697 update_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
698 {
699    if (_mesa_is_winsys_fbo(fb)) {
700       /* This is a window-system framebuffer */
701       /* Need to update the FB's GL_DRAW_BUFFER state to match the
702        * context state (GL_READ_BUFFER too).
703        */
704       if (fb->ColorDrawBuffer[0] != ctx->Color.DrawBuffer[0]) {
705          _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers,
706                            ctx->Color.DrawBuffer, NULL);
707       }
708    }
709    else {
710       /* This is a user-created framebuffer.
711        * Completeness only matters for user-created framebuffers.
712        */
713       if (fb->_Status != GL_FRAMEBUFFER_COMPLETE) {
714          _mesa_test_framebuffer_completeness(ctx, fb);
715       }
716    }
717
718    /* Strictly speaking, we don't need to update the draw-state
719     * if this FB is bound as ctx->ReadBuffer (and conversely, the
720     * read-state if this FB is bound as ctx->DrawBuffer), but no
721     * harm.
722     */
723    update_color_draw_buffers(ctx, fb);
724    update_color_read_buffer(ctx, fb);
725
726    compute_depth_max(fb);
727 }
728
729
730 /**
731  * Update state related to the current draw/read framebuffers.
732  */
733 void
734 _mesa_update_framebuffer(struct gl_context *ctx)
735 {
736    struct gl_framebuffer *drawFb;
737    struct gl_framebuffer *readFb;
738
739    assert(ctx);
740    drawFb = ctx->DrawBuffer;
741    readFb = ctx->ReadBuffer;
742
743    update_framebuffer(ctx, drawFb);
744    if (readFb != drawFb)
745       update_framebuffer(ctx, readFb);
746
747    _mesa_update_clamp_vertex_color(ctx);
748    _mesa_update_clamp_fragment_color(ctx);
749 }
750
751
752 /**
753  * Check if the renderbuffer for a read/draw operation exists.
754  * \param format  a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA,
755  *                GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL.
756  * \param reading  if TRUE, we're going to read from the buffer,
757                    if FALSE, we're going to write to the buffer.
758  * \return GL_TRUE if buffer exists, GL_FALSE otherwise
759  */
760 static GLboolean
761 renderbuffer_exists(struct gl_context *ctx,
762                     struct gl_framebuffer *fb,
763                     GLenum format,
764                     GLboolean reading)
765 {
766    const struct gl_renderbuffer_attachment *att = fb->Attachment;
767
768    /* If we don't know the framebuffer status, update it now */
769    if (fb->_Status == 0) {
770       _mesa_test_framebuffer_completeness(ctx, fb);
771    }
772
773    if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
774       return GL_FALSE;
775    }
776
777    switch (format) {
778    case GL_COLOR:
779    case GL_RED:
780    case GL_GREEN:
781    case GL_BLUE:
782    case GL_ALPHA:
783    case GL_LUMINANCE:
784    case GL_LUMINANCE_ALPHA:
785    case GL_INTENSITY:
786    case GL_RG:
787    case GL_RGB:
788    case GL_BGR:
789    case GL_RGBA:
790    case GL_BGRA:
791    case GL_ABGR_EXT:
792    case GL_RED_INTEGER_EXT:
793    case GL_RG_INTEGER:
794    case GL_GREEN_INTEGER_EXT:
795    case GL_BLUE_INTEGER_EXT:
796    case GL_ALPHA_INTEGER_EXT:
797    case GL_RGB_INTEGER_EXT:
798    case GL_RGBA_INTEGER_EXT:
799    case GL_BGR_INTEGER_EXT:
800    case GL_BGRA_INTEGER_EXT:
801    case GL_LUMINANCE_INTEGER_EXT:
802    case GL_LUMINANCE_ALPHA_INTEGER_EXT:
803       if (reading) {
804          /* about to read from a color buffer */
805          const struct gl_renderbuffer *readBuf = fb->_ColorReadBuffer;
806          if (!readBuf) {
807             return GL_FALSE;
808          }
809          ASSERT(_mesa_get_format_bits(readBuf->Format, GL_RED_BITS) > 0 ||
810                 _mesa_get_format_bits(readBuf->Format, GL_ALPHA_BITS) > 0 ||
811                 _mesa_get_format_bits(readBuf->Format, GL_TEXTURE_LUMINANCE_SIZE) > 0 ||
812                 _mesa_get_format_bits(readBuf->Format, GL_TEXTURE_INTENSITY_SIZE) > 0 ||
813                 _mesa_get_format_bits(readBuf->Format, GL_INDEX_BITS) > 0);
814       }
815       else {
816          /* about to draw to zero or more color buffers (none is OK) */
817          return GL_TRUE;
818       }
819       break;
820    case GL_DEPTH:
821    case GL_DEPTH_COMPONENT:
822       if (att[BUFFER_DEPTH].Type == GL_NONE) {
823          return GL_FALSE;
824       }
825       break;
826    case GL_STENCIL:
827    case GL_STENCIL_INDEX:
828       if (att[BUFFER_STENCIL].Type == GL_NONE) {
829          return GL_FALSE;
830       }
831       break;
832    case GL_DEPTH_STENCIL_EXT:
833       if (att[BUFFER_DEPTH].Type == GL_NONE ||
834           att[BUFFER_STENCIL].Type == GL_NONE) {
835          return GL_FALSE;
836       }
837       break;
838    default:
839       _mesa_problem(ctx,
840                     "Unexpected format 0x%x in renderbuffer_exists",
841                     format);
842       return GL_FALSE;
843    }
844
845    /* OK */
846    return GL_TRUE;
847 }
848
849
850 /**
851  * Check if the renderbuffer for a read operation (glReadPixels, glCopyPixels,
852  * glCopyTex[Sub]Image, etc) exists.
853  * \param format  a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA,
854  *                GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL.
855  * \return GL_TRUE if buffer exists, GL_FALSE otherwise
856  */
857 GLboolean
858 _mesa_source_buffer_exists(struct gl_context *ctx, GLenum format)
859 {
860    return renderbuffer_exists(ctx, ctx->ReadBuffer, format, GL_TRUE);
861 }
862
863
864 /**
865  * As above, but for drawing operations.
866  */
867 GLboolean
868 _mesa_dest_buffer_exists(struct gl_context *ctx, GLenum format)
869 {
870    return renderbuffer_exists(ctx, ctx->DrawBuffer, format, GL_FALSE);
871 }
872
873
874 /**
875  * Used to answer the GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES query.
876  */
877 GLenum
878 _mesa_get_color_read_format(struct gl_context *ctx)
879 {
880    if (!ctx->ReadBuffer || !ctx->ReadBuffer->_ColorReadBuffer) {
881       /* The spec is unclear how to handle this case, but NVIDIA's
882        * driver generates GL_INVALID_OPERATION.
883        */
884       _mesa_error(ctx, GL_INVALID_OPERATION,
885                   "glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT: "
886                   "no GL_READ_BUFFER)");
887       return GL_NONE;
888    }
889    else {
890       const GLenum format = ctx->ReadBuffer->_ColorReadBuffer->Format;
891       const GLenum data_type = _mesa_get_format_datatype(format);
892
893       if (format == MESA_FORMAT_ARGB8888)
894          return GL_BGRA;
895       else if (format == MESA_FORMAT_RGB565)
896          return GL_BGR;
897
898       switch (data_type) {
899       case GL_UNSIGNED_INT:
900       case GL_INT:
901          return GL_RGBA_INTEGER;
902       default:
903          return GL_RGBA;
904       }
905    }
906 }
907
908
909 /**
910  * Used to answer the GL_IMPLEMENTATION_COLOR_READ_TYPE_OES query.
911  */
912 GLenum
913 _mesa_get_color_read_type(struct gl_context *ctx)
914 {
915    if (!ctx->ReadBuffer || !ctx->ReadBuffer->_ColorReadBuffer) {
916       /* The spec is unclear how to handle this case, but NVIDIA's
917        * driver generates GL_INVALID_OPERATION.
918        */
919       _mesa_error(ctx, GL_INVALID_OPERATION,
920                   "glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE: "
921                   "no GL_READ_BUFFER)");
922       return GL_NONE;
923    }
924    else {
925       const GLenum format = ctx->ReadBuffer->_ColorReadBuffer->Format;
926       const GLenum data_type = _mesa_get_format_datatype(format);
927
928       if (format == MESA_FORMAT_RGB565)
929          return GL_UNSIGNED_SHORT_5_6_5_REV;
930
931       switch (data_type) {
932       case GL_SIGNED_NORMALIZED:
933          return GL_BYTE;
934       case GL_UNSIGNED_INT:
935       case GL_INT:
936       case GL_FLOAT:
937          return data_type;
938       case GL_UNSIGNED_NORMALIZED:
939       default:
940          return GL_UNSIGNED_BYTE;
941       }
942    }
943 }
944
945
946 /**
947  * Returns the read renderbuffer for the specified format.
948  */
949 struct gl_renderbuffer *
950 _mesa_get_read_renderbuffer_for_format(const struct gl_context *ctx,
951                                        GLenum format)
952 {
953    const struct gl_framebuffer *rfb = ctx->ReadBuffer;
954
955    if (_mesa_is_color_format(format)) {
956       return rfb->Attachment[rfb->_ColorReadBufferIndex].Renderbuffer;
957    } else if (_mesa_is_depth_format(format) ||
958               _mesa_is_depthstencil_format(format)) {
959       return rfb->Attachment[BUFFER_DEPTH].Renderbuffer;
960    } else {
961       return rfb->Attachment[BUFFER_STENCIL].Renderbuffer;
962    }
963 }
964
965
966 /**
967  * Print framebuffer info to stderr, for debugging.
968  */
969 void
970 _mesa_print_framebuffer(const struct gl_framebuffer *fb)
971 {
972    GLuint i;
973
974    fprintf(stderr, "Mesa Framebuffer %u at %p\n", fb->Name, (void *) fb);
975    fprintf(stderr, "  Size: %u x %u  Status: %s\n", fb->Width, fb->Height,
976            _mesa_lookup_enum_by_nr(fb->_Status));
977    fprintf(stderr, "  Attachments:\n");
978
979    for (i = 0; i < BUFFER_COUNT; i++) {
980       const struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
981       if (att->Type == GL_TEXTURE) {
982          const struct gl_texture_image *texImage = att->Renderbuffer->TexImage;
983          fprintf(stderr,
984                  "  %2d: Texture %u, level %u, face %u, slice %u, complete %d\n",
985                  i, att->Texture->Name, att->TextureLevel, att->CubeMapFace,
986                  att->Zoffset, att->Complete);
987          fprintf(stderr, "       Size: %u x %u x %u  Format %s\n",
988                  texImage->Width, texImage->Height, texImage->Depth,
989                  _mesa_get_format_name(texImage->TexFormat));
990       }
991       else if (att->Type == GL_RENDERBUFFER) {
992          fprintf(stderr, "  %2d: Renderbuffer %u, complete %d\n",
993                  i, att->Renderbuffer->Name, att->Complete);
994          fprintf(stderr, "       Size: %u x %u  Format %s\n",
995                  att->Renderbuffer->Width, att->Renderbuffer->Height,
996                  _mesa_get_format_name(att->Renderbuffer->Format));
997       }
998       else {
999          fprintf(stderr, "  %2d: none\n", i);
1000       }
1001    }
1002 }