/* * $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 * */ // TO DO - optimize all of this byte-reading nonsense! #include "displaylists.h" #include "sysinc.h" #include #include #include #include #include "mgl_profileitems.h" /* Note: These functions are basically the same as in pack.c, with the difference * of using a ARGB source buffer instead of RGBA. * This makes ReadPixels faster since it does not need to convert the result * of BltBitMapTags first. */ extern char *format_to_string(GLenum format); extern char *type_to_string(GLenum type); static inline uint16 load_16_little(uint16 *addr) { uint16 x; __asm volatile ("lhbrx %0, 0, %1" : "=r" (x) : "r" (addr)); return x; } static inline void store_16_little(uint16 *addr, uint16 val) { __asm volatile ("sthbrx %0, 0, %1" :: "r" (val), "r" (addr)); } static inline uint32 load_32_little(uint32 *addr) { uint32 x; __asm volatile ("lwbrx %0, 0, %1" : "=r" (x) : "r" (addr)); return x; } static inline void store_32_little(uint32 *addr, uint32 val) { __asm volatile ("stwbrx %0, 0, %1" :: "r" (val), "r" (addr)); } #define A_COMPONENT 0 #define R_COMPONENT 1 #define G_COMPONENT 2 #define B_COMPONENT 3 #define SIGNED_BYTE(c) ((int8)(((int32)(c)) - 128)) static void _pack_rgb_b(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { uint8 *from = (uint8 *)src; uint8 *to = (uint8 *)dst->current; /* Note: swap_bytes not applicable to three-byte pixels */ while (num_pixels--) { *to++ = from[R_COMPONENT]; *to++ = from[G_COMPONENT]; *to++ = from[B_COMPONENT]; from += 4; } } static void _pack_rgba_b(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { uint8 *from = (uint8 *)src; uint8 *to = (uint8 *)dst->current; if (pack->swap_bytes) { while (num_pixels--) { *to++ = from[A_COMPONENT]; *to++ = from[B_COMPONENT]; *to++ = from[G_COMPONENT]; *to++ = from[R_COMPONENT]; from += 4; } } else { while (num_pixels--) { *to++ = from[R_COMPONENT]; *to++ = from[G_COMPONENT]; *to++ = from[B_COMPONENT]; *to++ = from[A_COMPONENT]; from += 4; } } } static void _pack_rgba_sb(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { uint8 *from = (uint8 *)src; int8 *to = (int8 *)dst->current; if (pack->swap_bytes) { while (num_pixels--) { *to++ = SIGNED_BYTE(from[A_COMPONENT]); *to++ = SIGNED_BYTE(from[B_COMPONENT]); *to++ = SIGNED_BYTE(from[G_COMPONENT]); *to++ = SIGNED_BYTE(from[R_COMPONENT]); from += 4; } } else { while (num_pixels--) { *to++ = SIGNED_BYTE(from[R_COMPONENT]); *to++ = SIGNED_BYTE(from[G_COMPONENT]); *to++ = SIGNED_BYTE(from[B_COMPONENT]); *to++ = SIGNED_BYTE(from[A_COMPONENT]); from += 4; } } } static void _pack_abgr_b(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { uint8 *from = (uint8 *)src; uint8 *to = (uint8 *)dst->current; if (pack->swap_bytes) { while (num_pixels--) { *to++ = from[R_COMPONENT]; *to++ = from[G_COMPONENT]; *to++ = from[B_COMPONENT]; *to++ = from[A_COMPONENT]; from += 4; } } else { while (num_pixels--) { *to++ = from[A_COMPONENT]; *to++ = from[B_COMPONENT]; *to++ = from[G_COMPONENT]; *to++ = from[R_COMPONENT]; from += 4; } } } static void _pack_bgra_b(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { uint32 *from = (uint32 *)src; uint32 *to = (uint32 *)dst->current; if (!pack->swap_bytes) { while (num_pixels--) { *to++ = *from++; } } else { while (num_pixels--) { *to++ = load_32_little(from++); } } } static void _pack_a_b(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { uint8 *from = (uint8 *)src; uint8 *to = (uint8 *)dst->current; while (num_pixels--) { *to++ = from[A_COMPONENT]; from += 4; } } static void _pack_l_b(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { uint8 *from = (uint8 *)src; uint8 *to = (uint8 *)dst->current; while (num_pixels--) { uint32 l = from[R_COMPONENT] + from[G_COMPONENT] + from[B_COMPONENT]; if (l > 255) { l = 255; } *to++ = l; from += 4; } } static void _pack_la_b(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { uint8 *from = (uint8 *)src; uint8 *to = (uint8 *)dst->current; if (pack->swap_bytes) { while (num_pixels--) { uint32 l = from[R_COMPONENT] + from[G_COMPONENT] + from[B_COMPONENT]; if (l > 255) { l = 255; } *to++ = from[A_COMPONENT]; *to++ = l; from += 4; } } else { while (num_pixels--) { uint32 l = from[R_COMPONENT] + from[G_COMPONENT] + from[B_COMPONENT]; if (l > 255) { l = 255; } *to++ = l; *to++ = from[A_COMPONENT]; from += 4; } } } static void _pack_i_b(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { uint8 *from = (uint8 *)src; uint8 *to = (uint8 *)dst->current; while (num_pixels--) { *to++ = from[R_COMPONENT]; from += 4; } } static void _pack_rgb_us565(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { uint8 *from = (uint8 *)src; uint16 *to = (uint16 *)dst->current; if (pack->swap_bytes) { while (num_pixels--) { store_16_little(to, ((from[R_COMPONENT] & 0xf8) << 8) | ((from[G_COMPONENT] & 0xfc) << 3) | ((from[B_COMPONENT] & 0xf8) >> 3)); from += 4; to++; } } else { while (num_pixels--) { *to++ = ((from[R_COMPONENT] & 0xf8) << 8) | ((from[G_COMPONENT] & 0xfc) << 3) | ((from[B_COMPONENT] & 0xf8) >> 3); from += 4; } } } static void _pack_rgb_us565r(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { uint8 *from = (uint8 *)src; uint16 *to = (uint16 *)dst->current; if (pack->swap_bytes) { while (num_pixels--) { store_16_little(to, ((from[B_COMPONENT] & 0xf8) << 8) | ((from[G_COMPONENT] & 0xfc) << 3) | ((from[R_COMPONENT] & 0xf8) >> 3)); from += 4; to++; } } else { while (num_pixels--) { *to++ = ((from[B_COMPONENT] & 0xf8) << 8) | ((from[G_COMPONENT] & 0xfc) << 3) | ((from[R_COMPONENT] & 0xf8) >> 3); from += 4; } } } static void _pack_rgba_us4444(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { uint8 *from = (uint8 *)src; uint16 *to = (uint16 *)dst->current; if (pack->swap_bytes) { while (num_pixels--) { store_16_little(to, ((from[R_COMPONENT] & 0xf0) << 8) | ((from[G_COMPONENT] & 0xf0) << 4) | ((from[B_COMPONENT] & 0xf0) ) | ((from[A_COMPONENT] & 0xf0) >> 4)); from += 4; to++; } } else { while (num_pixels--) { *to++ = ((from[R_COMPONENT] & 0xf0) << 8) | ((from[G_COMPONENT] & 0xf0) << 4) | ((from[B_COMPONENT] & 0xf0) ) | ((from[A_COMPONENT] & 0xf0) >> 4); from += 4; } } } static void _pack_rgba_us4444r(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { uint8 *from = (uint8 *)src; uint16 *to = (uint16 *)dst->current; if (pack->swap_bytes) { while (num_pixels--) { store_16_little(to, ((from[A_COMPONENT] & 0xf0) << 8) | ((from[B_COMPONENT] & 0xf0) << 4) | ((from[G_COMPONENT] & 0xf0) ) | ((from[R_COMPONENT] & 0xf0) >> 4)); from += 4; to++; } } else { while (num_pixels--) { *to++ = ((from[A_COMPONENT] & 0xf0) << 8) | ((from[B_COMPONENT] & 0xf0) << 4) | ((from[G_COMPONENT] & 0xf0) ) | ((from[R_COMPONENT] & 0xf0) >> 4); from += 4; } } } static void _pack_rgba_us1555(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { uint8 *from = (uint8 *)src; uint16 *to = (uint16 *)dst->current; if (pack->swap_bytes) { while (num_pixels--) { store_16_little(to, ((from[A_COMPONENT] & 0x80) << 8) | ((from[R_COMPONENT] & 0xf8) << 7) | ((from[G_COMPONENT] & 0xf8) << 2) | ((from[B_COMPONENT] & 0xf8) >> 3)); from += 4; to++; } } else { while (num_pixels--) { *to++ = ((from[A_COMPONENT] & 0x80) << 8) | ((from[R_COMPONENT] & 0xf8) << 7) | ((from[G_COMPONENT] & 0xf8) << 2) | ((from[B_COMPONENT] & 0xf8) >> 3); from += 4; } } } static void _pack_rgba_us1555r(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { uint8 *from = (uint8 *)src; uint16 *to = (uint16 *)dst->current; if (pack->swap_bytes) { while (num_pixels--) { store_16_little(to, ((from[A_COMPONENT] & 0x80) >> 7) | ((from[B_COMPONENT] & 0xf8) << 8) | ((from[G_COMPONENT] & 0xf8) << 3) | ((from[R_COMPONENT] & 0xf8) >> 2)); from += 4; to++; } } else { while (num_pixels--) { *to++ =((from[A_COMPONENT] & 0x80) >> 7) | ((from[B_COMPONENT] & 0xf8) << 8) | ((from[G_COMPONENT] & 0xf8) << 3) | ((from[R_COMPONENT] & 0xf8) >> 2); from += 4; } } } GLpack mglPackersARGB[] = { {GL_RGB, GL_UNSIGNED_BYTE, _pack_rgb_b, 3}, {3, GL_UNSIGNED_BYTE, _pack_rgb_b, 3}, {GL_RGBA, GL_UNSIGNED_BYTE, _pack_rgba_b, 4}, {4, GL_UNSIGNED_BYTE, _pack_rgba_b, 4}, {GL_RGBA, GL_BYTE, _pack_rgba_sb, 4}, {GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, _pack_abgr_b, 4}, /* Note: BGRA with unsigned int reversed is BGRA in big-endian format */ {GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, _pack_bgra_b, 4}, {GL_ALPHA, GL_UNSIGNED_BYTE, _pack_a_b, 1}, {GL_LUMINANCE, GL_UNSIGNED_BYTE, _pack_l_b, 1}, {1, GL_UNSIGNED_BYTE, _pack_l_b, 1}, {GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, _pack_la_b, 2}, {2, GL_UNSIGNED_BYTE, _pack_la_b, 2}, {GL_INTENSITY, GL_UNSIGNED_BYTE, _pack_i_b, 1}, {GL_RGB5, GL_UNSIGNED_SHORT_5_6_5, _pack_rgb_us565, 2}, {GL_RGB, GL_UNSIGNED_SHORT_5_6_5, _pack_rgb_us565, 2}, {GL_RGB5, GL_UNSIGNED_SHORT_5_6_5_REV, _pack_rgb_us565r, 2}, {GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, _pack_rgb_us565r, 2}, {GL_RGB4, GL_UNSIGNED_SHORT_4_4_4_4, _pack_rgba_us4444, 2}, {GL_RGB, GL_UNSIGNED_SHORT_4_4_4_4, _pack_rgba_us4444, 2}, {GL_RGB4, GL_UNSIGNED_SHORT_4_4_4_4_REV, _pack_rgba_us4444r, 2}, {GL_RGB, GL_UNSIGNED_SHORT_4_4_4_4_REV, _pack_rgba_us4444r, 2}, {GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1, _pack_rgba_us1555, 2}, {GL_RGB, GL_UNSIGNED_SHORT_5_5_5_1, _pack_rgba_us1555, 2}, {GL_RGB5_A1, GL_UNSIGNED_SHORT_1_5_5_5_REV, _pack_rgba_us1555r, 2}, {GL_RGB, GL_UNSIGNED_SHORT_1_5_5_5_REV, _pack_rgba_us1555r, 2}, {GL_NONE, GL_NONE, NULL, 0}, }; _glPackFn MGLSelectPackerARGB(GLenum format, GLenum type, GLuint *pixelStride) { int i = 0; while (mglPackersARGB[i].format != GL_NONE) { if (format == mglPackersARGB[i].format && type == mglPackersARGB[i].type) { if (pixelStride) *pixelStride = mglPackersARGB[i].stride; return mglPackersARGB[i].pack; } i++; } IExec->DebugPrintF("Missing ARGB pack support for %s/%s\n", format_to_string(format), type_to_string(type)); return NULL; }