/**
 * Update a gl_framebuffer's derived state.
 *
 * Specifically, update these framebuffer fields:
 *    _ColorDrawBuffers
 *    _NumColorDrawBuffers
 *    _ColorReadBuffer
 *
 * If the framebuffer is user-created, make sure it's complete.
 *
 * The following functions (at least) can effect framebuffer state:
 * glReadBuffer, glDrawBuffer, glDrawBuffersARB, glFramebufferRenderbufferEXT,
 * glRenderbufferStorageEXT.
 */
static void
update_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
{
   if (_mesa_is_winsys_fbo(fb)) {
      /* This is a window-system framebuffer */
      /* Need to update the FB's GL_DRAW_BUFFER state to match the
       * context state (GL_READ_BUFFER too).
       */
      if (fb->ColorDrawBuffer[0] != ctx->Color.DrawBuffer[0]) {
         _mesa_drawbuffers(ctx, fb, ctx->Const.MaxDrawBuffers,
                           ctx->Color.DrawBuffer, NULL);
      }
   }
   else {
      /* This is a user-created framebuffer.
       * Completeness only matters for user-created framebuffers.
       */
      if (fb->_Status != GL_FRAMEBUFFER_COMPLETE) {
         _mesa_test_framebuffer_completeness(ctx, fb);
      }
   }

   /* Strictly speaking, we don't need to update the draw-state
    * if this FB is bound as ctx->ReadBuffer (and conversely, the
    * read-state if this FB is bound as ctx->DrawBuffer), but no
    * harm.
    */
   update_color_draw_buffers(ctx, fb);
   update_color_read_buffer(ctx, fb);

   compute_depth_max(fb);
}
Example #2
0
/**
 * Initialize a gl_framebuffer object.  Typically used to initialize
 * window system-created framebuffers, not user-created framebuffers.
 * \sa _mesa_create_framebuffer
 */
void
_mesa_initialize_framebuffer(struct gl_framebuffer *fb, const GLvisual *visual)
{
   assert(fb);
   assert(visual);

   _mesa_bzero(fb, sizeof(struct gl_framebuffer));

   _glthread_INIT_MUTEX(fb->Mutex);

   fb->RefCount = 1;

   /* save the visual */
   fb->Visual = *visual;

   /* Init glRead/DrawBuffer state */
   if (visual->doubleBufferMode) {
      fb->ColorDrawBuffer[0] = GL_BACK;
      fb->_ColorDrawBufferMask[0] = BUFFER_BIT_BACK_LEFT;
      fb->ColorReadBuffer = GL_BACK;
      fb->_ColorReadBufferIndex = BUFFER_BACK_LEFT;
   }
   else {
      fb->ColorDrawBuffer[0] = GL_FRONT;
      fb->_ColorDrawBufferMask[0] = BUFFER_BIT_FRONT_LEFT;
      fb->ColorReadBuffer = GL_FRONT;
      fb->_ColorReadBufferIndex = BUFFER_FRONT_LEFT;
   }

   fb->Delete = _mesa_destroy_framebuffer;
   fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;

   compute_depth_max(fb);
}
Example #3
0
static void
update_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
{
   /* Completeness only matters for user-created framebuffers */
   if (fb->Name != 0) {
      /* XXX: EXT_framebuffer_blit:
         framebuffer must still be complete wrt read/draw? */
      _mesa_test_framebuffer_completeness(ctx, fb);
      _mesa_update_framebuffer_visual(fb);
   }

   /* update_color_draw/read_buffers not needed for
      read/draw only fb, but shouldn't hurt ??? */
   update_color_draw_buffers(ctx, fb);
   update_color_read_buffer(ctx, fb);
   _mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH);
   _mesa_update_stencil_buffer(ctx, fb, BUFFER_STENCIL);

   compute_depth_max(fb);
}
/**
 * Initialize a gl_framebuffer object.  Typically used to initialize
 * window system-created framebuffers, not user-created framebuffers.
 * \sa _mesa_initialize_user_framebuffer
 */
void
_mesa_initialize_window_framebuffer(struct gl_framebuffer *fb,
				     const struct gl_config *visual)
{
   assert(fb);
   assert(visual);

   memset(fb, 0, sizeof(struct gl_framebuffer));

   mtx_init(&fb->Mutex, mtx_plain);

   fb->RefCount = 1;

   /* save the visual */
   fb->Visual = *visual;

   /* Init read/draw renderbuffer state */
   if (visual->doubleBufferMode) {
      fb->_NumColorDrawBuffers = 1;
      fb->ColorDrawBuffer[0] = GL_BACK;
      fb->_ColorDrawBufferIndexes[0] = BUFFER_BACK_LEFT;
      fb->ColorReadBuffer = GL_BACK;
      fb->_ColorReadBufferIndex = BUFFER_BACK_LEFT;
   }
   else {
      fb->_NumColorDrawBuffers = 1;
      fb->ColorDrawBuffer[0] = GL_FRONT;
      fb->_ColorDrawBufferIndexes[0] = BUFFER_FRONT_LEFT;
      fb->ColorReadBuffer = GL_FRONT;
      fb->_ColorReadBufferIndex = BUFFER_FRONT_LEFT;
   }

   fb->Delete = _mesa_destroy_framebuffer;
   fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
   fb->_AllColorBuffersFixedPoint = !visual->floatMode;
   fb->_HasSNormOrFloatColorBuffer = visual->floatMode;
   fb->_HasAttachments = true;

   compute_depth_max(fb);
}
/**
 * Initialize a gl_framebuffer object.  Typically used to initialize
 * window system-created framebuffers, not user-created framebuffers.
 * \sa _mesa_initialize_user_framebuffer
 */
void
_mesa_initialize_window_framebuffer(struct gl_framebuffer *fb,
				     const struct gl_config *visual)
{
   assert(fb);
   assert(visual);

   memset(fb, 0, sizeof(struct gl_framebuffer));

   _glthread_INIT_MUTEX(fb->Mutex);

   fb->RefCount = 1;

   /* save the visual */
   fb->Visual = *visual;

   /* Init read/draw renderbuffer state */
   if (visual->doubleBufferMode) {
      fb->_NumColorDrawBuffers = 1;
      fb->ColorDrawBuffer[0] = GL_BACK;
      fb->_ColorDrawBufferIndexes[0] = BUFFER_BACK_LEFT;
      fb->ColorReadBuffer = GL_BACK;
      fb->_ColorReadBufferIndex = BUFFER_BACK_LEFT;
   }
   else {
      fb->_NumColorDrawBuffers = 1;
      fb->ColorDrawBuffer[0] = GL_FRONT;
      fb->_ColorDrawBufferIndexes[0] = BUFFER_FRONT_LEFT;
      fb->ColorReadBuffer = GL_FRONT;
      fb->_ColorReadBufferIndex = BUFFER_FRONT_LEFT;
   }

   fb->Delete = _mesa_destroy_framebuffer;
   fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;

   compute_depth_max(fb);
}
/**
 * The glGet queries of the framebuffer red/green/blue size, stencil size,
 * etc. are satisfied by the fields of ctx->DrawBuffer->Visual.  These can
 * change depending on the renderbuffer bindings.  This function updates
 * the given framebuffer's Visual from the current renderbuffer bindings.
 *
 * This may apply to user-created framebuffers or window system framebuffers.
 *
 * Also note: ctx->DrawBuffer->Visual.depthBits might not equal
 * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits.
 * The former one is used to convert floating point depth values into
 * integer Z values.
 */
void
_mesa_update_framebuffer_visual(struct gl_context *ctx,
				struct gl_framebuffer *fb)
{
   GLuint i;

   memset(&fb->Visual, 0, sizeof(fb->Visual));
   fb->Visual.rgbMode = GL_TRUE; /* assume this */

   /* find first RGB renderbuffer */
   for (i = 0; i < BUFFER_COUNT; i++) {
      if (fb->Attachment[i].Renderbuffer) {
         const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
         const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
         const mesa_format fmt = rb->Format;

         /* Grab samples and sampleBuffers from any attachment point (assuming
          * the framebuffer is complete, we'll get the same answer from all
          * attachments).
          */
         fb->Visual.samples = rb->NumSamples;
         fb->Visual.sampleBuffers = rb->NumSamples > 0 ? 1 : 0;

         if (_mesa_is_legal_color_format(ctx, baseFormat)) {
            fb->Visual.redBits = _mesa_get_format_bits(fmt, GL_RED_BITS);
            fb->Visual.greenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS);
            fb->Visual.blueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS);
            fb->Visual.alphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS);
            fb->Visual.rgbBits = fb->Visual.redBits
               + fb->Visual.greenBits + fb->Visual.blueBits;
            if (_mesa_get_format_color_encoding(fmt) == GL_SRGB)
                fb->Visual.sRGBCapable = ctx->Extensions.EXT_framebuffer_sRGB;
            break;
         }
      }
   }

   fb->Visual.floatMode = GL_FALSE;
   for (i = 0; i < BUFFER_COUNT; i++) {
      if (fb->Attachment[i].Renderbuffer) {
         const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
         const mesa_format fmt = rb->Format;

         if (_mesa_get_format_datatype(fmt) == GL_FLOAT) {
            fb->Visual.floatMode = GL_TRUE;
            break;
         }
      }
   }

   if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) {
      const struct gl_renderbuffer *rb =
         fb->Attachment[BUFFER_DEPTH].Renderbuffer;
      const mesa_format fmt = rb->Format;
      fb->Visual.haveDepthBuffer = GL_TRUE;
      fb->Visual.depthBits = _mesa_get_format_bits(fmt, GL_DEPTH_BITS);
   }

   if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) {
      const struct gl_renderbuffer *rb =
         fb->Attachment[BUFFER_STENCIL].Renderbuffer;
      const mesa_format fmt = rb->Format;
      fb->Visual.haveStencilBuffer = GL_TRUE;
      fb->Visual.stencilBits = _mesa_get_format_bits(fmt, GL_STENCIL_BITS);
   }

   if (fb->Attachment[BUFFER_ACCUM].Renderbuffer) {
      const struct gl_renderbuffer *rb =
         fb->Attachment[BUFFER_ACCUM].Renderbuffer;
      const mesa_format fmt = rb->Format;
      fb->Visual.haveAccumBuffer = GL_TRUE;
      fb->Visual.accumRedBits = _mesa_get_format_bits(fmt, GL_RED_BITS);
      fb->Visual.accumGreenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS);
      fb->Visual.accumBlueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS);
      fb->Visual.accumAlphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS);
   }

   compute_depth_max(fb);
}
Example #7
0
/**
 * The glGet queries of the framebuffer red/green/blue size, stencil size,
 * etc. are satisfied by the fields of ctx->DrawBuffer->Visual.  These can
 * change depending on the renderbuffer bindings.  This function updates
 * the given framebuffer's Visual from the current renderbuffer bindings.
 *
 * This may apply to user-created framebuffers or window system framebuffers.
 *
 * Also note: ctx->DrawBuffer->Visual.depthBits might not equal
 * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits.
 * The former one is used to convert floating point depth values into
 * integer Z values.
 */
void
_mesa_update_framebuffer_visual(struct gl_context *ctx,
				struct gl_framebuffer *fb)
{
   GLuint i;

   memset(&fb->Visual, 0, sizeof(fb->Visual));
   fb->Visual.rgbMode = GL_TRUE; /* assume this */

#if 0 /* this _might_ be needed */
   if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      /* leave visual fields zero'd */
      return;
   }
#endif

   /* find first RGB renderbuffer */
   for (i = 0; i < BUFFER_COUNT; i++) {
      if (fb->Attachment[i].Renderbuffer) {
         const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
         const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
         const gl_format fmt = rb->Format;

         if (_mesa_is_legal_color_format(ctx, baseFormat)) {
            fb->Visual.redBits = _mesa_get_format_bits(fmt, GL_RED_BITS);
            fb->Visual.greenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS);
            fb->Visual.blueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS);
            fb->Visual.alphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS);
            fb->Visual.rgbBits = fb->Visual.redBits
               + fb->Visual.greenBits + fb->Visual.blueBits;
            fb->Visual.samples = rb->NumSamples;
            fb->Visual.sampleBuffers = rb->NumSamples > 0 ? 1 : 0;
            if (_mesa_get_format_color_encoding(fmt) == GL_SRGB)
                fb->Visual.sRGBCapable = ctx->Const.sRGBCapable;
            break;
         }
      }
   }

   fb->Visual.floatMode = GL_FALSE;
   for (i = 0; i < BUFFER_COUNT; i++) {
      if (fb->Attachment[i].Renderbuffer) {
         const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
         const gl_format fmt = rb->Format;

         if (_mesa_get_format_datatype(fmt) == GL_FLOAT) {
            fb->Visual.floatMode = GL_TRUE;
            break;
         }
      }
   }

   if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) {
      const struct gl_renderbuffer *rb =
         fb->Attachment[BUFFER_DEPTH].Renderbuffer;
      const gl_format fmt = rb->Format;
      fb->Visual.haveDepthBuffer = GL_TRUE;
      fb->Visual.depthBits = _mesa_get_format_bits(fmt, GL_DEPTH_BITS);
   }

   if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) {
      const struct gl_renderbuffer *rb =
         fb->Attachment[BUFFER_STENCIL].Renderbuffer;
      const gl_format fmt = rb->Format;
      fb->Visual.haveStencilBuffer = GL_TRUE;
      fb->Visual.stencilBits = _mesa_get_format_bits(fmt, GL_STENCIL_BITS);
   }

   if (fb->Attachment[BUFFER_ACCUM].Renderbuffer) {
      const struct gl_renderbuffer *rb =
         fb->Attachment[BUFFER_ACCUM].Renderbuffer;
      const gl_format fmt = rb->Format;
      fb->Visual.haveAccumBuffer = GL_TRUE;
      fb->Visual.accumRedBits = _mesa_get_format_bits(fmt, GL_RED_BITS);
      fb->Visual.accumGreenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS);
      fb->Visual.accumBlueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS);
      fb->Visual.accumAlphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS);
   }

   compute_depth_max(fb);
}
Example #8
0
/**
 * The glGet queries of the framebuffer red/green/blue size, stencil size,
 * etc. are satisfied by the fields of ctx->DrawBuffer->Visual.  These can
 * change depending on the renderbuffer bindings.  This function updates
 * the given framebuffer's Visual from the current renderbuffer bindings.
 *
 * This may apply to user-created framebuffers or window system framebuffers.
 *
 * Also note: ctx->DrawBuffer->Visual.depthBits might not equal
 * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits.
 * The former one is used to convert floating point depth values into
 * integer Z values.
 */
void
_mesa_update_framebuffer_visual(struct gl_framebuffer *fb)
{
   GLuint i;

   _mesa_bzero(&fb->Visual, sizeof(fb->Visual));
   fb->Visual.rgbMode = GL_TRUE; /* assume this */

#if 0 /* this _might_ be needed */
   if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      /* leave visual fields zero'd */
      return;
   }
#endif

   /* find first RGB or CI renderbuffer */
   for (i = 0; i < BUFFER_COUNT; i++) {
      if (fb->Attachment[i].Renderbuffer) {
         const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
         if (rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB) {
            fb->Visual.redBits = rb->RedBits;
            fb->Visual.greenBits = rb->GreenBits;
            fb->Visual.blueBits = rb->BlueBits;
            fb->Visual.alphaBits = rb->AlphaBits;
            fb->Visual.rgbBits = fb->Visual.redBits
               + fb->Visual.greenBits + fb->Visual.blueBits;
            fb->Visual.floatMode = GL_FALSE;
            break;
         }
         else if (rb->_BaseFormat == GL_COLOR_INDEX) {
            fb->Visual.indexBits = rb->IndexBits;
            fb->Visual.rgbMode = GL_FALSE;
            break;
         }
      }
   }

   if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) {
      fb->Visual.haveDepthBuffer = GL_TRUE;
      fb->Visual.depthBits
         = fb->Attachment[BUFFER_DEPTH].Renderbuffer->DepthBits;
   }

   if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) {
      fb->Visual.haveStencilBuffer = GL_TRUE;
      fb->Visual.stencilBits
         = fb->Attachment[BUFFER_STENCIL].Renderbuffer->StencilBits;
   }

   if (fb->Attachment[BUFFER_ACCUM].Renderbuffer) {
      fb->Visual.haveAccumBuffer = GL_TRUE;
      fb->Visual.accumRedBits
         = fb->Attachment[BUFFER_ACCUM].Renderbuffer->RedBits;
      fb->Visual.accumGreenBits
         = fb->Attachment[BUFFER_ACCUM].Renderbuffer->GreenBits;
      fb->Visual.accumBlueBits
         = fb->Attachment[BUFFER_ACCUM].Renderbuffer->BlueBits;
      fb->Visual.accumAlphaBits
         = fb->Attachment[BUFFER_ACCUM].Renderbuffer->AlphaBits;
   }

   compute_depth_max(fb);
}