/* * $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 "mgl_profileitems.h" extern char *format_to_string(GLenum format); extern char *type_to_string(GLenum type); /* * This file implements span unpackers that unpack from a given format/datatype * combination to a 32 bit ARGB buffer (color), 32 bit float (depth) buffer, or * 32 bit integer (stencil) buffer. * * NOTE: This functionality duplicates some of textureconvert.c, however, this is * goint to replace that functionality later on. */ #define REDBYTE(rgb) (((uint16)rgb & 0xF800) >> 8) #define GREENBYTE(rgb) (((uint16)rgb & 0x07E0) >> 3) #define BLUEBYTE(rgb) (((uint16)rgb & 0x001F) << 3) #define REDBYTEA(rgba) (((uint16)rgba & 0x0f00) >> 4) #define GREENBYTEA(rgba) (((uint16)rgba & 0x00f0)) #define BLUEBYTEA(rgba) (((uint16)rgba & 0x000f) << 4) #define ALPHABYTEA(rgba) (((uint16)rgba & 0xf000) >> 8) #define REDBYTE5551(rgba) (((uint16)rgba & 0x7C00) >> 7) #define GREENBYTE5551(rgba) (((uint16)rgba & 0x03e0) >> 2) #define BLUEBYTE5551(rgba) (((uint16)rgba & 0x001F) << 3) #define ALPHABYTE5551(rgba) (((uint16)rgba & 0x8000) ? 0xff : 0x00) 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 _unpack_rgb_b(GLcontext context, int num_pixels, GLimage_info *src, GLpixel_store *unpack, void *dst) { PROFILE_ENTRY(FID_UNPACK_RGB_B); uint8 *to = (uint8 *)dst; uint8 *from = (uint8 *)src->current; /* Note: swap_bytes not defined for three-byte pixels */ while (num_pixels--) { to[R_COMPONENT] = *from++; to[G_COMPONENT] = *from++; to[B_COMPONENT] = *from++; to[A_COMPONENT] = 0xff; to += 4; } PROFILE_EXIT(FID_UNPACK_RGB_B); } static void _unpack_rgba_b(GLcontext context, int num_pixels, GLimage_info *src, GLpixel_store *unpack, void *dst) { PROFILE_ENTRY(FID_UNPACK_RGBA_B); uint8 *to = (uint8 *)dst; uint8 *from = (uint8 *)src->current; if (unpack->swap_bytes) { while (num_pixels--) { to[A_COMPONENT] = *from++; to[B_COMPONENT] = *from++; to[G_COMPONENT] = *from++; to[R_COMPONENT] = *from++; to += 4; } } else { while (num_pixels--) { to[R_COMPONENT] = *from++; to[G_COMPONENT] = *from++; to[B_COMPONENT] = *from++; to[A_COMPONENT] = *from++; to += 4; } } PROFILE_EXIT(FID_UNPACK_RGBA_B); } static void _unpack_argb_b(GLcontext context, int num_pixels, GLimage_info *src, GLpixel_store *unpack, void *dst) { PROFILE_ENTRY(FID_UNPACK_ARGB_B); uint32 *to = (uint32 *)dst; uint32 *from = (uint32 *)src->current; if (unpack->swap_bytes) { while (num_pixels--) { *to++ = load_32_little(from++); } } else { while (num_pixels--) { *to++ = *from++; } } PROFILE_EXIT(FID_UNPACK_ARGB_B); } static void _unpack_a_b(GLcontext context, int num_pixels, GLimage_info *src, GLpixel_store *unpack, void *dst) { PROFILE_ENTRY(FID_UNPACK_A_B); uint8 *to = (uint8 *)dst; uint8 *from = (uint8 *)src->current; /* Note: swap_bytes not defined for one-byte pixels */ while (num_pixels--) { to[R_COMPONENT] = 0; to[G_COMPONENT] = 0; to[B_COMPONENT] = 0; to[A_COMPONENT] = *from++; to += 4; } PROFILE_EXIT(FID_UNPACK_A_B); } static void _unpack_ci_b(GLcontext context, int num_pixels, GLimage_info *src, GLpixel_store *unpack, void *dst) { PROFILE_ENTRY(FID_UNPACK_CI_B); uint8 *to = (uint8 *)dst; uint8 *from = (uint8 *)src->current; uint8 *pal = (uint8 *)context->PaletteData; if (context->PaletteFormat == GL_RGB) { while (num_pixels--) { uint32 idx = *from++; to[R_COMPONENT] = pal[idx*3]; to[G_COMPONENT] = pal[idx*3+1]; to[B_COMPONENT] = pal[idx*3+2]; to[A_COMPONENT] = 0xff; to += 4; } } else { while (num_pixels--) { uint32 idx = *from++; to[R_COMPONENT] = pal[idx*4]; to[G_COMPONENT] = pal[idx*4+1]; to[B_COMPONENT] = pal[idx*4+2]; to[A_COMPONENT] = pal[idx*4+3]; to += 4; } } PROFILE_EXIT(FID_UNPACK_CI_B); } static void _unpack_rgb_us565(GLcontext context, int num_pixels, GLimage_info *src, GLpixel_store *unpack, void *dst) { PROFILE_ENTRY(FID_UNPACK_RGB_US565); uint8 *to = (uint8 *)dst; uint16 *from = (uint16 *)src->current; if (unpack->swap_bytes) { while (num_pixels--) { GLushort rgb = load_16_little(from); from++; to[R_COMPONENT] = REDBYTE(rgb); to[G_COMPONENT] = GREENBYTE(rgb); to[B_COMPONENT] = BLUEBYTE(rgb); to[A_COMPONENT] = 0xff; to += 4; } } else { while (num_pixels--) { GLushort rgb = *from++; to[R_COMPONENT] = REDBYTE(rgb); to[G_COMPONENT] = GREENBYTE(rgb); to[B_COMPONENT] = BLUEBYTE(rgb); to[A_COMPONENT] = 0xff; to += 4; } } PROFILE_EXIT(FID_UNPACK_RGB_US565); } static void _unpack_rgba_us444(GLcontext context, int num_pixels, GLimage_info *src, GLpixel_store *unpack, void *dst) { PROFILE_ENTRY(FID_UNPACK_RGBA_US444); uint8 *to = (uint8 *)dst; uint16 *from = (uint16 *)src->current; if (unpack->swap_bytes) { while (num_pixels--) { GLushort rgba = load_16_little(from); from++; to[R_COMPONENT] = REDBYTEA(rgba); to[G_COMPONENT] = GREENBYTEA(rgba); to[B_COMPONENT] = BLUEBYTEA(rgba); to[A_COMPONENT] = ALPHABYTEA(rgba); to += 4; } } else { while (num_pixels--) { GLushort rgba = *from++; to[R_COMPONENT] = REDBYTEA(rgba); to[G_COMPONENT] = GREENBYTEA(rgba); to[B_COMPONENT] = BLUEBYTEA(rgba); to[A_COMPONENT] = ALPHABYTEA(rgba); to += 4; } } PROFILE_EXIT(FID_UNPACK_RGBA_US444); } static void _unpack_bgr_b(GLcontext context, int num_pixels, GLimage_info *src, GLpixel_store *unpack, void *dst) { PROFILE_ENTRY(FID_UNPACK_BGR_B); uint8 *to = (uint8 *)dst; uint8 *from = (uint8 *)src->current; /* Note: swap_bytes not defined for three-byte pixels */ while (num_pixels--) { to[B_COMPONENT] = *from++; to[G_COMPONENT] = *from++; to[R_COMPONENT] = *from++; to[A_COMPONENT] = 0xff; to += 4; } PROFILE_EXIT(FID_UNPACK_BGR_B); } static void _unpack_bgra_b(GLcontext context, int num_pixels, GLimage_info *src, GLpixel_store *unpack, void *dst) { PROFILE_ENTRY(FID_UNPACK_BGRA_B); uint8 *to = (uint8 *)dst; uint8 *from = (uint8 *)src->current; if (unpack->swap_bytes) { while (num_pixels--) { to[A_COMPONENT] = *from++; to[R_COMPONENT] = *from++; to[G_COMPONENT] = *from++; to[B_COMPONENT] = *from++; to += 4; } } else { while (num_pixels--) { to[B_COMPONENT] = *from++; to[G_COMPONENT] = *from++; to[R_COMPONENT] = *from++; to[A_COMPONENT] = *from++; to += 4; } } PROFILE_EXIT(FID_UNPACK_BGRA_B); } static void _unpack_bgra_us1555rev(GLcontext context, int num_pixels, GLimage_info *src, GLpixel_store *unpack, void *dst) { PROFILE_ENTRY(FID_UNPACK_BGRA_US1555REV); uint8 *to = (uint8 *)dst; uint16 *from = (uint16 *)src->current; if (unpack->swap_bytes) { while (num_pixels--) { GLushort rgb = load_16_little(from); from++; to[R_COMPONENT] = REDBYTE5551(rgb); to[G_COMPONENT] = GREENBYTE5551(rgb); to[B_COMPONENT] = BLUEBYTE5551(rgb); to[A_COMPONENT] = ALPHABYTE5551(rgb); to += 4; } } else { while (num_pixels--) { GLushort rgb = *from++; to[R_COMPONENT] = REDBYTE5551(rgb); to[G_COMPONENT] = GREENBYTE5551(rgb); to[B_COMPONENT] = BLUEBYTE5551(rgb); to[A_COMPONENT] = ALPHABYTE5551(rgb); to += 4; } } PROFILE_EXIT(FID_UNPACK_BGRA_US1555REV); } static void _unpack_l_b(GLcontext context, int num_pixels, GLimage_info *src, GLpixel_store *unpack, void *dst) { PROFILE_ENTRY(FID_UNPACK_L_B); uint8 *to = (uint8 *)dst; uint8 *from = (uint8 *)src->current; /* Note: swap_bytes not defined for one-byte pixels */ while (num_pixels--) { uint8 val = *from++; to[R_COMPONENT] = val; to[G_COMPONENT] = val; to[B_COMPONENT] = val; to[A_COMPONENT] = 0xff; to += 4; } PROFILE_EXIT(FID_UNPACK_L_B); } static void _unpack_la_b(GLcontext context, int num_pixels, GLimage_info *src, GLpixel_store *unpack, void *dst) { PROFILE_ENTRY(FID_UNPACK_LA_B); uint8 *to = (uint8 *)dst; uint8 *from = (uint8 *)src->current; if (unpack->swap_bytes) { while (num_pixels--) { uint8 a = *from++; uint8 l = *from++; to[R_COMPONENT] = l; to[G_COMPONENT] = l; to[B_COMPONENT] = l; to[A_COMPONENT] = a; to += 4; } } else { while (num_pixels--) { uint8 l = *from++; uint8 a = *from++; to[R_COMPONENT] = l; to[G_COMPONENT] = l; to[B_COMPONENT] = l; to[A_COMPONENT] = a; to += 4; } } PROFILE_EXIT(FID_UNPACK_L_B); } static void _unpack_i_b(GLcontext context, int num_pixels, GLimage_info *src, GLpixel_store *unpack, void *dst) { PROFILE_ENTRY(FID_UNPACK_I_B); uint8 *to = (uint8 *)dst; uint8 *from = (uint8 *)src->current; /* Note: swap_bytes not defined for one-byte pixels */ while (num_pixels--) { uint8 val = *from++; to[R_COMPONENT] = val; to[G_COMPONENT] = val; to[B_COMPONENT] = val; to[A_COMPONENT] = val; to += 4; } PROFILE_EXIT(FID_UNPACK_I_B); } static void _unpack_l_ui(GLcontext context, int num_pixels, GLimage_info *src, GLpixel_store *unpack, void *dst) { PROFILE_ENTRY(FID_UNPACK_L_UI); uint8 *to = (uint8 *)dst; uint32 *from = (uint32 *)src->current; if (unpack->swap_bytes) { while (num_pixels--) { GLuint l = load_32_little(from); from++; uint8 val = (l)>>24; to[R_COMPONENT] = val; to[G_COMPONENT] = val; to[B_COMPONENT] = val; to[A_COMPONENT] = 0xff; to += 4; } } else { while (num_pixels--) { uint8 val = (*from++)>>24; to[R_COMPONENT] = val; to[G_COMPONENT] = val; to[B_COMPONENT] = val; to[A_COMPONENT] = 0xff; to += 4; } } PROFILE_EXIT(FID_UNPACK_L_UI); } GLunpack mglUnpackers[] = { {GL_RGB, GL_UNSIGNED_BYTE, _unpack_rgb_b, 3}, {GL_RGBA, GL_UNSIGNED_BYTE, _unpack_rgba_b, 4}, {GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, _unpack_argb_b, 4}, // ##### FIXME! ##### missing GL_ABGR {GL_ALPHA, GL_UNSIGNED_BYTE, _unpack_a_b, 1}, {GL_COLOR_INDEX, GL_UNSIGNED_BYTE, _unpack_ci_b, 1}, {GL_RGB, GL_UNSIGNED_SHORT_5_6_5, _unpack_rgb_us565, 2}, {GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, _unpack_rgba_us444, 2}, {GL_BGR, GL_UNSIGNED_BYTE, _unpack_bgr_b, 3}, {GL_BGRA, GL_UNSIGNED_BYTE, _unpack_bgra_b, 4}, {GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, _unpack_bgra_us1555rev, 2}, {GL_LUMINANCE, GL_UNSIGNED_BYTE, _unpack_l_b, 1}, {GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, _unpack_la_b, 2}, {GL_INTENSITY, GL_UNSIGNED_BYTE, _unpack_i_b, 3}, {GL_LUMINANCE, GL_UNSIGNED_INT, _unpack_l_ui, 4}, {GL_NONE, GL_NONE, NULL, 0}, }; _glUnpackFn MGLSelectUnpacker(GLenum format, GLenum type, GLuint *pixelStride) { int i = 0; while (mglUnpackers[i].format != GL_NONE) { if (format == mglUnpackers[i].format && type == mglUnpackers[i].type) { if (pixelStride) { *pixelStride = mglUnpackers[i].stride; } return mglUnpackers[i].unpack; } i++; } IExec->DebugPrintF("Missing unpack support for %s/%s\n", format_to_string(format), type_to_string(type)); return NULL; }