mesa: Allow GL_TEXTURE_CUBE_MAP target with compressed internal formats
[mesa.git] / src / mesa / main / pbo.c
index ce362b9e44443f5cf1d5d8340a72c8ec43b2f7ab..a0d61a6436bda63a0cd2cc26d7962facc09a212b 100644 (file)
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
  */
 
 
@@ -32,6 +33,7 @@
 
 #include "glheader.h"
 #include "bufferobj.h"
+#include "glformats.h"
 #include "image.h"
 #include "imports.h"
 #include "mtypes.h"
@@ -68,8 +70,8 @@ _mesa_validate_pbo_access(GLuint dimensions,
                           GLenum format, GLenum type, GLsizei clientMemSize,
                           const GLvoid *ptr)
 {
-   const GLvoid *start, *end, *offset;
-   const GLubyte *sizeAddr; /* buffer size, cast to a pointer */
+   /* unsigned, to detect overflow/wrap-around */
+   uintptr_t start, end, offset, size;
 
    /* If no PBO is bound, 'ptr' is a pointer to client memory containing
       'clientMemSize' bytes.
@@ -78,29 +80,45 @@ _mesa_validate_pbo_access(GLuint dimensions,
     */
    if (!_mesa_is_bufferobj(pack->BufferObj)) {
       offset = 0;
-      sizeAddr = ((const GLubyte *) 0) + clientMemSize;
+      size = clientMemSize;
    } else {
-      offset = ptr;
-      sizeAddr = ((const GLubyte *) 0) + pack->BufferObj->Size;
+      offset = (uintptr_t)ptr;
+      size = pack->BufferObj->Size;
+      /* The ARB_pixel_buffer_object spec says:
+       *    "INVALID_OPERATION is generated by ColorTable, ColorSubTable,
+       *    ConvolutionFilter2D, ConvolutionFilter1D, SeparableFilter2D,
+       *    TexImage1D, TexImage2D, TexImage3D, TexSubImage1D,
+       *    TexSubImage2D, TexSubImage3D, and DrawPixels if the current
+       *    PIXEL_UNPACK_BUFFER_BINDING_ARB value is non-zero and the data
+       *    parameter is not evenly divisible into the number of basic machine
+       *    units needed to store in memory a datum indicated by the type
+       *    parameter."
+       */
+      if (type != GL_BITMAP &&
+          (offset % _mesa_sizeof_packed_type(type)))
+         return GL_FALSE;
    }
 
-   if (sizeAddr == 0)
+   if (size == 0)
       /* no buffer! */
       return GL_FALSE;
 
    /* get the offset to the first pixel we'll read/write */
-   start = _mesa_image_address(dimensions, pack, offset, width, height,
-                               format, type, 0, 0, 0);
+   start = _mesa_image_offset(dimensions, pack, width, height,
+                              format, type, 0, 0, 0);
 
    /* get the offset to just past the last pixel we'll read/write */
-   end =  _mesa_image_address(dimensions, pack, offset, width, height,
-                              format, type, depth-1, height-1, width);
+   end =  _mesa_image_offset(dimensions, pack, width, height,
+                             format, type, depth-1, height-1, width);
 
-   if ((const GLubyte *) start > sizeAddr) {
+   start += offset;
+   end += offset;
+
+   if (start > size) {
       /* This will catch negative values / wrap-around */
       return GL_FALSE;
    }
-   if ((const GLubyte *) end > sizeAddr) {
+   if (end > size) {
       /* Image read/write goes beyond end of buffer */
       return GL_FALSE;
    }
@@ -128,9 +146,11 @@ _mesa_map_pbo_source(struct gl_context *ctx,
 
    if (_mesa_is_bufferobj(unpack->BufferObj)) {
       /* unpack from PBO */
-      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx,
-                                              GL_READ_ONLY_ARB,
-                                              unpack->BufferObj);
+      buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0,
+                                                  unpack->BufferObj->Size,
+                                                  GL_MAP_READ_BIT,
+                                                  unpack->BufferObj,
+                                                   MAP_INTERNAL);
       if (!buf)
          return NULL;
 
@@ -155,11 +175,12 @@ _mesa_map_pbo_source(struct gl_context *ctx,
  */
 const GLvoid *
 _mesa_map_validate_pbo_source(struct gl_context *ctx,
-                                 GLuint dimensions,
-                                 const struct gl_pixelstore_attrib *unpack,
-                                 GLsizei width, GLsizei height, GLsizei depth,
-                                 GLenum format, GLenum type, GLsizei clientMemSize,
-                                 const GLvoid *ptr, const char *where)
+                              GLuint dimensions,
+                              const struct gl_pixelstore_attrib *unpack,
+                              GLsizei width, GLsizei height, GLsizei depth,
+                              GLenum format, GLenum type,
+                              GLsizei clientMemSize,
+                              const GLvoid *ptr, const char *where)
 {
    ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3);
 
@@ -181,7 +202,7 @@ _mesa_map_validate_pbo_source(struct gl_context *ctx,
       return ptr;
    }
 
-   if (_mesa_bufferobj_mapped(unpack->BufferObj)) {
+   if (_mesa_check_disallowed_mapping(unpack->BufferObj)) {
       /* buffer is already mapped - that's an error */
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where);
       return NULL;
@@ -201,7 +222,7 @@ _mesa_unmap_pbo_source(struct gl_context *ctx,
 {
    ASSERT(unpack != &ctx->Pack); /* catch pack/unpack mismatch */
    if (_mesa_is_bufferobj(unpack->BufferObj)) {
-      ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj);
+      ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL);
    }
 }
 
@@ -223,9 +244,11 @@ _mesa_map_pbo_dest(struct gl_context *ctx,
 
    if (_mesa_is_bufferobj(pack->BufferObj)) {
       /* pack into PBO */
-      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx,
-                                              GL_WRITE_ONLY_ARB,
-                                              pack->BufferObj);
+      buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0,
+                                                  pack->BufferObj->Size,
+                                                  GL_MAP_WRITE_BIT,
+                                                  pack->BufferObj,
+                                                   MAP_INTERNAL);
       if (!buf)
          return NULL;
 
@@ -250,11 +273,11 @@ _mesa_map_pbo_dest(struct gl_context *ctx,
  */
 GLvoid *
 _mesa_map_validate_pbo_dest(struct gl_context *ctx,
-                               GLuint dimensions,
-                               const struct gl_pixelstore_attrib *unpack,
-                               GLsizei width, GLsizei height, GLsizei depth,
-                               GLenum format, GLenum type, GLsizei clientMemSize,
-                               GLvoid *ptr, const char *where)
+                            GLuint dimensions,
+                            const struct gl_pixelstore_attrib *unpack,
+                            GLsizei width, GLsizei height, GLsizei depth,
+                            GLenum format, GLenum type, GLsizei clientMemSize,
+                            GLvoid *ptr, const char *where)
 {
    ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3);
 
@@ -276,7 +299,7 @@ _mesa_map_validate_pbo_dest(struct gl_context *ctx,
       return ptr;
    }
 
-   if (_mesa_bufferobj_mapped(unpack->BufferObj)) {
+   if (_mesa_check_disallowed_mapping(unpack->BufferObj)) {
       /* buffer is already mapped - that's an error */
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where);
       return NULL;
@@ -296,7 +319,7 @@ _mesa_unmap_pbo_dest(struct gl_context *ctx,
 {
    ASSERT(pack != &ctx->Unpack); /* catch pack/unpack mismatch */
    if (_mesa_is_bufferobj(pack->BufferObj)) {
-      ctx->Driver.UnmapBuffer(ctx, pack->BufferObj);
+      ctx->Driver.UnmapBuffer(ctx, pack->BufferObj, MAP_INTERNAL);
    }
 }
 
@@ -321,15 +344,20 @@ _mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions,
       return pixels;
    }
    if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
-                                     format, type, INT_MAX, pixels)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access)");
+                                  format, type, INT_MAX, pixels)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(invalid PBO access)",
+                  funcName, dimensions);
       return NULL;
    }
 
-   buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_READ_ONLY_ARB,
-                                          unpack->BufferObj);
+   buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0,
+                                                unpack->BufferObj->Size,
+                                               GL_MAP_READ_BIT,
+                                               unpack->BufferObj,
+                                                MAP_INTERNAL);
    if (!buf) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped)");
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName,
+                  dimensions);
       return NULL;
    }
 
@@ -346,7 +374,8 @@ _mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions,
  */
 const GLvoid *
 _mesa_validate_pbo_compressed_teximage(struct gl_context *ctx,
-                                 GLsizei imageSize, const GLvoid *pixels,
+                                 GLuint dimensions, GLsizei imageSize,
+                                 const GLvoid *pixels,
                                  const struct gl_pixelstore_attrib *packing,
                                  const char *funcName)
 {
@@ -359,13 +388,19 @@ _mesa_validate_pbo_compressed_teximage(struct gl_context *ctx,
    if ((const GLubyte *) pixels + imageSize >
        ((const GLubyte *) 0) + packing->BufferObj->Size) {
       /* out of bounds read! */
-      _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access)");
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(invalid PBO access)",
+                  funcName, dimensions);
       return NULL;
    }
 
-   buf = (GLubyte*) ctx->Driver.MapBuffer(ctx, GL_READ_ONLY_ARB, packing->BufferObj);
+   buf = (GLubyte*) ctx->Driver.MapBufferRange(ctx, 0,
+                                              packing->BufferObj->Size,
+                                              GL_MAP_READ_BIT,
+                                              packing->BufferObj,
+                                               MAP_INTERNAL);
    if (!buf) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName,
+                  dimensions);
       return NULL;
    }
 
@@ -382,8 +417,6 @@ _mesa_unmap_teximage_pbo(struct gl_context *ctx,
                          const struct gl_pixelstore_attrib *unpack)
 {
    if (_mesa_is_bufferobj(unpack->BufferObj)) {
-      ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj);
+      ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL);
    }
 }
-
-