/* * $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" 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 static void _pack_rgb_b(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { PROFILE_ENTRY(FID_PACK_RGB_B) 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; } PROFILE_EXIT(FID_PACK_RGB_B) } static void _pack_rgba_b(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { PROFILE_ENTRY(FID_PACK_RGBA_B) uint32 *from = (uint32 *)src; uint32 *to = (uint32 *)dst->current; if (pack->swap_bytes) { while (num_pixels--) { uint32 temp = load_32_little(from++); *to++ = temp >> 8 | temp << 24; } } else { while (num_pixels--) { *to++ = (*from << 8) | (*from >> 24); from++; } } PROFILE_EXIT(FID_PACK_RGBA_B) } static void _pack_abgr_b(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { PROFILE_ENTRY(FID_PACK_ABGR_B) uint32 *from = (uint32 *)src; uint32 *to = (uint32 *)dst->current; if (pack->swap_bytes) { while (num_pixels--) { *to++ = (*from << 8) | (*from >> 24); from++; } } else { while (num_pixels--) { uint32 temp = load_32_little(from++); *to++ = temp >> 8 | temp << 24; } } PROFILE_EXIT(FID_PACK_ABGR_B) } static void _pack_argb_b(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { uint32 *from = (uint32 *)src; uint32 *to = (uint32 *)dst->current; /* Note: assumes BGRA byte reversed */ if (!pack->swap_bytes) { while (num_pixels--) { *to++ = load_32_little(from++); } } else { while (num_pixels--) { *to++ = *from++; } } } static void _pack_a_b(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { PROFILE_ENTRY(FID_PACK_A_B) uint8 *from = (uint8 *)src; uint8 *to = (uint8 *)dst->current; while (num_pixels--) { *to++ = from[A_COMPONENT]; from += 4; } PROFILE_EXIT(FID_PACK_A_B) } static void _pack_l_b(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { PROFILE_ENTRY(FID_PACK_L_B) 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; } PROFILE_EXIT(FID_PACK_L_B) } static void _pack_la_b(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { PROFILE_ENTRY(FID_PACK_LA_B) 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; } } PROFILE_EXIT(FID_PACK_LA_B) } static void _pack_i_b(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { PROFILE_ENTRY(FID_PACK_I_B) uint8 *from = (uint8 *)src; uint8 *to = (uint8 *)dst->current; while (num_pixels--) { *to++ = from[R_COMPONENT]; from += 4; } PROFILE_EXIT(FID_PACK_I_B) } static void _pack_rgb_us565(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { PROFILE_ENTRY(FID_PACK_RGB_US565) 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; } } PROFILE_EXIT(FID_PACK_RGB_US565) } static void _pack_rgb_us565r(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { PROFILE_ENTRY(FID_PACK_RGB_US565R) 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; } } PROFILE_ENTRY(FID_PACK_RGB_US565R) } static void _pack_rgba_us4444(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { PROFILE_ENTRY(FID_PACK_RGBA_US4444) 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; } } PROFILE_EXIT(FID_PACK_RGBA_US4444) } static void _pack_rgba_us4444r(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { PROFILE_ENTRY(FID_PACK_RGBA_US4444R) 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; } } PROFILE_EXIT(FID_PACK_RGBA_US4444R) } static void _pack_rgba_us1555(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { PROFILE_ENTRY(FID_PACK_RGBA_US1555) 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; } } PROFILE_EXIT(FID_PACK_RGBA_US1555) } static void _pack_rgba_us1555r(GLcontext context, int num_pixels, void *src, GLimage_info *dst, GLpixel_store *pack) { PROFILE_ENTRY(FID_PACK_RGBA_US1555R) 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; } } PROFILE_EXIT(FID_PACK_RGBA_US1555R) } GLpack mglPackers[] = { {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_UNSIGNED_INT_8_8_8_8_REV, _pack_abgr_b, 4}, /* Note: BGRA with unsigned int reversed is ARGB */ {GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, _pack_argb_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 MGLSelectPacker(GLenum format, GLenum type, GLuint *pixelStride) { int i = 0; while (mglPackers[i].format != GL_NONE) { if (format == mglPackers[i].format && type == mglPackers[i].type) { if (pixelStride) { *pixelStride = mglPackers[i].stride; } return mglPackers[i].pack; } i++; } IExec->DebugPrintF( "Missing pack support for %s/%s\n", format_to_string(format), type_to_string(type) ); return NULL; }