/* * $Id$ * * $Date$ * $Revision$ * * (C) 1999 by Hyperion * All rights reserved * * This file is part of the MiniGL library project * See the file Licence.txt for more details * */ #include "sysinc.h" #include #include #include #include #include #include #define min(x,y) (x) < (y) ? (x) : (y) #define max(x,y) (x) > (y) ? (x) : (y) static char rcsid[] UNUSED = "$Id$"; _glTransferFn MGLSelectTransferARGB(GLenum format, struct GLpixel_state *pixelState); extern GLboolean MGLTransferImage(GLcontext context, GLsizei width, GLsizei height, GLimage_info *src, GLpixel_store *srcPs, GLimage_info *dst, GLpixel_store *dstPs, struct GLpixel_state *pixelState); extern GLboolean MGLPackImage(GLcontext context, GLsizei width, GLsizei height, GLimage_info *src, GLimage_info *dst, GLboolean doPixelState); extern _glPackFn MGLSelectPackerARGB(GLenum format, GLenum type, GLuint *pixelStride); BOOL EnsureBitmapBackingStore(GLcontext context, uint32 dataSize); void cgl_GLReadPixels(struct GLContextIFace *Self, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) { int i; GLcontext context = GET_INSTANCE(Self); /* Note: ReadPixels is not compiled into display lists */ GLFlagError(context, pixels == NULL, GL_INVALID_VALUE); GLFlagError(context, width < 0, GL_INVALID_VALUE); GLFlagError(context, height < 0, GL_INVALID_VALUE); GLFlagError(context, context->readBuffer->bitMap == NULL, GL_INVALID_OPERATION); // if (!EnsureBitmapBackingStore(context, width * sizeof(uint32))) // return; uint32 *buffer = alloca(width * sizeof(uint32)); //(uint32 *)context->CurrentBitmapBackingStore; /* How it works: * ReadPixels reads from the read buffer line by line. Each line is packed * into client space by using the packer functionality. */ GLimage_info dst_image; _glPackFn pack; _glTransferFn transfer; GLuint dst_pixel_stride; pack = MGLSelectPackerARGB(format, type, &dst_pixel_stride); GLFlagError(context, pack == NULL, GL_INVALID_ENUM); uint32 lineWidth = (max(context->pixel_store.pack.row_length, width)) * dst_pixel_stride; /* Setup destination image for the packer */ dst_image.data = (GLubyte *)pixels; dst_image.stride = lineWidth; dst_image.format = format; dst_image.type = type; dst_image.pixel_stride = dst_pixel_stride; dst_image.current = dst_image.data; /* Select a transfer function */ transfer = MGLSelectTransferARGB(format, &context->pixel); /* Walk through the image */ for (i = 0; i < height; i++) { int32 succ = IGraphics->BltBitMapTags( BLITA_Source, context->readBuffer->bitMap, BLITA_SrcType, BLITT_BITMAP, BLITA_SrcX, x, BLITA_SrcY, context->readBuffer->height - 1 - (y + i + 1), /* Grows upwards */ BLITA_Width, width, BLITA_Height, 1, BLITA_Dest, buffer, BLITA_DestType, BLITT_ARGB32, BLITA_DestX, 0, BLITA_DestY, 0, BLITA_DestBytesPerRow, width*sizeof(uint32), BLITA_Minterm, 0xc0, TAG_DONE); if (succ >= 0) { context->CurrentError = GL_INVALID_OPERATION; return; } if (transfer) transfer(context, width, buffer, &context->pixel); pack(context, width, buffer, &dst_image, &context->pixel_store.pack); dst_image.current += lineWidth; } }