#include "glheader.h"
#include "imports.h"
-#include "colormac.h"
#include "context.h"
#include "drawpix.h"
#include "feedback.h"
-#include "macros.h"
+#include "image.h"
#include "state.h"
-#include "mtypes.h"
+
+
+/**
+ * Do error checking of the format/type parameters to glReadPixels and
+ * glDrawPixels.
+ * \param drawing if GL_TRUE do checking for DrawPixels, else do checking
+ * for ReadPixels.
+ * \return GL_TRUE if error detected, GL_FALSE if no errors
+ */
+static GLboolean
+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
+ && format != GL_DEPTH_STENCIL_EXT) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "gl%sPixels(format is not GL_DEPTH_STENCIL_EXT)", readDraw);
+ return GL_TRUE;
+ }
+
+ /* basic combinations test */
+ if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "gl%sPixels(format or type)", readDraw);
+ return GL_TRUE;
+ }
+
+ /* additional checks */
+ switch (format) {
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGB:
+ case GL_BGR:
+ case GL_RGBA:
+ case GL_BGRA:
+ case GL_ABGR_EXT:
+ if (drawing && !ctx->Visual.rgbMode) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDrawPixels(drawing RGB pixels into color index 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");
+ return GL_TRUE;
+ }
+ break;
+ case GL_STENCIL_INDEX:
+ if (fb->Visual.stencilBits == 0) {
+ _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) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "gl%sPixels(no depth buffer)", readDraw);
+ return GL_TRUE;
+ }
+ break;
+ case GL_DEPTH_STENCIL_EXT:
+ if (!ctx->Extensions.EXT_packed_depth_stencil ||
+ type != GL_UNSIGNED_INT_24_8_EXT) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw);
+ return GL_TRUE;
+ }
+ if (fb->Visual.depthBits == 0 || fb->Visual.stencilBits == 0) {
+ _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() */
+ _mesa_problem(ctx, "unexpected format in _mesa_%sPixels", readDraw);
+ return GL_TRUE;
+ }
+
+ /* no errors */
+ return GL_FALSE;
+}
+
#if _HAVE_FULL_GL
return;
}
- if (!ctx->Current.RasterPosValid) {
+ if (ctx->NewState) {
+ _mesa_update_state(ctx);
+ }
+
+ if (error_check_format_type(ctx, format, type, GL_TRUE)) {
+ /* found an error */
return;
}
- if (ctx->NewState) {
- _mesa_update_state(ctx);
+ if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glDrawPixels(incomplete framebuffer)" );
+ return;
+ }
+
+ if (!ctx->Current.RasterPosValid) {
+ return;
}
if (ctx->RenderMode == GL_RENDER) {
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ if (ctx->NewState) {
+ _mesa_update_state(ctx);
+ }
+
if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glCopyPixels (invalid fragment program)");
}
if (width < 0 || height < 0) {
- _mesa_error( ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)" );
+ _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)");
return;
}
- if (ctx->NewState) {
- _mesa_update_state(ctx);
+ 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,
+ "glCopyPixels(incomplete framebuffer)" );
+ return;
}
if (!ctx->Current.RasterPosValid) {
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) {
if (ctx->NewState)
_mesa_update_state(ctx);
+ if (error_check_format_type(ctx, format, type, GL_FALSE)) {
+ /* found an error */
+ return;
+ }
+
+ if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glReadPixels(incomplete framebuffer)" );
+ return;
+ }
+
+ if (!rb) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
+ return;
+ }
+
ctx->Driver.ReadPixels(ctx, x, y, width, height,
format, type, &ctx->Pack, pixels);
}
_mesa_update_state(ctx);
}
+ if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glBitmap(incomplete framebuffer)");
+ return;
+ }
+
if (ctx->RenderMode == GL_RENDER) {
/* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */
GLint x = IFLOOR(ctx->Current.RasterPos[0] - xorig);
_mesa_update_state(ctx);
}
+ if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glDrawDepthPixelsMESA(incomplete framebuffer)");
+ return;
+ }
+
if (ctx->RenderMode == GL_RENDER) {
/* Round, to satisfy conformance tests (matches SGI's OpenGL) */
GLint x = IROUND(ctx->Current.RasterPos[0]);