Remove unused texunit parameter to ctx->Driver.GenerateMipmap()
[mesa.git] / src / mesa / main / drawpix.c
index a95ee02097c446623bf3198b0587890e25d83444..fde933843095522911387a0804b379076b836cd7 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5
+ * Version:  7.1
  *
- * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2008  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"),
 
 #include "glheader.h"
 #include "imports.h"
+#include "bufferobj.h"
 #include "context.h"
 #include "drawpix.h"
 #include "feedback.h"
+#include "framebuffer.h"
 #include "image.h"
 #include "state.h"
 
@@ -43,7 +45,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 +79,34 @@ 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_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() */
@@ -138,14 +149,18 @@ _mesa_DrawPixels( GLsizei width, GLsizei height,
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
-   if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glDrawPixels (invalid fragment program)");
+   if (width < 0 || height < 0) {
+      _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" );
       return;
    }
 
-   if (width < 0 || height < 0) {
-      _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" );
+   if (ctx->NewState) {
+      _mesa_update_state(ctx);
+   }
+
+   if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glDrawPixels (invalid fragment program)");
       return;
    }
 
@@ -154,10 +169,6 @@ _mesa_DrawPixels( GLsizei width, GLsizei height,
       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)" );
@@ -172,6 +183,23 @@ _mesa_DrawPixels( GLsizei width, GLsizei height,
       /* Round, to satisfy conformance tests (matches SGI's OpenGL) */
       GLint x = IROUND(ctx->Current.RasterPos[0]);
       GLint y = IROUND(ctx->Current.RasterPos[1]);
+
+      if (ctx->Unpack.BufferObj->Name) {
+         /* unpack from PBO */
+         if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
+                                        format, type, pixels)) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glDrawPixels(invalid PBO access)");
+            return;
+         }
+         if (ctx->Unpack.BufferObj->Pointer) {
+            /* buffer is mapped - that's an error */
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glDrawPixels(PBO is mapped)");
+            return;
+         }
+      }
+
       ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type,
                             &ctx->Unpack, pixels);
    }
@@ -199,6 +227,10 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
    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)");
@@ -210,49 +242,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->NewState) {
-      _mesa_update_state(ctx);
-   }
-
    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 +249,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 +291,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) {
@@ -304,25 +299,40 @@ _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
       return;
    }
 
+   if (ctx->NewState)
+      _mesa_update_state(ctx);
+
    if (error_check_format_type(ctx, format, type, GL_FALSE)) {
       /* found an error */
       return;
    }
 
-   if (ctx->NewState)
-      _mesa_update_state(ctx);
-
    if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
       _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
                   "glReadPixels(incomplete framebuffer)" );
       return;
    }
 
-   if (!rb) {
+   if (!_mesa_source_buffer_exists(ctx, format)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
       return;
    }
 
+   if (ctx->Pack.BufferObj->Name) {
+      if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
+                                     format, type, pixels)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glReadPixels(invalid PBO access)");
+         return;
+      }
+
+      if (ctx->Pack.BufferObj->Pointer) {
+         /* buffer is mapped - that's an error */
+         _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
+         return;
+      }
+   }
+
    ctx->Driver.ReadPixels(ctx, x, y, width, height,
                          format, type, &ctx->Pack, pixels);
 }
@@ -337,12 +347,6 @@ _mesa_Bitmap( GLsizei width, GLsizei height,
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
-   if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glBitmap (invalid fragment program)");
-      return;
-   }
-
    if (width < 0 || height < 0) {
       _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" );
       return;
@@ -356,6 +360,12 @@ _mesa_Bitmap( GLsizei width, GLsizei height,
       _mesa_update_state(ctx);
    }
 
+   if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glBitmap (invalid fragment program)");
+      return;
+   }
+
    if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
       _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
                   "glBitmap(incomplete framebuffer)");
@@ -364,8 +374,26 @@ _mesa_Bitmap( GLsizei width, GLsizei height,
 
    if (ctx->RenderMode == GL_RENDER) {
       /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */
-      GLint x = IFLOOR(ctx->Current.RasterPos[0] - xorig);
-      GLint y = IFLOOR(ctx->Current.RasterPos[1] - yorig);
+      const GLfloat epsilon = 0.0001;
+      GLint x = IFLOOR(ctx->Current.RasterPos[0] + epsilon - xorig);
+      GLint y = IFLOOR(ctx->Current.RasterPos[1] + epsilon - yorig);
+
+      if (ctx->Unpack.BufferObj->Name) {
+         /* unpack from PBO */
+         if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
+                                        GL_COLOR_INDEX, GL_BITMAP,
+                                        (GLvoid *) bitmap)) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glBitmap(invalid PBO access)");
+            return;
+         }
+         if (ctx->Unpack.BufferObj->Pointer) {
+            /* buffer is mapped - that's an error */
+            _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)");
+            return;
+         }
+      }
+
       ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap );
    }
 #if _HAVE_FULL_GL