mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 09:28:07 +02:00
merge from trunk (additional renderbuffer error checks, debug code)
This commit is contained in:
parent
2a8bd4e329
commit
eb75ec2349
5 changed files with 189 additions and 53 deletions
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue