/* * $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 "displaylists.h" #include "sysinc.h" #include #include #include #include #include #include "util.h" extern _glUnpackFn MGLSelectUnpacker(GLenum format, GLenum type, GLuint *pixelStride); extern _glPackFn MGLSelectPacker(GLenum format, GLenum type, GLuint *pixelStride); GLboolean isPixelStateNeutral(GLcontext context); char *format_to_string(GLenum format) { switch (format) { case GL_COLOR_INDEX: return "GL_COLOR_INDEX"; case GL_STENCIL_INDEX: return "GL_STENCIL_INDEX"; case GL_DEPTH_COMPONENT: return "GL_DEPTH_COMPONENT"; case GL_RED: return "GL_RED"; case GL_GREEN: return "GL_GREEN"; case GL_BLUE: return "GL_BLUE"; case GL_ALPHA: return "GL_ALPHA"; case GL_RGB: return "GL_RGB"; case GL_RGBA: return "GL_RGBA"; case GL_BGR: return "GL_BGR"; case GL_BGRA: return "GL_BGRA"; case GL_LUMINANCE: return "GL_LUMINANCE"; case GL_LUMINANCE_ALPHA: return "GL_LUMINANCE_ALPHA"; case MGL_ARGB4: return "MGL_ARGB4"; case MGL_A1_RGB5: return "MGL_A1_RGB5"; } return "Unknown"; } char *type_to_string(GLenum type) { switch (type) { case GL_UNSIGNED_BYTE: return "GL_UNSIGNED_BYTE"; case GL_BITMAP: return "GL_BITMAP"; case GL_BYTE: return "GL_BYTE"; case GL_UNSIGNED_SHORT: return "GL_UNSIGNED_SHORT"; case GL_SHORT: return "GL_SHORT"; case GL_UNSIGNED_INT: return "GL_UNSIGNED_INT"; case GL_INT: return "GL_INT"; case GL_FLOAT: return "GL_FLOAT"; case GL_UNSIGNED_BYTE_3_3_2: return "GL_UNSIGNED_BYTE_3_3_2"; case GL_UNSIGNED_BYTE_2_3_3_REV: return "GL_UNSIGNED_BYTE_2_3_3_REV"; case GL_UNSIGNED_SHORT_5_6_5: return "GL_UNSIGNED_SHORT_5_6_5"; case GL_UNSIGNED_SHORT_5_6_5_REV: return "GL_UNSIGNED_SHORT_5_6_5_REV"; case GL_UNSIGNED_SHORT_4_4_4_4: return "GL_UNSIGNED_SHORT_4_4_4_4"; case GL_UNSIGNED_SHORT_5_5_5_1: return "GL_UNSIGNED_SHORT_5_5_5_1"; case GL_UNSIGNED_SHORT_1_5_5_5_REV: return "GL_UNSIGNED_SHORT_1_5_5_5_REV"; case GL_UNSIGNED_INT_8_8_8_8: return "GL_UNSIGNED_INT_8_8_8_8"; case GL_UNSIGNED_INT_8_8_8_8_REV: return "GL_UNSIGNED_INT_8_8_8_8_REV"; case GL_UNSIGNED_INT_10_10_10_2: return "GL_UNSIGNED_INT_10_10_10_2"; case GL_UNSIGNED_INT_2_10_10_10_REV: return "GL_UNSIGNED_INT_2_10_10_10_REV"; case MGL_UNSIGNED_SHORT_1_5_5_5: return "MGL_UNSIGNED_SHORT_1_5_5_5"; default: break; } return "Unknown"; } void cgl_GLPixelStorei(struct GLContextIFace *Self, GLenum pname, GLint param) { GLcontext context = GET_INSTANCE(Self); switch(pname) { case GL_UNPACK_SWAP_BYTES: context->pixel_store.unpack.swap_bytes = param; break; case GL_UNPACK_LSB_FIRST: context->pixel_store.unpack.lsb_first = param; break; case GL_UNPACK_ROW_LENGTH: context->pixel_store.unpack.row_length = param; break; case GL_UNPACK_SKIP_ROWS: context->pixel_store.unpack.skip_rows = param; break; case GL_UNPACK_SKIP_PIXELS: context->pixel_store.unpack.skip_pixels = param; break; case GL_UNPACK_ALIGNMENT: context->pixel_store.unpack.alignment = param; break; case GL_PACK_SWAP_BYTES: context->pixel_store.pack.swap_bytes = param; break; case GL_PACK_LSB_FIRST: context->pixel_store.pack.lsb_first = param; break; case GL_PACK_ROW_LENGTH: context->pixel_store.pack.row_length = param; break; case GL_PACK_SKIP_ROWS: context->pixel_store.pack.skip_rows = param; break; case GL_PACK_SKIP_PIXELS: context->pixel_store.pack.skip_pixels = param; break; case GL_PACK_ALIGNMENT: context->pixel_store.pack.alignment = param; break; default: // Others here break; } } void cgl_GLPixelTransferf(struct GLContextIFace *Self, GLenum param, GLfloat value) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(PixelTransfer(Self, param, value)) switch (param) { case GL_MAP_COLOR: context->pixel.map_color = (GLboolean)value; break; case GL_MAP_STENCIL: context->pixel.map_stencil = (GLboolean)value; break; case GL_ALPHA_SCALE: context->pixel.alpha_scale = value; break; case GL_BLUE_SCALE: context->pixel.blue_scale = value; break; case GL_GREEN_SCALE: context->pixel.green_scale = value; break; case GL_RED_SCALE: context->pixel.red_scale = value; break; case GL_DEPTH_SCALE: context->pixel.depth_scale = value; break; case GL_ALPHA_BIAS: context->pixel.alpha_bias = value; break; case GL_BLUE_BIAS: context->pixel.blue_bias = value; break; case GL_GREEN_BIAS: context->pixel.green_bias = value; break; case GL_RED_BIAS: context->pixel.red_bias = value; break; case GL_DEPTH_BIAS: context->pixel.depth_bias = value; break; default: context->CurrentError = GL_INVALID_ENUM; return; } context->pixel.pixel_state_neutral = isPixelStateNeutral(context); } #define A_COMPONENT 0 #define R_COMPONENT 1 #define G_COMPONENT 2 #define B_COMPONENT 3 #define CLAMPI(x) ((x) > 255 ? 255 : (x) < 0 ? 0 : (x)) /* PixelTransfer functionality * These function scale and/or bias color data */ void _transfer_scale(GLcontext context, int num_pixels, void *buffer, struct GLpixel_state *ps) { /* int ascale = (int)(255.0 * ps->alpha_scale); int bscale = (int)(255.0 * ps->blue_scale); int gscale = (int)(255.0 * ps->green_scale); int rscale = (int)(255.0 * ps->red_scale); */ int ascale = (int)fast_normalized_to_u8(ps->alpha_scale); int bscale = (int)fast_normalized_to_u8(ps->blue_scale); int gscale = (int)fast_normalized_to_u8(ps->green_scale); int rscale = (int)fast_normalized_to_u8(ps->red_scale); uint8 *to = (uint8 *)buffer; while (num_pixels--) { to[A_COMPONENT] = CLAMPI((int)(to[A_COMPONENT] * ascale) >> 8); to[R_COMPONENT] = CLAMPI((int)(to[R_COMPONENT] * rscale) >> 8); to[G_COMPONENT] = CLAMPI((int)(to[G_COMPONENT] * gscale) >> 8); to[B_COMPONENT] = CLAMPI((int)(to[B_COMPONENT] * bscale) >> 8); to += 4; } } void _transfer_scale_bias(GLcontext context, int num_pixels, void *buffer, struct GLpixel_state *ps) { /* int abias = (int)(255.0 * ps->alpha_bias); int bbias = (int)(255.0 * ps->blue_bias); int gbias = (int)(255.0 * ps->green_bias); int rbias = (int)(255.0 * ps->red_scale); int ascale = (int)(255.0 * ps->alpha_scale); int bscale = (int)(255.0 * ps->blue_scale); int gscale = (int)(255.0 * ps->green_scale); int rscale = (int)(255.0 * ps->red_scale); */ int abias = (int)fast_normalized_to_u8(ps->alpha_bias); int bbias = (int)fast_normalized_to_u8(ps->blue_bias); int gbias = (int)fast_normalized_to_u8(ps->green_bias); int rbias = (int)fast_normalized_to_u8(ps->red_scale); int ascale = (int)fast_normalized_to_u8(ps->alpha_scale); int bscale = (int)fast_normalized_to_u8(ps->blue_scale); int gscale = (int)fast_normalized_to_u8(ps->green_scale); int rscale = (int)fast_normalized_to_u8(ps->red_scale); uint8 *to = (uint8 *)buffer; while (num_pixels--) { int res = (int)to[A_COMPONENT]; res = ((res * ascale) >> 8) + abias; to[A_COMPONENT] = CLAMPI(res); res = (int)to[R_COMPONENT]; res = ((res * rscale) >> 8) + rbias; to[R_COMPONENT] = CLAMPI(res); res = (int)to[G_COMPONENT]; res = ((res * gscale) >> 8) + gbias; to[G_COMPONENT] = CLAMPI(res); res = (int)to[B_COMPONENT]; res = ((res * bscale) >> 8) + bbias; to[B_COMPONENT] = CLAMPI(res); to += 4; } } void _transfer_bias(GLcontext context, int num_pixels, void *buffer, struct GLpixel_state *ps) { /* int abias = (int)(255.0 * ps->alpha_bias); int bbias = (int)(255.0 * ps->blue_bias); int gbias = (int)(255.0 * ps->green_bias); int rbias = (int)(255.0 * ps->red_scale); */ int abias = (int)fast_normalized_to_u8(ps->alpha_bias); int bbias = (int)fast_normalized_to_u8(ps->blue_bias); int gbias = (int)fast_normalized_to_u8(ps->green_bias); int rbias = (int)fast_normalized_to_u8(ps->red_scale); uint8 *to = (uint8 *)buffer; while (num_pixels--) { to[A_COMPONENT] = CLAMPI((int)(to[A_COMPONENT] + abias)); to[R_COMPONENT] = CLAMPI((int)(to[R_COMPONENT] + rbias)); to[G_COMPONENT] = CLAMPI((int)(to[G_COMPONENT] + gbias)); to[B_COMPONENT] = CLAMPI((int)(to[B_COMPONENT] + bbias)); to += 4; } } _glTransferFn MGLSelectTransfer(GLenum format, struct GLpixel_state *pixelState) { GLboolean scale = GL_FALSE; GLboolean bias = GL_FALSE; /* Assume color for now */ if ((pixelState->alpha_scale == 1.0) && (pixelState->blue_scale == 1.0) && (pixelState->green_scale == 1.0) && (pixelState->red_scale == 1.0) ) { scale = GL_FALSE; } else { scale = GL_TRUE; } if ((pixelState->alpha_bias == 0.0) && (pixelState->blue_bias == 0.0) && (pixelState->green_bias == 0.0) && (pixelState->red_bias == 0.0) ) { bias = GL_FALSE; } else { bias = GL_TRUE; } if (scale && bias) { return _transfer_scale_bias; } else if (scale) { return _transfer_scale; } else if (bias) { return _transfer_bias; } return NULL; } /* This function converts from src image to destination image. The srcPs and * dstPs GLpixel_store give the appropriate packing modes. Set to NULL for * default. * pixelState can be NULL, too, in which case no pixel transformation is done. * Note that the GLimage_infos will be modified. */ GLboolean MGLTransferImage( GLcontext context, GLsizei width, GLsizei height, GLimage_info *src, GLpixel_store *srcPs, GLimage_info *dst, GLpixel_store *dstPs, struct GLpixel_state *pixelState ); /* Unpack image with current unpack state */ GLboolean MGLUnpackImage( GLcontext context, GLsizei width, GLsizei height, GLimage_info *src, GLimage_info *dst, GLboolean doPixelState ) { return MGLTransferImage( context, width, height, src, &context->pixel_store.unpack, dst, NULL, doPixelState == GL_TRUE ? &context->pixel : NULL ); } /* Pack image with current unpack state */ GLboolean MGLPackImage( GLcontext context, GLsizei width, GLsizei height, GLimage_info *src, GLimage_info *dst, GLboolean doPixelState ) { return MGLTransferImage(context, width, height, src, NULL, dst, &context->pixel_store.pack, doPixelState == GL_TRUE ? &context->pixel : NULL); } GLboolean MGLTransferImage( GLcontext context, GLsizei width, GLsizei height, GLimage_info *src, GLpixel_store *srcPs, GLimage_info *dst, GLpixel_store *dstPs, struct GLpixel_state *pixelState ) { GLpixel_store defaultPixelStore = {GL_FALSE, GL_FALSE, 0, 0, 0, 4}; /* Apply unpack parameters to images */ if (srcPs) { if (srcPs->row_length > 0) { src->stride = srcPs->row_length * src->pixel_stride; } src->current = src->data + (srcPs->skip_rows * src->stride) + (srcPs->skip_pixels * src->pixel_stride); } else { src->current = src->data; } if (dstPs) { if (dstPs->row_length > 0) { dst->stride = dstPs->row_length * dst->pixel_stride; } dst->current = dst->data + (dstPs->skip_rows * dst->stride) + (dstPs->skip_pixels * dst->pixel_stride); } else { dst->current = dst->data; } /* Note: we unpack from src and pack to dst */ _glPackFn pack; _glUnpackFn unpack; _glTransferFn transfer = NULL; unpack = MGLSelectUnpacker(src->format, src->type, NULL); if (!unpack) { return GL_FALSE; } pack = MGLSelectPacker(dst->format, dst->type, NULL); if (!pack) { return GL_FALSE; } if (pixelState) { transfer = MGLSelectTransfer(src->format, pixelState); } void *buffer = alloca(width * sizeof(GLuint)); if (!buffer) { return GL_FALSE; } if (!srcPs) { srcPs = &defaultPixelStore; } if (!dstPs) { dstPs = &defaultPixelStore; } while (height --) { unpack(context, width, src, srcPs, buffer); if (transfer) { transfer(context, width, buffer, pixelState); } pack(context, width, buffer, dst, dstPs); src->current += src->stride; dst->current += dst->stride; } return GL_TRUE; } struct W3DtoGL _w3dgl[] = {// Format bpp r g b a l i GL format GL type {W3D_A8, 1, 0, 0, 0, 8, 0, 0, GL_ALPHA, GL_UNSIGNED_BYTE}, {W3D_L8, 1, 0, 0, 0, 0, 8, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE}, {W3D_L8, 1, 0, 0, 0, 0, 8, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE}, {W3D_L8A8, 2, 0, 0, 0, 8, 8, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE}, {W3D_L8A8, 2, 0, 0, 0, 8, 8, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE}, {W3D_I8, 1, 0, 0, 0, 0, 0, 8, GL_INTENSITY, GL_UNSIGNED_BYTE}, {W3D_R8G8B8, 3, 8, 8, 8, 0, 0, 0, GL_RGB, GL_UNSIGNED_BYTE}, {W3D_R8G8B8, 3, 8, 8, 8, 0, 0, 0, GL_RGB, GL_UNSIGNED_BYTE}, {W3D_A8R8G8B8, 4, 8, 8, 8, 8, 0, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV}, {W3D_A8R8G8B8, 4, 8, 8, 8, 8, 0, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV}, {W3D_R5G6B5, 2, 5, 6, 7, 0, 0, 0, GL_RGB5, GL_UNSIGNED_SHORT_5_6_5}, {W3D_R5G6B5, 2, 5, 6, 5, 0, 0, 0, GL_RGB4, GL_UNSIGNED_SHORT_5_6_5}, {W3D_A4R4G4B4, 2, 4, 4, 4, 4, 0, 0, MGL_ARGB4, GL_UNSIGNED_SHORT_4_4_4_4}, {W3D_A1R5G5B5, 2, 5, 5, 5, 1, 0, 0, MGL_A1_RGB5, MGL_UNSIGNED_SHORT_1_5_5_5}, {W3D_R8G8B8, 3, 8, 8, 8, 0, 0, 0, GL_RGB, GL_UNSIGNED_BYTE}, {W3D_A8R8G8B8, 4, 8, 8, 8, 8, 0, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV}, {0, 0} }; struct W3DtoGL *MGLGetFormatInfo(uint32 w3dFormat) { int i; for (i = 0; _w3dgl[i].w3dFormat != 0; i++) { if (_w3dgl[i].w3dFormat == w3dFormat) { return &_w3dgl[i]; } } return NULL; } /* These variants use an internal buffer of ARGB data instead of RGBA, to * accelerate glReadPixels */ #undef A_COMPONENT #undef R_COMPONENT #undef G_COMPONENT #undef B_COMPONENT #define A_COMPONENT 0 #define R_COMPONENT 1 #define G_COMPONENT 2 #define B_COMPONENT 3 void _transfer_scaleARGB(GLcontext context, int num_pixels, void *buffer, struct GLpixel_state *ps) { /* int ascale = (int)(255.0 * ps->alpha_scale); int bscale = (int)(255.0 * ps->blue_scale); int gscale = (int)(255.0 * ps->green_scale); int rscale = (int)(255.0 * ps->red_scale); */ int ascale = (int)fast_normalized_to_u8(ps->alpha_scale); int bscale = (int)fast_normalized_to_u8(ps->blue_scale); int gscale = (int)fast_normalized_to_u8(ps->green_scale); int rscale = (int)fast_normalized_to_u8(ps->red_scale); uint8 *to = (uint8 *)buffer; while (num_pixels--) { to[A_COMPONENT] = CLAMPI((int)(to[A_COMPONENT] * ascale) >> 8); to[R_COMPONENT] = CLAMPI((int)(to[R_COMPONENT] * rscale) >> 8); to[G_COMPONENT] = CLAMPI((int)(to[G_COMPONENT] * gscale) >> 8); to[B_COMPONENT] = CLAMPI((int)(to[B_COMPONENT] * bscale) >> 8); to += 4; } } void _transfer_scale_biasARGB(GLcontext context, int num_pixels, void *buffer, struct GLpixel_state *ps) { /* int abias = (int)(255.0 * ps->alpha_bias); int bbias = (int)(255.0 * ps->blue_bias); int gbias = (int)(255.0 * ps->green_bias); int rbias = (int)(255.0 * ps->red_scale); int ascale = (int)(255.0 * ps->alpha_scale); int bscale = (int)(255.0 * ps->blue_scale); int gscale = (int)(255.0 * ps->green_scale); int rscale = (int)(255.0 * ps->red_scale); */ int abias = (int)fast_normalized_to_u8(ps->alpha_bias); int bbias = (int)fast_normalized_to_u8(ps->blue_bias); int gbias = (int)fast_normalized_to_u8(ps->green_bias); int rbias = (int)fast_normalized_to_u8(ps->red_scale); int ascale = (int)fast_normalized_to_u8(ps->alpha_scale); int bscale = (int)fast_normalized_to_u8(ps->blue_scale); int gscale = (int)fast_normalized_to_u8(ps->green_scale); int rscale = (int)fast_normalized_to_u8(ps->red_scale); uint8 *to = (uint8 *)buffer; while (num_pixels--) { int res = (int)to[A_COMPONENT]; res = ((res * ascale) >> 8) + abias; to[A_COMPONENT] = CLAMPI(res); res = (int)to[R_COMPONENT]; res = ((res * rscale) >> 8) + rbias; to[R_COMPONENT] = CLAMPI(res); res = (int)to[G_COMPONENT]; res = ((res * gscale) >> 8) + gbias; to[G_COMPONENT] = CLAMPI(res); res = (int)to[B_COMPONENT]; res = ((res * bscale) >> 8) + bbias; to[B_COMPONENT] = CLAMPI(res); to += 4; } } void _transfer_biasARGB(GLcontext context, int num_pixels, void *buffer, struct GLpixel_state *ps) { /* int abias = (int)(255.0 * ps->alpha_bias); int bbias = (int)(255.0 * ps->blue_bias); int gbias = (int)(255.0 * ps->green_bias); int rbias = (int)(255.0 * ps->red_scale); */ int abias = (int)fast_normalized_to_u8(ps->alpha_bias); int bbias = (int)fast_normalized_to_u8(ps->blue_bias); int gbias = (int)fast_normalized_to_u8(ps->green_bias); int rbias = (int)fast_normalized_to_u8(ps->red_scale); uint8 *to = (uint8 *)buffer; while (num_pixels--) { to[A_COMPONENT] = CLAMPI((int)(to[A_COMPONENT] + abias)); to[R_COMPONENT] = CLAMPI((int)(to[R_COMPONENT] + rbias)); to[G_COMPONENT] = CLAMPI((int)(to[G_COMPONENT] + gbias)); to[B_COMPONENT] = CLAMPI((int)(to[B_COMPONENT] + bbias)); to += 4; } } _glTransferFn MGLSelectTransferARGB(GLenum format, struct GLpixel_state *pixelState) { GLboolean scale = GL_FALSE; GLboolean bias = GL_FALSE; /* Assume color for now */ if ((pixelState->alpha_scale == 1.0) && (pixelState->blue_scale == 1.0) && (pixelState->green_scale == 1.0) && (pixelState->red_scale == 1.0) ) { scale = GL_FALSE; } else { scale = GL_TRUE; } if ((pixelState->alpha_bias == 0.0) && (pixelState->blue_bias == 0.0) && (pixelState->green_bias == 0.0) && (pixelState->red_bias == 0.0) ) { bias = GL_FALSE; } else { bias = GL_TRUE; } if (scale && bias) { return _transfer_scale_biasARGB; } else if (scale) { return _transfer_scaleARGB; } else if (bias) { return _transfer_biasARGB; } return NULL; } GLboolean isPixelStateNeutral(GLcontext context) { struct GLpixel_state *pixel = &context->pixel; if (pixel->alpha_scale != 1.0 || pixel->blue_scale != 1.0 || pixel->green_scale != 1.0 || pixel->red_scale != 1.0 || pixel->depth_scale != 1.0 || pixel->alpha_bias != 0.0 || pixel->blue_bias != 0.0 || pixel->green_bias != 0.0 || pixel->red_bias != 0.0 || pixel->depth_bias != 0.0 || pixel->zoom_x != 1.0 || pixel->zoom_y != 1.0) { return GL_FALSE; } return GL_TRUE; }