Subversion Repositories Kolibri OS

Rev

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