/*
* Mesa 3-D graphics library
- * Version: 6.2
+ * Version: 6.3
*
* Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
*
/**
- * Get the address of a pixel in an image (actually a volume).
+ * Return the address of a specific pixel in an image (1D, 2D or 3D).
*
* Pixel unpacking/packing parameters are observed according to \p packing.
*
- * \param image start of image data.
- * \param width image width.
- * \param height image height.
- * \param format pixel format.
- * \param type pixel data type.
- * \param packing the pixelstore attributes
- * \param img which image in the volume (0 for 1D or 2D images)
- * \param row of pixel in the image
- * \param column of pixel in the image
+ * \param dimensions either 1, 2 or 3 to indicate dimensionality of image
+ * \param image starting address of image data
+ * \param width the image width
+ * \param height theimage height
+ * \param format the pixel format
+ * \param type the pixel data type
+ * \param packing the pixelstore attributes
+ * \param img which image in the volume (0 for 1D or 2D images)
+ * \param row row of pixel in the image (0 for 1D images)
+ * \param column column of pixel in the image
*
* \return address of pixel on success, or NULL on error.
*
- * According to the \p packing information calculates the number of pixel/bytes
- * per row/image and refers it.
- *
* \sa gl_pixelstore_attrib.
*/
GLvoid *
-_mesa_image_address( const struct gl_pixelstore_attrib *packing,
- const GLvoid *image, GLsizei width,
- GLsizei height, GLenum format, GLenum type,
+_mesa_image_address( GLuint dimensions,
+ const struct gl_pixelstore_attrib *packing,
+ const GLvoid *image,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
GLint img, GLint row, GLint column )
{
GLint alignment; /* 1, 2 or 4 */
GLint skipimages; /* for 3-D volume images */
GLubyte *pixel_addr;
+ ASSERT(dimensions >= 1 && dimensions <= 3);
+
alignment = packing->Alignment;
if (packing->RowLength > 0) {
pixels_per_row = packing->RowLength;
else {
rows_per_image = height;
}
- skiprows = packing->SkipRows;
+
skippixels = packing->SkipPixels;
- skipimages = packing->SkipImages;
+ /* Note: SKIP_ROWS _is_ used for 1D images */
+ skiprows = packing->SkipRows;
+ /* Note: SKIP_IMAGES is only used for 3D images */
+ skipimages = (dimensions == 3) ? packing->SkipImages : 0;
if (type == GL_BITMAP) {
/* BITMAP data */
}
+GLvoid *
+_mesa_image_address1d( const struct gl_pixelstore_attrib *packing,
+ const GLvoid *image,
+ GLsizei width,
+ GLenum format, GLenum type,
+ GLint column )
+{
+ return _mesa_image_address(1, packing, image, width, 1,
+ format, type, 0, 0, column);
+}
+
+
+GLvoid *
+_mesa_image_address2d( const struct gl_pixelstore_attrib *packing,
+ const GLvoid *image,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ GLint row, GLint column )
+{
+ return _mesa_image_address(2, packing, image, width, height,
+ format, type, 0, row, column);
+}
+
+
+GLvoid *
+_mesa_image_address3d( const struct gl_pixelstore_attrib *packing,
+ const GLvoid *image,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ GLint img, GLint row, GLint column )
+{
+ return _mesa_image_address(3, packing, image, width, height,
+ format, type, img, row, column);
+}
+
+
+
/**
* Compute the stride between image rows.
*
dst = buffer;
for (row = 0; row < height; row++) {
const GLubyte *src = (const GLubyte *)
- _mesa_image_address(packing, pixels, width, height,
- GL_COLOR_INDEX, GL_BITMAP, 0, row, 0);
+ _mesa_image_address2d(packing, pixels, width, height,
+ GL_COLOR_INDEX, GL_BITMAP, row, 0);
if (!src) {
FREE(buffer);
return NULL;
width_in_bytes = CEILING( width, 8 );
src = source;
for (row = 0; row < height; row++) {
- GLubyte *dst = (GLubyte *) _mesa_image_address( packing, dest,
- width, height, GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 );
+ GLubyte *dst = (GLubyte *) _mesa_image_address2d(packing, dest,
+ width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
if (!dst)
return;
* need a copy of the data in a standard format.
*/
void *
-_mesa_unpack_image( GLsizei width, GLsizei height, GLsizei depth,
+_mesa_unpack_image( GLuint dimensions,
+ GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type, const GLvoid *pixels,
const struct gl_pixelstore_attrib *unpack )
{
dst = destBuffer;
for (img = 0; img < depth; img++) {
for (row = 0; row < height; row++) {
- const GLvoid *src = _mesa_image_address(unpack, pixels,
+ const GLvoid *src = _mesa_image_address(dimensions, unpack, pixels,
width, height, format, type, img, row, 0);
MEMCPY(dst, src, bytesPerRow);
/* byte flipping/swapping */
}
#endif
+
+
+/**
+ * Perform clipping for glDrawPixels. The image's window position
+ * and size, and the unpack skipPixels and skipRows are adjusted so
+ * that the image region is entirely within the window and scissor bounds.
+ * NOTE: this will only work when glPixelZoom is (1, 1).
+ *
+ * \return GL_TRUE if image is ready for drawing or
+ * GL_FALSE if image was completely clipped away (draw nothing)
+ */
+GLboolean
+_mesa_clip_drawpixels(const GLcontext *ctx,
+ GLint *destX, GLint *destY,
+ GLsizei *width, GLsizei *height,
+ GLint *skipPixels, GLint *skipRows)
+{
+ const GLframebuffer *buffer = ctx->DrawBuffer;
+
+ ASSERT(ctx->Pixel.ZoomX == 1.0F && ctx->Pixel.ZoomY == 1.0F);
+
+ /* left clipping */
+ if (*destX < buffer->_Xmin) {
+ *skipPixels += (buffer->_Xmin - *destX);
+ *width -= (buffer->_Xmin - *destX);
+ *destX = buffer->_Xmin;
+ }
+ /* right clipping */
+ if (*destX + *width > buffer->_Xmax)
+ *width -= (*destX + *width - buffer->_Xmax);
+
+ if (*width <= 0)
+ return GL_FALSE;
+
+ /* bottom clipping */
+ if (*destY < buffer->_Ymin) {
+ *skipRows += (buffer->_Ymin - *destY);
+ *height -= (buffer->_Ymin - *destY);
+ *destY = buffer->_Ymin;
+ }
+ /* top clipping */
+ if (*destY + *height > buffer->_Ymax)
+ *height -= (*destY + *height - buffer->_Ymax);
+
+ if (*height <= 0)
+ return GL_TRUE;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Perform clipping for glReadPixels. The image's window position
+ * and size, and the pack skipPixels and skipRows are adjusted so
+ * that the image region is entirely within the window bounds.
+ * Note: this is different from _mesa_clip_drawpixels() in that the
+ * scissor box is ignored, and we use the bounds of the current "read"
+ * surface;
+ *
+ * \return GL_TRUE if image is ready for drawing or
+ * GL_FALSE if image was completely clipped away (draw nothing)
+ */
+GLboolean
+_mesa_clip_readpixels(const GLcontext *ctx,
+ GLint *srcX, GLint *srcY,
+ GLsizei *width, GLsizei *height,
+ GLint *skipPixels, GLint *skipRows)
+{
+ const GLframebuffer *buffer = ctx->ReadBuffer;
+
+ /* left clipping */
+ if (*srcX < 0) {
+ *skipPixels += (0 - *srcX);
+ *width -= (0 - *srcX);
+ *srcX = 0;
+ }
+ /* right clipping */
+ if (*srcX + *width > (GLsizei) buffer->Width)
+ *width -= (*srcX + *width - buffer->Width);
+
+ if (*width <= 0)
+ return GL_FALSE;
+
+ /* bottom clipping */
+ if (*srcY < 0) {
+ *skipRows += (0 - *srcY);
+ *height -= (0 - *srcY);
+ *srcY = 0;
+ }
+ /* top clipping */
+ if (*srcY + *height > (GLsizei) buffer->Height)
+ *height -= (*srcY + *height - buffer->Height);
+
+ if (*height <= 0)
+ return GL_TRUE;
+
+ return GL_TRUE;
+}
+