- GLvoid *start, *end;
- const GLubyte *sizeAddr; /* buffer size, cast to a pointer */
-
- if (!_mesa_is_bufferobj(pack->BufferObj))
- return GL_TRUE; /* no PBO, OK */
+ /* 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.
+ If a PBO is bound, 'ptr' is an offset into the bound PBO.
+ In that case 'clientMemSize' is ignored: we just use the PBO's size.
+ */
+ if (!_mesa_is_bufferobj(pack->BufferObj)) {
+ offset = 0;
+ size = clientMemSize;
+ } else {
+ 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;
+ }