/**
 * 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);
}
Beispiel #2
0
GLenum GLAPIENTRY
_mesa_CheckFramebufferStatusEXT(GLenum target)
{
   struct gl_framebuffer *buffer;
   GET_CURRENT_CONTEXT(ctx);

   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);

   switch (target) {
#if FEATURE_EXT_framebuffer_blit
   case GL_DRAW_FRAMEBUFFER_EXT:
      if (!ctx->Extensions.EXT_framebuffer_blit) {
         _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
         return 0;
      }
      buffer = ctx->DrawBuffer;
      break;
   case GL_READ_FRAMEBUFFER_EXT:
      if (!ctx->Extensions.EXT_framebuffer_blit) {
         _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
         return 0;
      }
      buffer = ctx->ReadBuffer;
      break;
#endif
   case GL_FRAMEBUFFER_EXT:
      buffer = ctx->DrawBuffer;
      break;
   default:
      _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
      return 0; /* formerly GL_FRAMEBUFFER_STATUS_ERROR_EXT */
   }

   if (buffer->Name == 0) {
      /* The window system / default framebuffer is always complete */
      return GL_FRAMEBUFFER_COMPLETE_EXT;
   }

   FLUSH_VERTICES(ctx, _NEW_BUFFERS);

   _mesa_test_framebuffer_completeness(ctx, buffer);
   return buffer->_Status;
}
Beispiel #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);
}
/**
 * Check if the renderbuffer for a read/draw operation exists.
 * \param format  a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA,
 *                GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL.
 * \param reading  if TRUE, we're going to read from the buffer,
                   if FALSE, we're going to write to the buffer.
 * \return GL_TRUE if buffer exists, GL_FALSE otherwise
 */
static GLboolean
renderbuffer_exists(struct gl_context *ctx,
                    struct gl_framebuffer *fb,
                    GLenum format,
                    GLboolean reading)
{
   const struct gl_renderbuffer_attachment *att = fb->Attachment;

   /* If we don't know the framebuffer status, update it now */
   if (fb->_Status == 0) {
      _mesa_test_framebuffer_completeness(ctx, fb);
   }

   if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      return GL_FALSE;
   }

   switch (format) {
   case GL_COLOR:
   case GL_RED:
   case GL_GREEN:
   case GL_BLUE:
   case GL_ALPHA:
   case GL_LUMINANCE:
   case GL_LUMINANCE_ALPHA:
   case GL_INTENSITY:
   case GL_RG:
   case GL_RGB:
   case GL_BGR:
   case GL_RGBA:
   case GL_BGRA:
   case GL_ABGR_EXT:
   case GL_RED_INTEGER_EXT:
   case GL_RG_INTEGER:
   case GL_GREEN_INTEGER_EXT:
   case GL_BLUE_INTEGER_EXT:
   case GL_ALPHA_INTEGER_EXT:
   case GL_RGB_INTEGER_EXT:
   case GL_RGBA_INTEGER_EXT:
   case GL_BGR_INTEGER_EXT:
   case GL_BGRA_INTEGER_EXT:
   case GL_LUMINANCE_INTEGER_EXT:
   case GL_LUMINANCE_ALPHA_INTEGER_EXT:
      if (reading) {
         /* about to read from a color buffer */
         const struct gl_renderbuffer *readBuf = fb->_ColorReadBuffer;
         if (!readBuf) {
            return GL_FALSE;
         }
         assert(_mesa_get_format_bits(readBuf->Format, GL_RED_BITS) > 0 ||
                _mesa_get_format_bits(readBuf->Format, GL_ALPHA_BITS) > 0 ||
                _mesa_get_format_bits(readBuf->Format, GL_TEXTURE_LUMINANCE_SIZE) > 0 ||
                _mesa_get_format_bits(readBuf->Format, GL_TEXTURE_INTENSITY_SIZE) > 0 ||
                _mesa_get_format_bits(readBuf->Format, GL_INDEX_BITS) > 0);
      }
      else {
         /* about to draw to zero or more color buffers (none is OK) */
         return GL_TRUE;
      }
      break;
   case GL_DEPTH:
   case GL_DEPTH_COMPONENT:
      if (att[BUFFER_DEPTH].Type == GL_NONE) {
         return GL_FALSE;
      }
      break;
   case GL_STENCIL:
   case GL_STENCIL_INDEX:
      if (att[BUFFER_STENCIL].Type == GL_NONE) {
         return GL_FALSE;
      }
      break;
   case GL_DEPTH_STENCIL_EXT:
      if (att[BUFFER_DEPTH].Type == GL_NONE ||
          att[BUFFER_STENCIL].Type == GL_NONE) {
         return GL_FALSE;
      }
      break;
   default:
      _mesa_problem(ctx,
                    "Unexpected format 0x%x in renderbuffer_exists",
                    format);
      return GL_FALSE;
   }

   /* OK */
   return GL_TRUE;
}
/**
 * As above, but for drawing operations.
 * XXX could do some code merging w/ above function.
 */
GLboolean
_mesa_dest_buffer_exists(struct gl_context *ctx, GLenum format)
{
   const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment;

   /* If we don't know the framebuffer status, update it now */
   if (ctx->DrawBuffer->_Status == 0) {
      _mesa_test_framebuffer_completeness(ctx, ctx->DrawBuffer);
   }

   if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      return GL_FALSE;
   }

   switch (format) {
   case GL_COLOR:
   case GL_RED:
   case GL_GREEN:
   case GL_BLUE:
   case GL_ALPHA:
   case GL_LUMINANCE:
   case GL_LUMINANCE_ALPHA:
   case GL_INTENSITY:
   case GL_RGB:
   case GL_BGR:
   case GL_RGBA:
   case GL_BGRA:
   case GL_ABGR_EXT:
   case GL_COLOR_INDEX:
   case GL_RED_INTEGER_EXT:
   case GL_GREEN_INTEGER_EXT:
   case GL_BLUE_INTEGER_EXT:
   case GL_ALPHA_INTEGER_EXT:
   case GL_RGB_INTEGER_EXT:
   case GL_RGBA_INTEGER_EXT:
   case GL_BGR_INTEGER_EXT:
   case GL_BGRA_INTEGER_EXT:
   case GL_LUMINANCE_INTEGER_EXT:
   case GL_LUMINANCE_ALPHA_INTEGER_EXT:
      /* Nothing special since GL_DRAW_BUFFER could be GL_NONE. */
      /* Could assert that colorbuffer has RedBits > 0 */
      break;
   case GL_DEPTH:
   case GL_DEPTH_COMPONENT:
      if (!att[BUFFER_DEPTH].Renderbuffer) {
         return GL_FALSE;
      }
      /*ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);*/
      break;
   case GL_STENCIL:
   case GL_STENCIL_INDEX:
      if (!att[BUFFER_STENCIL].Renderbuffer) {
         return GL_FALSE;
      }
      /*ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);*/
      break;
   case GL_DEPTH_STENCIL_EXT:
      if (!att[BUFFER_DEPTH].Renderbuffer ||
          !att[BUFFER_STENCIL].Renderbuffer) {
         return GL_FALSE;
      }
      /*
      ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);
      ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);
      */
      break;
   default:
      _mesa_problem(ctx,
                    "Unexpected format 0x%x in _mesa_dest_buffer_exists",
                    format);
      return GL_FALSE;
   }

   /* OK */
   return GL_TRUE;
}
/**
 * Check if the renderbuffer for a read operation (glReadPixels, glCopyPixels,
 * glCopyTex[Sub]Image, etc) exists.
 * \param format  a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA,
 *                GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL.
 * \return GL_TRUE if buffer exists, GL_FALSE otherwise
 */
GLboolean
_mesa_source_buffer_exists(struct gl_context *ctx, GLenum format)
{
   const struct gl_renderbuffer_attachment *att = ctx->ReadBuffer->Attachment;

   /* If we don't know the framebuffer status, update it now */
   if (ctx->ReadBuffer->_Status == 0) {
      _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
   }

   if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      return GL_FALSE;
   }

   switch (format) {
   case GL_COLOR:
   case GL_RED:
   case GL_GREEN:
   case GL_BLUE:
   case GL_ALPHA:
   case GL_LUMINANCE:
   case GL_LUMINANCE_ALPHA:
   case GL_INTENSITY:
   case GL_RG:
   case GL_RGB:
   case GL_BGR:
   case GL_RGBA:
   case GL_BGRA:
   case GL_ABGR_EXT:
   case GL_COLOR_INDEX:
   case GL_RED_INTEGER_EXT:
   case GL_GREEN_INTEGER_EXT:
   case GL_BLUE_INTEGER_EXT:
   case GL_ALPHA_INTEGER_EXT:
   case GL_RGB_INTEGER_EXT:
   case GL_RGBA_INTEGER_EXT:
   case GL_BGR_INTEGER_EXT:
   case GL_BGRA_INTEGER_EXT:
   case GL_LUMINANCE_INTEGER_EXT:
   case GL_LUMINANCE_ALPHA_INTEGER_EXT:
      if (ctx->ReadBuffer->_ColorReadBuffer == NULL) {
         return GL_FALSE;
      }
      ASSERT(_mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_RED_BITS) > 0 ||
             _mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_ALPHA_BITS) > 0 ||
             _mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_INDEX_BITS) > 0);
      break;
   case GL_DEPTH:
   case GL_DEPTH_COMPONENT:
      if (!att[BUFFER_DEPTH].Renderbuffer) {
         return GL_FALSE;
      }
      /*ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);*/
      break;
   case GL_STENCIL:
   case GL_STENCIL_INDEX:
      if (!att[BUFFER_STENCIL].Renderbuffer) {
         return GL_FALSE;
      }
      /*ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);*/
      break;
   case GL_DEPTH_STENCIL_EXT:
      if (!att[BUFFER_DEPTH].Renderbuffer ||
          !att[BUFFER_STENCIL].Renderbuffer) {
         return GL_FALSE;
      }
      /*
      ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);
      ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);
      */
      break;
   default:
      _mesa_problem(ctx,
                    "Unexpected format 0x%x in _mesa_source_buffer_exists",
                    format);
      return GL_FALSE;
   }

   /* OK */
   return GL_TRUE;
}