merge from trunk (additional renderbuffer error checks, debug code)

This commit is contained in:
Brian Paul 2006-03-20 15:39:30 +00:00
parent 2a8bd4e329
commit eb75ec2349
5 changed files with 189 additions and 53 deletions

View file

@ -547,12 +547,12 @@ _mesa_ReadBuffer(GLenum buffer)
/* general case / window-system framebuffer */
srcBuffer = read_buffer_enum_to_index(buffer);
if (srcBuffer == -1) {
_mesa_error(ctx, GL_INVALID_ENUM, "glReadBuffer(buffer)");
_mesa_error(ctx, GL_INVALID_ENUM, "glReadBuffer(buffer=0x%x)", buffer);
return;
}
supportedMask = supported_buffer_bitmask(ctx, bufferID);
if (((1 << srcBuffer) & supportedMask) == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glReadBuffer(buffer)");
_mesa_error(ctx, GL_INVALID_OPERATION, "glReadBuffer(buffer=0x%x)", buffer);
return;
}
}

View file

@ -27,6 +27,7 @@
#include "context.h"
#include "drawpix.h"
#include "feedback.h"
#include "framebuffer.h"
#include "image.h"
#include "state.h"
@ -43,7 +44,6 @@ error_check_format_type(GLcontext *ctx, GLenum format, GLenum type,
GLboolean drawing)
{
const char *readDraw = drawing ? "Draw" : "Read";
struct gl_framebuffer *fb = drawing ? ctx->DrawBuffer : ctx->ReadBuffer;
if (ctx->Extensions.EXT_packed_depth_stencil
&& type == GL_UNSIGNED_INT_24_8_EXT
@ -78,23 +78,35 @@ error_check_format_type(GLcontext *ctx, GLenum format, GLenum type,
"glDrawPixels(drawing RGB pixels into color index buffer)");
return GL_TRUE;
}
if (!drawing && !_mesa_dest_buffer_exists(ctx, GL_COLOR)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glReadPixels(no color buffer)");
return GL_TRUE;
}
break;
case GL_COLOR_INDEX:
if (!drawing && ctx->Visual.rgbMode) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glReadPixels(reading color index format from RGB buffer");
"glReadPixels(reading color index format from RGB buffer)");
return GL_TRUE;
}
if (!drawing && !_mesa_dest_buffer_exists(ctx, GL_COLOR)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glReadPixels(no color buffer)");
return GL_TRUE;
}
break;
case GL_STENCIL_INDEX:
if (fb->Visual.stencilBits == 0) {
if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
(!drawing && !_mesa_source_buffer_exists(ctx, format))) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"gl%sPixels(no stencil buffer)", readDraw);
return GL_TRUE;
}
break;
case GL_DEPTH_COMPONENT:
if (fb->Visual.depthBits == 0) {
if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
(!drawing && !_mesa_source_buffer_exists(ctx, format))) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"gl%sPixels(no depth buffer)", readDraw);
return GL_TRUE;
@ -106,13 +118,12 @@ error_check_format_type(GLcontext *ctx, GLenum format, GLenum type,
_mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw);
return GL_TRUE;
}
if (fb->Visual.depthBits == 0 || fb->Visual.stencilBits == 0) {
if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
(!drawing && !_mesa_source_buffer_exists(ctx, format))) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"gl%sPixels(no depth or stencil buffer)", readDraw);
return GL_TRUE;
}
ASSERT(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
ASSERT(fb->Attachment[BUFFER_STENCIL].Renderbuffer);
break;
default:
/* this should have been caught in _mesa_is_legal_format_type() */
@ -214,45 +225,6 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
return;
}
switch (type) {
case GL_COLOR:
/* OK */
break;
case GL_DEPTH:
if (ctx->DrawBuffer->Visual.depthBits == 0 ||
ctx->ReadBuffer->Visual.depthBits == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glCopyPixels(no depth buffer)");
return;
}
break;
case GL_STENCIL:
if (ctx->DrawBuffer->Visual.stencilBits == 0 ||
ctx->ReadBuffer->Visual.stencilBits == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glCopyPixels(no stencil buffer)");
return;
}
break;
case GL_DEPTH_STENCIL_EXT:
if (!ctx->Extensions.EXT_packed_depth_stencil) {
_mesa_error(ctx, GL_INVALID_ENUM, "glCopyPixels");
return;
}
if (ctx->DrawBuffer->Visual.depthBits == 0 ||
ctx->ReadBuffer->Visual.depthBits == 0 ||
ctx->DrawBuffer->Visual.stencilBits == 0 ||
ctx->ReadBuffer->Visual.stencilBits == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glCopyPixels(no depth or stencil buffer)");
return;
}
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glCopyPixels");
return;
}
if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
_mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
@ -260,6 +232,13 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
return;
}
if (!_mesa_source_buffer_exists(ctx, type) ||
!_mesa_dest_buffer_exists(ctx, type)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glCopyPixels(missing source or dest buffer)");
return;
}
if (!ctx->Current.RasterPosValid) {
return;
}
@ -295,7 +274,6 @@ _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type, GLvoid *pixels )
{
GET_CURRENT_CONTEXT(ctx);
const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
if (width < 0 || height < 0) {
@ -318,7 +296,7 @@ _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
return;
}
if (!rb) {
if (!_mesa_source_buffer_exists(ctx, format)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
return;
}

View file

@ -317,18 +317,25 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format,
}
}
else if (att->Type == GL_RENDERBUFFER_EXT) {
if (att->Renderbuffer->Width < 1 || att->Renderbuffer->Height < 1) {
ASSERT(att->Renderbuffer);
if (!att->Renderbuffer->InternalFormat ||
att->Renderbuffer->Width < 1 ||
att->Renderbuffer->Height < 1) {
att->Complete = GL_FALSE;
return;
}
if (format == GL_COLOR) {
if (att->Renderbuffer->_BaseFormat != GL_RGB &&
att->Renderbuffer->_BaseFormat != GL_RGBA) {
ASSERT(att->Renderbuffer->RedBits);
ASSERT(att->Renderbuffer->GreenBits);
ASSERT(att->Renderbuffer->BlueBits);
att->Complete = GL_FALSE;
return;
}
}
else if (format == GL_DEPTH) {
ASSERT(att->Renderbuffer->DepthBits);
if (att->Renderbuffer->_BaseFormat == GL_DEPTH_COMPONENT) {
/* OK */
}
@ -343,6 +350,7 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format,
}
else {
assert(format == GL_STENCIL);
ASSERT(att->Renderbuffer->StencilBits);
if (att->Renderbuffer->_BaseFormat == GL_STENCIL_INDEX) {
/* OK */
}
@ -364,6 +372,18 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format,
}
/**
* Helpful for debugging
*/
static void
fbo_incomplete(const char *msg, int index)
{
/*
_mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index);
*/
}
/**
* Test if the given framebuffer object is complete and update its
* Status field with the results.
@ -394,6 +414,7 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
test_attachment_completeness(ctx, GL_DEPTH, att);
if (!att->Complete) {
fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
fbo_incomplete("depth attachment incomplete", -1);
return;
}
}
@ -402,6 +423,7 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
test_attachment_completeness(ctx, GL_STENCIL, att);
if (!att->Complete) {
fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
fbo_incomplete("stencil attachment incomplete", -1);
return;
}
}
@ -410,6 +432,7 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
test_attachment_completeness(ctx, GL_COLOR, att);
if (!att->Complete) {
fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
fbo_incomplete("color attachment incomplete", i);
return;
}
}
@ -424,6 +447,7 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
if (f != GL_RGB && f != GL_RGBA && f != GL_DEPTH_COMPONENT) {
/* XXX need GL_DEPTH_STENCIL_EXT test? */
fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
fbo_incomplete("texture attachment incomplete", -1);
return;
}
}
@ -449,10 +473,12 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
/* check that width, height, format are same */
if (w != width || h != height) {
fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
fbo_incomplete("width or height mismatch", -1);
return;
}
if (intFormat != GL_NONE && f != intFormat) {
fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
fbo_incomplete("format mismatch", -1);
return;
}
}
@ -466,6 +492,7 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
assert(att);
if (att->Type == GL_NONE) {
fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
fbo_incomplete("missing drawbuffer", i);
return;
}
}
@ -478,6 +505,7 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
assert(att);
if (att->Type == GL_NONE) {
fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
fbo_incomplete("missing readbuffer", -1);
return;
}
}
@ -494,6 +522,7 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
struct gl_renderbuffer *rb_j = fb->Attachment[j].Renderbuffer;
if (rb_i == rb_j && rb_i->_BaseFormat != GL_DEPTH_STENCIL_EXT) {
fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT;
fbo_incomplete("multiply bound renderbuffer", -1);
return;
}
}
@ -503,6 +532,7 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
if (numImages == 0) {
fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
fbo_incomplete("no attachments", -1);
return;
}

View file

@ -2,7 +2,7 @@
* Mesa 3-D graphics library
* Version: 6.5
*
* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -550,3 +550,124 @@ _mesa_update_framebuffer(GLcontext *ctx)
compute_depth_max(fb);
}
/**
* 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(GLcontext *ctx, GLenum format)
{
const struct gl_renderbuffer_attachment *att
= ctx->ReadBuffer->Attachment;
if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
return GL_FALSE;
}
switch (format) {
case GL_COLOR:
case GL_ALPHA:
case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
case GL_INTENSITY:
case GL_RGB:
case GL_RGBA:
case GL_COLOR_INDEX:
if (ctx->ReadBuffer->_ColorReadBuffer == NULL) {
return GL_FALSE;
}
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");
return GL_FALSE;
}
/* OK */
return GL_TRUE;
}
/**
* As above, but for drawing operations.
* XXX code do some code merging w/ above function.
*/
GLboolean
_mesa_dest_buffer_exists(GLcontext *ctx, GLenum format)
{
const struct gl_renderbuffer_attachment *att
= ctx->ReadBuffer->Attachment;
if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
return GL_FALSE;
}
switch (format) {
case GL_COLOR:
case GL_ALPHA:
case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
case GL_INTENSITY:
case GL_RGB:
case GL_RGBA:
case GL_COLOR_INDEX:
/* nothing special */
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");
return GL_FALSE;
}
/* OK */
return GL_TRUE;
}

View file

@ -2,7 +2,7 @@
* Mesa 3-D graphics library
* Version: 6.5
*
* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -55,4 +55,11 @@ _mesa_update_framebuffer_visual(struct gl_framebuffer *fb);
extern void
_mesa_update_framebuffer(GLcontext *ctx);
extern GLboolean
_mesa_source_buffer_exists(GLcontext *ctx, GLenum format);
extern GLboolean
_mesa_dest_buffer_exists(GLcontext *ctx, GLenum format);
#endif /* FRAMEBUFFER_H */